toys-core 0.23.0 → 0.24.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a09f479bfecbde001cec1076fdce57080117cbdeecfc2738879445a682b7363f
4
- data.tar.gz: 277635722c80c2691759147cf7fc4b928755f0349a54fd970327c46bae443170
3
+ metadata.gz: fcfc1b86a084e30ed82bd6712d7c4e3d1c0e4754eb4b090181a00a1d0809810a
4
+ data.tar.gz: 8c8b9ec8d4186ff53e6a3d5a967db37c274bc5caa57da108207af6d5138f1458
5
5
  SHA512:
6
- metadata.gz: 6cfaa55d28079f651f9eab9d8a693af1386ddc6d08e58553ab457c4c669265902da5bba6e0f336faa8113bf0a92b2fbbe2bde4b49480118fe1d63b00a38ba791
7
- data.tar.gz: f8b6b6efcc6c978d1a1ce7cece9040eb5475eb7baa58c6b1527ba2dc5bb780c8401f30917e62fcc43999224ecd755b136d03d05d79c03fdc26622efc306e02d3
6
+ metadata.gz: 71071ccc6322724bac6c56d8ef7889588008a0b29a5119488815f1bc1073556392d0c0697c4762cdd118a93dc1cb605f38a94c81673dcbf7a8c0f756a6063cb6
7
+ data.tar.gz: 27b5e9b5b252e5db056ec9a7bb2bcba68fa8d8b1c8dc20ecdbf166ca1aae905d0a68c262bb9c3d3b3f69675c097c9b0f6612494bd61b445115d525d1aa167e6f
data/.yardopts CHANGED
@@ -1,7 +1,6 @@
1
1
  --no-private
2
2
  --title=Toys Core
3
3
  --markup=markdown
4
- --markup-provider redcarpet
5
4
  --main=README.md
6
5
  ./lib/toys/**/*.rb
7
6
  ./lib/toys-core.rb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Release History
2
2
 
3
+ ### v0.24.0 / 2026-09-11
4
+
5
+ Feature updates:
6
+
7
+ * `SourceSpec::Gem` now includes optional `on_missing:` and `default_confirm:` fields to control how missing gems are handled.
8
+ * The `load_gem` directive now takes optional `on_missing:` and `default_confirm:` arguments to control how missing gems are handled.
9
+ * Passing options when activating a gem using the `:gems` mixin no longer clobbers options passed when instantiating the mixin.
10
+
11
+ Removed some old deprecated items. (All technically breaking changes)
12
+
13
+ * Removed deprecated `Toys::CORE_VERSION`. Use `Toys::Core::VERSION` instead.
14
+ * Removed deprecated `alias_tool` directive. Pass `delegate_relative:` to the `tool` directive instead.
15
+ * Removed deprecated `suppress_confirm:` argument to the `Gems` utility. Use `on_missing:` instead.
16
+
3
17
  ### v0.23.0 / 2026-09-09
4
18
 
5
19
  This is a major release, with several new features, a number of fixes, and a significant refactor of the tool loading and execution layers, including several breaking interface changes. It is a release candidate for the upcoming version 1.0.
data/lib/toys/core.rb CHANGED
@@ -9,13 +9,6 @@ module Toys
9
9
  # Current version of Toys core.
10
10
  # @return [String]
11
11
  #
12
- VERSION = "0.23.0"
12
+ VERSION = "0.24.0"
13
13
  end
14
-
15
- ##
16
- # Deprecated
17
- #
18
- # @private
19
- #
20
- CORE_VERSION = Core::VERSION
21
14
  end
data/lib/toys/dsl/tool.rb CHANGED
@@ -329,39 +329,6 @@ module Toys
329
329
  self
330
330
  end
331
331
 
