toys-core 0.11.0 → 0.11.5

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: 1cf20d64fb78cfa559000a8007d3f0567db38d1c66ea220daaf8a33f1275fcad
4
- data.tar.gz: da6b5f0f2e7d7bef30ded0a45b17014e0adc623583b7221f67b6b44fc9ca3805
3
+ metadata.gz: ae396604e3a0005b460ad94f95187b603f36e8d10d1147da2a78b069232f7963
4
+ data.tar.gz: 267209d6e7ab4575053219eee5fb1c6be47b9bd6ac6468b6da5c9abb9ed227c2
5
5
  SHA512:
6
- metadata.gz: e429973defa957eb444c1395c9d6c235052f7f365978d216e7fc4633ebbb7361242ce649845304cd96c47d5227e563d79021c41bd0d2529e9d9b4695edb09ae6
7
- data.tar.gz: 4cc2e28b0309130bd8c524a6ab3c17018e9160db4251225ad88aa082cf1ab1226eabda6d0e1ba8691d7ee2c107e8c6b4ea661265422d045a3a27692ce4b5745a
6
+ metadata.gz: 527f51e0e679f93786ecd671ff14386615e2014e0dbd4995fd4bb6e58040cb00b27d83d3721c412eb8cc83fdc82fe7dff63c97e0e3d8bca8f8b8d7b04a5d9f41
7
+ data.tar.gz: 07c617895710b6f5dd69c6fdb16613c2ed7474361a1cbd8617ae1d271eca647ffa457e77bec7e1b30915b1e01ad25173c74251f1728f261a5d5565ca29b80d68
data/CHANGELOG.md CHANGED
@@ -1,6 +1,28 @@
1
1
  # Release History
2
2
 
3
- ### 0.11.0 / 2020-08-21
3
+ ### v0.11.5 / 2021-03-28
4
+
5
+ * BREAKING CHANGE: The exit_on_nonzero_status option to exec now exits on signals and failures to spawn, in addition to error codes.
6
+ * ADDED: Support retries in the bundler integration.
7
+ * FIXED: Fix a bundler 2.2 integration issue that fails install in certain cases when an update is needed.
8
+
9
+ ### v0.11.4 / 2020-10-11
10
+
11
+ * FIXED: Doesn't modify bundler lockfiles when adding Toys to a bundle
12
+
13
+ ### v0.11.3 / 2020-09-13
14
+
15
+ * FIXED: The Exec library recognizes the argv0 option, and logs it appropriately
16
+
17
+ ### v0.11.2 / 2020-09-06
18
+
19
+ * FIXED: Fix a JRuby-specific race condition when capturing exec streams
20
+
21
+ ### v0.11.1 / 2020-08-24
22
+
23
+ * DOCS: Minor documentation tweaks.
24
+
25
+ ### v0.11.0 / 2020-08-21
4
26
 
5
27
  * ADDED: The load path can be truncated using the `truncate_load_path!` directive.
6
28
  * IMPROVED: Generated help for delegates now includes the information for the target tool, plus subtools of the delegate.
@@ -10,7 +32,7 @@
10
32
  * FIXED: Exec::Result correctly reports processes that terminated due to signals.
11
33
  * FIXED: Fixed a rare Exec capture failure that resulted from a race condition when closing streams.
12
34
 
13
- ### 0.10.5 / 2020-07-18
35
+ ### v0.10.5 / 2020-07-18
14
36
 
15
37
  * IMPROVED: The bundler mixin silences bundler output during bundle setup.
16
38
  * 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.
@@ -18,24 +40,24 @@
18
40
  * FIXED: Some cases of transitive dependency handling by the bundler mixin.
19
41
  * FIXED: Fixed a crash when computing suggestions, when running with a bundle on Ruby 2.6 or earlier.
20
42
 
21
- ### 0.10.4 / 2020-07-11
43
+ ### v0.10.4 / 2020-07-11
22
44
 
23
45
  * IMPROVED: Bundler integration can now handle Toys itself being in the bundle, as long as the version requirements cover the running Toys version.
24
46
  * IMPROVED: Passing `static: true` to the `:bundler` mixin installs the bundle at definition rather than execution time.
25
47
 
