puppet-debugger 0.16.0 → 1.1.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.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab-ci.yml +10 -26
  3. data/.rubocop.yml +64 -232
  4. data/.rubocop_todo.yml +89 -147
  5. data/.ruby-version +1 -1
  6. data/.vscode/launch.json +15 -0
  7. data/CHANGELOG.md +34 -0
  8. data/Gemfile +7 -5
  9. data/README.md +29 -261
  10. data/Rakefile +11 -12
  11. data/bin/pdb +1 -1
  12. data/lib/awesome_print/ext/awesome_puppet.rb +10 -8
  13. data/lib/plugins/puppet-debugger/input_responders/benchmark.rb +5 -4
  14. data/lib/plugins/puppet-debugger/input_responders/classes.rb +14 -2
  15. data/lib/plugins/puppet-debugger/input_responders/classification.rb +4 -2
  16. data/lib/plugins/puppet-debugger/input_responders/commands.rb +18 -18
  17. data/lib/plugins/puppet-debugger/input_responders/datatypes.rb +22 -6
  18. data/lib/plugins/puppet-debugger/input_responders/environment.rb +4 -2
  19. data/lib/plugins/puppet-debugger/input_responders/exit.rb +5 -3
  20. data/lib/plugins/puppet-debugger/input_responders/facterdb_filter.rb +4 -2
  21. data/lib/plugins/puppet-debugger/input_responders/facts.rb +4 -2
  22. data/lib/plugins/puppet-debugger/input_responders/functions.rb +34 -32
  23. data/lib/plugins/puppet-debugger/input_responders/help.rb +4 -2
  24. data/lib/plugins/puppet-debugger/input_responders/krt.rb +4 -2
  25. data/lib/plugins/puppet-debugger/input_responders/play.rb +22 -24
  26. data/lib/plugins/puppet-debugger/input_responders/reset.rb +5 -3
  27. data/lib/plugins/puppet-debugger/input_responders/resources.rb +16 -7
  28. data/lib/plugins/puppet-debugger/input_responders/set.rb +34 -32
  29. data/lib/plugins/puppet-debugger/input_responders/stacktrace.rb +31 -0
  30. data/lib/plugins/puppet-debugger/input_responders/types.rb +6 -2
  31. data/lib/plugins/puppet-debugger/input_responders/vars.rb +8 -7
  32. data/lib/plugins/puppet-debugger/input_responders/whereami.rb +5 -3
  33. data/lib/puppet-debugger.rb +1 -45
  34. data/lib/puppet-debugger/cli.rb +130 -92
  35. data/lib/puppet-debugger/code/code_file.rb +13 -14
  36. data/lib/puppet-debugger/code/code_range.rb +5 -3
  37. data/lib/puppet-debugger/code/loc.rb +1 -1
  38. data/lib/puppet-debugger/debugger_code.rb +2 -0
  39. data/lib/puppet-debugger/hooks.rb +15 -16
  40. data/lib/puppet-debugger/input_responder_plugin.rb +54 -52
  41. data/lib/puppet-debugger/monkey_patches.rb +57 -0
  42. data/lib/puppet-debugger/plugin_test_helper.rb +9 -8
  43. data/lib/puppet-debugger/support.rb +27 -17
  44. data/lib/puppet-debugger/support/environment.rb +6 -5
  45. data/lib/puppet-debugger/support/errors.rb +25 -27
  46. data/lib/puppet-debugger/support/facts.rb +5 -5
  47. data/lib/puppet-debugger/support/node.rb +4 -7
  48. data/lib/puppet-debugger/support/scope.rb +29 -0
  49. data/lib/puppet-debugger/trollop.rb +38 -31
  50. data/lib/puppet-debugger/version.rb +1 -1
  51. data/lib/puppet/application/debugger.rb +151 -126
  52. data/output.json +1 -0
  53. data/puppet-debugger.gemspec +17 -15
  54. data/spec/awesome_print/ext/awesome_puppet_spec.rb +30 -30
  55. data/spec/fixtures/pe-xl-core-0.puppet.vm.json +1 -0
  56. data/spec/fixtures/sample_start_debugger.pp +3 -2
  57. data/spec/hooks_spec.rb +33 -35
  58. data/spec/input_responder_plugin_spec.rb +7 -6
  59. data/spec/input_responders/benchmark_spec.rb +3 -1
  60. data/spec/input_responders/classes_spec.rb +12 -13
  61. data/spec/input_responders/classification_spec.rb +4 -2
  62. data/spec/input_responders/commands_spec.rb +2 -0
  63. data/spec/input_responders/datatypes_spec.rb +8 -2
  64. data/spec/input_responders/environment_spec.rb +2 -0
  65. data/spec/input_responders/exit_spec.rb +9 -11
  66. data/spec/input_responders/facterdb_filter_spec.rb +2 -0
  67. data/spec/input_responders/facts_spec.rb +2 -0
  68. data/spec/input_responders/functions_spec.rb +30 -28
  69. data/spec/input_responders/help_spec.rb +5 -3
  70. data/spec/input_responders/krt_spec.rb +3 -1
  71. data/spec/input_responders/play_spec.rb +10 -20
  72. data/spec/input_responders/reset_spec.rb +2 -0
  73. data/spec/input_responders/resources_spec.rb +7 -1
  74. data/spec/input_responders/set_spec.rb +3 -1
  75. data/spec/input_responders/stacktrace_spec.rb +15 -0
  76. data/spec/input_responders/types_spec.rb +2 -0
  77. data/spec/input_responders/vars_spec.rb +4 -4
  78. data/spec/input_responders/whereami_spec.rb +2 -0
  79. data/spec/pdb_spec.rb +0 -9
  80. data/spec/puppet/application/debugger_spec.rb +35 -17
  81. data/spec/puppet_debugger_spec.rb +81 -83
  82. data/spec/remote_node_spec.rb +1 -5
  83. data/spec/spec_helper.rb +22 -18
  84. data/spec/support_spec.rb +3 -5
  85. data/test_matrix.rb +1 -1
  86. metadata +56 -22