332
- ##
333
- # Create an alias, representing an "alternate name" for a tool.
334
- #
335
- # Note: This is functionally equivalent to creating a tool with the
336
- # `:delegate_relative` option. As such, `alias_tool` is considered
337
- # deprecated.
338
- #
339
- # ### Example
340
- #
341
- # This example defines a tool and an alias pointing to it. Both the tool
342
- # name `test` and the alias `t` will then refer to the same tool.
343
- #
344
- # tool "test" do
345
- # def run
346
- # puts "Running tests..."
347
- # end
348
- # end
349
- # alias_tool "t", "test"
350
- # # Note: the following is preferred over alias_tool:
351
- # # tool "t", delegate_relative: "test"
352
- #
353
- # @param word [String] The name of the alias
354
- # @param target [String,Array<String>] Relative path to the target of the
355
- # alias. This path may be given as an array of strings, or a single
356
- # string possibly delimited by path separators.
357
- # @return [self]
358
- # @deprecated Use {#tool} and pass `:delegate_relative` instead
359
- #
360
- def alias_tool(word, target)
361
- tool(word, delegate_relative: target)
362
- self
363
- end
364
-
365
332
  ##
366
333
  # Causes the current tool to delegate to another tool, specified by the
367
334
  # full tool name. When run, it simply invokes the target tool with the
@@ -508,6 +475,18 @@ module Toys
508
475
  # Context directory paths should generally be absolute. Relative
509
476
  # paths will be converted to absolute, using the current working
510
477
  # directory at the time of loading.
478
+ # @param on_missing [:confirm,:error,:install] What to do if the
479
+ # requested gem is not installed. Possible values:
480
+ #
481
+ # * `:confirm` - prompt the user on whether to install
482
+ # * `:error` - raise an exception
483
+ # * `:install` - just install the gem
484
+ #
485
+ # Defaults to the setting in the {Toys::Utils::Gems} utility used to
486
+ # activate the gem (usually `:confirm`).
487
+ # @param default_confirm [boolean] The default confirmation result, if
488
+ # `on_missing` is set to `:confirm`. Defaults to the setting in the
489
+ # {Toys::Utils::Gems} utility used to activate the gem (usually true).
511
490
  # @param as [String] Load into the given tool/namespace, relative to the
512
491
  # current namespace. If omitted, tools will be loaded into the
513
492
  # current namespace.
@@ -519,6 +498,8 @@ module Toys
519
498
  path: nil,
520
499
  toys_dir: nil,
521
500
  context_directory: nil,
501
+ on_missing: nil,
502
+ default_confirm: nil,
522
503
  as: nil)
523
504
  version = versions + Array(version)
524
505
  if as
@@ -527,7 +508,9 @@ module Toys
527
508
  version: version,
528
509
  path: path,
529
510
  toys_dir: toys_dir,
530
- context_directory: context_directory)
511
+ context_directory: context_directory,
512
+ on_missing: on_missing,
513
+ default_confirm: default_confirm)
531
514
  end
532
515
  return self
533
516
  end
@@ -535,7 +518,9 @@ module Toys
535
518
  version: version,
536
519
  path: path,
537
520
  toys_dir: toys_dir,
538
- context_directory: context_directory)
521
+ context_directory: context_directory,
522
+ on_missing: on_missing,
523
+ default_confirm: default_confirm)
539
524
  DSL::Internal.current_load_state(self).load_source(spec)
540
525
  self
541
526
  end
@@ -345,6 +345,8 @@ module Toys
345
345
  end
346
346
 
347
347
  def resolve_gem_spec(spec, parent, priority, gems_util)
348
+ gems_util ||= default_gems_util
349
+ gems_util = gems_util.with(on_missing: spec.on_missing, default_confirm: spec.default_confirm)
348
350
  gem_version, gem_path, source_path =
349
351
  resolve_gem_info(gems_util, spec.name, spec.version, spec.path, spec.toys_dir)
350
352
  source_path, type = check_path(source_path, false)
@@ -486,7 +488,7 @@ module Toys
486
488
  def resolve_gem_info(gems_util, gem_name, gem_versions, gem_path, gem_toys_dir)
487
489
  require "toys/utils/gems"
488
490
  begin