26
- ### 0.10.3 / 2020-07-04
48
+ ### v0.10.3 / 2020-07-04
27
49
 
28
50
  * FIXED: The `exec_separate_tool` method in the `:exec` mixin no longer throws ENOEXEC on Windows.
29
51
 
30
- ### 0.10.2 / 2020-07-03
52
+ ### v0.10.2 / 2020-07-03
31
53
 
32
54
  * FIXED: The load path no longer loses the toys and toys-core directories after a bundle install.
33
55
 
34
- ### 0.10.1 / 2020-03-07
56
+ ### v0.10.1 / 2020-03-07
35
57
 
36
58
  * FIXED: Setting `:exit_on_nonzero_status` explicitly to false now works as expected.
37
59
 
38
- ### 0.10.0 / 2020-02-24
60
+ ### v0.10.0 / 2020-02-24
39
61
 
40
62
  Functional changes:
41
63
 
@@ -65,16 +87,16 @@ Internal interface changes:
65
87
  * 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.
66
88
  * CHANGED: `Toys::Loader` uses an internal monitor rather than including `MonitorMixin`.
67
89
 
68
- ### 0.9.4 / 2020-01-26
90
+ ### v0.9.4 / 2020-01-26
69
91
 
70
92
  * FIXED: Crash in the loader when a non-ruby file appears in a toys directory
71
93
 
72
- ### 0.9.3 / 2020-01-05
94
+ ### v0.9.3 / 2020-01-05
73
95
 
74
96
  * FIXED: `delegate_to` directive could crash if an overriding tool has already been defined.
75
97
  * FIXED: A Ruby 2.7 warning when reporting a Toys file syntax error.
76
98
 
77
- ### 0.9.2 / 2020-01-03
99
+ ### v0.9.2 / 2020-01-03
78
100
 
79
101
  * IMPROVED: Mixins can now take real keyword arguments, and will pass them on properly to `on_initialize` and `on_include` blocks.
80
102
  * 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.
@@ -82,11 +104,11 @@ Internal interface changes:
82
104
  * 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.
83
105
  * IMPROVED: There is now a class for middleware specs, making possible a nicer syntax for building a middleware stack.
84
106
 
85
- ### 0.9.1 / 2019-12-22
107
+ ### v0.9.1 / 2019-12-22
86
108
 
87
109
  * IMPROVED: `delegate_to` and `alias_tool` can take symbols as well as strings.
88
110
 
89
- ### 0.9.0 / 2019-12-02
111
+ ### v0.9.0 / 2019-12-02
90
112
 
91
113
  Functional changes:
92
114
 
@@ -109,12 +131,12 @@ Internal interface changes:
109
131
  * ADDED: `Toys::Tool#delegate_to` causes the tool to delegate to another tool.
110
132
  * ADDED: The `Toys::Context::Key::DELEGATED_FROM` key provides the delegating context, if any.
111
133
 
112
- ### 0.8.1 / 2019-11-19
134
+ ### v0.8.1 / 2019-11-19
113
135
 
114
136
  * FIXED: Listing subtools would crash if a broken alias was present.
115
137
  * DOCUMENTATION: Switched from redcarpet to kramdown, and tried to make some structural fixes.
116
138
 
117
- ### 0.8.0 / 2019-06-20
139
+ ### v0.8.0 / 2019-06-20
118
140
 
119
141
  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.
120
142
 
@@ -213,17 +235,17 @@ Changes to internal interfaces:
213
235
  * ADDED: Range acceptor (`Acceptor::Range`) which validates against a range.
214
236
  * ADDED: Class methods `Acceptor.create` and `Acceptor.lookup_well_known`.
215
237
 
216
- ### 0.7.0 / 2019-01-23
238
+ ### v0.7.0 / 2019-01-23
217
239
 
218
240
  * ADDED: Flag groups, which enforce policies around which flags are required.
219
241
  * CHANGED: Flags within a group are sorted in help screens.
220
242
  * CHANGED: Canonical flag within a flag definition is now the first rather than the last.
221
243
 
222
- ### 0.6.1 / 2019-01-07
244
+ ### v0.6.1 / 2019-01-07
223
245
 
