toys-core 0.12.2 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +4 -1
  5. data/docs/guide.md +1 -1
  6. data/lib/toys/acceptor.rb +10 -1
  7. data/lib/toys/arg_parser.rb +1 -0
  8. data/lib/toys/cli.rb +127 -107
  9. data/lib/toys/compat.rb +54 -3
  10. data/lib/toys/completion.rb +15 -5
  11. data/lib/toys/context.rb +22 -20
  12. data/lib/toys/core.rb +6 -2
  13. data/lib/toys/dsl/base.rb +2 -0
  14. data/lib/toys/dsl/flag.rb +23 -17
  15. data/lib/toys/dsl/flag_group.rb +11 -7
  16. data/lib/toys/dsl/positional_arg.rb +23 -13
  17. data/lib/toys/dsl/tool.rb +10 -6
  18. data/lib/toys/errors.rb +63 -8
  19. data/lib/toys/flag.rb +660 -651
  20. data/lib/toys/flag_group.rb +19 -6
  21. data/lib/toys/input_file.rb +9 -3
  22. data/lib/toys/loader.rb +129 -115
  23. data/lib/toys/middleware.rb +45 -21
  24. data/lib/toys/mixin.rb +8 -6
  25. data/lib/toys/positional_arg.rb +18 -17
  26. data/lib/toys/settings.rb +81 -67
  27. data/lib/toys/source_info.rb +33 -24
  28. data/lib/toys/standard_middleware/add_verbosity_flags.rb +2 -0
  29. data/lib/toys/standard_middleware/apply_config.rb +1 -0
  30. data/lib/toys/standard_middleware/handle_usage_errors.rb +1 -0
  31. data/lib/toys/standard_middleware/set_default_descriptions.rb +1 -0
  32. data/lib/toys/standard_middleware/show_help.rb +2 -0
  33. data/lib/toys/standard_middleware/show_root_version.rb +2 -0
  34. data/lib/toys/standard_mixins/bundler.rb +22 -14
  35. data/lib/toys/standard_mixins/exec.rb +31 -20
  36. data/lib/toys/standard_mixins/fileutils.rb +3 -1
  37. data/lib/toys/standard_mixins/gems.rb +21 -17
  38. data/lib/toys/standard_mixins/git_cache.rb +5 -7
  39. data/lib/toys/standard_mixins/highline.rb +8 -8
  40. data/lib/toys/standard_mixins/terminal.rb +5 -5
  41. data/lib/toys/standard_mixins/xdg.rb +5 -5
  42. data/lib/toys/template.rb +9 -7
  43. data/lib/toys/tool_definition.rb +209 -202
  44. data/lib/toys/utils/completion_engine.rb +7 -2
  45. data/lib/toys/utils/exec.rb +158 -127
  46. data/lib/toys/utils/gems.rb +81 -57
  47. data/lib/toys/utils/git_cache.rb +674 -45
  48. data/lib/toys/utils/help_text.rb +27 -3
  49. data/lib/toys/utils/terminal.rb +10 -2
  50. data/lib/toys/wrappable_string.rb +9 -2
  51. data/lib/toys-core.rb +14 -5
  52. metadata +4 -4
data/lib/toys/settings.rb CHANGED
@@ -299,26 +299,16 @@ module Toys
299
299
  # grandchild_settings.str # => "value_from_root"
300
300
  #
301
301
  class Settings
302
+ # A special value indicating a type check failure.
303
+ ILLEGAL_VALUE = ::Object.new.freeze
304
+
305
+ # A special type specification indicating infer from the default value.
306
+ DEFAULT_TYPE = ::Object.new.freeze
307
+
302
308
  ##
303
309
  # Error raised when a value does not match the type constraint.
304
310
  #
305
311
  class FieldError < ::StandardError
306
- # @private
307
- def initialize(value, settings_class, field_name, type_description)
308
- @value = value
309
- @settings_class = settings_class
310
- @field_name = field_name
311
- @type_description = type_description
312
- message = "unable to set #{settings_class}##{field_name}"
313
- message =
314
- if type_description
315
- "#{message}: value #{value.inspect} does not match type #{type_description}"
316
- else
317
- "#{message}: field does not exist"
318
- end
319
- super(message)
320
- end
321
-
322
312
  ##
323
313
  # The value that did not match
324
314
  # @return [Object]
