toys-core 0.10.5 → 0.11.4

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: 3f0e62a1c71082677fd2c257f95adec476cd8c1f5d83a8f42854e48cfe52d1bf
4
- data.tar.gz: d5940e36d77ce386ce7be949b2e16af08454095300a5beb3ffafdf4f691abe26
3
+ metadata.gz: 387c4a7088a856603e671a0c6156982eaa5639a41d1168a7912892b6ca9ca822
4
+ data.tar.gz: f47e0683edea4d3fcfa848e0517299648c0d6a0564b7d9316405487ed2e6d4dd
5
5
  SHA512:
6
- metadata.gz: a59b68df5403e100330518056d0e8d9b8792f9e01e36792b445413300e40e2637a86847af9afe565084a55e3bf3b332f1eff15cacc42a56c95597c94a47bd27a
7
- data.tar.gz: a8d943e4ccb7a2b9f3278a0eabf4c33485fb09d2fce2440d3f3c3cdc605a30977a0d43da993018b6affb51933686f69e038b5bf1847df54e1cdfab981af77309
6
+ metadata.gz: f1a9e2501458d1c8cebeafc044a6fe9f4de131c687df533e73a8567aa81afef2a5ed02fbb769e0da9ed7f4632c2c4f9046efec21281a3bc8c8072437d4ecb844
7
+ data.tar.gz: f9c22a3b8d531825353d9eebc70735b3bdfddfc8f22ce55bc8bf62685bbbf9443fbb6d875b7671d70f8ee2ca1eb0990238d2b35b92289b5c1c3b7e392bae9537
@@ -1,31 +1,57 @@
1
1
  # Release History
2
2
 
3
- ### 0.10.5 / 2020-07-18
3
+ ### v0.11.4 / 2020-10-11
4
+
5
+ * FIXED: Doesn't modify bundler lockfiles when adding Toys to a bundle
6
+
7
+ ### v0.11.3 / 2020-09-13
8
+
9
+ * FIXED: The Exec library recognizes the argv0 option, and logs it appropriately
10
+
11
+ ### v0.11.2 / 2020-09-06
12
+
13
+ * FIXED: Fix a JRuby-specific race condition when capturing exec streams
14
+
15
+ ### v0.11.1 / 2020-08-24
16
+
17
+ * DOCS: Minor documentation tweaks.
18
+
19
+ ### v0.11.0 / 2020-08-21
20
+
21
+ * ADDED: The load path can be truncated using the `truncate_load_path!` directive.
22
+ * IMPROVED: Generated help for delegates now includes the information for the target tool, plus subtools of the delegate.
23
+ * IMPROVED: The `:bundler` mixin searches for `gems.rb` and `.gems.rb` in addition to `Gemfile`.
24
+ * IMPROVED: The `:budnler` mixin can load a specific Gemfile path.
25
+ * FIXED: The loader can now find data and lib directories at the root level of a Toys directory.
26
+ * FIXED: Exec::Result correctly reports processes that terminated due to signals.
27
+ * FIXED: Fixed a rare Exec capture failure that resulted from a race condition when closing streams.
28
+
29
+ ### v0.10.5 / 2020-07-18
4
30
 
5
31
  * IMPROVED: The bundler mixin silences bundler output during bundle setup.
6
32
  * 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.
7
- * IMPROVED: The bundler mixin utomatically updates the bundle if install fails (typically because a transitive dependency has been explicitly updated.)
33
+ * IMPROVED: The bundler mixin automatically updates the bundle if install fails (typically because a transitive dependency has been explicitly updated.)
8
34
  * FIXED: Some cases of transitive dependency handling by the bundler mixin.
9
35
  * FIXED: Fixed a crash when computing suggestions, when running with a bundle on Ruby 2.6 or earlier.
10
36
 
11
- ### 0.10.4 / 2020-07-11
37
+ ### v0.10.4 / 2020-07-11
12
38
 
13
39
  * IMPROVED: Bundler integration can now handle Toys itself being in the bundle, as long as the version requirements cover the running Toys version.
14
40
  * IMPROVED: Passing `static: true` to the `:bundler` mixin installs the bundle at definition rather than execution time.
15
41
 
16
- ### 0.10.3 / 2020-07-04
42
+ ### v0.10.3 / 2020-07-04
17
43
 