489
- (gems_util || default_gems_util).activate(gem_name, *gem_versions)
491
+ gems_util.activate(gem_name, *gem_versions)
490
492
  rescue ::Toys::Utils::Gems::ActivationFailedError => e
491
493
  raise ToolSourceError, e.message
492
494
  end
@@ -105,11 +105,25 @@ module Toys
105
105
  # @param source_name [String,nil] The source name that will be shown in
106
106
  # documentation for tools loaded from this source. If omitted, a
107
107
  # default is generated at resolution time.
108
+ # @param on_missing [:confirm,:error,:install] What to do if the
109
+ # requested gem is not installed. Possible values:
110
+ #
111
+ # * `:confirm` - prompt the user on whether to install
112
+ # * `:error` - raise an exception
113
+ # * `:install` - just install the gem
114
+ #
115
+ # Defaults to the setting in the {Toys::Utils::Gems} utility used to
116
+ # activate the gem (usually `:confirm`).
117
+ # @param default_confirm [boolean] The default confirmation result, if
118
+ # `on_missing` is set to `:confirm`. Defaults to the setting in the
119
+ # {Toys::Utils::Gems} utility used to activate the gem (usually true).
120
+ #
108
121
  # @return [Toys::SourceSpec::Gem]
109
122
  # @raise [ArgumentError] if an argument is not a legal value.
110
123
  #
111
- def gem(name, version: nil, path: nil, toys_dir: nil, context_directory: nil, source_name: nil)
112
- Gem.new(name, version, path, toys_dir, context_directory, source_name)
124
+ def gem(name, version: nil, path: nil, toys_dir: nil, context_directory: nil, source_name: nil,
125
+ on_missing: nil, default_confirm: nil)
126
+ Gem.new(name, version, path, toys_dir, context_directory, source_name, on_missing, default_confirm)
113
127
  end
114
128
 
115
129
  ##
@@ -249,6 +263,16 @@ module Toys
249
263
  def check_optional_string(value, name)
250
264
  value.nil? ? nil : check_string(value, name)
251
265
  end
266
+
267
+ ##
268
+ # Returns the given value if it is equal to one of the given valid values,
269
+ # otherwise raise. The name is used only to describe the offending field
270
+ # in the error message.
271
+ #
272
+ def check_one_of(value, name, valid_values)
273
+ return value if valid_values.include?(value)
274
+ raise ::ArgumentError, "Illegal #{name} value: #{value.inspect}"
275
+ end
252
276
  end
253
277
 
254
278
  ##
@@ -385,11 +409,13 @@ module Toys
385
409
  #
386
410
  # @private
387
411
  #
388
- def initialize(name, version, path, toys_dir, context_directory, source_name)
412
+ def initialize(name, version, path, toys_dir, context_directory, source_name, on_missing, default_confirm)
389
413
  @name = check_string(name, "name")
390
414
  @version = Array(version).map { |v| check_string(v, "version requirement") }.freeze
391
415
  @path = check_optional_string(path, "path")
392
416
  @toys_dir = check_optional_string(toys_dir, "toys_dir")
417
+ @on_missing = check_one_of(on_missing, "on_missing", [nil, :error, :confirm, :install])
418
+ @default_confirm = check_one_of(default_confirm, "default_confirm", [nil, true, false])
393
419
  super(context_directory, source_name)
394
420
  end
395
421
 
@@ -423,13 +449,31 @@ module Toys
423
449
  #
424
450
  attr_reader :toys_dir
425
451
 
452
+ ##
453
+ # What to do if the gem is not installed.
454
+ #
455
+ # @return [nil] to use the default behavior for the Gems util
456
+ # @return [:error] if an error should be raised
457
+ # @return [:confirm] if a confirmation prompt should be presented
458
+ # @return [:install] if the gem should be installed without confirmation
459
+ #
460
+ attr_reader :on_missing
461
+
462
+ ##
463
+ # The default response for a confirmation prompt
464
+ #
465
+ # @return [nil] to use the default behavior for the Gems util
466
+ # @return [boolean] to provide an override
467
+ #
468
+ attr_reader :default_confirm
469
+
426
470
  protected