@@ -342,13 +332,25 @@ module Toys
342
332
  # @return [String, nil]
343
333
  #
344
334
  attr_reader :type_description
345
- end
346
335
 
347
- # A special value indicating a type check failure.
348
- ILLEGAL_VALUE = ::Object.new.freeze
349
-
350
- # A special type specification indicating infer from the default value.
351
- DEFAULT_TYPE = ::Object.new.freeze
336
+ ##
337
+ # @private
338
+ #
339
+ def initialize(value, settings_class, field_name, type_description)
340
+ @value = value
341
+ @settings_class = settings_class
342
+ @field_name = field_name
343
+ @type_description = type_description
344
+ message = "unable to set #{settings_class}##{field_name}"
345
+ message =
346
+ if type_description
347
+ "#{message}: value #{value.inspect} does not match type #{type_description}"
348
+ else
349
+ "#{message}: field does not exist"
350
+ end
351
+ super(message)
352
+ end
353
+ end
352
354
 
353
355
  ##
354
356
  # A type object that checks values.
@@ -558,7 +560,9 @@ module Toys
558
560
  end
559
561
  end
560
562
 
563
+ ##
561
564
  # @private
565
+ #
562
566
  CONVERTERS = {
563
567
  ::Date => date_converter,
564
568
  ::DateTime => datetime_converter,
@@ -570,51 +574,6 @@ module Toys
570
574
  }.freeze
571
575
  end
572
576
 
573
- # @private
574
- SETTINGS_TYPE = Type.new("(settings object)") do |val|
575
- val.nil? || val.is_a?(Settings) ? val : ILLEGAL_VALUE
576
- end
577
-
578
- # @private
579
- class Field
580
- def initialize(container, name, type_spec, default_or_group_class)
581
- @container = container
582
- @name = name
583
- if type_spec == SETTINGS_TYPE
584
- @default = nil
585
- @group_class = default_or_group_class
586
- @type = type_spec
587
- else
588
- @group_class = nil
589
- if type_spec == DEFAULT_TYPE
590
- @default = default_or_group_class
591
- @type = Type.for_default_value(@default)
592
- else
593
- @type = Type.for_type_spec(type_spec)
594
- @default = validate(default_or_group_class)
595
- end
596
- end
597
- end
598
-
599
- attr_reader :container
600
- attr_reader :name
601
- attr_reader :type
602
- attr_reader :default
603
- attr_reader :group_class
604
-
605
- def group?
606
- !@group_class.nil?
607
- end
608
-
609
- def validate(value)
610
- validated_value = @type.call(value)
611
- if validated_value == ILLEGAL_VALUE
612
- raise FieldError.new(value, container, name, @type.description)
613
- end
614
- validated_value
615
- end
616
- end
617
-
618
577
  ##
619
578
  # Create a settings instance.
620
579
  #
@@ -716,6 +675,7 @@ module Toys
716
675
 
717
676
  ##
718
677
  # @private
678
+ #
719
679
  # Internal get field value, with fallback to parents.
720
680
  #
721
681
  def get!(field)
@@ -743,6 +703,7 @@ module Toys
743
703
 
744
704
  ##
745
705
  # @private
706
+ #
746
707
  # Internal set field value, with validation.
747
708
  #
748
709
  def set!(field, value)
@@ -754,6 +715,7 @@ module Toys
754
715
 
755
716
  ##
756
717
  # @private
718
+ #
757
719
  # Internal determine if the field is set locally.
758
720
  #
759
721
  def set?(field)
@@ -764,6 +726,7 @@ module Toys
764
726
 
765
727
  ##
766
728
  # @private
729
+ #
767
730
  # Internal unset field value.
768
731
  #
769
732
  def unset!(field)
@@ -772,6 +735,55 @@ module Toys
772
735
  end
773
736
  end
774
737
 