18
44
  * FIXED: The `exec_separate_tool` method in the `:exec` mixin no longer throws ENOEXEC on Windows.
19
45
 
20
- ### 0.10.2 / 2020-07-03
46
+ ### v0.10.2 / 2020-07-03
21
47
 
22
48
  * FIXED: The load path no longer loses the toys and toys-core directories after a bundle install.
23
49
 
24
- ### 0.10.1 / 2020-03-07
50
+ ### v0.10.1 / 2020-03-07
25
51
 
26
52
  * FIXED: Setting `:exit_on_nonzero_status` explicitly to false now works as expected.
27
53
 
28
- ### 0.10.0 / 2020-02-24
54
+ ### v0.10.0 / 2020-02-24
29
55
 
30
56
  Functional changes:
31
57
 
@@ -55,16 +81,16 @@ Internal interface changes:
55
81
  * 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.
56
82
  * CHANGED: `Toys::Loader` uses an internal monitor rather than including `MonitorMixin`.
57
83
 
58
- ### 0.9.4 / 2020-01-26
84
+ ### v0.9.4 / 2020-01-26
59
85
 
60
86
  * FIXED: Crash in the loader when a non-ruby file appears in a toys directory
61
87
 
62
- ### 0.9.3 / 2020-01-05
88
+ ### v0.9.3 / 2020-01-05
63
89
 
64
90
  * FIXED: `delegate_to` directive could crash if an overriding tool has already been defined.
65
91
  * FIXED: A Ruby 2.7 warning when reporting a Toys file syntax error.
66
92
 
67
- ### 0.9.2 / 2020-01-03
93
+ ### v0.9.2 / 2020-01-03
68
94
 
69
95
  * IMPROVED: Mixins can now take real keyword arguments, and will pass them on properly to `on_initialize` and `on_include` blocks.
70
96
  * 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.
@@ -72,11 +98,11 @@ Internal interface changes:
72
98
  * 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.
73
99
  * IMPROVED: There is now a class for middleware specs, making possible a nicer syntax for building a middleware stack.
74
100
 
75
- ### 0.9.1 / 2019-12-22
101
+ ### v0.9.1 / 2019-12-22
76
102
 
77
103
  * IMPROVED: `delegate_to` and `alias_tool` can take symbols as well as strings.
78
104
 
79
- ### 0.9.0 / 2019-12-02
105
+ ### v0.9.0 / 2019-12-02
80
106
 
81
107
  Functional changes:
82
108
 
@@ -99,12 +125,12 @@ Internal interface changes:
99
125
  * ADDED: `Toys::Tool#delegate_to` causes the tool to delegate to another tool.
100
126
  * ADDED: The `Toys::Context::Key::DELEGATED_FROM` key provides the delegating context, if any.
101
127
 
102
- ### 0.8.1 / 2019-11-19
128
+ ### v0.8.1 / 2019-11-19
103
129
 
104
130
  * FIXED: Listing subtools would crash if a broken alias was present.
105
131
  * DOCUMENTATION: Switched from redcarpet to kramdown, and tried to make some structural fixes.
106
132
 
107
- ### 0.8.0 / 2019-06-20
133
+ ### v0.8.0 / 2019-06-20
108
134
 
109
135
  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.
110
136
 
@@ -203,17 +229,17 @@ Changes to internal interfaces:
203
229
  * ADDED: Range acceptor (`Acceptor::Range`) which validates against a range.
204
230
  * ADDED: Class methods `Acceptor.create` and `Acceptor.lookup_well_known`.
205
231
 
206
- ### 0.7.0 / 2019-01-23
232
+ ### v0.7.0 / 2019-01-23
207
233
 
208
234
  * ADDED: Flag groups, which enforce policies around which flags are required.
209
235
  * CHANGED: Flags within a group are sorted in help screens.
210
236
  * CHANGED: Canonical flag within a flag definition is now the first rather than the last.
211
237
 
212
- ### 0.6.1 / 2019-01-07
238
+ ### v0.6.1 / 2019-01-07
213
239
 
214
240
  * FIXED: The presence of aliases caused subtool listing to crash.
215
241
 
216
- ### 0.6.0 / 2018-10-22
242
+ ### v0.6.0 / 2018-10-22
217
243
 
