rabbitt-githooks 1.3.0 → 1.3.2

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.
Files changed (39) hide show
  1. checksums.yaml +5 -13
  2. data/Gemfile.lock +29 -19
  3. data/Rakefile +20 -0
  4. data/bin/githooks +2 -1
  5. data/bin/githooks-runner +10 -2
  6. data/lib/githooks.rb +11 -7
  7. data/lib/githooks/action.rb +67 -53
  8. data/lib/githooks/cli.rb +9 -6
  9. data/lib/githooks/commands/config.rb +26 -19
  10. data/lib/githooks/core_ext.rb +2 -1
  11. data/lib/githooks/core_ext/array/extract_options.rb +5 -1
  12. data/lib/githooks/core_ext/array/min_max.rb +4 -4
  13. data/lib/githooks/core_ext/array/select_with_index.rb +1 -1
  14. data/lib/githooks/core_ext/colorize.rb +30 -0
  15. data/lib/githooks/core_ext/object.rb +8 -0
  16. data/lib/githooks/core_ext/pathname.rb +7 -6
  17. data/lib/githooks/core_ext/string.rb +1 -1
  18. data/lib/githooks/core_ext/string/sanitize.rb +51 -0
  19. data/lib/githooks/error.rb +1 -0
  20. data/lib/githooks/hook.rb +21 -26
  21. data/lib/githooks/repository.rb +31 -35
  22. data/lib/githooks/repository/config.rb +16 -24
  23. data/lib/githooks/repository/diff_index_entry.rb +3 -2
  24. data/lib/githooks/repository/file.rb +14 -7
  25. data/lib/githooks/runner.rb +38 -36
  26. data/lib/githooks/section.rb +13 -19
  27. data/lib/githooks/system_utils.rb +132 -47
  28. data/lib/githooks/version.rb +1 -1
  29. data/lib/tasks/dev.task +14 -0
  30. data/rabbitt-githooks.gemspec +18 -15
  31. metadata +58 -33
  32. data/.gitignore +0 -34
  33. data/.hooks/commit-messages.rb +0 -29
  34. data/.hooks/formatting.rb +0 -44
  35. data/.rubocop.yml +0 -87
  36. data/lib/githooks/core_ext/process.rb +0 -9
  37. data/lib/githooks/core_ext/string/strip_empty_lines.rb +0 -9
  38. data/lib/githooks/terminal_colors.rb +0 -62
  39. data/thoughts.txt +0 -56
@@ -1,6 +1,5 @@
1
1
  require 'ostruct'
2
2
  require 'pathname'
3
- require 'githooks/repository/file'
4
3
 
5
4
  module GitHooks
6
5
  class Repository
@@ -31,7 +30,8 @@ module GitHooks
31
30
  super parse_data(entry)
32
31
  end
33
32
 
