overcommit 0.26.0 → 0.27.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 +38 -0
- data/config/starter.yml +2 -1
- data/lib/overcommit/cli.rb +2 -0
- data/lib/overcommit/command_splitter.rb +144 -0
- data/lib/overcommit/configuration.rb +45 -10
- data/lib/overcommit/exceptions.rb +3 -0
- data/lib/overcommit/git_repo.rb +8 -0
- data/lib/overcommit/hook/base.rb +16 -2
- data/lib/overcommit/hook/post_rewrite/base.rb +1 -1
- data/lib/overcommit/hook/pre_commit/case_conflicts.rb +1 -1
- data/lib/overcommit/hook/pre_commit/hard_tabs.rb +1 -1
- data/lib/overcommit/hook/pre_commit/html_hint.rb +21 -0
- data/lib/overcommit/hook/pre_commit/local_paths_in_gemfile.rb +1 -1
- data/lib/overcommit/hook/pre_commit/merge_conflicts.rb +1 -1
- data/lib/overcommit/hook/pre_commit/semi_standard.rb +2 -2
- data/lib/overcommit/hook/pre_commit/standard.rb +2 -2
- data/lib/overcommit/hook/pre_commit/trailing_whitespace.rb +1 -1
- data/lib/overcommit/hook_context/base.rb +43 -1
- data/lib/overcommit/hook_context/commit_msg.rb +2 -2
- data/lib/overcommit/hook_context/post_checkout.rb +8 -0
- data/lib/overcommit/hook_context/post_rewrite.rb +29 -0
- data/lib/overcommit/hook_context/pre_commit.rb +1 -14
- data/lib/overcommit/hook_loader/plugin_hook_loader.rb +42 -3
- data/lib/overcommit/hook_runner.rb +12 -0
- data/lib/overcommit/hook_signer.rb +41 -6
- data/lib/overcommit/logger.rb +5 -0
- data/lib/overcommit/printer.rb +1 -1
- data/lib/overcommit/subprocess.rb +22 -1
- data/lib/overcommit/utils.rb +58 -4
- data/lib/overcommit/version.rb +1 -1
- data/template-dir/hooks/commit-msg +24 -4
- data/template-dir/hooks/overcommit-hook +24 -4
- data/template-dir/hooks/post-checkout +24 -4
- data/template-dir/hooks/post-commit +24 -4
- data/template-dir/hooks/post-merge +24 -4
- data/template-dir/hooks/post-rewrite +24 -4
- data/template-dir/hooks/pre-commit +24 -4
- data/template-dir/hooks/pre-push +24 -4
- data/template-dir/hooks/pre-rebase +24 -4
- metadata +6 -3
@@ -2,7 +2,7 @@ module Overcommit::Hook::PreCommit
|
|
2
2
|
# Checks for unresolved merge conflicts
|
3
3
|
class MergeConflicts < Base
|
4
4
|
def run
|
5
|
-
result = execute(command
|
5
|
+
result = execute(command, args: applicable_files)
|
6
6
|
|
7
7
|
unless result.stdout.empty?
|
8
8
|
return :fail, "Merge conflict markers detected:\n#{result.stdout}"
|
@@ -5,14 +5,14 @@ module Overcommit::Hook::PreCommit
|
|
5
5
|
class SemiStandard < Base
|
6
6
|
def run
|
7
7
|
result = execute(command + applicable_files)
|
8
|
-
output = result.
|
8
|
+
output = result.stdout.chomp
|
9
9
|
return :pass if result.success? && output.empty?
|
10
10
|
|
11
11
|
# example message:
|
12
12
|
# path/to/file.js:1:1: Error message (ruleName)
|
13
13
|
extract_messages(
|
14
14
|
output.split("\n")[1..-1], # ignore header line
|
15
|
-
|
15
|
+
/^\s*(?<file>[^:]+):(?<line>\d+)/
|
16
16
|
)
|
17
17
|
end
|
18
18
|
end
|
@@ -5,14 +5,14 @@ module Overcommit::Hook::PreCommit
|
|
5
5
|
class Standard < Base
|
6
6
|
def run
|
7
7
|
result = execute(command + applicable_files)
|
8
|
-
output = result.
|
8
|
+
output = result.stdout.chomp
|
9
9
|
return :pass if result.success? && output.empty?
|
10
10
|
|
11
11
|
# example message:
|
12
12
|
# path/to/file.js:1:1: Error message (ruleName)
|
13
13
|
extract_messages(
|
14
14
|
output.split("\n")[1..-1], # ignore header line
|
15
|
-
|
15
|
+
/^\s*(?<file>[^:]+):(?<line>\d+)/
|
16
16
|
)
|
17
17
|
end
|
18
18
|
end
|
@@ -2,7 +2,7 @@ module Overcommit::Hook::PreCommit
|
|
2
2
|
# Checks for trailing whitespace in files.
|
3
3
|
class TrailingWhitespace < Base
|
4
4
|
def run
|
5
|
-
result = execute(command
|
5
|
+
result = execute(command, args: applicable_files)
|
6
6
|
|
7
7
|
extract_messages(
|
8
8
|
result.stdout.split("\n"),
|
@@ -22,6 +22,15 @@ module Overcommit::HookContext
|
|
22
22
|
@input = input
|
23
23
|
end
|
24
24
|
|
25
|
+
# Executes a command as if it were a regular git hook, passing all
|
26
|
+
# command-line arguments and the standard input stream.
|
27
|
+
#
|
28
|
+
# This is intended to be used by ad hoc hooks so developers can link up
|
29
|
+
# their existing git hooks with Overcommit.
|
30
|
+
def execute_hook(command)
|
31
|
+
Overcommit::Utils.execute(command, args: @args, input: input_string)
|
32
|
+
end
|
33
|
+
|
25
34
|
# Returns the camel-cased type of this hook (e.g. PreCommit)
|
26
35
|
#
|
27
36
|
# @return [String]
|
@@ -70,12 +79,45 @@ module Overcommit::HookContext
|
|
70
79
|
[]
|
71
80
|
end
|
72
81
|
|
82
|
+
# Returns the contents of the entire standard input stream that were passed
|
83
|
+
# to the hook.
|
84
|
+
#
|
85
|
+
# @return [String]
|
86
|
+
def input_string
|
87
|
+
@input_string ||= @input.read
|
88
|
+
end
|
89
|
+
|
73
90
|
# Returns an array of lines passed to the hook via the standard input
|
74
91
|
# stream.
|
75
92
|
#
|
76
93
|
# @return [Array<String>]
|
77
94
|
def input_lines
|
78
|
-
@input_lines ||=
|
95
|
+
@input_lines ||= input_string.split("\n")
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def filter_modified_files(modified_files)
|
101
|
+
filter_directories(filter_nonexistent(modified_files))
|
102
|
+
end
|
103
|
+
|
104
|
+
# Filter out non-existent files (unless it's a broken symlink, in which case
|
105
|
+
# it's a file that points to a non-existent file). This could happen if a
|
106
|
+
# file was renamed as part of an amendment, leading to the old file no
|
107
|
+
# longer existing.
|
108
|
+
def filter_nonexistent(modified_files)
|
109
|
+
modified_files.select do |file|
|
110
|
+
File.exist?(file) || Overcommit::Utils.broken_symlink?(file)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Filter out directories. This could happen when changing a symlink to a
|
115
|
+
# directory as part of an amendment, since the symlink will still appear as
|
116
|
+
# a file, but the actual working tree will have a directory.
|
117
|
+
def filter_directories(modified_files)
|
118
|
+
modified_files.reject do |file|
|
119
|
+
File.directory?(file) && !File.symlink?(file)
|
120
|
+
end
|
79
121
|
end
|
80
122
|
end
|
81
123
|
end
|
@@ -19,8 +19,8 @@ module Overcommit::HookContext
|
|
19
19
|
|
20
20
|
def commit_message_lines
|
21
21
|
raw_commit_message_lines.
|
22
|
-
|
23
|
-
|
22
|
+
take_while { |line| !line.start_with?('diff --git') }.
|
23
|
+
reject { |line| line =~ /^#/ }
|
24
24
|
end
|
25
25
|
|
26
26
|
def commit_message_file
|
@@ -22,5 +22,13 @@ module Overcommit::HookContext
|
|
22
22
|
def file_checkout?
|
23
23
|
!branch_checkout?
|
24
24
|
end
|
25
|
+
|
26
|
+
# Get a list of files that have been added or modified between
|
27
|
+
# `previous_head` and `new_head`. Renames and deletions are ignored, since
|
28
|
+
# there should be nothing to check.
|
29
|
+
def modified_files
|
30
|
+
@modified_files ||=
|
31
|
+
Overcommit::GitRepo.modified_files(refs: "#{previous_head} #{new_head}")
|
32
|
+
end
|
25
33
|
end
|
26
34
|
end
|
@@ -14,5 +14,34 @@ module Overcommit::HookContext
|
|
14
14
|
def rebase?
|
15
15
|
@args[0] == 'rebase'
|
16
16
|
end
|
17
|
+
|
18
|
+
# Returns the list of commits rewritten by the action that triggered this
|
19
|
+
# hook run.
|
20
|
+
#
|
21
|
+
# @return [Array<RewrittenCommit>]
|
22
|
+
def rewritten_commits
|
23
|
+
@rewritten_commits ||= input_lines.map do |line|
|
24
|
+
RewrittenCommit.new(*line.split(' '))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get a list of files that have been added or modified as part of a
|
29
|
+
# rewritten commit. Renames and deletions are ignored, since there should be
|
30
|
+
# nothing to check.
|
31
|
+
def modified_files
|
32
|
+
@modified_files ||= begin
|
33
|
+
@modified_files = []
|
34
|
+
|
35
|
+
rewritten_commits.each do |rewritten_commit|
|
36
|
+
refs = "#{rewritten_commit.old_hash} #{rewritten_commit.new_hash}"
|
37
|
+
@modified_files |= Overcommit::GitRepo.modified_files(refs: refs)
|
38
|
+
end
|
39
|
+
|
40
|
+
filter_modified_files(@modified_files)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Struct encapsulating the old and new SHA1 hashes of a rewritten commit
|
45
|
+
RewrittenCommit = Struct.new(:old_hash, :new_hash)
|
17
46
|
end
|
18
47
|
end
|
@@ -95,20 +95,7 @@ module Overcommit::HookContext
|
|
95
95
|
if amendment?
|
96
96
|
subcmd = 'show --format=%n'
|
97
97
|
previously_modified = Overcommit::GitRepo.modified_files(subcmd: subcmd)
|
98
|
-
|
99
|
-
# Filter out non-existent files. This could happen if a file was
|
100
|
-
# renamed as part of the amendment, leading to the old file no longer
|
101
|
-
# existing.
|
102
|
-
previously_modified.select! { |file| File.exist?(file) }
|
103
|
-
|
104
|
-
# Filter out directories. This could happen when changing a symlink to
|
105
|
-
# a directory as part of an amendment, since the symlink will still
|
106
|
-
# appear as a file, but the actual working tree will have a directory.
|
107
|
-
previously_modified.reject! do |file|
|
108
|
-
File.directory?(file) && !File.symlink?(file)
|
109
|
-
end
|
110
|
-
|
111
|
-
@modified_files |= previously_modified
|
98
|
+
@modified_files |= filter_modified_files(previously_modified)
|
112
99
|
end
|
113
100
|
end
|
114
101
|
@modified_files
|
@@ -7,12 +7,16 @@ module Overcommit::HookLoader
|
|
7
7
|
def load_hooks
|
8
8
|
check_for_modified_plugins if @config.verify_plugin_signatures?
|
9
9
|
|
10
|
-
plugin_paths.map do |plugin_path|
|
10
|
+
hooks = plugin_paths.map do |plugin_path|
|
11
11
|
require plugin_path
|
12
12
|
|
13
13
|
hook_name = Overcommit::Utils.camel_case(File.basename(plugin_path, '.rb'))
|
14
14
|
create_hook(hook_name)
|
15
15
|
end
|
16
|
+
|
17
|
+
hooks + ad_hoc_hook_names.map do |hook_name|
|
18
|
+
create_ad_hoc_hook(hook_name)
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
22
|
def update_signatures
|
@@ -31,9 +35,19 @@ module Overcommit::HookLoader
|
|
31
35
|
Dir[File.join(directory, '*.rb')].sort
|
32
36
|
end
|
33
37
|
|
38
|
+
def plugin_hook_names
|
39
|
+
plugin_paths.map do |path|
|
40
|
+
Overcommit::Utils.camel_case(File.basename(path, '.rb'))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def ad_hoc_hook_names
|
45
|
+
@config.enabled_ad_hoc_hooks(@context)
|
46
|
+
end
|
47
|
+
|
34
48
|
def modified_plugins
|
35
|
-
|
36
|
-
map { |
|
49
|
+
(plugin_hook_names + ad_hoc_hook_names).
|
50
|
+
map { |hook_name| Overcommit::HookSigner.new(hook_name, @config, @context) }.
|
37
51
|
select(&:signature_changed?)
|
38
52
|
end
|
39
53
|
|
@@ -57,5 +71,30 @@ module Overcommit::HookLoader
|
|
57
71
|
|
58
72
|
raise Overcommit::Exceptions::InvalidHookSignature
|
59
73
|
end
|
74
|
+
|
75
|
+
def create_ad_hoc_hook(hook_name)
|
76
|
+
hook_module = Overcommit::Hook.const_get(@context.hook_class_name)
|
77
|
+
hook_base = hook_module.const_get('Base')
|
78
|
+
|
79
|
+
# Implement a simple class that executes the command and returns pass/fail
|
80
|
+
# based on the exit status
|
81
|
+
hook_class = Class.new(hook_base) do
|
82
|
+
def run # rubocop:disable Lint/NestedMethodDefinition
|
83
|
+
result = @context.execute_hook(command)
|
84
|
+
|
85
|
+
if result.success?
|
86
|
+
:pass
|
87
|
+
else
|
88
|
+
[:fail, result.stdout + result.stderr]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
hook_module.const_set(hook_name, hook_class).new(@config, @context)
|
94
|
+
rescue LoadError, NameError => error
|
95
|
+
raise Overcommit::Exceptions::HookLoadError,
|
96
|
+
"Unable to load hook '#{hook_name}': #{error}",
|
97
|
+
error.backtrace
|
98
|
+
end
|
60
99
|
end
|
61
100
|
end
|
@@ -144,6 +144,18 @@ module Overcommit
|
|
144
144
|
|
145
145
|
# Load plugin hooks after so they can subclass existing hooks
|
146
146
|
@hooks += HookLoader::PluginHookLoader.new(@config, @context, @log).load_hooks
|
147
|
+
rescue LoadError => ex
|
148
|
+
# Include a more helpful message that will probably save some confusion
|
149
|
+
message = 'A load error occurred. ' +
|
150
|
+
if @config['gemfile']
|
151
|
+
"Did you forget to specify a gem in your `#{@config['gemfile']}`?"
|
152
|
+
else
|
153
|
+
'Did you forget to install a gem?'
|
154
|
+
end
|
155
|
+
|
156
|
+
raise Overcommit::Exceptions::HookLoadError,
|
157
|
+
"#{message}\n#{ex.message}",
|
158
|
+
ex.backtrace
|
147
159
|
end
|
148
160
|
end
|
149
161
|
end
|
@@ -1,21 +1,56 @@
|
|
1
1
|
module Overcommit
|
2
2
|
# Calculates, stores, and retrieves stored signatures of hook plugins.
|
3
3
|
class HookSigner
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :hook_name
|
5
5
|
|
6
6
|
# We don't want to include the skip setting as it is set by Overcommit
|
7
7
|
# itself
|
8
8
|
IGNORED_CONFIG_KEYS = %w[skip]
|
9
9
|
|
10
|
-
# @param
|
10
|
+
# @param hook_name [String] name of the hook
|
11
11
|
# @param config [Overcommit::Configuration]
|
12
12
|
# @param context [Overcommit::HookContext]
|
13
|
-
def initialize(
|
14
|
-
@
|
13
|
+
def initialize(hook_name, config, context)
|
14
|
+
@hook_name = hook_name
|
15
15
|
@config = config
|
16
16
|
@context = context
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the path of the file that should be incorporated into this hooks
|
20
|
+
# signature.
|
21
|
+
#
|
22
|
+
# @return [String]
|
23
|
+
def hook_path
|
24
|
+
@hook_path ||= begin
|
25
|
+
plugin_path = File.join(@config.plugin_directory,
|
26
|
+
@context.hook_type_name,
|
27
|
+
"#{Overcommit::Utils.snake_case(@hook_name)}.rb")
|
28
|
+
|
29
|
+
if File.exist?(plugin_path)
|
30
|
+
plugin_path
|
31
|
+
else
|
32
|
+
# Otherwise this is an ad hoc hook using an existing hook script
|
33
|
+
hook_config = @config.for_hook(@hook_name, @context.hook_class_name)
|
34
|
+
|
35
|
+
command = Array(hook_config['command'] ||
|
36
|
+
hook_config['required_executable'])
|
37
|
+
|
38
|
+
unless !@config.verify_plugin_signatures? ||
|
39
|
+
signable_file?(command.first)
|
40
|
+
raise Overcommit::Exceptions::InvalidHookDefinition,
|
41
|
+
'Hook must specify a `required_executable` or `command` that ' \
|
42
|
+
'is tracked by git (i.e. is a path relative to the root ' \
|
43
|
+
'of the repository) so that it can be signed'
|
44
|
+
end
|
45
|
+
|
46
|
+
File.join(Overcommit::Utils.repo_root, command.first)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
17
50
|
|
18
|
-
|
51
|
+
def signable_file?(file)
|
52
|
+
file.start_with?(".#{File::SEPARATOR}") &&
|
53
|
+
Overcommit::GitRepo.tracked?(file)
|
19
54
|
end
|
20
55
|
|
21
56
|
# Return whether the signature for this hook has changed since it was last
|
@@ -54,7 +89,7 @@ module Overcommit
|
|
54
89
|
end
|
55
90
|
|
56
91
|
def hook_contents
|
57
|
-
File.
|
92
|
+
File.read(hook_path)
|
58
93
|
end
|
59
94
|
|
60
95
|
def stored_signature
|
data/lib/overcommit/logger.rb
CHANGED
@@ -30,6 +30,11 @@ module Overcommit
|
|
30
30
|
@out.puts(*args)
|
31
31
|
end
|
32
32
|
|
33
|
+
# Write a line of output if debug mode is enabled.
|
34
|
+
def debug(*args)
|
35
|
+
color('35', *args) unless ENV.fetch('OVERCOMMIT_DEBUG', '').empty?
|
36
|
+
end
|
37
|
+
|
33
38
|
# Write a line of output that is intended to be emphasized.
|
34
39
|
def bold(*args)
|
35
40
|
color('1', *args)
|
data/lib/overcommit/printer.rb
CHANGED
@@ -6,6 +6,10 @@ module Overcommit
|
|
6
6
|
# standard out/error output.
|
7
7
|
class Subprocess
|
8
8
|
# Encapsulates the result of a process.
|
9
|
+
#
|
10
|
+
# @attr_reader status [Integer] exit status code returned by process
|
11
|
+
# @attr_reader stdout [String] standard output stream output
|
12
|
+
# @attr_reader stderr [String] standard error stream output
|
9
13
|
Result = Struct.new(:status, :stdout, :stderr) do
|
10
14
|
def success?
|
11
15
|
status == 0
|
@@ -15,12 +19,29 @@ module Overcommit
|
|
15
19
|
class << self
|
16
20
|
# Spawns a new process using the given array of arguments (the first
|
17
21
|
# element is the command).
|
18
|
-
|
22
|
+
#
|
23
|
+
# @param args [Array<String>]
|
24
|
+
# @param options [Hash]
|
25
|
+
# @option options [String] input string to pass via standard input stream
|
26
|
+
# @return [Result]
|
27
|
+
def spawn(args, options = {})
|
19
28
|
process = ChildProcess.build(*args)
|
20
29
|
|
21
30
|
out, err = assign_output_streams(process)
|
22
31
|
|
32
|
+
process.duplex = true if options[:input] # Make stdin available if needed
|
23
33
|
process.start
|
34
|
+
if options[:input]
|
35
|
+
begin
|
36
|
+
process.io.stdin.puts(options[:input])
|
37
|
+
rescue
|
38
|
+
# Silently ignore if the standard input stream of the spawned
|
39
|
+
# process is closed before we get a chance to write to it. This
|
40
|
+
# happens on JRuby a lot.
|
41
|
+
ensure
|
42
|
+
process.io.stdin.close
|
43
|
+
end
|
44
|
+
end
|
24
45
|
process.wait
|
25
46
|
|
26
47
|
err.rewind
|
data/lib/overcommit/utils.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require 'overcommit/subprocess'
|
3
|
+
require 'overcommit/command_splitter'
|
4
|
+
require 'tempfile'
|
3
5
|
|
4
6
|
module Overcommit
|
5
7
|
# Utility functions for general use.
|
@@ -23,6 +25,9 @@ module Overcommit
|
|
23
25
|
end
|
24
26
|
|
25
27
|
class << self
|
28
|
+
# @return [Overcommit::Logger] logger with which to send debug output
|
29
|
+
attr_accessor :log
|
30
|
+
|
26
31
|
def script_path(script)
|
27
32
|
File.join(Overcommit::HOME, 'libexec', script)
|
28
33
|
end
|
@@ -72,6 +77,16 @@ module Overcommit
|
|
72
77
|
end
|
73
78
|
end
|
74
79
|
|
80
|
+
# Remove ANSI escape sequences from a string.
|
81
|
+
#
|
82
|
+
# This is useful for stripping colorized output from external tools.
|
83
|
+
#
|
84
|
+
# @param text [String]
|
85
|
+
# @return [String]
|
86
|
+
def strip_color_codes(text)
|
87
|
+
text.gsub(/\e\[(\d+)(;\d+)*m/, '')
|
88
|
+
end
|
89
|
+
|
75
90
|
# Shamelessly stolen from:
|
76
91
|
# stackoverflow.com/questions/1509915/converting-camel-case-to-underscore-case-in-ruby
|
77
92
|
def snake_case(str)
|
@@ -131,15 +146,40 @@ module Overcommit
|
|
131
146
|
# This is intended to provide a centralized place to perform any checks or
|
132
147
|
# filtering of the command before executing it.
|
133
148
|
#
|
134
|
-
#
|
149
|
+
# The `args` option provides a convenient way of splitting up long
|
150
|
+
# argument lists which would otherwise exceed the maximum command line
|
151
|
+
# length of the OS. It will break up the list into chunks and run the
|
152
|
+
# command with the same prefix `initial_args`, finally combining the
|
153
|
+
# output together at the end.
|
154
|
+
#
|
155
|
+
# This requires that the external command you are running can have its
|
156
|
+
# work split up in this way and still produce the same resultant output
|
157
|
+
# when outputs of the individual commands are concatenated back together.
|
158
|
+
#
|
159
|
+
# @param initial_args [Array<String>]
|
160
|
+
# @param options [Hash]
|
161
|
+
# @option options [Array<String>] :args long list of arguments to split up
|
135
162
|
# @return [Overcommit::Subprocess::Result] status, stdout, and stderr
|
136
|
-
def execute(
|
137
|
-
if
|
163
|
+
def execute(initial_args, options = {})
|
164
|
+
if initial_args.include?('|')
|
138
165
|
raise Overcommit::Exceptions::InvalidCommandArgs,
|
139
166
|
'Cannot pipe commands with the `execute` helper'
|
140
167
|
end
|
141
168
|
|
142
|
-
|
169
|
+
result =
|
170
|
+
if (splittable_args = options.fetch(:args, [])).any?
|
171
|
+
debug(initial_args.join(' ') + " ... (#{splittable_args.length} splittable args)")
|
172
|
+
Overcommit::CommandSplitter.execute(initial_args, options)
|
173
|
+
else
|
174
|
+
debug(initial_args.join(' '))
|
175
|
+
Overcommit::Subprocess.spawn(initial_args, options)
|
176
|
+
end
|
177
|
+
|
178
|
+
debug("EXIT STATUS: #{result.status}")
|
179
|
+
debug("STDOUT: #{result.stdout.inspect}")
|
180
|
+
debug("STDERR: #{result.stderr.inspect}")
|
181
|
+
|
182
|
+
result
|
143
183
|
end
|
144
184
|
|
145
185
|
# Execute a command in a subprocess, returning immediately.
|
@@ -155,6 +195,7 @@ module Overcommit
|
|
155
195
|
'Cannot pipe commands with the `execute_in_background` helper'
|
156
196
|
end
|
157
197
|
|
198
|
+
debug("Spawning background task: #{args.join(' ')}")
|
158
199
|
Subprocess.spawn_detached(args)
|
159
200
|
end
|
160
201
|
|
@@ -200,6 +241,19 @@ module Overcommit
|
|
200
241
|
File::FNM_DOTMATCH # Wildcards match dotfiles
|
201
242
|
)
|
202
243
|
end
|
244
|
+
|
245
|
+
private
|
246
|
+
|
247
|
+
# Log debug output.
|
248
|
+
#
|
249
|
+
# This is necessary since some specs indirectly call utility functions but
|
250
|
+
# don't explicitly set the logger for the Utils class, so we do a quick
|
251
|
+
# check here to see if it's set before we attempt to log.
|
252
|
+
#
|
253
|
+
# @param args [Array<String>]
|
254
|
+
def debug(*args)
|
255
|
+
log.debug(*args) if log
|
256
|
+
end
|
203
257
|
end
|
204
258
|
end
|
205
259
|
end
|