224
246
  * FIXED: The presence of aliases caused subtool listing to crash.
225
247
 
226
- ### 0.6.0 / 2018-10-22
248
+ ### v0.6.0 / 2018-10-22
227
249
 
228
250
  * CHANGED: Replaced Toys::Definition::DataFinder with Toys::Definition::SourceInfo.
229
251
  * CHANGED: Removed Toys::Definition#find_data. Use Toys::Definition#source_info and call find_data.
@@ -232,7 +254,7 @@ Changes to internal interfaces:
232
254
  from subtool lists.
233
255
  * IMPROVED: Optionally omit non-runnable namespaces from recursive subtool lists.
234
256
 
235
- ### 0.5.0 / 2018-10-07
257
+ ### v0.5.0 / 2018-10-07
236
258
 
237
259
  * FIXED: Template instantiation was failing if the hosting tool was priority-masked.
238
260
  * ADDED: Several additional characters can optionally be used as tool path delimiters.
@@ -242,31 +264,31 @@ Changes to internal interfaces:
242
264
  * IMPROVED: The tool directive can now take an array as the tool name.
243
265
  * IMPROVED: The tool directive can now take an `if_defined` argument.
244
266
 
245
- ### 0.4.5 / 2018-08-05
267
+ ### v0.4.5 / 2018-08-05
246
268
 
247
269
  * CHANGED: Dropped preload file feature
248
270
 
249
- ### 0.4.4 / 2018-07-21
271
+ ### v0.4.4 / 2018-07-21
250
272
 
251
273
  * FIXED: Utils::Exec wasn't closing streams after copying.
252
274
  * IMPROVED: Utils::Exec::Controller can capture or redirect the remainder of a controlled stream.
253
275
  * ADDED: Terminal#ask
254
276
 
255
- ### 0.4.3 / 2018-07-13
277
+ ### v0.4.3 / 2018-07-13
256
278
 
257
279
  * IMPROVED: Utils::Exec methods can now spawn subprocesses in the background
258
280
  * IMPROVED: Utils::Exec capture methods can now yield a controller
259
281
 
260
- ### 0.4.2 / 2018-07-08
282
+ ### v0.4.2 / 2018-07-08
261
283
 
262
284
  * FIXED: Raise an error rather than cause unexpected behavior if a mixin is included twice.
263
285
  * IMPROVED: The `include?` method extended to support mixin names in a tool dsl.
264
286
 
265
- ### 0.4.1 / 2018-07-03
287
+ ### v0.4.1 / 2018-07-03
266
288
 
267
289
  * FIXED: Terminal#confirm uppercased "N" for the wrong default.
268
290
 
269
- ### 0.4.0 / 2018-07-03
291
+ ### v0.4.0 / 2018-07-03
270
292
 
271
293
  Now declaring this alpha quality. Backward-incompatible changes are still
272
294
  possible from this point, but I'll try to avoid them.
@@ -278,13 +300,13 @@ possible from this point, but I'll try to avoid them.
278
300
  * IMPROVED: Utils::Gems installation is now much faster.
279
301
  * FIXED: Utils::Gems didn't reset the specifications on Ruby 2.3.
280
302
 
281
- ### 0.3.11 / 2018-07-02
303
+ ### v0.3.11 / 2018-07-02
282
304
 
283
305
  * CHANGED: Require Ruby 2.3 or later
284
306
  * CHANGED: Renamed "set" directive to "static" to reduce confusion with Tool#set.
285
307
  * ADDED: Convenience methods for getting option values
286
308
 
287
- ### 0.3.10 / 2018-06-30
309
+ ### v0.3.10 / 2018-06-30
288
310
 
289
311
  * CHANGED: Dropped Tool#option. Use Tool#get instead.
290
312
  * CHANGED: "run" directive renamed to "to_run"
@@ -293,11 +315,11 @@ possible from this point, but I'll try to avoid them.
293
315
  * ADDED: Mixins can provide initializers
294
316
  * ADDED: Loader can load an inline block
295
317
 
296
- ### 0.3.9.1 / 2018-06-24
318
+ ### v0.3.9.1 / 2018-06-24
297
319
 
298
320
  * FIXED: Built-in flags were interfering with disable_argument_parsing