218
244
  * CHANGED: Replaced Toys::Definition::DataFinder with Toys::Definition::SourceInfo.
219
245
  * CHANGED: Removed Toys::Definition#find_data. Use Toys::Definition#source_info and call find_data.
@@ -222,7 +248,7 @@ Changes to internal interfaces:
222
248
  from subtool lists.
223
249
  * IMPROVED: Optionally omit non-runnable namespaces from recursive subtool lists.
224
250
 
225
- ### 0.5.0 / 2018-10-07
251
+ ### v0.5.0 / 2018-10-07
226
252
 
227
253
  * FIXED: Template instantiation was failing if the hosting tool was priority-masked.
228
254
  * ADDED: Several additional characters can optionally be used as tool path delimiters.
@@ -232,31 +258,31 @@ Changes to internal interfaces:
232
258
  * IMPROVED: The tool directive can now take an array as the tool name.
233
259
  * IMPROVED: The tool directive can now take an `if_defined` argument.
234
260
 
235
- ### 0.4.5 / 2018-08-05
261
+ ### v0.4.5 / 2018-08-05
236
262
 
237
263
  * CHANGED: Dropped preload file feature
238
264
 
239
- ### 0.4.4 / 2018-07-21
265
+ ### v0.4.4 / 2018-07-21
240
266
 
241
267
  * FIXED: Utils::Exec wasn't closing streams after copying.
242
268
  * IMPROVED: Utils::Exec::Controller can capture or redirect the remainder of a controlled stream.
243
269
  * ADDED: Terminal#ask
244
270
 
245
- ### 0.4.3 / 2018-07-13
271
+ ### v0.4.3 / 2018-07-13
246
272
 
247
273
  * IMPROVED: Utils::Exec methods can now spawn subprocesses in the background
248
274
  * IMPROVED: Utils::Exec capture methods can now yield a controller
249
275
 
250
- ### 0.4.2 / 2018-07-08
276
+ ### v0.4.2 / 2018-07-08
251
277
 
252
278
  * FIXED: Raise an error rather than cause unexpected behavior if a mixin is included twice.
253
279
  * IMPROVED: The `include?` method extended to support mixin names in a tool dsl.
254
280
 
255
- ### 0.4.1 / 2018-07-03
281
+ ### v0.4.1 / 2018-07-03
256
282
 
257
283
  * FIXED: Terminal#confirm uppercased "N" for the wrong default.
258
284
 
259
- ### 0.4.0 / 2018-07-03
285
+ ### v0.4.0 / 2018-07-03
260
286
 
261
287
  Now declaring this alpha quality. Backward-incompatible changes are still
262
288
  possible from this point, but I'll try to avoid them.
@@ -268,13 +294,13 @@ possible from this point, but I'll try to avoid them.
268
294
  * IMPROVED: Utils::Gems installation is now much faster.
269
295
  * FIXED: Utils::Gems didn't reset the specifications on Ruby 2.3.
270
296
 
271
- ### 0.3.11 / 2018-07-02
297
+ ### v0.3.11 / 2018-07-02
272
298
 
273
299
  * CHANGED: Require Ruby 2.3 or later
274
300
  * CHANGED: Renamed "set" directive to "static" to reduce confusion with Tool#set.
275
301
  * ADDED: Convenience methods for getting option values
276
302
 
277
- ### 0.3.10 / 2018-06-30
303
+ ### v0.3.10 / 2018-06-30
278
304
 
279
305
  * CHANGED: Dropped Tool#option. Use Tool#get instead.
280
306
  * CHANGED: "run" directive renamed to "to_run"
@@ -283,11 +309,11 @@ possible from this point, but I'll try to avoid them.
283
309
  * ADDED: Mixins can provide initializers
284
310
  * ADDED: Loader can load an inline block
285
311
 
286
- ### 0.3.9.1 / 2018-06-24
312
+ ### v0.3.9.1 / 2018-06-24
287
313
 
288
314
  * FIXED: Built-in flags were interfering with disable_argument_parsing
289
315
 
290
- ### 0.3.9 / 2018-06-24
316
+ ### v0.3.9 / 2018-06-24
291
317
 
292
318
  * CHANGED: Cli#add_search_path_hierarchy changed the behavior of the base/terminate param