427
471
 
428
472
  ##
429
473
  # @private
430
474
  #
431
475
  def equality_fields
432
- super + [@name, @version, @path, @toys_dir]
476
+ super + [@name, @version, @path, @toys_dir, @on_missing, @default_confirm]
433
477
  end
434
478
  end
435
479
 
@@ -80,8 +80,7 @@ module Toys
80
80
  # @raise [ActivationFailedError] if activation or install failed
81
81
  #
82
82
  def gem(name, *requirements, **options)
83
- gems_util = options.empty? ? gems : Utils::Gems.new(**options)
84
- gems_util.activate(name, *requirements)
83
+ gems.with(**options).activate(name, *requirements)
85
84
  end
86
85
 
87
86
  ##
@@ -114,8 +113,7 @@ module Toys
114
113
  # @raise [ActivationFailedError] if activation or install failed
115
114
  #
116
115
  def gem(name, *requirements, **options)
117
- gems_util = options.empty? ? gems : Utils::Gems.new(**options)
118
- gems_util.activate(name, *requirements)
116
+ gems.with(**options).activate(name, *requirements)
119
117
  end
120
118
  end
121
119
 
@@ -160,7 +160,6 @@ module Toys
160
160
  # * `:install` - just install the gem
161
161
  #
162
162
  # The default is `:confirm`.
163
- #
164
163
  # @param on_conflict [:error,:warn,:ignore] What to do if bundler has
165
164
  # already been run with a different Gemfile. Possible values:
166
165
  #
@@ -169,40 +168,64 @@ module Toys
169
168
  # * `:warn` - print a warning and proceed without bundling again
170
169
  #
171
170
  # The default is `:error`.
172
- #
173
171
  # @param default_confirm [boolean] The default confirmation result, if
174
172
  # `on_missing` is set to `:confirm`. Defaults to true.
175
173
  # @param terminal [Toys::Utils::Terminal] Terminal to use (optional)
176
174
  # @param input [IO] Input IO (optional, defaults to STDIN)
177
175
  # @param output [IO] Output IO (optional, defaults to STDOUT)
178
- # @param suppress_confirm [boolean] Deprecated. Use `on_missing` instead.
179
176
  #
180
177
  def initialize(on_missing: nil,
181
178
  on_conflict: nil,
179
+ default_confirm: nil,
182
180
  terminal: nil,
183
181
  input: nil,
184
- output: nil,
185
- suppress_confirm: nil,
186
- default_confirm: nil)
182
+ output: nil)
187
183
  require "rubygems"
188
- unless suppress_confirm.nil?
189
- warn("The :suppress_confirm argument to Toys::Utils::Gems is deprecated. " \
190
- "Use :on_missing instead.")
184
+ unless [nil, :confirm, :install, :error].include?(on_missing)
185
+ raise ::ArgumentError, "Illegal value for on_missing: #{on_missing.inspect}"
191
186
  end
192
- default_confirm = true if default_confirm.nil?
193
- @default_confirm = default_confirm ? true : false
194
- @on_missing = on_missing ||
195
- if suppress_confirm
196
- @default_confirm ? :install : :error
197
- else
198
- :confirm
199
- end
187
+ unless [nil, :error, :warn, :ignore].include?(on_conflict)
188
+ raise ::ArgumentError, "Illegal value for on_conflict: #{on_conflict.inspect}"
189
+ end
190
+ unless [nil, true, false].include?(default_confirm)
191
+ raise ::ArgumentError, "Illegal value for default_confirm: #{default_confirm.inspect}"
192
+ end
193
+ @on_missing = on_missing || :confirm
200
194
  @on_conflict = on_conflict || :error
195
+ default_confirm = true if default_confirm.nil?
196
+ @default_confirm = default_confirm
197
+ # The terminal passed in is remembered separately from the one this
198
+ # object may later derive from the input and output, so that #with
199
+ # copies the former. Copying a derived terminal would silently defeat
200
+ # an input or output override.
201
+ @param_terminal = terminal
201
202
  @terminal = terminal