299
321
 
300
- ### 0.3.9 / 2018-06-24
322
+ ### v0.3.9 / 2018-06-24
301
323
 
302
324
  * CHANGED: Cli#add_search_path_hierarchy changed the behavior of the base/terminate param
303
325
  * CHANGED: Removed alias_as directive since it's incompatible with selective loading.
@@ -306,7 +328,7 @@ possible from this point, but I'll try to avoid them.
306
328
  * ADDED: Exec#exec_proc and Exec#exec_tool that supports all the stream redirects
307
329
  * IMPROVED: Acceptors can be looked up recursively in the same way as mixins and templates
308
330
 
309
- ### 0.3.8 / 2018-06-10
331
+ ### v0.3.8 / 2018-06-10
310
332
 
311
333
  * CHANGED: Renamed helpers to mixins.
312
334
  * CHANGED: ModuleLookup is now a customizable class and can have multiple sources.
@@ -316,11 +338,11 @@ possible from this point, but I'll try to avoid them.
316
338
  * IMPROVED: Exec raises an error if passed an unknown option.
317
339
  * IMPROVED: Exec now accepts nearly all the same stream specifications as Process#spawn.
318
340
 
319
- ### 0.3.7.1 / 2018-05-30
341
+ ### v0.3.7.1 / 2018-05-30
320
342
 
321
343
  * No changes.
322
344
 
323
- ### 0.3.7 / 2018-05-30
345
+ ### v0.3.7 / 2018-05-30
324
346
 
325
347
  * CHANGED: Execution runs in the same scope as the DSL, which lets us use normal methods instead of helper-blocks.
326
348
  * CHANGED: Renamed "script" to "run", and allow setting of runnable by defining a "run" method
@@ -333,7 +355,7 @@ possible from this point, but I'll try to avoid them.
333
355
  * ADDED: Helper modules scoped to the tool hierarchy
334
356
  * ADDED: Utility that installs and activates third-party gems.
335
357
 
336
- ### 0.3.6 / 2018-05-21
358
+ ### v0.3.6 / 2018-05-21
337
359
 
338
360
  * CHANGED: Renamed show_version middleware to show_root_version.
339
361
  * CHANGED: Reworked set_default_descriptions interface for more flexibility.
@@ -345,14 +367,14 @@ possible from this point, but I'll try to avoid them.
345
367
  * IMPROVED: Support custom acceptors.
346
368
  * IMPROVED: Highline helper automatically sets use_color based on the type of stdout.
347
369
 
348
- ### 0.3.5 / 2018-05-15
370
+ ### v0.3.5 / 2018-05-15
349
371
 
350
372
  * CHANGED: Exec logic now lives in a utils class.
351
373
  * CHANGED: Moved flag and arg blocks from Tool into the DSL.
352
374
  * CHANGED: Renamed `execute do` to `script do`, and Tool#executor to Tool#script.
353
375
  * IMPROVED: Help display can use `less` if available.
354
376
 
355
- ### 0.3.4 / 2018-05-14
377
+ ### v0.3.4 / 2018-05-14
356
378
 
357
379
  * CHANGED: Renamed switch to flag
358
380
  * CHANGED: Renamed Utils::Usage to Utils::HelpText
@@ -374,7 +396,7 @@ possible from this point, but I'll try to avoid them.
374
396
  * ADDED: Alias DSL methods `required`, `optional`, and `remaining`.
375
397
  * FIXED: Finish definitions for subtools since the desc may depend on it
376
398
 
377
- ### 0.3.3 / 2018-05-09
399
+ ### v0.3.3 / 2018-05-09
378
400
 
379
401
  * CHANGED: Renamed file_utils helper to fileutils.
380
402
  * CHANGED: Renamed `doc:` parameter to `docs:`.
@@ -387,7 +409,7 @@ possible from this point, but I'll try to avoid them.
387
409
  * IMPROVED: Usage can now customize the left column width and indent
388
410
  * IMPROVED: Newlines in documentation are properly indented
389
411
 
390
- ### 0.3.2 / 2018-05-07
412
+ ### v0.3.2 / 2018-05-07
391
413
 