293
319
  * CHANGED: Removed alias_as directive since it's incompatible with selective loading.
@@ -296,7 +322,7 @@ possible from this point, but I'll try to avoid them.
296
322
  * ADDED: Exec#exec_proc and Exec#exec_tool that supports all the stream redirects
297
323
  * IMPROVED: Acceptors can be looked up recursively in the same way as mixins and templates
298
324
 
299
- ### 0.3.8 / 2018-06-10
325
+ ### v0.3.8 / 2018-06-10
300
326
 
301
327
  * CHANGED: Renamed helpers to mixins.
302
328
  * CHANGED: ModuleLookup is now a customizable class and can have multiple sources.
@@ -306,11 +332,11 @@ possible from this point, but I'll try to avoid them.
306
332
  * IMPROVED: Exec raises an error if passed an unknown option.
307
333
  * IMPROVED: Exec now accepts nearly all the same stream specifications as Process#spawn.
308
334
 
309
- ### 0.3.7.1 / 2018-05-30
335
+ ### v0.3.7.1 / 2018-05-30
310
336
 
311
337
  * No changes.
312
338
 
313
- ### 0.3.7 / 2018-05-30
339
+ ### v0.3.7 / 2018-05-30
314
340
 
315
341
  * CHANGED: Execution runs in the same scope as the DSL, which lets us use normal methods instead of helper-blocks.
316
342
  * CHANGED: Renamed "script" to "run", and allow setting of runnable by defining a "run" method
@@ -323,7 +349,7 @@ possible from this point, but I'll try to avoid them.
323
349
  * ADDED: Helper modules scoped to the tool hierarchy
324
350
  * ADDED: Utility that installs and activates third-party gems.
325
351
 
326
- ### 0.3.6 / 2018-05-21
352
+ ### v0.3.6 / 2018-05-21
327
353
 
328
354
  * CHANGED: Renamed show_version middleware to show_root_version.
329
355
  * CHANGED: Reworked set_default_descriptions interface for more flexibility.
@@ -335,14 +361,14 @@ possible from this point, but I'll try to avoid them.
335
361
  * IMPROVED: Support custom acceptors.
336
362
  * IMPROVED: Highline helper automatically sets use_color based on the type of stdout.
337
363
 
338
- ### 0.3.5 / 2018-05-15
364
+ ### v0.3.5 / 2018-05-15
339
365
 
340
366
  * CHANGED: Exec logic now lives in a utils class.
341
367
  * CHANGED: Moved flag and arg blocks from Tool into the DSL.
342
368
  * CHANGED: Renamed `execute do` to `script do`, and Tool#executor to Tool#script.
343
369
  * IMPROVED: Help display can use `less` if available.
344
370
 
345
- ### 0.3.4 / 2018-05-14
371
+ ### v0.3.4 / 2018-05-14
346
372
 
347
373
  * CHANGED: Renamed switch to flag
348
374
  * CHANGED: Renamed Utils::Usage to Utils::HelpText
@@ -364,7 +390,7 @@ possible from this point, but I'll try to avoid them.
364
390
  * ADDED: Alias DSL methods `required`, `optional`, and `remaining`.
365
391
  * FIXED: Finish definitions for subtools since the desc may depend on it
366
392
 
367
- ### 0.3.3 / 2018-05-09
393
+ ### v0.3.3 / 2018-05-09
368
394
 
369
395
  * CHANGED: Renamed file_utils helper to fileutils.
370
396
  * CHANGED: Renamed `doc:` parameter to `docs:`.
@@ -377,7 +403,7 @@ possible from this point, but I'll try to avoid them.
377
403
  * IMPROVED: Usage can now customize the left column width and indent
378
404
  * IMPROVED: Newlines in documentation are properly indented
379
405
 
380
- ### 0.3.2 / 2018-05-07
406
+ ### v0.3.2 / 2018-05-07
381
407
 
382
408
  * CHANGED: Split core engine out into "toys-core" from the "toys" gem.
383
409
  * CHANGED: Renamed path types to "search" and "config" paths, and restricted the former to the CLI.
@@ -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
  #
@@ -9,7 +9,7 @@ module Toys
9
9
  # Current version of Toys core.
10
10
  # @return [String]
11
11
  #
12
- VERSION = "0.10.5"
12
+ VERSION = "0.11.4"
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