738
+ ##
739
+ # @private
740
+ #
741
+ SETTINGS_TYPE = Type.new("(settings object)") do |val|
742
+ val.nil? || val.is_a?(Settings) ? val : ILLEGAL_VALUE
743
+ end
744
+
745
+ ##
746
+ # @private
747
+ #
748
+ class Field
749
+ def initialize(container, name, type_spec, default_or_group_class)
750
+ @container = container
751
+ @name = name
752
+ if type_spec == SETTINGS_TYPE
753
+ @default = nil
754
+ @group_class = default_or_group_class
755
+ @type = type_spec
756
+ else
757
+ @group_class = nil
758
+ if type_spec == DEFAULT_TYPE
759
+ @default = default_or_group_class
760
+ @type = Type.for_default_value(@default)
761
+ else
762
+ @type = Type.for_type_spec(type_spec)
763
+ @default = validate(default_or_group_class)
764
+ end
765
+ end
766
+ end
767
+
768
+ attr_reader :container
769
+ attr_reader :name
770
+ attr_reader :type
771
+ attr_reader :default
772
+ attr_reader :group_class
773
+
774
+ def group?
775
+ !@group_class.nil?
776
+ end
777
+
778
+ def validate(value)
779
+ validated_value = @type.call(value)
780
+ if validated_value == ILLEGAL_VALUE
781
+ raise FieldError.new(value, container, name, @type.description)
782
+ end
783
+ validated_value
784
+ end
785
+ end
786
+
775
787
  class << self
776
788
  ##
777
789
  # Add an attribute field.
@@ -824,6 +836,7 @@ module Toys
824
836
 
825
837
  ##
826
838
  # @private
839
+ #
827
840
  # Returns the fields hash. This is shared between the settings class and
828
841
  # all its instances.
829
842
  #
@@ -833,6 +846,7 @@ module Toys
833
846
 
834
847
  ##
835
848
  # @private
849
+ #
836
850
  # When this base class is inherited, if its enclosing module is also a
837
851
  # Settings, add the new class as a group in the enclosing class.
838
852
  #
@@ -6,30 +6,6 @@ module Toys
6
6
  # or block that defined it.
7
7
  #
8
8
  class SourceInfo
9
- ##
10
- # Create a SourceInfo.
11
- # @private
12
- #
13
- def initialize(parent, priority, context_directory, source_type, source_path, source_proc,
14
- git_remote, git_path, git_commit, source_name, data_dir_name, lib_dir_name)
15
- @parent = parent
16
- @root = parent&.root || self
17
- @priority = priority
18
- @context_directory = context_directory
19
- @source_type = source_type
20
- @source = source_type == :proc ? source_proc : source_path
21
- @source_path = source_path
22
- @source_proc = source_proc
23
- @git_remote = git_remote
24
- @git_path = git_path
25
- @git_commit = git_commit
26
- @source_name = source_name
27
- @data_dir_name = data_dir_name
28
- @lib_dir_name = lib_dir_name
29
- @data_dir = find_special_dir(data_dir_name)
30
- @lib_dir = find_special_dir(lib_dir_name)
31
- end
32
-
33
9
  ##
34
10
  # The parent of this SourceInfo.
35
11
  #
@@ -161,8 +137,34 @@ module Toys
161
137
  self
162
138
  end
163
139
 
140
+ ##
141
+ # Create a SourceInfo.
142
+ #
143
+ # @private
144
+ #
145
+ def initialize(parent, priority, context_directory, source_type, source_path, source_proc,
146
+ git_remote, git_path, git_commit, source_name, data_dir_name, lib_dir_name)
147
+ @parent = parent
148
+ @root = parent&.root || self
149
+ @priority = priority
150
+ @context_directory = context_directory
151
+ @source_type = source_type
152
+ @source = source_type == :proc ? source_proc : source_path
153
+ @source_path = source_path
154
+ @source_proc = source_proc
155
+ @git_remote = git_remote
156
+ @git_path = git_path
157
+ @git_commit = git_commit
158
+ @source_name = source_name
159
+ @data_dir_name = data_dir_name
160
+ @lib_dir_name = lib_dir_name
161
+ @data_dir = find_special_dir(data_dir_name)
162
+ @lib_dir = find_special_dir(lib_dir_name)
163
+ end
164
+
164
165
  ##
165
166
  # Create a child SourceInfo relative to the parent path.
167
+ #
166
168
  # @private
167
169
  #
168
170
  def relative_child(filename, source_name: nil)
@@ -186,6 +188,7 @@ module Toys
186
188
 
187
189
  ##
188
190
  # Create a child SourceInfo with an absolute path.
191
+ #
189
192
  # @private
190
193
  #
191
194
  def absolute_child(child_path, source_name: nil)
@@ -197,6 +200,7 @@ module Toys
197
200
 
198
201
  ##
199
202
  # Create a child SourceInfo with a git source.
