toys-core 0.9.2 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -1
  3. data/CHANGELOG.md +47 -0
  4. data/LICENSE.md +1 -1
  5. data/README.md +3 -3
  6. data/lib/toys-core.rb +14 -21
  7. data/lib/toys/acceptor.rb +0 -21
  8. data/lib/toys/arg_parser.rb +1 -22
  9. data/lib/toys/cli.rb +102 -70
  10. data/lib/toys/compat.rb +49 -41
  11. data/lib/toys/completion.rb +0 -21
  12. data/lib/toys/context.rb +0 -23
  13. data/lib/toys/core.rb +1 -22
  14. data/lib/toys/dsl/flag.rb +0 -21
  15. data/lib/toys/dsl/flag_group.rb +0 -21
  16. data/lib/toys/dsl/positional_arg.rb +0 -21
  17. data/lib/toys/dsl/tool.rb +136 -51
  18. data/lib/toys/errors.rb +1 -22
  19. data/lib/toys/flag.rb +0 -21
  20. data/lib/toys/flag_group.rb +0 -21
  21. data/lib/toys/input_file.rb +0 -21
  22. data/lib/toys/loader.rb +42 -78
  23. data/lib/toys/middleware.rb +146 -77
  24. data/lib/toys/mixin.rb +0 -21
  25. data/lib/toys/module_lookup.rb +3 -26
  26. data/lib/toys/positional_arg.rb +0 -21
  27. data/lib/toys/source_info.rb +49 -38
  28. data/lib/toys/standard_middleware/add_verbosity_flags.rb +0 -23
  29. data/lib/toys/standard_middleware/apply_config.rb +42 -0
  30. data/lib/toys/standard_middleware/handle_usage_errors.rb +7 -28
  31. data/lib/toys/standard_middleware/set_default_descriptions.rb +0 -23
  32. data/lib/toys/standard_middleware/show_help.rb +0 -23
  33. data/lib/toys/standard_middleware/show_root_version.rb +0 -23
  34. data/lib/toys/standard_mixins/bundler.rb +89 -0
  35. data/lib/toys/standard_mixins/exec.rb +478 -128
  36. data/lib/toys/standard_mixins/fileutils.rb +0 -21
  37. data/lib/toys/standard_mixins/gems.rb +2 -24
  38. data/lib/toys/standard_mixins/highline.rb +0 -21
  39. data/lib/toys/standard_mixins/terminal.rb +0 -21
  40. data/lib/toys/template.rb +0 -21
  41. data/lib/toys/tool.rb +22 -34
  42. data/lib/toys/utils/completion_engine.rb +0 -21
  43. data/lib/toys/utils/exec.rb +142 -71
  44. data/lib/toys/utils/gems.rb +181 -63
  45. data/lib/toys/utils/help_text.rb +0 -21
  46. data/lib/toys/utils/terminal.rb +46 -37
  47. data/lib/toys/wrappable_string.rb +0 -21
  48. metadata +25 -9
@@ -1,26 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2019 Daniel Azuma
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
- # IN THE SOFTWARE.
22
- ;
23
-
24
3
  require "fileutils"
25
4
 
26
5
  module Toys
@@ -1,26 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2019 Daniel Azuma
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
- # IN THE SOFTWARE.
22
- ;
23
-
24
3
  module Toys
25
4
  module StandardMixins
26
5
  ##
@@ -39,10 +18,9 @@ module Toys
39
18
  # If you pass additional options to the include directive, those are used
40
19
  # to initialize settings for the gem install process. For example:
41
20
  #
42
- # include :gems, output: $stdout, default_confirm: false
21
+ # include :gems, on_missing: :error
43
22
  #
44
- # This is a frontend for {Toys::Utils::Gems}. More information is
45
- # available in that class's documentation.
23
+ # See {Toys::Utils::Gems#initialize} for a list of supported options.
46
24
  #
47
25
  module Gems
48
26
  include Mixin
@@ -1,26 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2019 Daniel Azuma
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
- # IN THE SOFTWARE.
22
- ;
23
-
24
3
  module Toys
25
4
  module StandardMixins
26
5
  ##
@@ -1,26 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2019 Daniel Azuma
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
- # IN THE SOFTWARE.
22
- ;
23
-
24
3
  module Toys