392
414
  * CHANGED: Split core engine out into "toys-core" from the "toys" gem.
393
415
  * CHANGED: Renamed path types to "search" and "config" paths, and restricted the former to the CLI.
data/lib/toys/acceptor.rb CHANGED
@@ -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
  #
data/lib/toys/core.rb CHANGED
@@ -9,7 +9,7 @@ module Toys
9
9
  # Current version of Toys core.
10
10
  # @return [String]
11
11
  #
12
- VERSION = "0.11.0"
12
+ VERSION = "0.11.5"
13
13
  end
14
14
 
15
15
  ## @private deprecated
data/lib/toys/dsl/flag.rb CHANGED
@@ -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,
data/lib/toys/dsl/tool.rb CHANGED
@@ -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
@@ -57,6 +57,9 @@ module Toys
57
57
  # * `:ignore` - just silently proceed without bundling again.
58
58
  # * `:warn` - print a warning and proceed without bundling again.
59
59
  #
60
+ # * `:retries` (Integer) Number of times to retry bundler operations
61
+ # (optional)
62
+ #
60
63
  # * `:terminal` (Toys::Utils::Terminal) Terminal to use (optional)
61
64
  # * `:input` (IO) Input IO (optional, defaults to STDIN)
62
65
  # * `:output` (IO) Output IO (optional, defaults to STDOUT)
@@ -100,6 +103,7 @@ module Toys
100
103
  groups: nil,
101
104
  on_missing: nil,
102
105
  on_conflict: nil,
106
+ retries: nil,
103
107
  terminal: nil,
104
108
  input: nil,
105
109
  output: nil)
@@ -111,7 +115,7 @@ module Toys
111
115
  end
112
116
  gems = ::Toys::Utils::Gems.new(on_missing: on_missing, on_conflict: on_conflict,
113
117
  terminal: terminal, input: input, output: output)
114
- gems.bundle(groups: groups, gemfile_path: gemfile_path)
118
+ gems.bundle(groups: groups, gemfile_path: gemfile_path, retries: retries)
115
119
  end
116
120
 
117
121
  # @private
@@ -708,7 +708,16 @@ module Toys
708
708
 
709
709
  ## @private
710
710
  def self._interpret_e(value, context)
711
- value ? proc { |r| context.exit(r.exit_code) if r.error? } : nil
711
+ return nil unless value
712
+ proc do |result|
713
+ if result.failed?
714
+ context.exit(127)
715
+ elsif result.signaled?
716
+ context.exit(result.signal_code + 128)
717
+ elsif result.error?
718
+ context.exit(result.exit_code)
719
+ end
720
+ end
712
721
  end
713
722
 
714
723
  ## @private
@@ -250,13 +250,14 @@ module Toys
250
250
  exec_opts = Opts.new(@default_opts).add(opts)
251
251
  spawn_cmd =
252
252
  if cmd.is_a?(::Array)
253
- if cmd.size == 1 && cmd.first.is_a?(::String)
254
- [[cmd.first, exec_opts.config_opts[:argv0] || cmd.first]]
253
+ if cmd.size > 1
254
+ binary = canonical_binary_spec(cmd.first, exec_opts)
255
+ [binary] + cmd[1..-1].map(&:to_s)
255
256
  else
256
- cmd
257
+ [canonical_binary_spec(Array(cmd.first), exec_opts)]
257
258
  end
258
259
  else
259
- [cmd]
260
+ [cmd.to_s]
260
261
  end
261
262
  executor = Executor.new(exec_opts, spawn_cmd, block)
262
263
  executor.execute
@@ -492,7 +493,8 @@ module Toys
492
493
  #
493
494
  class Controller
494
495
  ## @private
495
- def initialize(name, controller_streams, captures, pid, join_threads, result_callback)
496
+ def initialize(name, controller_streams, captures, pid, join_threads,
497
+ result_callback, mutex)
496
498
  @name = name
497
499
  @in = controller_streams[:in]
498
500
  @out = controller_streams[:out]
@@ -508,6 +510,7 @@ module Toys
508
510
  end
509
511
  @join_threads = join_threads
510
512
  @result_callback = result_callback
513
+ @mutex = mutex
511
514
  @result = nil
512
515
  end
