toys-core 0.10.3 → 0.11.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b02cdff2a475e8868e2b657c16ced39c83f8b729552408cc09a22060f783ca5
4
- data.tar.gz: 5a0d9db1a99cc425de54f12ea8b888ef8d91a15e2991fcbc782a1a1e0e85c137
3
+ metadata.gz: 37117af06be544465a07f95706310e3b8de1ad4dbc58f53e113b2595eed70e47
4
+ data.tar.gz: 6e27a716c74435ff2060838dbde56af35b4df93dcdc671051397755f478cc233
5
5
  SHA512:
6
- metadata.gz: c7547679c269c0b882a82e0704d8d664b9e75872e72ca9368b673118fc3d20948fe5ab1588fea0b0e2c1def7685e4e378ea537ec1b7809e60809fee25bc0baf4
7
- data.tar.gz: e6767c8ae11fd7bfbadbc0b4bb23f86ee055b5832a67577dd4d72109e7e0d9a015d7d7d92612893e292e6257d89014c86aba6fcbd769701196748822cb4b6869
6
+ metadata.gz: a9dc2dc2e8287fbdb1c7695ed9111360d7bfcfc17167c6b790b170843988acb198daa8d99050d910ee5ea41876b2bb6c2e22cbab9629e322c9e7687f90a34c99
7
+ data.tar.gz: '03283300b1140b477ae56276a066953eb4fc6c71aa2a14b2e0fbe66cc9934c3afbd30862349ee922d98c4e0b9e80e74e50ba180bddc939dec99ead630eb7ddf2'
@@ -1,18 +1,49 @@
1
1
  # Release History
2
2
 
3
- ### 0.10.3 / 2020-07-04
3
+ ### v0.11.2 / 2020-09-06
4
+
5
+ * FIXED: Fix a JRuby-specific race condition when capturing exec streams
6
+
7
+ ### v0.11.1 / 2020-08-24
8
+
9
+ * DOCS: Minor documentation tweaks.
10
+
11
+ ### v0.11.0 / 2020-08-21
12
+
13
+ * ADDED: The load path can be truncated using the `truncate_load_path!` directive.
14
+ * IMPROVED: Generated help for delegates now includes the information for the target tool, plus subtools of the delegate.
15
+ * IMPROVED: The `:bundler` mixin searches for `gems.rb` and `.gems.rb` in addition to `Gemfile`.
16
+ * IMPROVED: The `:budnler` mixin can load a specific Gemfile path.
17
+ * FIXED: The loader can now find data and lib directories at the root level of a Toys directory.
18
+ * FIXED: Exec::Result correctly reports processes that terminated due to signals.
19
+ * FIXED: Fixed a rare Exec capture failure that resulted from a race condition when closing streams.
20
+
21
+ ### v0.10.5 / 2020-07-18
22
+
23
+ * IMPROVED: The bundler mixin silences bundler output during bundle setup.
24
+ * IMPROVED: The bundler mixin allows toys and toys-core to be in the Gemfile. It checks their version requirements against the running Toys version, and either adds the corret version to the bundle or raises IncompatibleToysError.
25
+ * IMPROVED: The bundler mixin automatically updates the bundle if install fails (typically because a transitive dependency has been explicitly updated.)
26
+ * FIXED: Some cases of transitive dependency handling by the bundler mixin.
27
+ * FIXED: Fixed a crash when computing suggestions, when running with a bundle on Ruby 2.6 or earlier.
28
+
29
+ ### v0.10.4 / 2020-07-11
30
+
31
+ * IMPROVED: Bundler integration can now handle Toys itself being in the bundle, as long as the version requirements cover the running Toys version.
32
+ * IMPROVED: Passing `static: true` to the `:bundler` mixin installs the bundle at definition rather than execution time.
33
+
34
+ ### v0.10.3 / 2020-07-04
4
35
 
5
36
  * FIXED: The `exec_separate_tool` method in the `:exec` mixin no longer throws ENOEXEC on Windows.
6
37
 
7
- ### 0.10.2 / 2020-07-03
38
+ ### v0.10.2 / 2020-07-03
8
39
 
9
40
  * FIXED: The load path no longer loses the toys and toys-core directories after a bundle install.
10
41
 
11
- ### 0.10.1 / 2020-03-07
42
+ ### v0.10.1 / 2020-03-07
12
43
 
13
44
  * FIXED: Setting `:exit_on_nonzero_status` explicitly to false now works as expected.
14
45
 
15
- ### 0.10.0 / 2020-02-24
46
+ ### v0.10.0 / 2020-02-24
16
47
 
17
48
  Functional changes:
18
49
 
@@ -42,16 +73,16 @@ Internal interface changes:
42
73
  * CHANGED: `Toys::CLI.default_logger` removed and replaced with `Toys::CLI.default_logger_factory`. In general, global loggers for CLI are now discouraged because they are not thread-safe.
43
74
  * CHANGED: `Toys::Loader` uses an internal monitor rather than including `MonitorMixin`.
44
75
 
45
- ### 0.9.4 / 2020-01-26
76
+ ### v0.9.4 / 2020-01-26
46
77
 
47
78
  * FIXED: Crash in the loader when a non-ruby file appears in a toys directory
48
79
 
49
- ### 0.9.3 / 2020-01-05
80
+ ### v0.9.3 / 2020-01-05
50
81
 
51
82
  * FIXED: `delegate_to` directive could crash if an overriding tool has already been defined.
52
83
  * FIXED: A Ruby 2.7 warning when reporting a Toys file syntax error.
53
84
 
54
- ### 0.9.2 / 2020-01-03
85
+ ### v0.9.2 / 2020-01-03
55
86
 
56
87
  * IMPROVED: Mixins can now take real keyword arguments, and will pass them on properly to `on_initialize` and `on_include` blocks.
57
88
  * CHANGED: `Toys::Utils::Exec` and the `:exec` mixin methods now take real keyword arguments rather than an `opts` hash. This means you should use keywords (or the double-splat operator) to avoid a deprecation warning on Ruby 2.7.
@@ -59,11 +90,11 @@ Internal interface changes:
59
90
  * IMPROVED: `Toys::Loader` is now thread-safe. This means it is now possible for a single `Toys::CLI` to run multiple tools in different threads.
60
91
  * IMPROVED: There is now a class for middleware specs, making possible a nicer syntax for building a middleware stack.
61
92
 
62
- ### 0.9.1 / 2019-12-22
93
+ ### v0.9.1 / 2019-12-22
63
94
 
64
95
  * IMPROVED: `delegate_to` and `alias_tool` can take symbols as well as strings.
65
96
 
66
- ### 0.9.0 / 2019-12-02
97
+ ### v0.9.0 / 2019-12-02
67
98
 
68
99
  Functional changes:
69
100
 
@@ -86,12 +117,12 @@ Internal interface changes:
86
117
  * ADDED: `Toys::Tool#delegate_to` causes the tool to delegate to another tool.
87
118
  * ADDED: The `Toys::Context::Key::DELEGATED_FROM` key provides the delegating context, if any.
88
119
 
89
- ### 0.8.1 / 2019-11-19
120
+ ### v0.8.1 / 2019-11-19
90
121
 
91
122
  * FIXED: Listing subtools would crash if a broken alias was present.
92
123
  * DOCUMENTATION: Switched from redcarpet to kramdown, and tried to make some structural fixes.
93
124
 
94
- ### 0.8.0 / 2019-06-20
125
+ ### v0.8.0 / 2019-06-20
95
126
 
96
127
  This is a major update with significant new features and a bunch of fixes. It also includes a significant amount of internal reorganization and cleanup, some of which resulted in backward incompatible changes. Basic use should not be affected. All signifiant features planned for beta are now implemented.
97
128
 
@@ -190,17 +221,17 @@ Changes to internal interfaces:
190
221
  * ADDED: Range acceptor (`Acceptor::Range`) which validates against a range.
191
222
  * ADDED: Class methods `Acceptor.create` and `Acceptor.lookup_well_known`.
192
223
 
193
- ### 0.7.0 / 2019-01-23
224
+ ### v0.7.0 / 2019-01-23
194
225
 
195
226
  * ADDED: Flag groups, which enforce policies around which flags are required.
196
227
  * CHANGED: Flags within a group are sorted in help screens.
197
228
  * CHANGED: Canonical flag within a flag definition is now the first rather than the last.
198
229
 
199
- ### 0.6.1 / 2019-01-07
230
+ ### v0.6.1 / 2019-01-07
200
231
 
201
232
  * FIXED: The presence of aliases caused subtool listing to crash.
202
233
 
203
- ### 0.6.0 / 2018-10-22
234
+ ### v0.6.0 / 2018-10-22
204
235
 
205
236
  * CHANGED: Replaced Toys::Definition::DataFinder with Toys::Definition::SourceInfo.
206
237
  * CHANGED: Removed Toys::Definition#find_data. Use Toys::Definition#source_info and call find_data.
@@ -209,7 +240,7 @@ Changes to internal interfaces:
209
240
  from subtool lists.