25
4
  module StandardMixins
26
5
  ##
@@ -1,26 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2019 Daniel Azuma
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
- # IN THE SOFTWARE.
22
- ;
23
-
24
3
  module Toys
25
4
  ##
26
5
  # A template definition. Template classes should include this module.
@@ -1,26 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2019 Daniel Azuma
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
- # IN THE SOFTWARE.
22
- ;
23
-
24
3
  require "set"
25
4
 
26
5
  module Toys
@@ -37,11 +16,12 @@ module Toys
37
16
  # Should be created only from the DSL via the Loader.
38
17
  # @private
39
18
  #
40
- def initialize(loader, parent, full_name, priority, middleware_stack)
19
+ def initialize(loader, parent, full_name, priority, middleware_stack, middleware_lookup)
41
20
  @parent = parent
42
21
  @full_name = full_name.dup.freeze
43
22
  @priority = priority
44
- @middleware_stack = middleware_stack
23
+ @built_middleware = middleware_stack.build(middleware_lookup)
24
+ @subtool_middleware_stack = middleware_stack.dup
45
25
 
46
26
  @acceptors = {}
47
27
  @mixins = {}
@@ -201,11 +181,20 @@ module Toys
201
181
  attr_reader :default_data
202
182
 
203
183
  ##
204
- # The middleware stack active for this tool.
184
+ # The stack of middleware specs used for subtools.
185
+ #
186
+ # This array may be modified in place.
187
+ #
188
+ # @return [Array<Toys::Middleware::Spec>]
189
+ #
190
+ attr_reader :subtool_middleware_stack
191
+
192
+ ##
193
+ # The stack of built middleware specs for this tool.
205
194
  #
206
195
  # @return [Array<Toys::Middleware>]
207
196
  #
208
- attr_reader :middleware_stack
197
+ attr_reader :built_middleware
209
198
 
210
199
  ##
211
200
  # Info on the source of this tool.
@@ -473,18 +462,13 @@ module Toys
473
462
  ##
474
463
  # Sets the path to the file that defines this tool.
475
464
  # A tool may be defined from at most one path. If a different path is
476
- # already set, raises {Toys::ToolDefinitionError}
465
+ # already set, it is left unchanged.
477
466
  #
478
467
  # @param source [Toys::SourceInfo] Source info
479
468
  # @return [self]
480
469
  #
481
470
  def lock_source(source)
482
- if source_info && source_info.source != source.source
483
- raise ToolDefinitionError,
484
- "Cannot redefine tool #{display_name.inspect} in #{source.source_name}" \
485
- " (already defined in #{source_info.source_name})"
486
- end
487
- @source_info = source
471
+ @source_info ||= source
488
472
  self
489
473
  end
490
474
 
@@ -1073,7 +1057,7 @@ module Toys
1073
1057
  unless @definition_finished
1074
1058
  ContextualError.capture("Error installing tool middleware!", tool_name: full_name) do
1075
1059
  config_proc = proc {}
1076
- middleware_stack.reverse_each do |middleware|
1060
+ @built_middleware.reverse_each do |middleware|
1077
1061
  config_proc = make_config_proc(middleware, loader, config_proc)
1078
1062
  end
1079
1063
  config_proc.call
@@ -1306,7 +1290,11 @@ module Toys
1306
1290
  private
1307
1291
 
1308
1292
  def make_config_proc(middleware, loader, next_config)
1309
- proc { middleware.config(self, loader, &next_config) }
1293
+ if middleware.respond_to?(:config)
1294
+ proc { middleware.config(self, loader, &next_config) }
1295
+ else
1296
+ next_config
1297
+ end
1310
1298
  end
1311
1299
 
1312
1300
  def make_delegation_run_handler(target)
@@ -1,26 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2019 Daniel Azuma
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
- # IN THE SOFTWARE.
22
- ;
23
-
24
3
  require "shellwords"
25
4
 
26
5
  module Toys
@@ -1,26 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2019 Daniel Azuma
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
- # IN THE SOFTWARE.
22
- ;
23
-
3
+ require "rbconfig"
24
4
  require "logger"
25
5
  require "shellwords"
26
6
 
@@ -36,48 +16,39 @@ module Toys
36
16
  # This class is not loaded by default. Before using it directly, you should