513
516
 
@@ -575,7 +578,10 @@ module Toys
575
578
  stream = stream_for(which)
576
579
  @join_threads << ::Thread.new do
577
580
  begin
578
- @captures[which] = stream.read
581
+ data = stream.read
582
+ @mutex.synchronize do
583
+ @captures[which] = data
584
+ end
579
585
  ensure
580
586
  stream.close
581
587
  end
@@ -791,7 +797,7 @@ module Toys
791
797
  # {Result#success?} or {Result#error?} will return true, and
792
798
  # {Result.exit_code} will return the numeric exit code.
793
799
  # * The process executed but was terminated by an uncaught signal.
794
- # {Result#signaled?} will return true, and {Result#term_signal} will
800
+ # {Result#signaled?} will return true, and {Result#signal_code} will
795
801
  # return the numeric signal code.
796
802
  #
797
803
  class Result
@@ -843,6 +849,8 @@ module Toys
843
849
  # The exception raised if a process couldn't be started.
844
850
  #
845
851
  # Exactly one of {#exception} and {#status} will be non-nil.
852
+ # Exactly one of {#exception}, {#exit_code}, or {#signal_code} will be
853
+ # non-nil.
846
854
  #
847
855
  # @return [Exception] The exception raised from process start.
848
856
  # @return [nil] if the process started successfully.
@@ -852,7 +860,7 @@ module Toys
852
860
  ##
853
861
  # The numeric status code for a process that exited normally,
854
862
  #
855
- # Exactly one of {#exception}, {#exit_code}, and {#term_signal} will be
863
+ # Exactly one of {#exception}, {#exit_code}, or {#signal_code} will be
856
864
  # non-nil.
857
865
  #
858
866
  # @return [Integer] the numeric status code, if the process started
@@ -867,16 +875,17 @@ module Toys
867
875
  ##
868
876
  # The numeric signal code that caused process termination.
869
877
  #
870
- # Exactly one of {#exception}, {#exit_code}, and {#term_signal} will be
878
+ # Exactly one of {#exception}, {#exit_code}, or {#signal_code} will be
871
879
  # non-nil.
872
880
  #
873
881
  # @return [Integer] The signal that caused the process to terminate.
874
882
  # @return [nil] if the process did not start successfully, or executed
875
883
  # and exited with a normal exit code.
876
884
  #
877
- def term_signal
885
+ def signal_code
878
886
  status&.termsig
879
887
  end
888
+ alias term_signal signal_code
880
889
 
881
890
  ##
882
891
  # Returns true if the subprocess failed to start, or false if the
@@ -895,7 +904,7 @@ module Toys
895
904
  # @return [Boolean]
896
905
  #
897
906
  def signaled?
898
- !term_signal.nil?
907
+ !signal_code.nil?
899
908
  end
900
909
 
901
910
  ##
@@ -940,6 +949,7 @@ module Toys
940
949
  @parent_streams = []
941
950
  @block = block
942
951
  @default_stream = @config_opts[:background] ? :null : :inherit
952
+ @mutex = ::Mutex.new
943
953
  end
944
954
 
945
955
  def execute
@@ -962,12 +972,19 @@ module Toys
962
972
  def log_command
963
973
  logger = @config_opts[:logger]
964
974
  if logger && @config_opts[:log_level] != false
965
- cmd_str = @config_opts[:log_cmd]
966
- cmd_str ||= @spawn_cmd.size == 1 ? @spawn_cmd.first : @spawn_cmd.inspect if @spawn_cmd
975
+ cmd_str = @config_opts[:log_cmd] || default_log_str(@spawn_cmd)
967
976
  logger.add(@config_opts[:log_level] || ::Logger::INFO, cmd_str) if cmd_str
968
977
  end
969
978
  end
970
979
 
980
+ def default_log_str(spawn_cmd)
981
+ return nil unless spawn_cmd
982
+ return spawn_cmd.first if spawn_cmd.size == 1 && spawn_cmd.first.is_a?(::String)
983
+ cmd_binary = spawn_cmd.first
984
+ cmd_binary = cmd_binary.first if cmd_binary.is_a?(::Array)
985
+ ([cmd_binary] + spawn_cmd[1..-1]).inspect
986
+ end
987
+
971
988
  def start_with_controller
