overcommit 0.26.0 → 0.27.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 +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
|