34
- def parse_data(entry) # rubocop:disable MethodLength
33
+ # rubocop:disable MultilineOperationIndentation
34
+ def parse_data(entry) # rubocop:disable MethodLength, AbcSize
35
35
  data = Hash[
36
36
  DIFF_STRUCTURE_REGEXP.names.collect(&:to_sym).zip(
37
37
  entry.match(DIFF_STRUCTURE_REGEXP).captures
@@ -53,6 +53,7 @@ module GitHooks
53
53
  score: data[:score].to_i
54
54
  }
55
55
  end
56
+ # rubocop:enable MultilineOperationIndentation
56
57
 
57
58
  def to_repo_file
58
59
  Repository::File.new(self)
@@ -17,16 +17,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
17
17
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
  =end
19
19
 
20
- require 'ostruct'
21
20
  require 'delegate'
22
21
 
23
- # allow for reloading of class
24
- unless defined? DiffIndexEntryDelegateClass
25
- DiffIndexEntryDelegateClass = DelegateClass(GitHooks::Repository::DiffIndexEntry)
26
- end
27
-
28
22
  module GitHooks
29
23
  class Repository
24
+ # allow for reloading of class
25
+ unless defined? DiffIndexEntryDelegateClass
26
+ DiffIndexEntryDelegateClass = DelegateClass(DiffIndexEntry)
27
+ end
28
+
30
29
  class File < DiffIndexEntryDelegateClass
31
30
  def initialize(entry)
32
31
  unless entry.is_a? Repository::DiffIndexEntry
@@ -68,7 +67,7 @@ module GitHooks
68
67
  end
69
68
  end
70
69
 
71
- def match(type, selector)
70
+ def match(type, selector) # rubocop:disable AbcSize
72
71
  value = attribute_value(type)
73
72
  return selector.call(value) if selector.respond_to? :call
74
73
 
@@ -122,6 +121,14 @@ module GitHooks
122
121
  return [] unless fd
123
122
  strip_newlines ? fd.readlines.collect(&:chomp!) : fd.readlines
124
123
  end
124
+
125
+ def <=>(other)
126
+ path.to_s <=> other.path.to_s
127
+ end
128
+
129
+ def ==(other)
130
+ path.to_s == other.path.to_s
131
+ end
125
132
  end
126
133
  end
127
134
  end
@@ -17,23 +17,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
17
17
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
  =end
19
19
 
20
+ require 'thor'
20
21
  require 'fileutils'
21
- require 'githooks/terminal_colors'
22
22
  require 'shellwords'
23
- require 'thor'
23
+
24
+ require_relative 'error'
25
+ require_relative 'hook'
26
+ require_relative 'repository'
27
+ require_relative 'system_utils'
24
28
 
25
29
  module GitHooks
26
30
  module Runner
27
- extend TerminalColors
28
-
29
- MARK_SUCCESS = '✓'
30
- MARK_FAILURE = 'X'
31
- MARK_UNKNOWN = '?'
32
-
33
- def run(options = {}) # rubocop:disable CyclomaticComplexity, MethodLength
34
- # unfreeze options
31
+ # rubocop:disable CyclomaticComplexity, MethodLength, AbcSize, PerceivedComplexity
32
+ def run(options = {})
35
33
  options = Thor::CoreExt::HashWithIndifferentAccess.new(options)
36
34
 
35
+ options['staged'] = options['staged'].nil? ? true : options['staged']
36
+
37
37
  repo = options['repo'] ||= Repository.root_path
38
38
  script = options['script'] ||= Repository.instance(repo).config.script
39
39
  libpath = options['path'] ||= Repository.instance(repo).config.path
@@ -56,7 +56,7 @@ module GitHooks
56
56
  load_tests(libpath, options['skip-bundler'])
57
57
  start(options)
58
58
  else
59
- puts 'I can\'t figure out what to run - specify either path or script to give me a hint...'
59
+ puts %q"I can't figure out what to run - specify either path or script to give me a hint..."
60
60
  end
61
61
 
62
62
  if options['skip-post']
@@ -64,17 +64,17 @@ module GitHooks
64
64
  else
65
65
  run_externals('post-run-execute', repo, args)
66
66
  end
67
- rescue GitHooks::Error::NotAGitRepo
67
+ rescue GitHooks::Error::NotAGitRepo => e
68
68
  puts "Unable to find a valid git repo in #{repo}."
69
69
  puts 'Please specify path to repo via --repo <path>' if GitHooks::SCRIPT_NAME == 'githooks'
70
+ raise e
70
71
  end
71
72
  module_function :run
72
73
 
73
- def attach(options = {}) # rubocop:disable CyclomaticComplexity, MethodLength
74
+ def attach(options = {})
74
75
  repo_path = options[:repo] || Repository.root_path
75
76
  repo_path = Pathname.new(repo_path) unless repo_path.nil?
76
- repo_hooks = repo_path + '.git' + 'hooks'
77
-
77
+ repo_hooks = repo_path.join('.git', 'hooks')
78
78
  entry_path = options[:script] || options[:path]
79
79
 
80
80
  hook_phases = options[:hooks]
@@ -114,7 +114,7 @@ module GitHooks
114
114
 
115
115
  def detach(repo_path, hook_phases)
116
116
  repo_path ||= Repository.root_path
117
- repo_hooks = Pathname.new(repo_path) + '.git' + 'hooks'
117
+ repo_hooks = Pathname.new(repo_path).join('.git', 'hooks')
118
118
  hook_phases ||= Hook::VALID_PHASES
119
119
 
120
120
  repo = Repository.instance(repo_path)
@@ -136,7 +136,7 @@ module GitHooks
136
136
  end
137
137
  module_function :detach
138
138
 
139
- def list(repo_path) # rubocop:disable Style/CyclomaticComplexity, Style/MethodLength
139
+ def list(repo_path)
140
140
  repo_path ||= Pathname.new(Repository.root_path)
141
141
 
142
142
  repo = Repository.instance(repo_path)
@@ -149,9 +149,7 @@ module GitHooks
149
149
 
150
150
  if (executables = repo.config.pre_run_execute).size > 0
151
151
  puts 'PreRun Executables (in execution order):'
152
- executables.each do |exe|
153
- puts " #{exe}"
154
- end
152
+ puts executables.collect { |exe| " #{exe}" }.join("\n")
155
153
  puts
156
154
  end
157
155
 
@@ -196,9 +194,10 @@ module GitHooks
196
194
  end
197
195
  puts
198
196
  end
199
- rescue GitHooks::Error::NotAGitRepo
197
+ rescue Error::NotAGitRepo
200
198
  puts "Unable to find a valid git repo in #{repo}."
201
199
  puts 'Please specify path to repo via --repo <path>' if GitHooks::SCRIPT_NAME == 'githooks'
200
+ raise
202
201
  end
203
202
  module_function :list
204
203
 
@@ -206,7 +205,7 @@ module GitHooks
206
205
 
207
206
  def run_externals(which, repo_path, args)
208
207
  Repository.instance(repo_path).config[which].all? do |executable|
209
- command = SystemUtils::Command.new(File.basename(executable), path: executable)
208
+ command = SystemUtils::Command.new(File.basename(executable), bin_path: executable)
210
209
 
211
210
  puts "#{which.camelize}: #{command.build_command(args)}" if GitHooks.verbose
212
211
  unless (r = command.execute(*args)).status.success?
@@ -222,7 +221,7 @@ module GitHooks
222
221
  end
223
222
  module_function :run_externals
224
223
 
225
- def start(options = {}) # rubocop:disable Style/CyclomaticComplexity, Style/MethodLength
224
+ def start(options = {}) # rubocop:disable CyclomaticComplexity, MethodLength
226
225
  phase = options[:hook] || GitHooks.hook_name || 'pre-commit'
227
226
  puts "PHASE: #{phase}" if GitHooks.debug
228
227
 
@@ -237,21 +236,22 @@ module GitHooks
237
236
  end
238
237
 
239
238
  success = active_hook.run
240
- section_length = active_hook.sections.max { |s| s.title.length }
239
+ section_length = active_hook.sections.maximum { |s| s.title.length }
241
240
  sections = active_hook.sections.select { |section| !section.actions.empty? }
242
241
 
242
+ # TODO: refactor to show this in realtime instead of after the hooks have run
243
243
  sections.each do |section|
244
244
  hash_tail_length = (section_length - section.title.length)
245
245
  printf "===== %s %s===== (%ds)\n", section.colored_name(phase), ('=' * hash_tail_length), section.benchmark
246
-
247
246
  section.actions.each_with_index do |action, index|
248
- printf " %d. [ %s ] %s (%ds)\n", (index + 1), action.state_symbol, action.colored_title, action.benchmark
247
+ printf " %d. [ %s ] %s (%ds)\n", (index + 1), action.status_symbol, action.colored_title, action.benchmark
249
248
 
250
249
  action.errors.each do |error|
251
- printf " %s %s\n", color_bright_red(MARK_FAILURE), error
250
+ printf " %s %s\n", GitHooks::FAILURE_SYMBOL, error
252
251
  end
253
252
 
254
- state_string = ( action.success? ? color_bright_green(MARK_SUCCESS) : color_bright_yellow(MARK_UNKNOWN))
253
+ state_string = action.success? ? GitHooks::SUCCESS_SYMBOL : GitHooks::UNKNOWN_SYMBOL
254
+
255
255
  action.warnings.each do |warning|
256
256
  printf " %s %s\n", state_string, warning
257
257
  end
@@ -270,11 +270,11 @@ module GitHooks
270
270
  end
271
271
  module_function :start
272
272
 
273
- def load_tests(path, skip_bundler = false) # rubocop:disable MethodLength,Style/CyclomaticComplexity
273
+ def load_tests(path, skip_bundler = false)
274
274
  hooks_root = Pathname.new(path).realpath
275
- hooks_path = (p = (hooks_root + 'hooks')).exist? ? p : (hooks_root + '.hooks')
276
- hooks_libs = hooks_root + 'libs'
277
- gemfile = hooks_root + 'Gemfile'
275
+ hooks_path = (p = (hooks_root.join('hooks'))).exist? ? p : (hooks_root.join('.hooks'))
276
+ hooks_libs = hooks_root.join('libs')
277
+ gemfile = hooks_root.join('Gemfile')
278
278
 
279
279
  if gemfile.exist? && !skip_bundler
280
280
  puts "loading Gemfile from: #{gemfile}" if GitHooks.verbose
@@ -286,16 +286,16 @@ module GitHooks
286
286
  # executable-hooks gem preloading bundler. hence the following ...
287
287
  if defined? Bundler
288
288
  [:@settings, :@bundle_path, :@configured, :@definition, :@load].each do |var|
289
- Bundler.instance_variable_set(var, nil)
289
+ ::Bundler.instance_variable_set(var, nil)
290
290
  end
291
291
  else
292
292
  require 'bundler'
293
293
  end
294
- Bundler.require(:default)
294
+ ::Bundler.require(:default)
295
295
  rescue LoadError
296
- puts %Q|Unable to load bundler - please make sure it's installed.|
296
+ puts %q"Unable to load bundler - please make sure it's installed."
297
297
  raise # rubocop:disable SignalException
298
- rescue Bundler::GemNotFound => e
298
+ rescue ::Bundler::GemNotFound => e
299
299
  puts "Error: #{e.message}"
300
300
  puts 'Did you bundle install your Gemfile?'
301
301
  raise # rubocop:disable SignalException
@@ -311,5 +311,7 @@ module GitHooks
311
311
  end
312
312
  end
313
313
  module_function :load_tests
314
+
315
+ # rubocop:enable CyclomaticComplexity, MethodLength, AbcSize, PerceivedComplexity
314
316
  end
315
317
  end
@@ -21,8 +21,6 @@ require 'delegate'
21
21
 
22
22
  module GitHooks
23
23
  class Section < DelegateClass(Array)
24
- include TerminalColors
25
-
26
24
  attr_reader :name, :hook, :success, :actions, :benchmark
27
25
  alias_method :title, :name
28
26
  alias_method :success?, :success
@@ -49,7 +47,7 @@ module GitHooks
49
47
  # overrides previous action method to only return
50
48
  # actions that have a non-empty manifest
51
49
  def actions
52
- @actions.select { |action| !action.manifest.empty? }
50
+ @actions.reject { |action| action.manifest.empty? }
53
51
  end
54
52
  alias_method :__getobj__, :actions
55
53
 
@@ -63,40 +61,36 @@ module GitHooks
63
61
  end
64
62
 
65
63
  def completed?
66
- @actions.all? { |action| action.finished? }
64
+ @actions.all?(&:finished?)
67
65
  end
68
66
 
69
67
  def wait_count
70
- @actions.select { |action| action.waiting? }.size
68
+ @actions.select(&:waiting?).size
71
69
  end
72
70
 
73
71
  def name(phase = GitHooks::HOOK_NAME)
74
- phase = (phase || GitHooks::HOOK_NAME).to_s.gsub('-', '_').camelize
75
- "#{phase} :: #{@name}"
72
+ "#{(phase || GitHooks::HOOK_NAME).to_s.camelize} :: #{@name}"
73
+ end
74
+
75
+ def colored_name(phase = GitHooks::HOOK_NAME)
76
+ status_colorize name(phase)
76
77
  end
77
78
 
78
79
  def key_name
79
80
  self.class.key_from_name(@name)
80
81
  end
81
82
 
82
- def colored_name(phase = GitHooks::HOOK_NAME)
83
- status_colorize name(phase)
83
+ def status_colorize(text)
84
+ return text.unknown! unless finished? && completed?
85
+ success? ? text.success! : text.failure!
84
86
  end
85
87
 
86
- def action(title, options = {}, &block)
87
- fail ArgumentError, 'Missing required block to #perform' unless block_given?
88
+ def action(title, &block)
89
+ fail ArgumentError, 'expected block, received none' unless block_given?
88
90
  @actions << Action.new(title, self, &block)
89
91
  self
90
92
  end
91
93
 
92
- def status_colorize(text)
93
- if finished? && completed?
94
- success? ? color_bright_green(text) : color_bright_red(text)
95
- else
96
- color_dark_cyan(text)
97
- end
98
- end
99
-
100
94
  def run
101
95
  running!
102
96
  begin
@@ -1,7 +1,8 @@
1
- # encoding: utf-8
1
+ # sublime: x_syntax Packages/Ruby/Ruby.tmLanguage
2
+ # sublime: translate_tabs_to_spaces true; tab_size 2
3
+
2
4
  require 'pathname'
3
- require 'open3'
4
- require 'ostruct'
5
+ require 'tempfile'
5
6
  require 'shellwords'
6
7
 
7
8
  module GitHooks
@@ -22,7 +23,7 @@ module GitHooks
22
23
  end
23
24
  module_function :find_bin
24
25
 
25
- def with_path(path, &block)
26
+ def with_path(path, &_block)
26
27
  fail ArgumentError, 'Missing required block' unless block_given?
27
28
  begin
28
29
  cwd = Dir.getwd
@@ -34,7 +35,7 @@ module GitHooks
34
35
  end
35
36
  module_function :with_path
36
37
 
37
- def quiet(&block)
38
+ def quiet(&_block)
38
39
  od, ov = GitHooks.debug, GitHooks.verbose
39
40
  GitHooks.debug, GitHooks.verbose = false, false
40
41
  yield
@@ -43,67 +44,151 @@ module GitHooks
43
44
  end
44
45
  module_function :quiet
45
46
 
47
+ def command(name)
48
+ (@commands ||= {})[name] ||= begin
49
+ Command.new(name).tap { |cmd|
50
+ define_method("command_#{cmd.name}") { |*args| cmd.execute(*args) }
51
+ alias_method cmd.method, "command_#{cmd.name}"
52
+ }
53
+ end
54
+ end
55
+ module_function :command
56
+
57
+ def commands(*names)
58
+ names.each { |name| command(name) }
59
+ end
60
+ module_function :commands
61
+
46
62
  class Command
47
63
  include Shellwords
48
64
 
49
- attr_reader :aliases, :path, :name
50
- def initialize(name, options = {})
51
- @name = name
52
- @path = options.delete(:path) || SystemUtils.which(name)
65
+ ENV_WHITELIST = %w(
66
+ PATH HOME LDFLAGS CPPFLAGS DISPLAY EDITOR
67
+ LANG LC_ALL SHELL SHLVL TERM TMPDIR USER
68
+ SSH_USER SSH_AUTH_SOCK
69
+ GEM_HOME GEM_PATH MY_RUBY_HOME
70
+ )
71
+
72
+ class Result
73
+ attr_reader :output, :error, :status
74
+ def initialize(output, error, status)
75
+ @output = output.strip
76
+ @error = error.strip
77
+ @status = status
78
+ end
53
79
 
54
- @aliases = options.delete(:aliases) || []
55
- @aliases << name
56
- @aliases.collect! { |alias_name| normalize(alias_name) }
57
- @aliases.uniq!
80
+ def output_lines(prefix = nil)
81
+ @output.split(/\n/).collect { |line|
82
+ prefix ? "#{prefix}: #{line}" : line
83
+ }
84
+ end
85
+
86
+ def error_lines(prefix = nil)
87
+ @error.split(/\n/).collect { |line|
88
+ prefix ? "#{prefix}: #{line}" : line
89
+ }
90
+ end
91
+
92
+ def sanitize!(*args)
93
+ @output.sanitize!(*args)
94
+ @error.sanitize!(*args)
95
+ end
96
+
97
+ def success?
98
+ status? ? @status.success? : false
99
+ end
100
+
101
+ def failure?
102
+ !success?
103
+ end
104
+
105
+ def status?
106
+ !!@status
107
+ end
108
+
109
+ def exitstatus
110
+ status? ? @status.exitstatus : -1
111
+ end
112
+ alias_method :code, :exitstatus
113
+ end
114
+
115
+ attr_reader :run_path, :bin_path, :name
116
+
117
+ def initialize(name, options = {})
118
+ @bin_path = options.delete(:bin_path) || SystemUtils.which(name) || name
119
+ @run_path = options.delete(:chdir)
120
+ @name = name.to_s.gsub(/([\W-]+)/, '_')
58
121
  end
59
122
 
60
- def command_path
61
- path || name.to_s
123
+ def method
124
+ @name.to_sym
62
125
  end
63
126
 
64
- def build_command(args, options = {})
65
- change_to_path = options['path'] || options[:path]
127
+ def build_command(args, options)
128
+ Array(args).unshift(command_path(options))
129
+ end
66
130
 
67
- args = [args].flatten
68
- args.collect! { |arg| arg.is_a?(Repository::File) ? arg.path.to_s : arg }
69
- args.collect!(&:to_s)
131
+ def command_path(options = {})
132
+ options.delete(:use_name) ? name : bin_path.to_s
133
+ end
70
134
 
71
- command = shelljoin([command_path] | args)
72
- command = ("cd #{shellescape(change_to_path.to_s)} ; " + command) unless change_to_path.nil?
73
- command
135
+ def prep_env(env = {})
136
+ Hash[env].each_with_object([]) do |(k, v), array|
137
+ array << %Q|#{k}="#{v}"| if ENV_WHITELIST.include? k
138
+ end.join(' ')
74
139
  end
75
140
 
76
- def execute(*args, &block) # rubocop:disable MethodLength, CyclomaticComplexity
77
- options = args.extract_options
78
- strip_empty_lines = !!options.delete(:strip_empty_lines)
141
+ def execute(*args, &_block) # rubocop:disable MethodLength, CyclomaticComplexity, AbcSize, PerceivedComplexity
142
+ options = args.extract_options!
79
143
 
80
144
  command = build_command(args, options)
81
- result = OpenStruct.new(output: nil, error: nil, status: nil).tap do |r|
82
- puts "#{Dir.getwd} $ #{command}" if GitHooks.debug
83
-
84
- r.output, r.error, r.status = if RUBY_ENGINE == 'jruby'
85
- _, o, e, t = Open3.popen3('/usr/bin/env', 'sh', '-c', command)
86
- [o.read, e.read, t.value]
87
- else
88
- Open3.capture3(command)
89
- end
90
-
91
- if strip_empty_lines
92
- r.output = r.output.strip_empty_lines!
93
- r.error = r.error.strip_empty_lines!
145
+ command.unshift("cd #{run_path} ;") if run_path
146
+ command.unshift('sudo') if options.delete(:use_sudo)
147
+ command = Array(command.flatten.join(' '))
148
+
149
+ command.unshift options.delete(:pre_pipe) if options[:pre_pipe]
150
+ command.push options.delete(:post_pipe) if options[:post_pipe]
151
+ command = Array(command.flatten.join('|'))
152
+
153
+ command.unshift options.delete(:pre_run) if options[:pre_run]
154
+ command.push options.delete(:post_run) if options[:post_run]
155
+ command = shellwords(command.flatten.join(';'))
156
+
157
+ environment = prep_env(options.delete(:env) || ENV)
158
+
159
+ error_file = Tempfile.new('ghstderr')
160
+ begin
161
+ real_command = %Q{
162
+ /usr/bin/env -i #{environment} bash -c '
163
+ ( #{command.join(' ').gsub("'", %q|'"'"'|)}) 2>#{error_file.path}
164
+ '
165
+ }
166
+
167
+ $stderr.puts real_command if GitHooks.debug?
168
+
169
+ output = %x{ #{real_command} }
170
+ result = Result.new(output, error_file.read, $?)
171
+
172
+ if GitHooks.verbose? && result.failure?
173
+ STDERR.puts "Command failed with exit code [#{result.status.exitstatus}]",
174
+ "ENVIRONMENT:\n\t#{environment}\n\n",
175
+ "COMMAND:\n\t#{command.join(' ')}\n\n",
176
+ "OUTPUT:\n-----\n#{result.output}\n-----\n\n",
177
+ "ERROR:\n-----\n#{result.error}\n-----\n\n"
94
178
  end
95
- end
96
179
 
97
- puts result.inspect if GitHooks.debug
180
+ sanitize = [ :strip, :non_printable ]
181
+ sanitize << :colors unless options.delete(:color)
182
+ sanitize << :empty_lines if options.delete(:strip_empty_lines)
183
+ result.sanitize!(*sanitize)
98
184
 
99
- block_given? ? yield(result) : result
185
+ block_given? ? yield(result) : result
186
+ ensure
187
+ error_file.close
188
+ error_file.unlink
189
+ end
100
190
  end
101
191
  alias_method :call, :execute
102
-
103
- def normalize(name)
104
- name.to_s.gsub(/[^a-z_]+/, '_')
105
- end
106
- private :normalize
107
192
  end
108
193
  end
109
194
  end