972
989
  pid =
973
990
  begin
@@ -977,7 +994,7 @@ module Toys
977
994
  end
978
995
  @child_streams.each(&:close)
979
996
  Controller.new(@config_opts[:name], @controller_streams, @captures, pid,
980
- @join_threads, @config_opts[:result_callback])
997
+ @join_threads, @config_opts[:result_callback], @mutex)
981
998
  end
982
999
 
983
1000
  def start_process
@@ -1284,13 +1301,27 @@ module Toys
1284
1301
  stream = make_out_pipe(key)
1285
1302
  @join_threads << ::Thread.new do
1286
1303
  begin
1287
- @captures[key] = stream.read
1304
+ data = stream.read
1305
+ @mutex.synchronize do
1306
+ @captures[key] = data
1307
+ end
1288
1308
  ensure
1289
1309
  stream.close
1290
1310
  end
1291
1311
  end
1292
1312
  end
1293
1313
  end
1314
+
1315
+ private
1316
+
1317
+ def canonical_binary_spec(cmd, exec_opts)
1318
+ config_argv0 = exec_opts.config_opts[:argv0]
1319
+ return cmd.to_s if !config_argv0 && !cmd.is_a?(::Array)
1320
+ cmd = Array(cmd)
1321
+ actual_cmd = cmd.first
1322
+ argv0 = cmd[1] || config_argv0 || actual_cmd
1323
+ [actual_cmd.to_s, argv0.to_s]
1324
+ end
1294
1325
  end
1295
1326
  end
1296
1327
  end
@@ -170,12 +170,16 @@ module Toys
170
170
  # recognized as Gemfiles, when searching because gemfile_path is not
171
171
  # given. Defaults to {DEFAULT_GEMFILE_NAMES}.
172
172
  #
173
+ # @param retries [Integer] Number of times to retry bundler operations.
174
+ # Optional.
175
+ #
173
176
  # @return [void]
174
177
  #
175
178
  def bundle(groups: nil,
176
179
  gemfile_path: nil,
177
180
  search_dirs: nil,
178
- gemfile_names: nil)
181
+ gemfile_names: nil,
182
+ retries: nil)
179
183
  Array(search_dirs).each do |dir|
180
184
  break if gemfile_path
181
185
  gemfile_path = Gems.find_gemfile(dir, gemfile_names: gemfile_names)
@@ -185,7 +189,8 @@ module Toys
185
189
  if configure_gemfile(gemfile_path)
186
190
  activate("bundler", "~> 2.1")
187
191
  require "bundler"
188
- setup_bundle(gemfile_path, groups || [])
192
+ lockfile_path = find_lockfile_path(gemfile_path)
193
+ setup_bundle(gemfile_path, lockfile_path, groups: groups, retries: retries)
189
194
  end
190
195
  end
191
196
  end
@@ -287,21 +292,47 @@ module Toys
287
292
  true
288
293
  end
289
294
 
290
- def setup_bundle(gemfile_path, groups)
295
+ def find_lockfile_path(gemfile_path)
296
+ if ::File.basename(gemfile_path) == "gems.rb"
297
+ ::File.join(::File.dirname(gemfile_path), "gems.locked")
298
+ else
299
+ gemfile_path + ".lock"
300
+ end
301
+ end
302
+
303
+ def setup_bundle(gemfile_path, lockfile_path, groups: nil, retries: nil)
304
+ groups = Array(groups)
305
+ old_lockfile_contents = save_old_lockfile(lockfile_path)
291
306
  begin
292
- modify_bundle_definition(gemfile_path)
307
+ modify_bundle_definition(gemfile_path, lockfile_path)
293
308
  ::Bundler.ui.silence { ::Bundler.setup(*groups) }
294
309
  rescue ::Bundler::GemNotFound, ::Bundler::VersionConflict
295
310
  restore_toys_libs
296
- install_bundle(gemfile_path)
311
+ install_bundle(gemfile_path, retries: retries)
312
+ old_lockfile_contents = save_old_lockfile(lockfile_path)
297
313
  ::Bundler.reset!