37
17
  # `require "toys/utils/exec"`
38
18
  #
39
- # ## Configuration options
19
+ # ## Features
40
20
  #
41
- # A variety of options can be used to control subprocesses. These include:
21
+ # ### Controlling processes
42
22
  #
43
- # * `:name` (Object) An optional object that can be used to identify this
44
- # subprocess. It is available in the controller and result objects.
45
- # * `:env` (Hash) Environment variables to pass to the subprocess
46
- # * `:logger` (Logger) Logger to use for logging the actual command. If
47
- # not present, the command is not logged.
48
- # * `:log_level` (Integer,false) Level for logging the actual command.
49
- # Defaults to Logger::INFO if not present. You may also pass `false` to
50
- # disable logging of the command.
51
- # * `:log_cmd` (String) The string logged for the actual command.
52
- # Defaults to the `inspect` representation of the command.
53
- # * `:background` (Boolean) Runs the process in the background, returning
54
- # a controller object instead of a result object.
55
- # * `:result_callback` (Proc) Called and passed the result object when a
56
- # subprocess exits.
57
- # * `:in` Connects the input stream of the subprocess. See the section on
58
- # stream handling.
59
- # * `:out` Connects the standard output stream of the subprocess. See the
60
- # section on stream handling.
61
- # * `:err` Connects the standard error stream of the subprocess. See the
62
- # section on stream handling.
23
+ # A process can be started in the *foreground* or the *background*. If you
24
+ # start a foreground process, it will "take over" your standard input and
25
+ # output streams by default, and it will keep control until it completes.
26
+ # If you start a background process, its streams will be redirected to null
27
+ # by default, and control will be returned to you immediately.
28
+ #
29
+ # When a process is running, you can control it using a
30
+ # {Toys::Utils::Exec::Controller} object. Use a controller to interact with
31
+ # the process's input and output streams, send it signals, or wait for it
32
+ # to complete.
63
33
  #
64
- # In addition, the following options recognized by `Process#spawn` are
65
- # supported.
34
+ # When running a process in the foreground, the controller will be yielded
35
+ # to an optional block. For example, the following code starts a process in
36
+ # the foreground and passes its output stream to a controller.
66
37
  #
67
- # * `:chdir`
68
- # * `:close_others`
69
- # * `:new_pgroup`
70
- # * `:pgroup`
71
- # * `:umask`
72
- # * `:unsetenv_others`
38
+ # exec_service.exec(["git", "init"], out: :controller) do |controller|
39
+ # loop do
40
+ # line = controller.out.gets
41
+ # break if line.nil?
42
+ # puts "Got line: #{line}"
43
+ # end
44
+ # end
73
45
  #
74
- # Any other options are ignored.
46
+ # When running a process in the background, the controller is returned from
47
+ # the method that starts the process:
75
48
  #
76
- # Configuration options may be provided to any method that starts a
77
- # subprocess. You may also modify default values by calling
78
- # {Toys::Utils::Exec#configure_defaults}.
49
+ # controller = exec_service.exec(["git", "init"], background: true)
79
50
  #
80
- # ## Stream handling
51
+ # ### Stream handling
81
52
  #
82
53
  # By default, subprocess streams are connected to the corresponding streams
83
54
  # in the parent process. You can change this behavior, redirecting streams
@@ -94,16 +65,16 @@ module Toys
94
65
  # Following is a full list of the stream handling options, along with how
95
66
  # to specify them using the `:in`, `:out`, and `:err` options.
96
67
  #
97
- # * **Close the stream:** You may close the stream by passing `:close` as
98
- # the option value. This is the same as passing `:close` to
99
- # `Process#spawn`.
68
+ # * **Inherit parent stream:** You may inherit the corresponding stream
69
+ # in the parent process by passing `:inherit` as the option value. This
70
+ # is the default if the subprocess is *not* run in the background.
100
71
  # * **Redirect to null:** You may redirect to a null stream by passing
101
72
  # `:null` as the option value. This connects to a stream that is not
102
73
  # closed but contains no data, i.e. `/dev/null` on unix systems. This
103
74
  # is the default if the subprocess is run in the background.