210
241
  * IMPROVED: Optionally omit non-runnable namespaces from recursive subtool lists.
211
242
 
212
- ### 0.5.0 / 2018-10-07
243
+ ### v0.5.0 / 2018-10-07
213
244
 
214
245
  * FIXED: Template instantiation was failing if the hosting tool was priority-masked.
215
246
  * ADDED: Several additional characters can optionally be used as tool path delimiters.
@@ -219,31 +250,31 @@ Changes to internal interfaces:
219
250
  * IMPROVED: The tool directive can now take an array as the tool name.
220
251
  * IMPROVED: The tool directive can now take an `if_defined` argument.
221
252
 
222
- ### 0.4.5 / 2018-08-05
253
+ ### v0.4.5 / 2018-08-05
223
254
 
224
255
  * CHANGED: Dropped preload file feature
225
256
 
226
- ### 0.4.4 / 2018-07-21
257
+ ### v0.4.4 / 2018-07-21
227
258
 
228
259
  * FIXED: Utils::Exec wasn't closing streams after copying.
229
260
  * IMPROVED: Utils::Exec::Controller can capture or redirect the remainder of a controlled stream.
230
261
  * ADDED: Terminal#ask
231
262
 
232
- ### 0.4.3 / 2018-07-13
263
+ ### v0.4.3 / 2018-07-13
233
264
 
234
265
  * IMPROVED: Utils::Exec methods can now spawn subprocesses in the background
235
266
  * IMPROVED: Utils::Exec capture methods can now yield a controller
236
267
 
237
- ### 0.4.2 / 2018-07-08
268
+ ### v0.4.2 / 2018-07-08
238
269
 
239
270
  * FIXED: Raise an error rather than cause unexpected behavior if a mixin is included twice.
240
271
  * IMPROVED: The `include?` method extended to support mixin names in a tool dsl.
241
272
 
242
- ### 0.4.1 / 2018-07-03
273
+ ### v0.4.1 / 2018-07-03
243
274
 
244
275
  * FIXED: Terminal#confirm uppercased "N" for the wrong default.
245
276
 
246
- ### 0.4.0 / 2018-07-03
277
+ ### v0.4.0 / 2018-07-03
247
278
 
248
279
  Now declaring this alpha quality. Backward-incompatible changes are still
249
280
  possible from this point, but I'll try to avoid them.
@@ -255,13 +286,13 @@ possible from this point, but I'll try to avoid them.
255
286
  * IMPROVED: Utils::Gems installation is now much faster.
256
287
  * FIXED: Utils::Gems didn't reset the specifications on Ruby 2.3.
257
288
 
258
- ### 0.3.11 / 2018-07-02
289
+ ### v0.3.11 / 2018-07-02
259
290
 
260
291
  * CHANGED: Require Ruby 2.3 or later
261
292
  * CHANGED: Renamed "set" directive to "static" to reduce confusion with Tool#set.
262
293
  * ADDED: Convenience methods for getting option values
263
294
 
264
- ### 0.3.10 / 2018-06-30
295
+ ### v0.3.10 / 2018-06-30
265
296
 
266
297
  * CHANGED: Dropped Tool#option. Use Tool#get instead.
267
298
  * CHANGED: "run" directive renamed to "to_run"
@@ -270,11 +301,11 @@ possible from this point, but I'll try to avoid them.
270
301
  * ADDED: Mixins can provide initializers
271
302
  * ADDED: Loader can load an inline block
272
303
 
273
- ### 0.3.9.1 / 2018-06-24
304
+ ### v0.3.9.1 / 2018-06-24
274
305
 
275
306
  * FIXED: Built-in flags were interfering with disable_argument_parsing
276
307
 
277
- ### 0.3.9 / 2018-06-24
308
+ ### v0.3.9 / 2018-06-24
278
309
 
279
310
  * CHANGED: Cli#add_search_path_hierarchy changed the behavior of the base/terminate param
280
311
  * CHANGED: Removed alias_as directive since it's incompatible with selective loading.
@@ -283,7 +314,7 @@ possible from this point, but I'll try to avoid them.
283
314
  * ADDED: Exec#exec_proc and Exec#exec_tool that supports all the stream redirects
284
315
  * IMPROVED: Acceptors can be looked up recursively in the same way as mixins and templates
285
316
 
286
- ### 0.3.8 / 2018-06-10
317
+ ### v0.3.8 / 2018-06-10
287
318
 
288
319
  * CHANGED: Renamed helpers to mixins.
289
320
  * CHANGED: ModuleLookup is now a customizable class and can have multiple sources.
