Skip to content

Commit 453a32c

Browse files
committed
Extract printing concern from HookRunner into helper
The `HookRunner` class was the largest class, and arguably one of the most complicated. An obvious separation of concerns was the flow of events versus the printing of output to the user. A solution was to separate the printing into a separate helper class which the `HookRunner` could just send messages to when certain events occurred. It's a bit crude since we're still passing a few parameters here and there that should probably be encapsulated in separate objects, but this already provides us some benefit in terms of reducing the size of the class. We also should probably consider having the printer passed to the `HookLoader` implementations as well, but right now things still work and this is something that can be shipped. Change-Id: I93c639b69e4d468ac1766cf86599c413d6c482eb Reviewed-on: http://gerrit.causes.com/40459 Tested-by: jenkins <jenkins@causes.com> Reviewed-by: Shane da Silva <shane.dasilva@brigade.com>
1 parent f45314d commit 453a32c

File tree

4 files changed

+115
-56
lines changed

4 files changed

+115
-56
lines changed

lib/overcommit.rb

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
require 'overcommit/hook_loader/built_in_hook_loader'
1414
require 'overcommit/hook_loader/plugin_hook_loader'
1515
require 'overcommit/interrupt_handler'
16+
require 'overcommit/printer'
1617
require 'overcommit/hook_runner'
1718
require 'overcommit/installer'
1819
require 'overcommit/logger'

lib/overcommit/hook_runner.rb

+9-55
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ class HookRunner
88
# @param logger [Overcommit::Logger]
99
# @param context [Overcommit::HookContext]
1010
# @param input [Overcommit::UserInput]
11-
def initialize(config, logger, context, input)
11+
def initialize(config, logger, context, input, printer)
1212
@config = config
1313
@log = logger
1414
@context = context
1515
@input = input
16+
@printer = printer
1617
@hooks = []
1718
end
1819

@@ -33,7 +34,7 @@ def run
3334

3435
def run_hooks
3536
if @hooks.any? { |hook| hook.run? || hook.skip? }
36-
log.bold "Running #{hook_script_name} hooks"
37+
@printer.start_run
3738

3839
interrupted = false
3940
run_failed = false
@@ -50,23 +51,19 @@ def run_hooks
5051
end
5152
end
5253

53-
log.log # Newline
54-
print_summary(run_failed, interrupted)
55-
log.log # Newline
54+
@printer.end_run(interrupted, run_failed)
5655

5756
!(run_failed || interrupted)
5857
else
59-
log.success "✓ No applicable #{hook_script_name} hooks to run"
58+
@printer.nothing_to_run
6059
true # Run was successful
6160
end
6261
end
6362

6463
def run_hook(hook)
6564
return if should_skip?(hook)
6665

67-
unless hook.quiet?
68-
print_header(hook)
69-
end
66+
@printer.start_hook(hook)
7067

7168
begin
7269
# Disable the interrupt handler during individual hook run so that
@@ -84,65 +81,26 @@ def run_hook(hook)
8481
InterruptHandler.enable!
8582
end
8683

87-
# Want to print the header in the event the result wasn't good so that the
88-
# user knows what failed
89-
print_header(hook) if hook.quiet? && status != :good
90-
91-
print_result(hook, status, output)
84+
@printer.end_hook(hook, status, output)
9285

9386
status
9487
end
9588

96-
def print_header(hook)
97-
log.partial hook.description
98-
log.partial '.' * (70 - hook.description.length)
99-
end
100-
10189
def should_skip?(hook)
10290
return true unless hook.enabled?
10391

10492
if hook.skip?
10593
if hook.required?
106-
log.warning "Cannot skip #{hook.name} since it is required"
94+
@printer.required_hook_not_skipped
10795
else
108-
log.warning "Skipping #{hook.name}"
96+
@printer.hook_skipped
10997
return true
11098
end
11199
end
112100

113101
!hook.run?
114102
end
115103