104
- # * **Inherit parent stream:** You may inherit the corresponding stream
105
- # in the parent process by passing `:inherit` as the option value. This
106
- # is the default if the subprocess is *not* run in the background.
75
+ # * **Close the stream:** You may close the stream by passing `:close` as
76
+ # the option value. This is the same as passing `:close` to
77
+ # `Process#spawn`.
107
78
  # * **Redirect to a file:** You may redirect to a file. This reads from
108
79
  # an existing file when connected to `:in`, and creates or appends to a
109
80
  # file when connected to `:out` or `:err`. To specify a file, use the
@@ -133,6 +104,104 @@ module Toys
133
104
  # yields the {Toys::Utils::Exec::Controller}, giving you access to
134
105
  # streams.
135
106
  #
107
+ # ### Result handling
108
+ #
109
+ # A subprocess result is represented by a {Toys::Utils::Exec::Result}
110
+ # object, which includes the exit code, the content of any captured output
111
+ # streams, and any exeption raised when attempting to run the process.
112
+ # When you run a process in the foreground, the method will return a result
113
+ # object. When you run a process in the background, you can obtain the
114
+ # result from the controller once the process completes.
115
+ #
116
+ # The following example demonstrates running a process in the foreground
117
+ # and getting the exit code:
118
+ #
119
+ # result = exec_service.exec(["git", "init"])
120
+ # puts "exit code: #{result.exit_code}"
121
+ #
122
+ # The following example demonstrates starting a process in the background,
123
+ # waiting for it to complete, and getting its exit code:
124
+ #
125
+ # controller = exec_service.exec(["git", "init"], background: true)
126
+ # result = controller.result(timeout: 1.0)
127
+ # if result
128
+ # puts "exit code: #{result.exit_code}"
129
+ # else
130
+ # puts "timed out"
131
+ # end
132
+ #
133
+ # You can also provide a callback that is executed once a process
134
+ # completes. For example:
135
+ #
136
+ # my_callback = proc do |result|
137
+ # puts "exit code: #{result.exit_code}"
138
+ # end
139
+ # exec_service.exec(["git", "init"], result_callback: my_callback)
140
+ #
141
+ # ## Configuration options
142
+ #
143
+ # A variety of options can be used to control subprocesses. These can be
144
+ # provided to any method that starts a subprocess. Youc an also set
145
+ # defaults by calling {Toys::Utils::Exec#configure_defaults}.
146
+ #
147
+ # Options that affect the behavior of subprocesses:
148
+ #
149
+ # * `:env` (Hash) Environment variables to pass to the subprocess.
150
+ # Keys represent variable names and should be strings. Values should be
151
+ # either strings or `nil`, which unsets the variable.
152
+ #
153
+ # * `:background` (Boolean) Runs the process in the background if `true`.
154
+ #
155
+ # * `:result_callback` (Proc) Called and passed the result object when
156
+ # the subprocess exits.
157
+ #
158
+ # Options for connecting input and output streams. See the section above on
159
+ # stream handling for info on the values that can be passed.
160
+ #
161
+ # * `:in` Connects the input stream of the subprocess. See the section on
162
+ # stream handling.
163
+ #
164
+ # * `:out` Connects the standard output stream of the subprocess. See the
165
+ # section on stream handling.
166
+ #
167
+ # * `:err` Connects the standard error stream of the subprocess. See the
168
+ # section on stream handling.
169
+ #
170
+ # Options related to logging and reporting:
171
+ #
172
+ # * `:logger` (Logger) Logger to use for logging the actual command. If
173
+ # not present, the command is not logged.
174
+ #
175
+ # * `:log_level` (Integer,false) Level for logging the actual command.
176
+ # Defaults to Logger::INFO if not present. You may also pass `false` to
177
+ # disable logging of the command.
178
+ #
179
+ # * `:log_cmd` (String) The string logged for the actual command.
180
+ # Defaults to the `inspect` representation of the command.
181
+ #
182
+ # * `:name` (Object) An optional object that can be used to identify this
183
+ # subprocess. It is available in the controller and result objects.
184
+ #
185
+ # In addition, the following options recognized by
186
+ # [`Process#spawn`](https://ruby-doc.org/core/Process.html#method-c-spawn)
187
+ # are supported.
188
+ #
189
+ # * `:chdir` (String) Set the working directory for the command.
190
+ #
191
+ # * `:close_others` (Boolean) Whether to close non-redirected
192
+ # non-standard file descriptors.
193
+ #
194
+ # * `:new_pgroup` (Boolean) Create new process group (Windows only).
195
+ #
196
+ # * `:pgroup` (Integer,true,nil) The process group setting.
197
+ #
198
+ # * `:umask` (Integer) Umask setting for the new process.
199
+ #
200
+ # * `:unsetenv_others` (Boolean) Clear environment variables except those
201
+ # explicitly set.
202
+ #
203
+ # Any other option key will result in an `ArgumentError`.
204
+ #
136
205
  class Exec