@@ -293,11 +324,11 @@ possible from this point, but I'll try to avoid them.
293
324
  * IMPROVED: Exec raises an error if passed an unknown option.
294
325
  * IMPROVED: Exec now accepts nearly all the same stream specifications as Process#spawn.
295
326
 
296
- ### 0.3.7.1 / 2018-05-30
327
+ ### v0.3.7.1 / 2018-05-30
297
328
 
298
329
  * No changes.
299
330
 
300
- ### 0.3.7 / 2018-05-30
331
+ ### v0.3.7 / 2018-05-30
301
332
 
302
333
  * CHANGED: Execution runs in the same scope as the DSL, which lets us use normal methods instead of helper-blocks.
303
334
  * CHANGED: Renamed "script" to "run", and allow setting of runnable by defining a "run" method
@@ -310,7 +341,7 @@ possible from this point, but I'll try to avoid them.
310
341
  * ADDED: Helper modules scoped to the tool hierarchy
311
342
  * ADDED: Utility that installs and activates third-party gems.
312
343
 
313
- ### 0.3.6 / 2018-05-21
344
+ ### v0.3.6 / 2018-05-21
314
345
 
315
346
  * CHANGED: Renamed show_version middleware to show_root_version.
316
347
  * CHANGED: Reworked set_default_descriptions interface for more flexibility.
@@ -322,14 +353,14 @@ possible from this point, but I'll try to avoid them.
322
353
  * IMPROVED: Support custom acceptors.
323
354
  * IMPROVED: Highline helper automatically sets use_color based on the type of stdout.
324
355
 
325
- ### 0.3.5 / 2018-05-15
356
+ ### v0.3.5 / 2018-05-15
326
357
 
327
358
  * CHANGED: Exec logic now lives in a utils class.
328
359
  * CHANGED: Moved flag and arg blocks from Tool into the DSL.
329
360
  * CHANGED: Renamed `execute do` to `script do`, and Tool#executor to Tool#script.
330
361
  * IMPROVED: Help display can use `less` if available.
331
362
 
332
- ### 0.3.4 / 2018-05-14
363
+ ### v0.3.4 / 2018-05-14
333
364
 
334
365
  * CHANGED: Renamed switch to flag
335
366
  * CHANGED: Renamed Utils::Usage to Utils::HelpText
@@ -351,7 +382,7 @@ possible from this point, but I'll try to avoid them.
351
382
  * ADDED: Alias DSL methods `required`, `optional`, and `remaining`.
352
383
  * FIXED: Finish definitions for subtools since the desc may depend on it
353
384
 
354
- ### 0.3.3 / 2018-05-09
385
+ ### v0.3.3 / 2018-05-09
355
386
 
356
387
  * CHANGED: Renamed file_utils helper to fileutils.
357
388
  * CHANGED: Renamed `doc:` parameter to `docs:`.
@@ -364,7 +395,7 @@ possible from this point, but I'll try to avoid them.
364
395
  * IMPROVED: Usage can now customize the left column width and indent
365
396
  * IMPROVED: Newlines in documentation are properly indented
366
397
 
367
- ### 0.3.2 / 2018-05-07
398
+ ### v0.3.2 / 2018-05-07
368
399
 
369
400
  * CHANGED: Split core engine out into "toys-core" from the "toys" gem.
370
401
  * CHANGED: Renamed path types to "search" and "config" paths, and restricted the former to the CLI.
data/README.md CHANGED
@@ -258,7 +258,7 @@ itself. However, the `toys-core` gem is a dependency, and your users will need
258
258
  to have it installed. You could alleviate this by wrapping your executable in a
259
259
  gem that can declare `toys-core` as a dependency explicitly.
260
260
 