202
203
  @input = input || $stdin
203
204
  @output = output || $stdout
204
205
  end
205
206
 
207
+ ##
208
+ # Return a gem activator with the same settings as this one, except for
209
+ # the provided overrides. See the constructor for argument docs. If no
210
+ # non-nil overrides are provided, self is returned.
211
+ #
212
+ # @param overrides [Hash] Overrides. See the constructor for details.
213
+ # @return [Toys::Utils::Gems]
214
+ #
215
+ def with(**overrides)
216
+ overrides = overrides.compact
217
+ return self if overrides.empty?
218
+ current_settings = {
219
+ on_missing: @on_missing,
220
+ on_conflict: @on_conflict,
221
+ default_confirm: @default_confirm,
222
+ terminal: @param_terminal,
223
+ input: @input,
224
+ output: @output,
225
+ }
226
+ Gems.new(**current_settings, **overrides)
227
+ end
228
+
206
229
  ##
207
230
  # Activate the given gem. If it is not present, attempt to install it (or
208
231
  # inform the user to update the bundle).
@@ -262,7 +285,7 @@ module Toys
262
285
  raise GemfileNotFoundError, "Gemfile not found" unless gemfile_path
263
286
  gemfile_path = ::File.absolute_path(gemfile_path)
264
287
  Gems.synchronize do
265
- setup_bundle(gemfile_path, groups: Array(groups), retries: retries)
288
+ setup_bundle(gemfile_path, Array(groups), retries)
266
289
  end
267
290
  end
268
291
 
@@ -369,7 +392,7 @@ module Toys
369
392
 
370
393
  # ---- Private methods as part of bundle install and setup ----
371
394
 
372
- def setup_bundle(gemfile_path, groups: nil, retries: nil)
395
+ def setup_bundle(gemfile_path, groups, retries)
373
396
  configure_gemfile(gemfile_path) do
374
397
  activate_bundler
375
398
  check_gemfile_compatibility(gemfile_path)
@@ -391,7 +414,7 @@ module Toys
391
414
  rescue *bundler_exceptions
392
415
  ::Bundler.reset!
393
416
  restore_toys_libs
394
- install_result = install_bundle(modified_gemfile_path, retries: retries)
417
+ install_result = install_bundle(modified_gemfile_path, retries)
395
418
  attempt_setup_bundle(modified_gemfile_path, groups)
396
419
  result = install_result
397
420
  ensure
@@ -702,7 +725,7 @@ module Toys
702
725
  end
703
726
  end
704
727
 
705
- def install_bundle(gemfile_path, retries: nil)
728
+ def install_bundle(gemfile_path, retries)
706
729
  gemfile_dir = ::File.dirname(gemfile_path)
707
730
  unless permission_to_bundle?
708
731
  raise BundleNotInstalledError,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toys-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.0
4
+ version: 0.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
@@ -99,10 +99,10 @@ homepage: https://github.com/dazuma/toys
99
99
  licenses:
100
100
  - MIT
101
101
  metadata:
102
- changelog_uri: https://dazuma.github.io/toys/gems/toys-core/v0.23.0/file.CHANGELOG.html
103
- source_code_uri: https://github.com/dazuma/toys/tree/toys-core/v0.23.0/toys-core
102
+ changelog_uri: https://dazuma.github.io/toys/gems/toys-core/v0.24.0/file.CHANGELOG.html
103
+ source_code_uri: https://github.com/dazuma/toys/tree/toys-core/v0.24.0/toys-core
104
104
  bug_tracker_uri: https://github.com/dazuma/toys/issues
105
- documentation_uri: https://dazuma.github.io/toys/gems/toys-core/v0.23.0
105
+ documentation_uri: https://dazuma.github.io/toys/gems/toys-core/v0.24.0
106
106
  rdoc_options: []
107
107
  require_paths:
108
108
  - lib