137
206
  ##
138
207
  # Create an exec service.
@@ -140,14 +209,16 @@ module Toys
140
209
  # @param block [Proc] A block that is called if a key is not found. It is
141
210
  # passed the unknown key, and expected to return a default value
142
211
  # (which can be nil).
143
- # @param opts [keywords] Initial default options.
212
+ # @param opts [keywords] Initial default options. See {Toys::Utils::Exec}
213
+ # for a description of the options.
144
214
  #
145
215
  def initialize(**opts, &block)
146
216
  @default_opts = Opts.new(&block).add(opts)
147
217
  end
148
218
 
149
219
  ##
150
- # Set default options
220
+ # Set default options. See {Toys::Utils::Exec} for a description of the
221
+ # options.
151
222
  #
152
223
  # @param opts [keywords] New default options to set
153
224
  # @return [self]
@@ -166,7 +237,7 @@ module Toys
166
237
  #
167
238
  # @param cmd [String,Array<String>] The command to execute.
168
239
  # @param opts [keywords] The command options. See the section on
169
- # configuration options in the {Toys::Utils::Exec} module docs.
240
+ # configuration options in the {Toys::Utils::Exec} class docs.
170
241
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
171
242
  # for the subprocess streams.
172
243
  #
@@ -199,7 +270,7 @@ module Toys
199
270
  #
200
271
  # @param args [String,Array<String>] The arguments to ruby.
201
272
  # @param opts [keywords] The command options. See the section on
202
- # configuration options in the {Toys::Utils::Exec} module docs.
273
+ # configuration options in the {Toys::Utils::Exec} class docs.
203
274
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
204
275
  # for the subprocess streams.
205
276
  #
@@ -224,7 +295,7 @@ module Toys
224
295
  #
225
296
  # @param func [Proc] The proc to call.
226
297
  # @param opts [keywords] The command options. See the section on
227
- # configuration options in the {Toys::Utils::Exec} module docs.
298
+ # configuration options in the {Toys::Utils::Exec} class docs.
228
299
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
229
300
  # for the subprocess streams.
230
301
  #
@@ -251,7 +322,7 @@ module Toys
251
322
  #
252
323
  # @param cmd [String,Array<String>] The command to execute.
253
324
  # @param opts [keywords] The command options. See the section on
254
- # configuration options in the {Toys::Utils::Exec} module docs.
325
+ # configuration options in the {Toys::Utils::Exec} class docs.
255
326
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
256
327
  # for the subprocess streams.
257
328
  #
@@ -273,7 +344,7 @@ module Toys
273
344
  #
274
345
  # @param args [String,Array<String>] The arguments to ruby.
275
346
  # @param opts [keywords] The command options. See the section on
276
- # configuration options in the {Toys::Utils::Exec} module docs.
347
+ # configuration options in the {Toys::Utils::Exec} class docs.
277
348
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
278
349
  # for the subprocess streams.
279
350
  #
@@ -295,7 +366,7 @@ module Toys
295
366
  #
296
367
  # @param func [Proc] The proc to call.
297
368
  # @param opts [keywords] The command options. See the section on
298
- # configuration options in the {Toys::Utils::Exec} module docs.
369
+ # configuration options in the {Toys::Utils::Exec} class docs.
299
370
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
300
371
  # for the subprocess streams.
301
372
  #
@@ -315,7 +386,7 @@ module Toys
315
386
  #
316
387
  # @param cmd [String] The shell command to execute.
317
388
  # @param opts [keywords] The command options. See the section on
318
- # configuration options in the {Toys::Utils::Exec} module docs.
389
+ # configuration options in the {Toys::Utils::Exec} class docs.
319
390
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
320
391
  # for the subprocess streams.
321
392
  #