261
- The [examples directory](https://github.com/dazuma/toys/tree/master/toys-core/examples)
261
+ The [examples directory](https://github.com/dazuma/toys/tree/main/toys-core/examples)
262
262
  includes a few simple examples that you can use as a starting point.
263
263
 
264
264
  To experiment with the examples, clone the Toys repo from GitHub:
@@ -272,7 +272,7 @@ Navigate to the simple-gem example:
272
272
 
273
273
  This example wraps the simple "greet" executable that we
274
274
  [covered earlier](#Add_some_functionality) in a gem. You can see the
275
- [executable file](https://github.com/dazuma/toys/tree/master/toys-core/examples/simple-gem/bin/toys-core-simple-example)
275
+ [executable file](https://github.com/dazuma/toys/tree/main/toys-core/examples/simple-gem/bin/toys-core-simple-example)
276
276
  in the bin directory.
277
277
 
278
278
  Try it out by building and installing the gem. From the `examples/simple-gem`
@@ -297,16 +297,16 @@ break it up into multiple files. The multi-file gem example demonstrates this.
297
297
  $ cd ../multi-file-gem
298
298
 
299
299
  This executable's implementation resides in its
300
- [lib directory](https://github.com/dazuma/toys/tree/master/toys-core/examples/multi-file-gem/lib),
300
+ [lib directory](https://github.com/dazuma/toys/tree/main/toys-core/examples/multi-file-gem/lib),
301
301
  a technique that may be familiar to writers of command line executables. More
302
302
  interestingly, the tools themselves are no longer defined in a block passed to
303
303
  the CLI object, but have been moved into a separate
304
- ["tools" directory](https://github.com/dazuma/toys/tree/master/toys-core/examples/multi-file-gem/tools).
304
+ ["tools" directory](https://github.com/dazuma/toys/tree/main/toys-core/examples/multi-file-gem/tools).
305
305
  This directory has the same structure and supports the same features that are
306
306
  available when writing complex sets of tools in a `.toys` directory. You then
307
307
  configure the CLI object to look in this directory for its tools definitions,
308
308
  as you can see in
309
- [the code](https://github.com/dazuma/toys/tree/master/toys-core/examples/multi-file-gem/lib/toys-core-multi-gem-example.rb).
309
+ [the code](https://github.com/dazuma/toys/tree/main/toys-core/examples/multi-file-gem/lib/toys-core-multi-gem-example.rb).
310
310
 
311
311
  Try it out now. From the `examples/multi-file-gem` directory, run:
312
312
 
@@ -1,4 +1,6 @@
1
+ <!--
1
2
  # @title Toys-Core User Guide
3
+ -->
2
4
 
3
5
  # Toys-Core User Guide
4
6
 
@@ -498,7 +498,7 @@ module Toys
498
498
  # well-known acceptor.
499
499
  #
500
500
  # @param spec [Object] See the description for recognized values.
501
- # @param options [Hash] Additional options to pass to the completion.
501
+ # @param options [Hash] Additional options to pass to the acceptor.
502
502
  # @param block [Proc] See the description for recognized forms.
503
503
  # @return [Toys::Acceptor::Base,Proc]
504
504
  #
@@ -33,7 +33,11 @@ module Toys
33
33
  require "did_you_mean"
34
34
  rescue ::LoadError
35
35
  require "rubygems"
36
- require "did_you_mean" rescue nil # rubocop:disable Style/RescueModifier
36
+ begin
37
+ require "did_you_mean"
38
+ rescue ::LoadError
39
+ # Oh well, it's not available
40
+ end
37
41
  end
38
42
  @supports_suggestions = defined?(::DidYouMean::SpellChecker)
39
43
  end
@@ -9,7 +9,7 @@ module Toys
9
9
  # Current version of Toys core.
10
10
  # @return [String]
11
11
  #
12
- VERSION = "0.10.3"
12
+ VERSION = "0.11.2"
13
13
  end
14
14
 
15
15
  ## @private deprecated
@@ -75,8 +75,8 @@ module Toys
75
75
  # string (e.g. `"foo"`) is taken as the value. Otherwise, the
76
76
  # following argument is taken as the value (e.g. for `--abc foo`, the
77
77
  # value is set to `"foo"`.) The following argument is treated as the
78
- # value even if it looks like a flag (e.g. `--abc --abc` causes the
79
- # string `"--abc"` to be taken as the value.)
78
+ # value even if it looks like a flag (e.g. `--abc --def` causes the
79
+ # string `"--def"` to be taken as the value.)
80
80
  # * `--abc[=VAL]` : A long flag that takes an optional value. If this
81
81
  # argument appears with a value attached (e.g. `--abc=foo`), the
82
82
  # attached string (e.g. `"foo"`) is taken as the value. Otherwise,
@@ -79,8 +79,8 @@ module Toys
79
79
  # string (e.g. `"foo"`) is taken as the value. Otherwise, the
80
80
  # following argument is taken as the value (e.g. for `--abc foo`, the
81
81
  # value is set to `"foo"`.) The following argument is treated as the
82
- # value even if it looks like a flag (e.g. `--abc --abc` causes the
83
- # string `"--abc"` to be taken as the value.)
82
+ # value even if it looks like a flag (e.g. `--abc --def` causes the
83
+ # string `"--def"` to be taken as the value.)
84
84
  # * `--abc[=VAL]` : A long flag that takes an optional value. If this
85
85
  # argument appears with a value attached (e.g. `--abc=foo`), the
86
86
  # attached string (e.g. `"foo"`) is taken as the value. Otherwise,
@@ -814,8 +814,8 @@ module Toys
814
814
  # string (e.g. `"foo"`) is taken as the value. Otherwise, the
815
815
  # following argument is taken as the value (e.g. for `--abc foo`, the
816
816
  # value is set to `"foo"`.) The following argument is treated as the
817
- # value even if it looks like a flag (e.g. `--abc --abc` causes the
818
- # string `"--abc"` to be taken as the value.)
817
+ # value even if it looks like a flag (e.g. `--abc --def` causes the
818
+ # string `"--def"` to be taken as the value.)
819
819
  # * `--abc[=VAL]` : A long flag that takes an optional value. If this
820
820
  # argument appears with a value attached (e.g. `--abc=foo`), the
821
821
  # attached string (e.g. `"foo"`) is taken as the value. Otherwise,
@@ -884,7 +884,8 @@ module Toys
884
884
  # @param flags [String...] The flags in OptionParser format.
885
885
  # @param accept [Object] An acceptor that validates and/or converts the
886
886
  # value. You may provide either the name of an acceptor you have
887
- # defined, or one of the default acceptors provided by OptionParser.
887
+ # defined, one of the default acceptors provided by OptionParser, or
888
+ # any other specification recognized by {Toys::Acceptor.create}.
888
889
  # Optional. If not specified, accepts any value as a string.
889
890
  # @param default [Object] The default value. This is the value that will
890
891
  # be set in the context if this flag is not provided on the command
@@ -979,7 +980,8 @@ module Toys
979
980
  # the execution context.
980
981
  # @param accept [Object] An acceptor that validates and/or converts the
981
982
  # value. You may provide either the name of an acceptor you have
982
- # defined, or one of the default acceptors provided by OptionParser.
983
+ # defined, one of the default acceptors provided by OptionParser, or
984
+ # any other specification recognized by {Toys::Acceptor.create}.
983
985
  # Optional. If not specified, accepts any value as a string.
984
986
  # @param complete [Object] A specifier for shell tab completion for
985
987
  # values of this arg. This is the empty completion by default. To
@@ -1050,7 +1052,8 @@ module Toys
1050
1052
  # line. Defaults to `nil`.
1051
1053
  # @param accept [Object] An acceptor that validates and/or converts the
1052
1054
  # value. You may provide either the name of an acceptor you have
1053
- # defined, or one of the default acceptors provided by OptionParser.
1055
+ # defined, one of the default acceptors provided by OptionParser, or
1056
+ # any other specification recognized by {Toys::Acceptor.create}.
1054
1057
  # Optional. If not specified, accepts any value as a string.
1055
1058
  # @param complete [Object] A specifier for shell tab completion for
1056
1059
  # values of this arg. This is the empty completion by default. To
@@ -1121,7 +1124,8 @@ module Toys
1121
1124
  # command line. Defaults to the empty array `[]`.
1122
1125
  # @param accept [Object] An acceptor that validates and/or converts the
1123
1126
  # value. You may provide either the name of an acceptor you have
1124
- # defined, or one of the default acceptors provided by OptionParser.
1127
+ # defined, one of the default acceptors provided by OptionParser, or
1128
+ # any other specification recognized by {Toys::Acceptor.create}.
1125
1129
  # Optional. If not specified, accepts any value as a string.
1126
1130
  # @param complete [Object] A specifier for shell tab completion for
1127
1131
  # values of this arg. This is the empty completion by default. To
@@ -1619,6 +1623,23 @@ module Toys
1619
1623
  self
1620
1624
  end
1621
1625
 
1626
+ ##
1627
+ # Remove lower-priority sources from the load path. This prevents lower-
1628
+ # priority sources (such as Toys files from parent or global directories)
1629
+ # from executing or defining tools.
1630
+ #
1631
+ # This works only if no such sources have already loaded yet.
1632
+ #
1633
+ # @raise [Toys::ToolDefinitionError] if any lower-priority tools have
1634
+ # already been loaded.
1635
+ #
1636
+ def truncate_load_path!
1637
+ unless @__loader.stop_loading_at_priority(@__priority)
1638
+ raise ToolDefinitionError,
1639
+ "Cannot truncate load path because tools have already been loaded"
1640
+ end
1641
+ end
1642
+
1622
1643
  ##
1623
1644
  # Determines whether the current Toys version satisfies the given
1624
1645
  # requirements.
@@ -8,6 +8,9 @@ module Toys
8
8
  # appropriate tool given a set of command line arguments.
9
9
  #
10
10
  class Loader
11
+ # @private
12
+ BASE_PRIORITY = -999_999
13
+
11
14
  ##
12
15
  # Create a Loader
13
16
  #
@@ -69,9 +72,11 @@ module Toys
69
72
  @worklist = []
70
73
  @tool_data = {}
71
74
  @max_priority = @min_priority = 0
75
+ @stop_priority = BASE_PRIORITY
76
+ @min_loaded_priority = 999_999
72
77
  @middleware_stack = Middleware.stack(middleware_stack)
73
78
  @delimiter_handler = DelimiterHandler.new(extra_delimiters)
74
- get_tool([], -999_999)
79
+ get_tool([], BASE_PRIORITY)
75
80
  end
76
81
 
77
82
  ##
@@ -89,7 +94,7 @@ module Toys
89
94
  raise "Cannot add a path after tool loading has started" if @loading_started
90
95
  priority = high_priority ? (@max_priority += 1) : (@min_priority -= 1)
91
96
  paths.each do |path|
92
- source = SourceInfo.create_path_root(path)
97
+ source = SourceInfo.create_path_root(path, @data_dir_name, @lib_dir_name)
93
98
  @worklist << [source, [], priority]
94
99
  end
95
100
  end
@@ -114,7 +119,7 @@ module Toys
114
119
  @mutex.synchronize do
115
120
  raise "Cannot add a block after tool loading has started" if @loading_started
116
121
  priority = high_priority ? (@max_priority += 1) : (@min_priority -= 1)
117
- source = SourceInfo.create_proc_root(block, name)
122
+ source = SourceInfo.create_proc_root(block, name, @data_dir_name, @lib_dir_name)
118
123
  @worklist << [source, [], priority]
119
124
  end
120
125
  self
@@ -178,15 +183,15 @@ module Toys
178
183
  load_for_prefix(words)
179
184
  found_tools = []
180
185
  len = words.length
181
- tool_data_snapshot.each do |n, td|
182
- next if n.empty?
186
+ all_cur_definitions.each do |tool|
187
+ name = tool.full_name
188
+ next if name.empty?
183
189
  if recursive
184
- next if n.length <= len || n.slice(0, len) != words
190
+ next if name.length <= len || name.slice(0, len) != words
185
191
  else
186
- next unless n.slice(0..-2) == words
192
+ next unless name.slice(0..-2) == words
187
193
  end
188
- tool = td.cur_definition
189
- found_tools << tool unless tool.nil?
194
+ found_tools << tool
190
195
  end
191
196
  sort_tools_by_name(found_tools)
192
197
  include_hidden ? found_tools : filter_hidden_subtools(found_tools)
@@ -202,8 +207,9 @@ module Toys
202
207
  def has_subtools?(words) # rubocop:disable Naming/PredicateName
203
208
  load_for_prefix(words)
204
209
  len = words.length
205
- tool_data_snapshot.each do |n, td|
206
- if !n.empty? && n.length > len && n.slice(0, len) == words && !td.empty?
210
+ all_cur_definitions.each do |tool|
211
+ name = tool.full_name
212
+ if !name.empty? && name.length > len && name.slice(0, len) == words
207
213
  return true
208
214
  end
209
215
  end
@@ -267,6 +273,20 @@ module Toys
267
273
  Tool.new(self, parent, words, priority, middleware_stack, @middleware_lookup)
268
274
  end
269
275
 
276
+ ##
277
+ # Stop search at the given priority. Returns true if successful.
278
+ # Called only from the DSL.
279
+ #
280
+ # @private
281
+ #
282
+ def stop_loading_at_priority(priority)
283
+ @mutex.synchronize do
284
+ return false if priority > @min_loaded_priority || priority < @stop_priority
285
+ @stop_priority = priority
286
+ true
287
+ end
288
+ end
289
+
270
290
  ##
271
291
  # Loads the subtree under the given prefix.
272
292
  #
@@ -278,6 +298,7 @@ module Toys
278
298
  cur_worklist = @worklist
279
299
  @worklist = []
280
300
  cur_worklist.each do |source, words, priority|
301
+ next if priority < @stop_priority
281
302
  remaining_words = calc_remaining_words(prefix, words)
282
303
  if source.source_proc
283
304
  load_proc(source, words, remaining_words, priority)
@@ -349,8 +370,15 @@ module Toys
349
370
 
350
371
  private
351
372
 
352
- def tool_data_snapshot
353
- @mutex.synchronize { @tool_data.dup }
373
+ def all_cur_definitions
374
+ result = []
375
+ @mutex.synchronize do
376
+ @tool_data.map do |_name, td|
377
+ tool = td.cur_definition
378
+ result << tool unless tool.nil?
379
+ end
380
+ end
381
+ result
354
382
  end
355
383
 
356
384
  def get_tool_data(words)
@@ -364,14 +392,16 @@ module Toys
364
392
  def finish_definitions_in_tree(words)
365
393
  load_for_prefix(words)
366
394
  len = words.length
367
- tool_data_snapshot.each do |n, td|
368
- next if n.length < len || n.slice(0, len) != words
369
- td.cur_definition&.finish_definition(self)
395
+ all_cur_definitions.each do |tool|
396
+ name = tool.full_name
397
+ next if name.length < len || name.slice(0, len) != words
398
+ tool.finish_definition(self)
370
399
  end
371
400
  end
372
401
 
373
402
  def load_proc(source, words, remaining_words, priority)
374
403
  if remaining_words
404
+ update_min_loaded_priority(priority)
375
405
  tool_class = get_tool(words, priority).tool_class
376
406
  DSL::Tool.prepare(tool_class, remaining_words, source) do
377
407
  ContextualError.capture("Error while loading Toys config!") do
@@ -393,6 +423,7 @@ module Toys
393
423
 
394
424
  def load_relevant_path(source, words, remaining_words, priority)
395
425
  if source.source_type == :file
426
+ update_min_loaded_priority(priority)
396
427
  tool_class = get_tool(words, priority).tool_class
397
428
  InputFile.evaluate(tool_class, remaining_words, source)
398
429
  else
@@ -406,7 +437,7 @@ module Toys
406
437
 
407
438
  def load_index_in(source, words, remaining_words, priority)
408
439
  return unless @index_file_name
409
- index_source = source.relative_child(@index_file_name, @data_dir_name, @lib_dir_name)
440
+ index_source = source.relative_child(@index_file_name)
410
441
  load_relevant_path(index_source, words, remaining_words, priority) if index_source
411
442
  end
412
443
 
@@ -414,7 +445,7 @@ module Toys
414
445
  return if child.start_with?(".") || child == @index_file_name ||
415
446
  child == @preload_file_name || child == @preload_dir_name ||
416
447
  child == @data_dir_name || child == @lib_dir_name
417
- child_source = source.relative_child(child, @data_dir_name, @lib_dir_name)
448
+ child_source = source.relative_child(child)
418
449
  return unless child_source
419
450
  child_word = ::File.basename(child, ".rb")
420
451
  next_words = words + [child_word]
@@ -422,6 +453,10 @@ module Toys
422
453
  load_validated_path(child_source, next_words, next_remaining, priority)
423
454
  end
424
455
 
456
+ def update_min_loaded_priority(priority)
457
+ @min_loaded_priority = priority if @min_loaded_priority > priority
458
+ end
459
+
425
460
  def do_preload(path)
426
461
  if @preload_file_name
427
462
  preload_file = ::File.join(path, @preload_file_name)
@@ -483,37 +518,42 @@ module Toys
483
518
  # @private
484
519
  #
485
520
  class ToolData
486
- ## @private
521
+ # @private
487
522
  def initialize(words)
488
523
  @words = words
489
524
  @definitions = {}
490
525
  @top_priority = @active_priority = nil
526
+ @mutex = ::Monitor.new
491
527
  end
492
528
 
493
- ## @private
529
+ # @private
494
530
  def cur_definition
495
- active_definition || top_definition
531
+ @mutex.synchronize { active_definition || top_definition }
496
532
  end
497
533
 
498
- ## @private
534
+ # @private
499
535
  def empty?
500
536
  @definitions.empty?
501
537
  end
502
538
 
503
- ## @private
539
+ # @private
504
540
  def get_tool(priority, loader)
505
- if @top_priority.nil? || @top_priority < priority
506
- @top_priority = priority
541
+ @mutex.synchronize do
542
+ if @top_priority.nil? || @top_priority < priority
543
+ @top_priority = priority
544
+ end
545
+ @definitions[priority] ||= loader.build_tool(@words, priority)
507
546
  end
508
- @definitions[priority] ||= loader.build_tool(@words, priority)
509
547
  end
510
548
 
511
- ## @private
549
+ # @private
512
550
  def activate_tool(priority, loader)
513
- return active_definition if @active_priority == priority
514
- return nil if @active_priority && @active_priority > priority
515
- @active_priority = priority
516
- get_tool(priority, loader)
551
+ @mutex.synchronize do
552
+ return active_definition if @active_priority == priority
553
+ return nil if @active_priority && @active_priority > priority
554
+ @active_priority = priority
555
+ get_tool(priority, loader)
556
+ end
517
557
  end
518
558
 
519
559
  private