@@ -1,31 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "puppet"
4
- require "readline"
5
- require "json"
6
- require "puppet-debugger/support"
7
- require "pluginator"
8
- require "puppet-debugger/hooks"
9
- require "forwardable"
10
- require "plugins/puppet-debugger/input_responders/functions"
11
- require "plugins/puppet-debugger/input_responders/datatypes"
12
-
3
+ require 'puppet'
4
+ require 'readline'
5
+ require 'json'
6
+ require 'puppet-debugger/support'
7
+ require 'pluginator'
8
+ require 'puppet-debugger/hooks'
9
+ require 'forwardable'
10
+ require 'plugins/puppet-debugger/input_responders/functions'
11
+ require 'plugins/puppet-debugger/input_responders/datatypes'
12
+ require 'tty-pager'
13
13
  module PuppetDebugger
14
14
  class Cli
15
15
  include PuppetDebugger::Support
16
16
  extend Forwardable
17
17
  attr_accessor :settings, :log_level, :in_buffer, :out_buffer, :html_mode, :extra_prompt, :bench
18
- attr_reader :source_file, :source_line_num, :hooks
18
+ attr_reader :source_file, :source_line_num, :hooks, :options
19
19
  def_delegators :hooks, :exec_hook, :add_hook, :delete_hook
20
-
20
+ OUT_SYMBOL = ' => '
21
21
  def initialize(options = {})
22
22
  do_initialize if Puppet[:codedir].nil?
23
23
  Puppet.settings[:name] = :debugger
24
- Puppet.settings[:trusted_server_facts] = true unless Puppet.settings[:trusted_server_facts].nil?
24
+ @options = options
25
25
  Puppet[:static_catalogs] = false unless Puppet.settings[:static_catalogs].nil?
26
26
  set_remote_node_name(options[:node_name])
27
27
  initialize_from_scope(options[:scope])
28
- @log_level = "notice"
28
+ set_catalog(options[:catalog])
29
+ @log_level = 'notice'
29
30
  @out_buffer = options[:out_buffer] || $stdout
30
31
  @html_mode = options[:html_mode] || false
31
32
  @source_file = options[:source_file] || nil