203
+ #
200
204
  # @private
201
205
  #
202
206
  def git_child(child_git_remote, child_git_path, child_git_commit, child_path,
@@ -211,6 +215,7 @@ module Toys
211
215
 
212
216
  ##
213
217
  # Create a proc child SourceInfo
218
+ #
214
219
  # @private
215
220
  #
216
221
  def proc_child(child_proc, source_name: nil)
@@ -222,6 +227,7 @@ module Toys
222
227
 
223
228
  ##
224
229
  # Create a root source info for a file path.
230
+ #
225
231
  # @private
226
232
  #
227
233
  def self.create_path_root(source_path, priority,
@@ -243,6 +249,7 @@ module Toys
243
249
 
244
250
  ##
245
251
  # Create a root source info for a cached git repo.
252
+ #
246
253
  # @private
247
254
  #
248
255
  def self.create_git_root(git_remote, git_path, git_commit, source_path, priority,
@@ -258,6 +265,7 @@ module Toys
258
265
 
259
266
  ##
260
267
  # Create a root source info for a proc.
268
+ #
261
269
  # @private
262
270
  #
263
271
  def self.create_proc_root(source_proc, priority,
@@ -272,6 +280,7 @@ module Toys
272
280
 
273
281
  ##
274
282
  # Check a path and determine the canonical path and type.
283
+ #
275
284
  # @private
276
285
  #
277
286
  def self.check_path(path, lenient)
@@ -48,6 +48,7 @@ module Toys
48
48
 
49
49
  ##
50
50
  # Configure the tool flags.
51
+ #
51
52
  # @private
52
53
  #
53
54
  def config(tool, _loader)
@@ -63,6 +64,7 @@ module Toys
63
64
 
64
65
  INCREMENT_HANDLER = ->(_val, cur) { cur.to_i + 1 }
65
66
  DECREMENT_HANDLER = ->(_val, cur) { cur.to_i - 1 }
67
+ private_constant :INCREMENT_HANDLER, :DECREMENT_HANDLER
66
68
 
67
69
  def add_verbose_flags(tool)
68
70
  verbose_flags = resolve_flags_spec(@verbose_flags, tool, DEFAULT_VERBOSE_FLAGS)
@@ -28,6 +28,7 @@ module Toys
28
28
 
29
29
  ##
30
30
  # Appends the configuration block.
31
+ #
31
32
  # @private
32
33
  #
33
34
  def config(tool, loader)
@@ -33,6 +33,7 @@ module Toys
33
33
 
34
34
  ##
35
35
  # Intercept and handle usage errors during execution.
36
+ #
36
37
  # @private
37
38
  #
38
39
  def run(context)
@@ -90,6 +90,7 @@ module Toys
90
90
 
91
91
  ##
92
92
  # Add default description text to tools.
93
+ #
93
94
  # @private
94
95
  #
95
96
  def config(tool, loader)
@@ -202,6 +202,7 @@ module Toys
202
202
 
203
203
  ##
204
204
  # Configure flags and default data.
205
+ #
205
206
  # @private
206
207
  #
207
208
  def config(tool, loader)
@@ -224,6 +225,7 @@ module Toys
224
225
 
225
226
  ##
226
227
  # Display help text if requested.
228
+ #
227
229
  # @private
228
230
  #
229
231
  def run(context)
@@ -46,6 +46,7 @@ module Toys
46
46
 
47
47
  ##
48
48
  # Adds the version flag if requested.
49
+ #
49
50
  # @private
50
51
  #
51
52
  def config(tool, _loader)
@@ -58,6 +59,7 @@ module Toys
58
59
 
59
60
  ##
60
61
  # This middleware displays the version.
62
+ #
61
63
  # @private
62
64
  #
63
65
  def run(context)
@@ -67,20 +67,6 @@ module Toys
67
67
  module Bundler
68
68
  include Mixin
69
69
 
70
- on_initialize do |static: false, **kwargs|
71
- unless static
72
- context_directory = self[::Toys::Context::Key::CONTEXT_DIRECTORY]
73
- source_info = self[::Toys::Context::Key::TOOL_SOURCE]
74
- ::Toys::StandardMixins::Bundler.setup_bundle(context_directory, source_info, **kwargs)
75
- end
76
- end
77
-
78
- on_include do |static: false, **kwargs|
79
- if static
80
- ::Toys::StandardMixins::Bundler.setup_bundle(context_directory, source_info, **kwargs)
81
- end
82
- end
83
-
84
70
  ##
85
71
  # Default search directories for Gemfiles.
86
72
  # @return [Array<String,Symbol>]
@@ -93,7 +79,9 @@ module Toys
93
79
  #
94
80
  DEFAULT_TOYS_GEMFILE_NAMES = [".gems.rb", "Gemfile"].freeze
95
81
 
82
+ ##
96
83
  # @private
84
+ #
97
85
  def self.setup_bundle(context_directory,
98
86
  source_info,
99
87
  gemfile_path: nil,
@@ -118,9 +106,27 @@ module Toys
118
106
  gems.bundle(groups: groups, gemfile_path: gemfile_path, retries: retries)
119
107
  end
120
108
 
109
+ on_initialize do |static: false, **kwargs|
110
+ unless static
111
+ context_directory = self[::Toys::Context::Key::CONTEXT_DIRECTORY]
112
+ source_info = self[::Toys::Context::Key::TOOL_SOURCE]
113
+ ::Toys::StandardMixins::Bundler.setup_bundle(context_directory, source_info, **kwargs)
114
+ end
115
+ end
116
+
117
+ on_include do |static: false, **kwargs|
118
+ if static
119
+ ::Toys::StandardMixins::Bundler.setup_bundle(context_directory, source_info, **kwargs)
120
+ end
121
+ end
122
+
123
+ ##
121
124
  # @private
125
+ #
122
126
  class GemfileFinder
127
+ ##
123
128
  # @private
129
+ #
124
130
  def initialize(context_directory, source_info, gemfile_names, toys_gemfile_names)
125
131
  @context_directory = context_directory
126
132
  @source_info = source_info
@@ -128,7 +134,9 @@ module Toys
128
134
  @toys_gemfile_names = toys_gemfile_names || DEFAULT_TOYS_GEMFILE_NAMES
129
135
  end
130
136
 
137
+ ##
131
138
  # @private
139
+ #
132
140
  def search(search_dir)
133
141
  case search_dir
134
142
  when ::Array
@@ -229,20 +229,6 @@ module Toys
229
229
  #
230
230
  KEY = ::Object.new.freeze
231
231
 
232
- on_initialize do |**opts|
233
- require "toys/utils/exec"
234
- context = self
235
- opts = Exec._setup_exec_opts(opts, context)
236
- context[KEY] = Utils::Exec.new(**opts) do |k|
237
- case k
238
- when :logger
239
- context[Context::Key::LOGGER]
240
- when :cli
241
- context[Context::Key::CLI]
242
- end
243
- end
244
- end
245
-
246
232
  ##
247
233
  # Set default configuration options.
248
234
  #
@@ -305,7 +291,7 @@ module Toys
305
291
  #
306
292
  # Execute a small script with warnings
307
293
  #
308
- # exec_ruby("-w", "-e", "(1..10).each { |i| puts i }")
294
+ # exec_ruby(["-w", "-e", "(1..10).each { |i| puts i }"])
309
295
  #
310
296
  # @param args [String,Array<String>] The arguments to ruby.
311
297
  # @param opts [keywords] The command options. See the section on
@@ -397,6 +383,7 @@ module Toys
397
383
  def exec_tool(cmd, **opts, &block)
398
384
  func = Exec._make_tool_caller(cmd)
399
385
  opts = Exec._setup_exec_opts(opts, self)
386
+ opts = {log_cmd: "exec tool: #{cmd.inspect}"}.merge(opts)
400
387
  self[KEY].exec_proc(func, **opts, &block)
401
388
  end
402
389
 
@@ -675,13 +662,17 @@ module Toys
675
662
  0
676
663
  end
677
664
 
678
- ## @private
665
+ ##
666
+ # @private
667
+ #
679
668
  def self._make_tool_caller(cmd)
680
669
  cmd = ::Shellwords.split(cmd) if cmd.is_a?(::String)
681
670
  proc { |config| ::Kernel.exit(config[:cli].run(*cmd)) }
682
671
  end
683
672
 
684
- ## @private
673
+ ##
674
+ # @private
675
+ #
685
676
  def self._setup_exec_opts(opts, context)
686
677
  count = 0
687
678
  result_callback = nil
@@ -704,7 +695,9 @@ module Toys
704
695
  opts
705
696
  end
706
697
 
707
- ## @private
698
+ ##
699
+ # @private
700
+ #
708
701
  def self._interpret_e(value, context)
709
702
  return nil unless value
710
703
  proc do |result|
@@ -718,7 +711,9 @@ module Toys
718
711
  end
719
712
  end
720
713
 
721
- ## @private
714
+ ##
715
+ # @private
716
+ #
722
717
  def self._interpret_result_callback(value, context)
723
718
  if value.is_a?(::Symbol)
724
719
  context.method(value)
@@ -731,7 +726,9 @@ module Toys
731
726
  end
732
727
  end
733
728
 
734
- ## @private
729
+ ##
730
+ # @private
731
+ #
735
732
  def self._setup_clean_process(cmd)
736
733
  raise ::ArgumentError, "Toys process is unknown" unless ::Toys.executable_path
737
734
  cmd = ::Shellwords.split(cmd) if cmd.is_a?(::String)
@@ -746,6 +743,20 @@ module Toys
746
743
  yield(cmd)
747
744
  end
748
745
  end
746
+
747
+ on_initialize do |**opts|
748
+ require "toys/utils/exec"
749
+ context = self
750
+ opts = Exec._setup_exec_opts(opts, context)
751
+ context[KEY] = Utils::Exec.new(**opts) do |k|
752
+ case k
753
+ when :logger
754
+ context[Context::Key::LOGGER]
755
+ when :cli
756
+ context[Context::Key::CLI]
757
+ end
758
+ end
759
+ end
749
760
  end
750
761
  end
751
762
  end
@@ -16,7 +16,9 @@ module Toys
16
16
  module Fileutils
17
17
  include Mixin
18
18
 
19
- ## @private
19
+ ##
20
+ # @private
21
+ #
20
22
  def self.included(mod)
21
23
  mod.include(::FileUtils)
22
24
  end
@@ -25,23 +25,6 @@ module Toys
25
25
  module Gems
26
26
  include Mixin
27
27
 
28
- on_include do |**opts|
29
- @__gems_opts = opts
30
-
31
- ## @private
32
- def self.gems
33
- require "toys/utils/gems"
34
- # rubocop:disable Naming/MemoizedInstanceVariableName
35
- @__gems ||= Utils::Gems.new(**@__gems_opts)
36
- # rubocop:enable Naming/MemoizedInstanceVariableName
37
- end
38
-
39
- ## @private
40
- def self.gem(name, *requirements)
41
- gems.activate(name, *requirements)
42
- end
43
- end
44
-
45
28
  ##
46
29
  # A tool-wide instance of {Toys::Utils::Gems}.
47
30
  # @return [Toys::Utils::Gems]
@@ -60,6 +43,27 @@ module Toys
60
43
  def gem(name, *requirements)
61
44
  self.class.gems.activate(name, *requirements)
62
45
  end
46
+
47
+ on_include do |**opts|
48
+ @__gems_opts = opts
49
+
50
+ ##
51
+ # @private
52
+ #
53
+ def self.gems
54
+ require "toys/utils/gems"
55
+ # rubocop:disable Naming/MemoizedInstanceVariableName
56
+ @__gems ||= Utils::Gems.new(**@__gems_opts)
57
+ # rubocop:enable Naming/MemoizedInstanceVariableName
58
+ end
59
+
60
+ ##
61
+ # @private
62
+ #
63
+ def self.gem(name, *requirements)
64
+ gems.activate(name, *requirements)
65
+ end
66
+ end
63
67
  end
64
68
  end
65
69
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "fileutils"
4
-
5
3
  module Toys
6
4
  module StandardMixins
7
5
  ##
@@ -30,11 +28,6 @@ module Toys
30
28
  #
31
29
  KEY = ::Object.new.freeze
32
30
 
33
- on_initialize do
34
- require "toys/utils/git_cache"
35
- self[KEY] = Utils::GitCache.new
36
- end
37
-
38
31
  ##
39
32
  # Access the builtin GitCache.
40
33
  #
@@ -43,6 +36,11 @@ module Toys
43
36
  def git_cache
44
37
  self[KEY]
45
38
  end
39
+
40
+ on_initialize do
41
+ require "toys/utils/git_cache"
42
+ self[KEY] = Utils::GitCache.new
43
+ end
46
44
  end
47
45
  end
48
46
  end