116-
def print_result(hook, status, output)
117-
case status
118-
when :good
119-
log.success 'OK' unless hook.quiet?
120-
when :warn
121-
log.warning 'WARNING'
122-
print_report(output, :bold_warning)
123-
when :bad
124-
log.error 'FAILED'
125-
print_report(output, :bold_error)
126-
when :interrupted
127-
log.error 'INTERRUPTED'
128-
print_report(output, :bold_error)
129-
end
130-
end
131-
132-
def print_report(output, format = :log)
133-
log.send(format, output) unless output.nil? || output.empty?
134-
end
135-
136-
def print_summary(run_failed, was_interrupted)
137-
if was_interrupted
138-
log.warning '⚠ Hook run interrupted by user'
139-
elsif run_failed
140-
log.error "✗ One or more #{hook_script_name} hooks failed"
141-
else
142-
log.success "✓ All #{hook_script_name} hooks passed"
143-
end
144-
end
145-
146104
def load_hooks
147105
require "overcommit/hook/#{@context.hook_type_name}/base"
148106

@@ -151,9 +109,5 @@ def load_hooks
151109
# Load plugin hooks after so they can subclass existing hooks
152110
@hooks += HookLoader::PluginHookLoader.new(@config, @context, @log, @input).load_hooks
153111
end
154-
155-
def hook_script_name
156-
@context.hook_script_name
157-
end
158112
end
159113
end

lib/overcommit/printer.rb

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
module Overcommit
2+
# Provide a set of callbacks which can be executed as events occur during the
3+
# course of {HookRunner#run}.
4+
class Printer
5+
attr_reader :log
6+
7+
def initialize(logger, context)
8+
@log = logger
9+
@context = context
10+
end
11+
12+
# Executed at the very beginning of running the collection of hooks.
13+
def start_run
14+
log.bold "Running #{hook_script_name} hooks"
15+
end
16+
17+
def nothing_to_run
18+
log.success "✓ No applicable #{hook_script_name} hooks to run"
19+
end
20+
21+
# Executed at the very end of running the collection of hooks.
22+
def end_run(run_failed, interrupted)
23+
log.log # Newline
24+
25+
if interrupted
26+
log.warning '⚠ Hook run interrupted by user'
27+
elsif run_failed
28+
log.error "✗ One or more #{hook_script_name} hooks failed"
29+
else
30+
log.success "✓ All #{hook_script_name} hooks passed"
31+
end
32+
33+
log.log # Newline
34+
end
35+
36+
# Executed at the start of an individual hook run.
37+
def start_hook(hook)
38+
unless hook.quiet?
39+
print_header(hook)
40+
end
41+
end
42+
43+
def hook_skipped(hook)
44+
log.warning "Skipping #{hook.name}"
45+
end
46+
47+
def required_hook_not_skipped(hook)
48+
log.warning "Cannot skip #{hook.name} since it is required"
49+
end
50+
51+
# Executed at the end of an individual hook run.
52+
def end_hook(hook, status, output)
53+
# Want to print the header for quiet hooks only if the result wasn't good
54+
# so that the user knows what failed
55+
print_header(hook) if hook.quiet? && status != :good
56+
57+
print_result(hook, status, output)
58+
end
59+
60+
private
61+
62+
def print_header(hook)
63+
log.partial hook.description
64+
log.partial '.' * (70 - hook.description.length)
65+
end
66+
67+
def print_result(hook, status, output)
68+
case status
69+
when :good
70+
log.success 'OK' unless hook.quiet?
71+
when :warn
72+
log.warning 'WARNING'
73+
print_report(output, :bold_warning)
74+
when :bad
75+
log.error 'FAILED'
76+
print_report(output, :bold_error)
77+
when :interrupted
78+
log.error 'INTERRUPTED'
79+
print_report(output, :bold_error)
80+
end
81+
end
82+
83+
def print_report(output, format = :log)
84+
log.send(format, output) unless output.nil? || output.empty?
85+
end
86+
87+
def run_interrupted
88+
log.warning '⚠ Hook run interrupted by user'
89+
end
90+
91+
def run_failed
92+
log.error "✗ One or more #{hook_script_name} hooks failed"
93+
end
94+
95+
def run_succeeded
96+
log.success "✓ All #{hook_script_name} hooks passed"
97+
end
98+
99+
def hook_script_name
100+
@context.hook_script_name
101+
end
102+
end
103+
end

template-dir/hooks/overcommit-hook

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ begin
6565

6666
input = Overcommit::UserInput.new(STDIN)
6767

68-
runner = Overcommit::HookRunner.new(config, logger, context, input)
68+
printer = Overcommit::Printer.new(logger, context)
69+
runner = Overcommit::HookRunner.new(config, logger, context, input, printer)
6970

7071
status = runner.run
7172

0 commit comments

Comments
 (0)