@@ -33,14 +34,23 @@ module PuppetDebugger
33
34
  @in_buffer = options[:in_buffer] || $stdin
34
35
  Readline.input = @in_buffer
35
36
  Readline.output = @out_buffer
36
- Readline.completion_append_character = ""
37
- Readline.basic_word_break_characters = " "
37
+ Readline.completion_append_character = ''
38
+ Readline.basic_word_break_characters = ' '
38
39
  Readline.completion_proc = command_completion
39
40
  AwesomePrint.defaults = {
40
41
  html: @html_mode,
41
42
  sort_keys: true,
42
- indent: 2,
43
+ indent: 2
43
44
  }
45
+ # Catch control-c sequences
46
+ trap('SIGINT') do
47
+ # control-d
48
+ exit 0
49
+ end
50
+ trap('INT') do
51
+ # control-c
52
+ # handle_output('Type exit or use control-d')
53
+ end
44
54
  end
45
55
 
46
56
  # @return [Proc] the proc used in the command completion for readline
@@ -50,11 +60,12 @@ module PuppetDebugger
50
60
  proc do |input|
51
61
  words = Readline.line_buffer.split(Readline.basic_word_break_characters)
52
62
  next key_words.grep(/^#{Regexp.escape(input)}/) if words.empty?
63
+
53
64
  first_word = words.shift
54
65
  plugins = PuppetDebugger::InputResponders::Commands.plugins.find_all do |p|
55
66
  p::COMMAND_WORDS.find { |word| word.start_with?(first_word) }
56
67
  end
57
- if plugins.count == 1 and /\A#{first_word}\s/.match(Readline.line_buffer)
68
+ if (plugins.count == 1) && /\A#{first_word}\s/.match(Readline.line_buffer)
58
69
  plugins.first.command_completion(words)
59
70
  else
60
71
  key_words.grep(/^#{Regexp.escape(input)}/)
@@ -76,7 +87,8 @@ module PuppetDebugger
76
87
  PuppetDebugger::InputResponders::Functions.instance.debugger = self
77
88
  funcs = PuppetDebugger::InputResponders::Functions.instance.func_list
78
89
  PuppetDebugger::InputResponders::Datatypes.instance.debugger = self
79
- (scoped_vars + funcs + static_responder_list + PuppetDebugger::InputResponders::Datatypes.instance.all_data_types).uniq.sort
90
+ (scoped_vars + funcs + static_responder_list +
91
+ PuppetDebugger::InputResponders::Datatypes.instance.all_data_types).uniq.sort
80
92
  end
81
93
 
82
94
  # looks up the type in the catalog by using the type and title
@@ -106,7 +118,7 @@ module PuppetDebugger
106
118
  end
107
119
 
108
120
  def contains_resources?(result)
109
- !Array(result).flatten.find { |r| r.class.to_s =~ /Puppet::Pops::Types/ }.nil?
121
+ !Array(result).flatten.find { |r| r.class.to_s =~ /Puppet::Pops::Types::PResourceType/ }.nil?
110
122
  end
111
123
 
112
124
  def normalize_output(result)
@@ -116,87 +128,108 @@ module PuppetDebugger
116
128
  # if the only output is a resource then return it
117
129
  # otherwise it is multiple items or an actually array
118
130
  return output.first if output.count == 1
131
+
119
132
  return output
120
133
  end
121
134
  result
122
135
  end
123
136
 
124
137
  def responder_list
125
- plugins = Pluginator.find(PuppetDebugger)
138
+ Pluginator.find(PuppetDebugger)
139
+ end
140
+
141
+ # @return [TTY::Pager] the pager object, disable if CI or testing is present
142
+ def pager
143
+ @pager ||= TTY::Pager.new(output: out_buffer, enabled: pager_enabled?)
144
+ end
145
+
146
+ def pager_enabled?
147
+ ENV['CI'].nil?
148
+ end
149
+
150
+ # @param output [String] - the content to output
151
+ # @summary outputs the output to the output buffer
152
+ # uses the pager if the screen height is less than the height of the
153
+ # output content
154
+ # Disabled if CI or testing is being done
155
+ def handle_output(output)
156
+ return if output.nil?
157
+
158
+ if pager_enabled? && output.lines.count >= TTY::Screen.height
159
+ output << "\n"
160
+ pager.page(output)
161
+ else
162
+ out_buffer.puts(output) unless output.empty?
163
+ end
126
164
  end
127
165
 
128
166
  # this method handles all input and expects a string of text.
129
- #
167
+ # @param input [String] - the input content to parse or run
130
168
  def handle_input(input)
131
169
  raise ArgumentError unless input.instance_of?(String)
132
- begin
133
- output = ""
134
- case input.strip
135
- when PuppetDebugger::InputResponders::Commands.command_list_regex
136
- args = input.split(" ")
137
- command = args.shift
138
- plugin = PuppetDebugger::InputResponders::Commands.plugin_from_command(command)
139
- output = plugin.execute(args, self)
140
- return out_buffer.puts output
141
- when "_"
142
- output = " => #{@last_item}"
143
- else
144
- result = puppet_eval(input)
145
- @last_item = result
146
- output = normalize_output(result)
147
- output = output.nil? ? "" : output.ai
170
+
171
+ output =
172
+ begin
173
+ case input.strip
174
+ when PuppetDebugger::InputResponders::Commands.command_list_regex
175
+ args = input.split(' ')
176
+ command = args.shift
177
+ plugin = PuppetDebugger::InputResponders::Commands.plugin_from_command(command)
178
+ plugin.execute(args, self) || ''
179
+ when '_'
180
+ " => #{@last_item}"
181
+ else
182
+ result = puppet_eval(input)
183
+ @last_item = result
184
+ o = normalize_output(result)
185
+ o.nil? ? '' : o.ai
186
+ end
187
+ rescue PuppetDebugger::Exception::InvalidCommand => e
188
+ e.message.fatal
189
+ rescue LoadError => e
190
+ e.message.fatal
191
+ rescue Errno::ETIMEDOUT => e
192
+ e.message.fatal
193
+ rescue ArgumentError => e
194
+ e.message.fatal
195
+ rescue Puppet::ResourceError => e
196
+ e.message.fatal
197
+ rescue Puppet::Error => e
198
+ e.message.fatal
199
+ rescue Puppet::ParseErrorWithIssue => e
200
+ e.message.fatal
201
+ rescue PuppetDebugger::Exception::FatalError => e
202
+ handle_output(e.message.fatal)
203
+ exit 1 # this can sometimes causes tests to fail
204
+ rescue PuppetDebugger::Exception::Error => e
205
+ e.message.fatal
206
+ rescue ::RuntimeError => e
207
+ handle_output(e.message.fatal)
208
+ exit 1
148
209
  end
149
- rescue PuppetDebugger::Exception::InvalidCommand => e
150
- output = e.message.fatal
151
- rescue LoadError => e
152
- output = e.message.fatal
153
- rescue Errno::ETIMEDOUT => e
154
- output = e.message.fatal
155
- rescue ArgumentError => e
156
- output = e.message.fatal
157
- rescue Puppet::ResourceError => e
158
- output = e.message.fatal
159
- rescue Puppet::Error => e
160
- output = e.message.fatal
161
- rescue Puppet::ParseErrorWithIssue => e
162
- output = e.message.fatal
163
- rescue PuppetDebugger::Exception::FatalError => e
164
- output = e.message.fatal
165
- out_buffer.puts output
166
- exit 1 # this can sometimes causes tests to fail
167
- rescue PuppetDebugger::Exception::Error => e
168
- output = e.message.fatal
169
- rescue ::RuntimeError => e
170
- output = e.message.fatal
171
- out_buffer.puts output
172
- exit 1
173
- end
174
- unless output.empty?
175
- out_buffer.print " => "
176
- out_buffer.puts output unless output.empty?
177
- exec_hook :after_output, out_buffer, self, self
178
- end
210
+ output = OUT_SYMBOL + output unless output.empty?
211
+ handle_output(output)
212
+ exec_hook :after_output, out_buffer, self, self
179
213
  end
180
214
 
181
215
  def self.print_repl_desc
182
- output = <<-EOT
183
- Ruby Version: #{RUBY_VERSION}
184
- Puppet Version: #{Puppet.version}
185
- Puppet Debugger Version: #{PuppetDebugger::VERSION}
186
- Created by: NWOps <corey@nwops.io>
187
- Type "commands" for a list of debugger commands
188
- or "help" to show the help screen.
216
+ <<~OUT
217
+ Ruby Version: #{RUBY_VERSION}
218
+ Puppet Version: #{Puppet.version}
219
+ Puppet Debugger Version: #{PuppetDebugger::VERSION}
220
+ Created by: NWOps <corey@nwops.io>
221
+ Type "commands" for a list of debugger commands
222
+ or "help" to show the help screen.
189
223
 
190
224
 
191
- EOT
192
- output
225
+ OUT
193
226
  end
194
227
 
195
228
  # tries to determine if the input is going to be a multiline input
196
229
  # by reading the parser error message
197
230
  # @return [Boolean] - return true if this is a multiline input, false otherwise
198
- def multiline_input?(e)
199
- case e.message
231
+ def multiline_input?(data)
232
+ case data.message
200
233
  when /Syntax error at end of/i
201
234
  true
202
235
  else
@@ -211,7 +244,7 @@ or "help" to show the help screen.
211
244
  # input
212
245
  def read_loop
213
246
  line_number = 1
214
- full_buffer = ""
247
+ full_buffer = ''
215
248
  while buf = Readline.readline("#{line_number}:#{extra_prompt}>> ", true)
216
249
  begin
217
250
  full_buffer += buf
@@ -222,14 +255,14 @@ or "help" to show the help screen.
222
255
  parser.parse_string(full_buffer)
223
256
  rescue Puppet::ParseErrorWithIssue => e
224
257
  if multiline_input?(e)
225
- out_buffer.print " "
258
+ out_buffer.print ' '
226
259
  full_buffer += "\n"
227
260
  next
228
261
  end
229
262
  end
230
263
  end
231
264
  handle_input(full_buffer)
232
- full_buffer = ""
265
+ full_buffer = ''
233
266
  end
234
267
  end
235
268
  end
@@ -251,7 +284,7 @@ or "help" to show the help screen.
251
284
  repl_obj.out_buffer.puts print_repl_desc unless options[:quiet]
252
285
  repl_obj.handle_input(options[:content]) if options[:content]
253
286
  # TODO: make the output optional so we can have different output destinations
254
- repl_obj.handle_input("whereami") if options[:source_file] && options[:source_line]
287
+ repl_obj.handle_input('whereami') if options[:source_file] && options[:source_line]
255
288
  repl_obj.handle_input("play #{options[:play]}") if options[:play]
256
289
  repl_obj.read_loop unless options[:run_once]
257
290
  end
@@ -262,10 +295,15 @@ or "help" to show the help screen.
262
295
  # @param [Hash] puppet scope object
263
296
  def self.start(options = { scope: nil })
264
297
  opts = Trollop.options do
265
- opt :play, "Url or file to load from", required: false, type: String
266
- opt :run_once, "Evaluate and quit", required: false, default: false
267
- opt :node_name, "Remote Node to grab facts from", required: false, type: String
268
- opt :quiet, "Do not display banner", required: false, default: false
298
+ opt :play, 'Url or file to load from', required: false, type: String
299
+ opt :run_once, 'Evaluate and quit', required: false, default: false
300
+ opt :node_name, 'Remote Node to grab facts from', required: false, type: String
301
+ opt :catalog, 'Import a catalog file to inspect', required: false, type: String
302
+ opt :quiet, 'Do not display banner', required: false, default: false
303
+ end
304
+ if !STDIN.tty? && !STDIN.closed?
305
+ options[:run_once] = true
306
+ options[:quiet] = true
269
307
  end
270
308
  options = opts.merge(options)
271
309
  options[:play] = options[:play].path if options[:play].respond_to?(:path)
@@ -273,14 +311,14 @@ or "help" to show the help screen.
273
311
  repl_obj.out_buffer.puts print_repl_desc unless options[:quiet]
274
312
  if options[:play]
275
313
  repl_obj.handle_input("play #{options[:play]}")
276
- elsif ARGF.filename != "-"
277
- # when the user supplied a file name without using the args (stdin)
278
- path = File.expand_path(ARGF.filename)
279
- repl_obj.handle_input("play #{path}")
280
- elsif (ARGF.filename == "-") && (!STDIN.tty? && !STDIN.closed?)
314
+ elsif (ARGF.filename == '-') && (!STDIN.tty? && !STDIN.closed?)
281
315
  # when the user supplied a file content using stdin, aka. cat,pipe,echo or redirection
282
316
  input = ARGF.read
283
317
  repl_obj.handle_input(input)
318
+ elsif ARGF.filename != '-'
319
+ # when the user supplied a file name without using the args (stdin)
320
+ path = File.expand_path(ARGF.filename)
321
+ repl_obj.handle_input("play #{path}")
284
322
  end
285
323
  # helper code to make tests exit the loop
286
324
  repl_obj.read_loop unless options[:run_once]
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
3
  class CodeFile
@@ -10,18 +9,18 @@ class CodeFile
10
9
  # List of all supported languages.
11
10
  # @return [Hash]
12
11
  EXTENSIONS = {
13
- %w[.py] => :python,
14
- %w[.js] => :javascript,
15
- %w[.pp] => :puppet,
16
- %w[.css] => :css,
17
- %w[.xml] => :xml,
18
- %w[.php] => :php,
19
- %w[.html] => :html,
20
- %w[.diff] => :diff,
21
- %w[.java] => :java,
22
- %w[.json] => :json,
23
- %w[.c .h] => :c,
24
- %w[.rhtml] => :rhtml,
12
+ %w[.py] => :python,
13
+ %w[.js] => :javascript,
14
+ %w[.pp] => :puppet,
15
+ %w[.css] => :css,
16
+ %w[.xml] => :xml,
17
+ %w[.php] => :php,
18
+ %w[.html] => :html,
19
+ %w[.diff] => :diff,
20
+ %w[.java] => :java,
21
+ %w[.json] => :json,
22
+ %w[.c .h] => :c,
23
+ %w[.rhtml] => :rhtml,
25
24
  %w[.yaml .yml] => :yaml,
26
25
  %w[.cpp .hpp .cc .h cxx] => :cpp,
27
26
  %w[.rb .ru .irbrc .gemspec .pryrc] => :ruby
@@ -96,4 +95,4 @@ class CodeFile
96
95
  def from_load_path
97
96
  $LOAD_PATH.map { |path| File.expand_path(@filename, path) }
98
97
  end
99
- end
98
+ end
@@ -47,13 +47,15 @@ class DebuggerCode
47
47
 
48
48
  # @return [Integer]
49
49
  def find_start_index(lines)
50
- return start_line if start_line < 0
50
+ return start_line if start_line.negative?
51
+
51
52
  lines.index { |loc| loc.lineno >= start_line } || lines.length
52
53
  end
53
54
 
54
55
  # @return [Integer]
55
56
  def find_end_index(lines)
56
- return end_line if end_line < 0
57
+ return end_line if end_line.negative?
58
+
57
59
  (lines.index { |loc| loc.lineno > end_line } || 0) - 1
58
60
  end
59
61
 
@@ -66,4 +68,4 @@ class DebuggerCode
66
68
  @start_line = start_line.first
67
69
  end
68
70
  end
69
- end
71
+ end
@@ -76,4 +76,4 @@ class DebuggerCode
76
76
  tuple[0] = "#{' ' * distance}#{line}"
77
77
  end
78
78
  end
79
- end
79
+ end
@@ -164,6 +164,7 @@ class DebuggerCode
164
164
  # @return [Code]
165
165
  def grep(pattern)
166
166
  return self unless pattern
167
+
167
168
  pattern = Regexp.new(pattern)
168
169
 
169
170
  select do |loc|
@@ -238,6 +239,7 @@ class DebuggerCode
238
239
 
239
240
  def add_file_reference
240
241
  return "From inline code: \n" unless filename
242
+
241
243
  "From file: #{File.basename(filename)}\n"
242
244
  end
243
245
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'puppet-debugger/support/errors'
2
4
 
3
5
  module PuppetDebugger
@@ -18,7 +20,7 @@ module PuppetDebugger
18
20
  end
19
21
 
20
22
  # Ensure that duplicates have their @hooks object.
21
- def initialize_copy(orig)
23
+ def initialize_copy(_orig)
22
24
  hooks_dup = @hooks.dup
23
25
  @hooks.each do |k, v|
24
26
  hooks_dup[k] = v.dup
@@ -37,8 +39,9 @@ module PuppetDebugger
37
39
  # @return [PuppetDebugger::Hooks] The receiver.
38
40
  # @see {#merge}
39
41
  def merge!(other)
40
- @hooks.merge!(other.dup.hooks) do |key, array, other_array|
41
- temp_hash, output = {}, []
42
+ @hooks.merge!(other.dup.hooks) do |_key, array, other_array|
43
+ temp_hash = {}
44
+ output = []
42
45
 
43
46
  (array + other_array).reverse_each do |pair|
44
47
  temp_hash[pair.first] ||= output.unshift(pair)
@@ -57,7 +60,7 @@ module PuppetDebugger
57
60
  # @return [PuppetDebugger::Hooks] a new `PuppetDebugger::Hooks` instance containing a merge of the
58
61
  # contents of two `PuppetDebugger::Hooks` instances.
59
62
  def merge(other)
60
- self.dup.tap do |v|
63
+ dup.tap do |v|
61
64
  v.merge!(other)
62
65
  end
63
66
  end
@@ -68,7 +71,7 @@ module PuppetDebugger
68
71
  # @param [#call] callable The callable.
69
72
  # @yield The block to use as the callable (if no `callable` provided).
70
73
  # @return [PuppetDebugger::Hooks] The receiver.
71
- def add_hook(event_name, hook_name, callable=nil, &block)
74
+ def add_hook(event_name, hook_name, callable = nil, &block)
72
75
  event_name = event_name.to_s
73
76
 
74
77
  # do not allow duplicates, but allow multiple `nil` hooks
@@ -77,12 +80,10 @@ module PuppetDebugger
77
80
  raise ArgumentError, "Hook with name '#{hook_name}' already defined!"
78
81
  end
79
82
 
80
- if !block && !callable
81
- raise ArgumentError, "Must provide a block or callable."
82
- end
83
+ raise ArgumentError, 'Must provide a block or callable.' if !block && !callable
83
84
 
84
85
  # ensure we only have one anonymous hook
85
- @hooks[event_name].delete_if { |h, k| h.nil? } if hook_name.nil?
86
+ @hooks[event_name].delete_if { |h, _k| h.nil? } if hook_name.nil?
86
87
 
87
88
  if block
88
89
  @hooks[event_name] << [hook_name, block]
@@ -98,7 +99,7 @@ module PuppetDebugger
98
99
  # @param [Array] args The arguments to pass to each hook function.
99
100
  # @return [Object] The return value of the last executed hook.
100
101
  def exec_hook(event_name, *args, &block)
101
- @hooks[event_name.to_s].map do |hook_name, callable|
102
+ @hooks[event_name.to_s].map do |_hook_name, callable|
102
103
  begin
103
104
  callable.call(*args, &block)
104
105
  rescue PuppetDebugger::Exception::Error, ::RuntimeError => e
@@ -118,10 +119,10 @@ module PuppetDebugger
118
119
  # @param [Symbol] hook_name The name of the hook
119
120
  # @return [#call] a specific hook for a given event.
120
121
  def get_hook(event_name, hook_name)
121
- hook = @hooks[event_name.to_s].find do |current_hook_name, callable|
122
+ hook = @hooks[event_name.to_s].find do |current_hook_name, _callable|
122
123
  current_hook_name == hook_name
123
124
  end
124
- hook.last if hook
125
+ hook&.last
125
126
  end
126
127
 
127
128
  # @param [Symbol] event_name The name of the event.
@@ -167,8 +168,6 @@ module PuppetDebugger
167
168
 
168
169
  protected
169
170
 
170
- def hooks
171
- @hooks
172
- end
171
+ attr_reader :hooks
173
172
  end
174
- end
173
+ end