overcommit 0.19.0 → 0.20.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 +2 -1
- data/lib/overcommit/cli.rb +41 -1
- data/lib/overcommit/configuration_validator.rb +1 -2
- data/lib/overcommit/exceptions.rb +3 -0
- data/lib/overcommit/git_repo.rb +9 -1
- data/lib/overcommit/hook/base.rb +54 -32
- data/lib/overcommit/hook/commit_msg/text_width.rb +23 -16
- data/lib/overcommit/hook/pre_commit/base.rb +61 -1
- data/lib/overcommit/hook/pre_commit/haml_lint.rb +9 -13
- data/lib/overcommit/hook/pre_commit/image_optim.rb +3 -3
- data/lib/overcommit/hook/pre_commit/jscs.rb +5 -13
- data/lib/overcommit/hook/pre_commit/jsxcs.rb +5 -13
- data/lib/overcommit/hook/pre_commit/reek.rb +8 -15
- data/lib/overcommit/hook/pre_commit/rubocop.rb +9 -15
- data/lib/overcommit/hook/pre_commit/scss_lint.rb +9 -13
- data/lib/overcommit/hook_context/base.rb +3 -2
- data/lib/overcommit/hook_context/pre_commit.rb +11 -3
- data/lib/overcommit/hook_context/run_all.rb +39 -0
- data/lib/overcommit/hook_context.rb +2 -2
- data/lib/overcommit/hook_loader/base.rb +1 -3
- data/lib/overcommit/hook_loader/plugin_hook_loader.rb +26 -16
- data/lib/overcommit/hook_runner.rb +19 -9
- data/lib/overcommit/installer.rb +9 -5
- data/lib/overcommit/logger.rb +27 -0
- data/lib/overcommit/message_processor.rb +132 -0
- data/lib/overcommit/printer.rb +21 -27
- data/lib/overcommit/subprocess.rb +25 -16
- data/lib/overcommit/utils.rb +20 -0
- data/lib/overcommit/version.rb +1 -1
- data/lib/overcommit.rb +0 -1
- data/template-dir/hooks/commit-msg +9 -38
- data/template-dir/hooks/overcommit-hook +9 -38
- data/template-dir/hooks/post-checkout +9 -38
- data/template-dir/hooks/pre-commit +9 -38
- metadata +63 -76
- data/lib/overcommit/user_input.rb +0 -26
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Overcommit::HookContext
|
4
|
+
# Simulates a pre-commit context pretending that all files have been changed.
|
5
|
+
#
|
6
|
+
# This results in pre-commit hooks running against the entire repository,
|
7
|
+
# which is useful for automated CI scripts.
|
8
|
+
class RunAll < Base
|
9
|
+
EMPTY_SET = Set.new
|
10
|
+
|
11
|
+
def modified_files
|
12
|
+
all_files
|
13
|
+
end
|
14
|
+
|
15
|
+
# Return an empty set since in this context the user didn't actually touch
|
16
|
+
# any lines.
|
17
|
+
def modified_lines_in_file(_file)
|
18
|
+
EMPTY_SET
|
19
|
+
end
|
20
|
+
|
21
|
+
def hook_class_name
|
22
|
+
'PreCommit'
|
23
|
+
end
|
24
|
+
|
25
|
+
def hook_type_name
|
26
|
+
'pre_commit'
|
27
|
+
end
|
28
|
+
|
29
|
+
def hook_script_name
|
30
|
+
'pre-commit'
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def all_files
|
36
|
+
@all_files ||= Overcommit::GitRepo.all_files
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# Utility module which manages the creation of {HookContext}s.
|
2
2
|
module Overcommit::HookContext
|
3
|
-
def self.create(hook_type, config, args
|
3
|
+
def self.create(hook_type, config, args)
|
4
4
|
hook_type_class = Overcommit::Utils.camel_case(hook_type)
|
5
5
|
underscored_hook_type = Overcommit::Utils.snake_case(hook_type)
|
6
6
|
|
7
7
|
require "overcommit/hook_context/#{underscored_hook_type}"
|
8
8
|
|
9
|
-
Overcommit::HookContext.const_get(hook_type_class).new(config, args
|
9
|
+
Overcommit::HookContext.const_get(hook_type_class).new(config, args)
|
10
10
|
rescue LoadError, NameError => error
|
11
11
|
# Could happen when a symlink was created for a hook type Overcommit does
|
12
12
|
# not yet support.
|
@@ -4,12 +4,10 @@ module Overcommit::HookLoader
|
|
4
4
|
# @param config [Overcommit::Configuration]
|
5
5
|
# @param context [Overcommit::HookContext]
|
6
6
|
# @param logger [Overcommit::Logger]
|
7
|
-
|
8
|
-
def initialize(config, context, logger, input)
|
7
|
+
def initialize(config, context, logger)
|
9
8
|
@config = config
|
10
9
|
@context = context
|
11
10
|
@log = logger
|
12
|
-
@input = input
|
13
11
|
end
|
14
12
|
|
15
13
|
# When implemented in subclasses, loads the hooks for which that subclass is
|
@@ -5,10 +5,7 @@ module Overcommit::HookLoader
|
|
5
5
|
# is running in.
|
6
6
|
class PluginHookLoader < Base
|
7
7
|
def load_hooks
|
8
|
-
|
9
|
-
plugin_paths = Dir[File.join(directory, '*.rb')].sort
|
10
|
-
|
11
|
-
check_for_modified_plugins(plugin_paths) if @config.verify_plugin_signatures?
|
8
|
+
check_for_modified_plugins if @config.verify_plugin_signatures?
|
12
9
|
|
13
10
|
plugin_paths.map do |plugin_path|
|
14
11
|
require plugin_path
|
@@ -18,34 +15,47 @@ module Overcommit::HookLoader
|
|
18
15
|
end
|
19
16
|
end
|
20
17
|
|
18
|
+
def update_signatures
|
19
|
+
log.success('No plugin signatures have changed') if modified_plugins.empty?
|
20
|
+
|
21
|
+
modified_plugins.each do |plugin|
|
22
|
+
plugin.update_signature!
|
23
|
+
log.warning "Updated signature of plugin #{plugin.hook_name}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
21
27
|
private
|
22
28
|
|
23
|
-
def
|
24
|
-
|
29
|
+
def plugin_paths
|
30
|
+
directory = File.join(@config.plugin_directory, @context.hook_type_name)
|
31
|
+
Dir[File.join(directory, '*.rb')].sort
|
32
|
+
end
|
33
|
+
|
34
|
+
def modified_plugins
|
35
|
+
plugin_paths.
|
25
36
|
map { |path| Overcommit::HookSigner.new(path, @config, @context) }.
|
26
37
|
select(&:signature_changed?)
|
38
|
+
end
|
27
39
|
|
40
|
+
def check_for_modified_plugins
|
28
41
|
return if modified_plugins.empty?
|
29
42
|
|
30
43
|
log.bold_warning "The following #{@context.hook_script_name} plugins " \
|
31
44
|
'have been added, changed, or had their configuration modified:'
|
32
|
-
log.
|
45
|
+
log.newline
|
33
46
|
|
34
47
|
modified_plugins.each do |signer|
|
35
48
|
log.warning " * #{signer.hook_name} in #{signer.hook_path}"
|
36
49
|
end
|
37
50
|
|
38
|
-
log.
|
39
|
-
log.bold_warning 'You should verify the changes
|
51
|
+
log.newline
|
52
|
+
log.bold_warning 'You should verify the changes and then run:'
|
53
|
+
log.newline
|
54
|
+
log.warning "overcommit --sign #{@context.hook_script_name}"
|
55
|
+
log.newline
|
40
56
|
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
57
|
|
48
|
-
|
58
|
+
raise Overcommit::Exceptions::InvalidHookSignature
|
49
59
|
end
|
50
60
|
end
|
51
61
|
end
|
@@ -5,12 +5,11 @@ module Overcommit
|
|
5
5
|
# @param config [Overcommit::Configuration]
|
6
6
|
# @param logger [Overcommit::Logger]
|
7
7
|
# @param context [Overcommit::HookContext]
|
8
|
-
# @param
|
9
|
-
def initialize(config, logger, context,
|
8
|
+
# @param printer [Overcommit::Printer]
|
9
|
+
def initialize(config, logger, context, printer)
|
10
10
|
@config = config
|
11
11
|
@log = logger
|
12
12
|
@context = context
|
13
|
-
@input = input
|
14
13
|
@printer = printer
|
15
14
|
@hooks = []
|
16
15
|
end
|
@@ -36,7 +35,7 @@ module Overcommit
|
|
36
35
|
attr_reader :log
|
37
36
|
|
38
37
|
def run_hooks
|
39
|
-
if @hooks.any?
|
38
|
+
if @hooks.any?(&:enabled?)
|
40
39
|
@printer.start_run
|
41
40
|
|
42
41
|
interrupted = false
|
@@ -54,7 +53,7 @@ module Overcommit
|
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
57
|
-
|
56
|
+
print_results(run_failed, interrupted)
|
58
57
|
|
59
58
|
!(run_failed || interrupted)
|
60
59
|
else
|
@@ -63,6 +62,16 @@ module Overcommit
|
|
63
62
|
end
|
64
63
|
end
|
65
64
|
|
65
|
+
def print_results(failed, interrupted)
|
66
|
+
if interrupted
|
67
|
+
@printer.run_interrupted
|
68
|
+
elsif failed
|
69
|
+
@printer.run_failed
|
70
|
+
else
|
71
|
+
@printer.run_succeeded
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
66
75
|
def run_hook(hook)
|
67
76
|
return if should_skip?(hook)
|
68
77
|
|
@@ -79,7 +88,7 @@ module Overcommit
|
|
79
88
|
end
|
80
89
|
rescue => ex
|
81
90
|
status = :fail
|
82
|
-
output = "Hook raised unexpected error\n#{ex.message}"
|
91
|
+
output = "Hook raised unexpected error\n#{ex.message}\n#{ex.backtrace.join("\n")}"
|
83
92
|
rescue Interrupt
|
84
93
|
# At this point, interrupt has been handled and protection is back in
|
85
94
|
# effect thanks to the InterruptHandler.
|
@@ -99,7 +108,8 @@ module Overcommit
|
|
99
108
|
if hook.required?
|
100
109
|
@printer.required_hook_not_skipped(hook)
|
101
110
|
else
|
102
|
-
|
111
|
+
# Tell user if hook was skipped only if it actually would have run
|
112
|
+
@printer.hook_skipped(hook) if hook.run?
|
103
113
|
return true
|
104
114
|
end
|
105
115
|
end
|
@@ -110,10 +120,10 @@ module Overcommit
|
|
110
120
|
def load_hooks
|
111
121
|
require "overcommit/hook/#{@context.hook_type_name}/base"
|
112
122
|
|
113
|
-
@hooks += HookLoader::BuiltInHookLoader.new(@config, @context, @log
|
123
|
+
@hooks += HookLoader::BuiltInHookLoader.new(@config, @context, @log).load_hooks
|
114
124
|
|
115
125
|
# Load plugin hooks after so they can subclass existing hooks
|
116
|
-
@hooks += HookLoader::PluginHookLoader.new(@config, @context, @log
|
126
|
+
@hooks += HookLoader::PluginHookLoader.new(@config, @context, @log).load_hooks
|
117
127
|
end
|
118
128
|
end
|
119
129
|
end
|
data/lib/overcommit/installer.rb
CHANGED
@@ -3,8 +3,8 @@ require 'fileutils'
|
|
3
3
|
module Overcommit
|
4
4
|
# Manages the installation of Overcommit hooks in a git repository.
|
5
5
|
class Installer # rubocop:disable ClassLength
|
6
|
-
|
7
|
-
|
6
|
+
TEMPLATE_DIRECTORY = File.join(OVERCOMMIT_HOME, 'template-dir')
|
7
|
+
MASTER_HOOK = File.join(TEMPLATE_DIRECTORY, 'hooks', 'overcommit-hook')
|
8
8
|
|
9
9
|
def initialize(logger)
|
10
10
|
@log = logger
|
@@ -115,13 +115,15 @@ module Overcommit
|
|
115
115
|
def can_replace_file?(file)
|
116
116
|
@options[:force] ||
|
117
117
|
!File.exist?(file) ||
|
118
|
-
|
118
|
+
overcommit_hook?(file)
|
119
119
|
end
|
120
120
|
|
121
121
|
def uninstall_hook_symlinks
|
122
|
+
return unless File.directory?(hooks_path)
|
123
|
+
|
122
124
|
Dir.chdir(hooks_path) do
|
123
125
|
Overcommit::Utils.supported_hook_types.each do |hook_type|
|
124
|
-
FileUtils.rm_rf(hook_type) if
|
126
|
+
FileUtils.rm_rf(hook_type) if overcommit_hook?(hook_type)
|
125
127
|
end
|
126
128
|
end
|
127
129
|
end
|
@@ -133,7 +135,9 @@ module Overcommit
|
|
133
135
|
FileUtils.cp(File.join(OVERCOMMIT_HOME, 'config', 'starter.yml'), repo_config_file)
|
134
136
|
end
|
135
137
|
|
136
|
-
def
|
138
|
+
def overcommit_hook?(file)
|
139
|
+
return true if File.read(file) =~ /OVERCOMMIT_DISABLE/
|
140
|
+
# TODO: Remove these checks once we hit version 1.0
|
137
141
|
File.symlink?(file) && File.readlink(file) == 'overcommit-hook'
|
138
142
|
rescue Errno::ENOENT
|
139
143
|
# Some Ruby implementations (e.g. JRuby) raise an error when the file
|
data/lib/overcommit/logger.rb
CHANGED
@@ -6,44 +6,71 @@ module Overcommit
|
|
6
6
|
new(File.open('/dev/null', 'w'))
|
7
7
|
end
|
8
8
|
|
9
|
+
# Creates a logger that will write to the given output stream.
|
10
|
+
#
|
11
|
+
# @param out [IO]
|
9
12
|
def initialize(out)
|
10
13
|
@out = out
|
11
14
|
end
|
12
15
|
|
16
|
+
# Write output without a trailing newline.
|
13
17
|
def partial(*args)
|
14
18
|
@out.print(*args)
|
15
19
|
end
|
16
20
|
|
21
|
+
# Prints a newline character (alias for readability).
|
22
|
+
def newline
|
23
|
+
log
|
24
|
+
end
|
25
|
+
|
26
|
+
# Write a line of output.
|
27
|
+
#
|
28
|
+
# A newline character will always be appended.
|
17
29
|
def log(*args)
|
18
30
|
@out.puts(*args)
|
19
31
|
end
|
20
32
|
|
33
|
+
# Write a line of output that is intended to be emphasized.
|
21
34
|
def bold(*args)
|
22
35
|
color('1', *args)
|
23
36
|
end
|
24
37
|
|
38
|
+
# Write a line of output indicating a problem or error.
|
25
39
|
def error(*args)
|
26
40
|
color(31, *args)
|
27
41
|
end
|
28
42
|
|
43
|
+
# Write a line of output indicating a problem or error which is emphasized
|
44
|
+
# over a regular problem or error.
|
29
45
|
def bold_error(*args)
|
30
46
|
color('1;31', *args)
|
31
47
|
end
|
32
48
|
|
49
|
+
# Write a line of output indicating a successful or noteworthy event.
|
33
50
|
def success(*args)
|
34
51
|
color(32, *args)
|
35
52
|
end
|
36
53
|
|
54
|
+
# Write a line of output indicating a potential cause for concern, but not
|
55
|
+
# an actual error.
|
37
56
|
def warning(*args)
|
38
57
|
color(33, *args)
|
39
58
|
end
|
40
59
|
|
60
|
+
# Write a line of output indicating a potential cause for concern, but with
|
61
|
+
# greater emphasize compared to other warnings.
|
41
62
|
def bold_warning(*args)
|
42
63
|
color('1;33', *args)
|
43
64
|
end
|
44
65
|
|
45
66
|
private
|
46
67
|
|
68
|
+
# Outputs text wrapped in ANSI escape code necessary to produce a given
|
69
|
+
# color/text display.
|
70
|
+
#
|
71
|
+
# @param code [String] ANSI escape code, e.g. '1;33' for "bold yellow"
|
72
|
+
# @param str [String] string to wrap
|
73
|
+
# @param partial [true,false] whether to omit a newline
|
47
74
|
def color(code, str, partial = false)
|
48
75
|
send(partial ? :partial : :log,
|
49
76
|
@out.tty? ? "\033[#{code}m#{str}\033[0m" : str)
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Overcommit
|
2
|
+
# Utility class that encapsulates the handling of hook messages and whether
|
3
|
+
# they affect lines the user has modified or not.
|
4
|
+
#
|
5
|
+
# This class exposes an endpoint that extracts an appropriate hook/status
|
6
|
+
# output tuple from an array of {Overcommit::Hook::Message}s, respecting the
|
7
|
+
# configuration settings for the given hook.
|
8
|
+
class MessageProcessor
|
9
|
+
ERRORS_MODIFIED_HEADER = 'Errors on modified lines:'
|
10
|
+
WARNINGS_MODIFIED_HEADER = 'Warnings on modified lines:'
|
11
|
+
ERRORS_UNMODIFIED_HEADER = "Errors on lines you didn't modify:"
|
12
|
+
WARNINGS_UNMODIFIED_HEADER = "Warnings on lines you didn't modify:"
|
13
|
+
|
14
|
+
# @param hook [Overcommit::Hook::Base]
|
15
|
+
# @param unmodified_lines_setting [String] how to treat messages on
|
16
|
+
# unmodified lines
|
17
|
+
def initialize(hook, unmodified_lines_setting)
|
18
|
+
@hook = hook
|
19
|
+
@setting = unmodified_lines_setting
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns a hook status/output tuple from the messages this processor was
|
23
|
+
# initialized with.
|
24
|
+
#
|
25
|
+
# @return [Array<Symbol,String>]
|
26
|
+
def hook_result(messages)
|
27
|
+
status, output = basic_status_and_output(messages)
|
28
|
+
|
29
|
+
# Nothing to do if there are no problems to begin with
|
30
|
+
return [status, output] if status == :pass
|
31
|
+
|
32
|
+
# Return as-is if this type of hook doesn't have the concept of modified lines
|
33
|
+
return [status, output] unless @hook.respond_to?(:modified_lines_in_file)
|
34
|
+
|
35
|
+
handle_modified_lines(messages, status)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def handle_modified_lines(messages, status)
|
41
|
+
messages = remove_ignored_messages(messages)
|
42
|
+
|
43
|
+
messages_on_modified_lines, messages_on_unmodified_lines =
|
44
|
+
messages.partition { |message| message_on_modified_line?(message) }
|
45
|
+
|
46
|
+
output = print_messages(
|
47
|
+
messages_on_modified_lines,
|
48
|
+
ERRORS_MODIFIED_HEADER,
|
49
|
+
WARNINGS_MODIFIED_HEADER
|
50
|
+
)
|
51
|
+
output += print_messages(
|
52
|
+
messages_on_unmodified_lines,
|
53
|
+
ERRORS_UNMODIFIED_HEADER,
|
54
|
+
WARNINGS_UNMODIFIED_HEADER
|
55
|
+
)
|
56
|
+
|
57
|
+
[transform_status(status, messages_on_modified_lines), output]
|
58
|
+
end
|
59
|
+
|
60
|
+
def transform_status(status, messages_on_modified_lines)
|
61
|
+
# `report` indicates user wants the original status
|
62
|
+
return status if @setting == 'report'
|
63
|
+
|
64
|
+
error_messages, warning_messages =
|
65
|
+
messages_on_modified_lines.partition { |msg| msg.type == :error }
|
66
|
+
|
67
|
+
if can_upgrade_to_warning?(status, error_messages)
|
68
|
+
status = :warn
|
69
|
+
end
|
70
|
+
|
71
|
+
if can_upgrade_to_passing?(status, warning_messages)
|
72
|
+
status = :pass
|
73
|
+
end
|
74
|
+
|
75
|
+
status
|
76
|
+
end
|
77
|
+
|
78
|
+
def can_upgrade_to_warning?(status, error_messages)
|
79
|
+
status == :fail && error_messages.empty?
|
80
|
+
end
|
81
|
+
|
82
|
+
def can_upgrade_to_passing?(status, warning_messages)
|
83
|
+
status == :warn && @setting == 'ignore' && warning_messages.empty?
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns status and output for messages assuming no special treatment of
|
87
|
+
# messages occurring on unmodified lines.
|
88
|
+
def basic_status_and_output(messages)
|
89
|
+
status =
|
90
|
+
if messages.any? { |message| message.type == :error }
|
91
|
+
:fail
|
92
|
+
elsif messages.any? { |message| message.type == :warning }
|
93
|
+
:warn
|
94
|
+
else
|
95
|
+
:pass
|
96
|
+
end
|
97
|
+
|
98
|
+
output = ''
|
99
|
+
if messages.any?
|
100
|
+
output += messages.join("\n") + "\n"
|
101
|
+
end
|
102
|
+
|
103
|
+
[status, output]
|
104
|
+
end
|
105
|
+
|
106
|
+
def print_messages(messages, error_heading, warning_heading)
|
107
|
+
output = ''
|
108
|
+
errors, warnings = messages.partition { |msg| msg.type == :error }
|
109
|
+
|
110
|
+
if errors.any?
|
111
|
+
output += "#{error_heading}\n#{errors.join("\n")}\n"
|
112
|
+
end
|
113
|
+
|
114
|
+
if warnings.any?
|
115
|
+
output += "#{warning_heading}\n#{warnings.join("\n")}\n"
|
116
|
+
end
|
117
|
+
|
118
|
+
output
|
119
|
+
end
|
120
|
+
|
121
|
+
def remove_ignored_messages(messages)
|
122
|
+
# If user wants to ignore messages on unmodified lines, simply remove them
|
123
|
+
return messages unless @setting == 'ignore'
|
124
|
+
|
125
|
+
messages.select { |message| message_on_modified_line?(message) }
|
126
|
+
end
|
127
|
+
|
128
|
+
def message_on_modified_line?(message)
|
129
|
+
@hook.modified_lines_in_file(message.file).include?(message.line)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/lib/overcommit/printer.rb
CHANGED
@@ -20,21 +20,6 @@ module Overcommit
|
|
20
20
|
log.success "✓ No applicable #{hook_script_name} hooks to run"
|
21
21
|
end
|
22
22
|
|
23
|
-
# Executed at the very end of running the collection of hooks.
|
24
|
-
def end_run(run_failed, interrupted)
|
25
|
-
log.log # Newline
|
26
|
-
|
27
|
-
if interrupted
|
28
|
-
log.warning '⚠ Hook run interrupted by user'
|
29
|
-
elsif run_failed
|
30
|
-
log.error "✗ One or more #{hook_script_name} hooks failed"
|
31
|
-
else
|
32
|
-
log.success "✓ All #{hook_script_name} hooks passed"
|
33
|
-
end
|
34
|
-
|
35
|
-
log.log # Newline
|
36
|
-
end
|
37
|
-
|
38
23
|
# Executed at the start of an individual hook run.
|
39
24
|
def start_hook(hook)
|
40
25
|
unless hook.quiet?
|
@@ -59,6 +44,27 @@ module Overcommit
|
|
59
44
|
print_result(hook, status, output)
|
60
45
|
end
|
61
46
|
|
47
|
+
# Executed when a hook run was interrupted/cancelled by user.
|
48
|
+
def run_interrupted
|
49
|
+
log.newline
|
50
|
+
log.warning '⚠ Hook run interrupted by user'
|
51
|
+
log.newline
|
52
|
+
end
|
53
|
+
|
54
|
+
# Executed when one or more hooks by the end of the run.
|
55
|
+
def run_failed
|
56
|
+
log.newline
|
57
|
+
log.error "✗ One or more #{hook_script_name} hooks failed"
|
58
|
+
log.newline
|
59
|
+
end
|
60
|
+
|
61
|
+
# Executed when no hooks failed by the end of the run.
|
62
|
+
def run_succeeded
|
63
|
+
log.newline
|
64
|
+
log.success "✓ All #{hook_script_name} hooks passed"
|
65
|
+
log.newline
|
66
|
+
end
|
67
|
+
|
62
68
|
private
|
63
69
|
|
64
70
|
def print_header(hook)
|
@@ -103,18 +109,6 @@ module Overcommit
|
|
103
109
|
log.send(format, output) unless output.nil? || output.empty?
|
104
110
|
end
|
105
111
|
|
106
|
-
def run_interrupted
|
107
|
-
log.warning '⚠ Hook run interrupted by user'
|
108
|
-
end
|
109
|
-
|
110
|
-
def run_failed
|
111
|
-
log.error "✗ One or more #{hook_script_name} hooks failed"
|
112
|
-
end
|
113
|
-
|
114
|
-
def run_succeeded
|
115
|
-
log.success "✓ All #{hook_script_name} hooks passed"
|
116
|
-
end
|
117
|
-
|
118
112
|
def hook_script_name
|
119
113
|
@context.hook_script_name
|
120
114
|
end
|
@@ -6,32 +6,41 @@ module Overcommit
|
|
6
6
|
# standard out/error output.
|
7
7
|
class Subprocess
|
8
8
|
# Encapsulates the result of a process.
|
9
|
-
Result = Struct.new(:status, :
|
9
|
+
Result = Struct.new(:status, :stdout, :stderr) do
|
10
10
|
def success?
|
11
11
|
status == 0
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
class << self
|
16
|
+
# Spawns a new process using the given array of arguments (the first
|
17
|
+
# element is the command).
|
18
|
+
def spawn(args)
|
19
|
+
process = ChildProcess.build(*args)
|
19
20
|
|
20
|
-
|
21
|
-
err.sync = true
|
22
|
-
out = ::Tempfile.new('out')
|
23
|
-
out.sync = true
|
21
|
+
out, err = assign_output_streams(process)
|
24
22
|
|
25
|
-
|
26
|
-
|
23
|
+
process.start
|
24
|
+
process.wait
|
27
25
|
|
28
|
-
|
29
|
-
|
26
|
+
err.rewind
|
27
|
+
out.rewind
|
30
28
|
|
31
|
-
|
32
|
-
|
29
|
+
Result.new(process.exit_code, out.read, err.read)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
33
|
|
34
|
-
|
34
|
+
# @param process [ChildProcess]
|
35
|
+
# @return [Array<IO>]
|
36
|
+
def assign_output_streams(process)
|
37
|
+
%w[out err].map do |stream_name|
|
38
|
+
::Tempfile.new(stream_name).tap do |stream|
|
39
|
+
stream.sync = true
|
40
|
+
process.io.send("std#{stream_name}=", stream)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
35
44
|
end
|
36
45
|
end
|
37
46
|
end
|
data/lib/overcommit/utils.rb
CHANGED
@@ -132,6 +132,26 @@ module Overcommit
|
|
132
132
|
# symlinks, so we need use File.size?
|
133
133
|
File.symlink?(file) && File.size?(file).nil?
|
134
134
|
end
|
135
|
+
|
136
|
+
# Convert a glob pattern to an absolute path glob pattern rooted from the
|
137
|
+
# repository root directory.
|
138
|
+
#
|
139
|
+
# @param glob [String]
|
140
|
+
# @return [String]
|
141
|
+
def convert_glob_to_absolute(glob)
|
142
|
+
File.join(repo_root, glob)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Return whether a pattern matches the given path.
|
146
|
+
#
|
147
|
+
# @param pattern [String]
|
148
|
+
# @param path [String]
|
149
|
+
def matches_path?(pattern, path)
|
150
|
+
File.fnmatch?(pattern, path,
|
151
|
+
File::FNM_PATHNAME | # Wildcard doesn't match separator
|
152
|
+
File::FNM_DOTMATCH # Wildcards match dotfiles
|
153
|
+
)
|
154
|
+
end
|
135
155
|
end
|
136
156
|
end
|
137
157
|
end
|
data/lib/overcommit/version.rb
CHANGED
data/lib/overcommit.rb
CHANGED
@@ -6,7 +6,6 @@ require 'overcommit/configuration_loader'
|
|
6
6
|
require 'overcommit/hook/base'
|
7
7
|
require 'overcommit/hook_context/base'
|
8
8
|
require 'overcommit/hook_context'
|
9
|
-
require 'overcommit/user_input'
|
10
9
|
require 'overcommit/git_repo'
|
11
10
|
require 'overcommit/hook_signer'
|
12
11
|
require 'overcommit/hook_loader/base'
|