298
- modify_bundle_definition(gemfile_path)
314
+ modify_bundle_definition(gemfile_path, lockfile_path)
299
315
  ::Bundler.ui.silence { ::Bundler.setup(*groups) }
300
316
  end
301
317
  restore_toys_libs
318
+ ensure
319
+ restore_old_lockfile(lockfile_path, old_lockfile_contents)
320
+ end
321
+
322
+ def save_old_lockfile(lockfile_path)
323
+ return nil unless ::File.readable?(lockfile_path) && ::File.writable?(lockfile_path)
324
+ ::File.read(lockfile_path)
325
+ end
326
+
327
+ def restore_old_lockfile(lockfile_path, contents)
328
+ if contents
329
+ ::File.open(lockfile_path, "w") do |file|
330
+ file.write(contents)
331
+ end
332
+ end
302
333
  end
303
334
 
304
- def modify_bundle_definition(gemfile_path)
335
+ def modify_bundle_definition(gemfile_path, lockfile_path)
305
336
  builder = ::Bundler::Dsl.new
306
337
  builder.eval_gemfile(gemfile_path)
307
338
  toys_gems = ["toys-core"]
@@ -312,7 +343,7 @@ module Toys
312
343
  add_gem_to_definition(builder, "toys")
313
344
  toys_gems << "toys"
314
345
  end
315
- definition = builder.to_definition(gemfile_path + ".lock", { gems: toys_gems })
346
+ definition = builder.to_definition(lockfile_path, { gems: toys_gems })
316
347
  ::Bundler.instance_variable_set(:@definition, definition)
317
348
  end
318
349
 
@@ -357,19 +388,21 @@ module Toys
357
388
  end
358
389
  end
359
390
 
360
- def install_bundle(gemfile_path)
391
+ def install_bundle(gemfile_path, retries: nil)
361
392
  gemfile_dir = ::File.dirname(gemfile_path)
362
393
  unless permission_to_bundle?
363
394
  raise BundleNotInstalledError,
364
395
  "Your bundle is not installed. Consider running" \
365
396
  " `cd #{gemfile_dir} && bundle install`"
366
397
  end
398
+ retries = retries.to_i
399
+ args = retries.positive? ? ["--retry=#{retries}"] : []
367
400
  require "bundler/cli"
368
401
  begin
369
- ::Bundler::CLI.start(["install"])
370
- rescue ::Bundler::GemNotFound, ::Bundler::InstallError
402
+ ::Bundler::CLI.start(["install"] + args)
403
+ rescue ::Bundler::GemNotFound, ::Bundler::InstallError, ::Bundler::VersionConflict
371
404
  terminal.puts("Failed to install. Trying update...")
372
- ::Bundler::CLI.start(["update"])
405
+ ::Bundler::CLI.start(["update"] + args)
373
406
  end
374
407
  end
375
408
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toys-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.11.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-21 00:00:00.000000000 Z
11
+ date: 2021-03-28 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Toys-Core is the command line tool framework underlying Toys. It can
14
14
  be used to create command line executables using the Toys DSL and classes.
@@ -69,10 +69,10 @@ homepage: https://github.com/dazuma/toys
69
69
  licenses:
70
70
  - MIT
71
71
  metadata:
72
- changelog_uri: https://dazuma.github.io/toys/gems/toys-core/v0.11.0/file.CHANGELOG.html
73
- source_code_uri: https://github.com/dazuma/toys
72
+ changelog_uri: https://dazuma.github.io/toys/gems/toys-core/v0.11.5/file.CHANGELOG.html
73
+ source_code_uri: https://github.com/dazuma/toys/tree/main/toys-core
74
74
  bug_tracker_uri: https://github.com/dazuma/toys/issues
75
- documentation_uri: https://dazuma.github.io/toys/gems/toys-core/v0.11.0
75
+ documentation_uri: https://dazuma.github.io/toys/gems/toys-core/v0.11.5
76
76
  post_install_message:
77
77
  rdoc_options: []
78
78
  require_paths:
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  requirements: []
91
- rubygems_version: 3.1.2
91
+ rubygems_version: 3.1.4
92
92
  signing_key:
93
93
  specification_version: 4
94
94
  summary: Framework for creating command line executables