ruby-sh 2.2.6 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,15 +18,6 @@ module Rubsh
18
18
  _no_err
19
19
  _long_sep
20
20
  _long_prefix
21
- _pipeline
22
- ]
23
-
24
- SPECIAL_KWARGS_WITHIN_PIPELINE = %i[
25
- _env
26
- _cwd
27
- _long_sep
28
- _long_prefix
29
- _pipeline
30
21
  ]
31
22
 
32
23
  # @!attribute [r] pid
@@ -53,8 +44,7 @@ module Rubsh
53
44
  # @return [String]
54
45
  attr_reader :stderr_data
55
46
 
56
- def initialize(sh, prog, progpath, *args, **kwargs)
57
- @sh = sh
47
+ def initialize(prog, progpath, *args, **kwargs)
58
48
  @prog = prog
59
49
  @progpath = progpath
60
50
  @args = []
@@ -101,9 +91,6 @@ module Rubsh
101
91
  @_long_sep = "="
102
92
  @_long_prefix = "--"
103
93
 
104
- # Special Kwargs - Misc
105
- @_pipeline = nil
106
-
107
94
  opts = []
108
95
  args.each do |arg|
109
96
  if arg.is_a?(::Hash)
@@ -113,7 +100,6 @@ module Rubsh
113
100
  end
114
101
  end
115
102
  kwargs.each { |k, v| opts << Option.build(k, v) }
116
- validate_opts(opts)
117
103
  extract_opts(opts)
118
104
  end
119
105
 
@@ -128,61 +114,29 @@ module Rubsh
128
114
  @_ok_code.include?(@exit_code)
129
115
  end
130
116
 
131
- # @return [void]
132
- def wait(timeout: nil)
133
- wait2(timeout: timeout)
134
- handle_return_code
135
- end
136
-
137
- # @return [String]
138
- def to_s
139
- @prog_with_args
140
- end
141
-
142
117
  # @!visibility private
143
118
  def __run
144
- if @_pipeline
145
- @_pipeline.__add_running_command(self)
119
+ if @_bg
120
+ spawn
146
121
  else
147
- @_bg ? run_in_background : run_in_foreground
122
+ spawn
123
+ wait(timeout: @_timeout)
148
124
  end
149
125
  end
150
126
 
151
- # @!visibility private
152
- def __spawn_arguments(env: nil, cwd: nil, redirection_args: nil)
153
- env ||= @_env
154
- cmd_args = compile_cmd_args
155
- redirection_args ||= compile_redirection_args
156
- extra_args = compile_extra_args(cwd: cwd)
157
-
158
- # For logging
159
- @prog_with_args = [@progpath].concat(cmd_args).join(" ")
160
-
161
- # .
162
- _args =
163
- if env
164
- [env, [@progpath, @prog], *cmd_args, **redirection_args, **extra_args, unsetenv_others: true]
165
- else
166
- [[@progpath, @prog], *cmd_args, **redirection_args, **extra_args]
167
- end
127
+ # @return [void]
128
+ def wait(timeout: nil)
129
+ wait2(@pid, timeout)
130
+ handle_return_code
168
131
  end
169
132
 
170
- # @!visibility private
171
- def __prog_with_args
133
+ # @return [String]
134
+ def to_s
172
135
  @prog_with_args
173
136
  end
174
137
 
175
138
  private
176
139
 
177
- def validate_opts(opts)
178
- within_pipeline = opts.any? { |opt| opt.special_kwarg?(:_pipeline) }
179
- within_pipeline && opts.each do |opt|
180
- if opt.special_kwarg? && !SPECIAL_KWARGS_WITHIN_PIPELINE.include?(opt.k.to_sym)
181
- raise ::ArgumentError, format("unsupported special kwargs within _pipeline `%s'", opt.k)
182
- end
183
- end
184
- end
185
-
186
140
  def extract_opts(opts)
187
141
  args_hash = {}
188
142
  opts.each do |opt|
@@ -200,6 +154,8 @@ module Rubsh
200
154
  @args << arg
201
155
  end
202
156
  end
157
+
158
+ raise ::ArgumentError, "kwargs :_bg conflicts with kwargs :_timeout" if @_bg && @_timeout
203
159
  end
204
160
 
205
161
  def extract_special_kwargs_opts(opt)
@@ -238,11 +194,52 @@ module Rubsh
238
194
  @_long_sep = opt.v
239
195
  when :_long_prefix
240
196
  @_long_prefix = opt.v
241
- when :_pipeline
242
- @_pipeline = opt.v
243
197
  end
244
198
  end
245
199
 
200
+ def spawn
201
+ args = spawn_arguments
202
+ @pid = ::Process.spawn(*args)
203
+ @started_at = Time.now
204
+ @in_wr&.write(@_in_data) if @_in_data
205
+ @in_wr&.close
206
+
207
+ if @out_rd
208
+ @out_rd_reader = StreamReader.new(@out_rd, bufsize: @_capture ? @_out_bufsize : nil, &proc { |chunk|
209
+ @stdout_data << chunk unless @_no_out
210
+ @_capture&.call(chunk, nil)
211
+ })
212
+ end
213
+ if @err_rd
214
+ @err_rd_reader = StreamReader.new(@err_rd, bufsize: @_capture ? @_err_bufsize : nil, &proc { |chunk|
215
+ @stderr_data << chunk unless @_no_err
216
+ @_capture&.call(nil, chunk)
217
+ })
218
+ end
219
+ ensure
220
+ @in_rd&.close
221
+ @out_wr&.close
222
+ @err_wr&.close
223
+ end
224
+
225
+ def spawn_arguments
226
+ env = @_env
227
+ cmd_args = compile_cmd_args
228
+ redirection_args = compile_redirection_args
229
+ extra_args = compile_extra_args
230
+
231
+ # For logging
232
+ @prog_with_args = [@progpath].concat(cmd_args).join(" ")
233
+
234
+ # .
235
+ _args =
236
+ if env
237
+ [env, [@progpath, @prog], *cmd_args, **redirection_args, **extra_args, unsetenv_others: true]
238
+ else
239
+ [[@progpath, @prog], *cmd_args, **redirection_args, **extra_args]
240
+ end
241
+ end
242
+
246
243
  def compile_cmd_args
247
244
  @args.map { |arg| arg.compile(long_sep: @_long_sep, long_prefix: @_long_prefix) }.compact.flatten
248
245
  end
@@ -277,67 +274,38 @@ module Rubsh
277
274
  args
278
275
  end
279
276
 
280
- def compile_extra_args(cwd: nil)
281
- chdir = cwd || @_cwd
282
-
277
+ def compile_extra_args
283
278
  args = {}
284
- args[:chdir] = chdir if chdir
279
+ args[:chdir] = @_cwd if @_cwd
285
280
  args
286
281
  end
287
282
 
288
- def spawn
289
- args = __spawn_arguments
290
- @pid = ::Process.spawn(*args)
291
- @started_at = Time.now
292
- @in_wr&.write(@_in_data) if @_in_data
293
- @in_wr&.close
294
-
295
- if @out_rd
296
- @out_rd_reader = StreamReader.new(@out_rd, bufsize: @_capture ? @_out_bufsize : nil, &proc { |chunk|
297
- @stdout_data << chunk unless @_no_out
298
- @_capture&.call(chunk, nil)
299
- })
300
- end
301
- if @err_rd
302
- @err_rd_reader = StreamReader.new(@err_rd, bufsize: @_capture ? @_err_bufsize : nil, &proc { |chunk|
303
- @stderr_data << chunk unless @_no_err
304
- @_capture&.call(nil, chunk)
305
- })
306
- end
307
- ensure
308
- @in_rd&.close
309
- @out_wr&.close
310
- @err_wr&.close
311
- end
312
-
313
- def wait2(timeout: nil)
283
+ def wait2(pid, timeout)
314
284
  timeout_occurred = false
315
285
  _, status = nil, nil
316
286
 
317
287
  if timeout
318
288
  begin
319
- ::Timeout.timeout(timeout) { _, status = ::Process.wait2(@pid) }
289
+ ::Timeout.timeout(timeout) { _, status = ::Process.wait2(pid) }
320
290
  rescue ::Timeout::Error
321
291
  timeout_occurred = true
322
292
 
323
- ::Process.kill("TERM", @pid) # graceful stop
293
+ ::Process.kill("TERM", pid) # graceful stop
324
294
  30.times do
325
- _, status = ::Process.wait2(@pid, ::Process::WNOHANG | ::Process::WUNTRACED)
295
+ _, status = ::Process.wait2(pid, ::Process::WNOHANG | ::Process::WUNTRACED)
326
296
  break if status
327
297
  sleep 0.1
328
298
  end
329
- failure = @pid if status.nil?
299
+ failure = pid if status.nil?
330
300
  failure && ::Process.kill("KILL", failure) # forceful stop
331
301
  end
332
302
  else
333
- _, status = ::Process.wait2(@pid)
303
+ _, status = ::Process.wait2(pid)
334
304
  end
335
305
 
336
- @exit_code = status&.exitstatus
306
+ @exit_code = status&.exitstatus || -1
337
307
  @finished_at = Time.now
338
308
  raise Exceptions::CommandTimeoutError, "execution expired" if timeout_occurred
339
- rescue Errno::ECHILD, Errno::ESRCH
340
- raise Exceptions::CommandTimeoutError, "execution expired" if timeout_occurred
341
309
  ensure
342
310
  @out_rd_reader&.wait
343
311
  @err_rd_reader&.wait
@@ -345,18 +313,8 @@ module Rubsh
345
313
 
346
314
  def handle_return_code
347
315
  return if ok?
348
- message = format("\n\n RAN: %s\n\n STDOUT:\n%s\n STDERR:\n%s\n", @prog_with_args, @stdout_data, @stderr_data)
316
+ message = format("\n\n $?: %s\n\n RAN: %s\n\n STDOUT:\n%s\n\n STDERR:\n%s\n", @exit_code, @prog_with_args, @stdout_data, @stderr_data)
349
317
  raise Exceptions::CommandReturnFailureError.new(@exit_code, message)
350
318
  end
351
-
352
- def run_in_background
353
- spawn
354
- Process.detach(@pid)
355
- end
356
-
357
- def run_in_foreground
358
- spawn
359
- wait(timeout: @_timeout)
360
- end
361
319
  end
362
320
  end
data/lib/rubsh/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rubsh
4
- VERSION = "2.2.6"
4
+ VERSION = "3.0.0"
5
5
  end
data/lib/rubsh.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "open3"
4
3
  require "timeout"
5
4
 
6
5
  require_relative "rubsh/argument"
@@ -8,14 +7,11 @@ require_relative "rubsh/command"
8
7
  require_relative "rubsh/exceptions"
9
8
  require_relative "rubsh/option"
10
9
  require_relative "rubsh/running_command"
11
- require_relative "rubsh/running_pipeline"
12
- require_relative "rubsh/shell/env"
13
- require_relative "rubsh/shell"
14
10
  require_relative "rubsh/stream_reader"
15
11
  require_relative "rubsh/version"
16
12
 
17
13
  module Rubsh
18
- def self.new
19
- Shell.new
14
+ def self.cmd(prog)
15
+ Command.new(prog)
20
16
  end
21
17
  end
data/rubsh.gemspec CHANGED
@@ -10,13 +10,13 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = "Rubsh (a.k.a. ruby-sh) - Inspired by python-sh, allows you to call any program as if it were a function."
12
12
  spec.description = "Rubsh (a.k.a. ruby-sh) - Inspired by python-sh, allows you to call any program as if it were a function."
13
- spec.homepage = "https://github.com/souk4711/rubsh"
13
+ spec.homepage = "https://github.com/souk4711/ruby-sh"
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = ">= 2.7.0"
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
- spec.metadata["source_code_uri"] = "https://github.com/souk4711/rubsh"
19
- spec.metadata["changelog_uri"] = "https://github.com/souk4711/rubsh"
18
+ spec.metadata["source_code_uri"] = "https://github.com/souk4711/ruby-sh"
19
+ spec.metadata["changelog_uri"] = "https://github.com/souk4711/ruby-sh"
20
20
 
21
21
  # Specify which files should be added to the gem when it is released.
22
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-sh
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.6
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Doe
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2023-09-26 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: Rubsh (a.k.a. ruby-sh) - Inspired by python-sh, allows you to call any
14
13
  program as if it were a function.
@@ -19,7 +18,6 @@ extensions: []
19
18
  extra_rdoc_files: []
20
19
  files:
21
20
  - ".editorconfig"
22
- - ".overcommit.yml"
23
21
  - ".rspec"
24
22
  - ".rubocop.yml"
25
23
  - ".ruby-version"
@@ -36,21 +34,17 @@ files:
36
34
  - lib/rubsh/exceptions.rb
37
35
  - lib/rubsh/option.rb
38
36
  - lib/rubsh/running_command.rb
39
- - lib/rubsh/running_pipeline.rb
40
- - lib/rubsh/shell.rb
41
- - lib/rubsh/shell/env.rb
42
37
  - lib/rubsh/stream_reader.rb
43
38
  - lib/rubsh/version.rb
44
39
  - rubsh.gemspec
45
- homepage: https://github.com/souk4711/rubsh
40
+ homepage: https://github.com/souk4711/ruby-sh
46
41
  licenses:
47
42
  - MIT
48
43
  metadata:
49
- homepage_uri: https://github.com/souk4711/rubsh
50
- source_code_uri: https://github.com/souk4711/rubsh
51
- changelog_uri: https://github.com/souk4711/rubsh
44
+ homepage_uri: https://github.com/souk4711/ruby-sh
45
+ source_code_uri: https://github.com/souk4711/ruby-sh
46
+ changelog_uri: https://github.com/souk4711/ruby-sh
52
47
  rubygems_mfa_required: 'true'
53
- post_install_message:
54
48
  rdoc_options: []
55
49
  require_paths:
56
50
  - lib
@@ -65,8 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
59
  - !ruby/object:Gem::Version
66
60
  version: '0'
67
61
  requirements: []
68
- rubygems_version: 3.3.7
69
- signing_key:
62
+ rubygems_version: 3.6.9
70
63
  specification_version: 4
71
64
  summary: Rubsh (a.k.a. ruby-sh) - Inspired by python-sh, allows you to call any program
72
65
  as if it were a function.
data/.overcommit.yml DELETED
@@ -1,26 +0,0 @@
1
- # Use this file to configure the Overcommit hooks you wish to use. This will
2
- # extend the default configuration defined in:
3
- # https://github.com/sds/overcommit/blob/master/config/default.yml
4
- #
5
- # At the topmost level of this YAML file is a key representing type of hook
6
- # being run (e.g. pre-commit, commit-msg, etc.). Within each type you can
7
- # customize each hook, such as whether to only run it on certain files (via
8
- # `include`), whether to only display output if it fails (via `quiet`), etc.
9
- #
10
- # For a complete list of hooks, see:
11
- # https://github.com/sds/overcommit/tree/master/lib/overcommit/hook
12
- #
13
- # For a complete list of options that you can use to customize hooks, see:
14
- # https://github.com/sds/overcommit#configuration
15
- #
16
- # Uncomment the following lines to make the configuration take effect.
17
-
18
- PreCommit:
19
- RuboCop:
20
- enabled: true
21
- command: 'bin/rubocop'
22
-
23
- PrePush:
24
- RSpec:
25
- enabled: true
26
- command: 'bin/rspec'
@@ -1,268 +0,0 @@
1
- module Rubsh
2
- class RunningPipeline
3
- SPECIAL_KWARGS = %i[
4
- _in_data
5
- _in
6
- _out
7
- _err
8
- _err_to_out
9
- _capture
10
- _bg
11
- _env
12
- _timeout
13
- _cwd
14
- _ok_code
15
- _out_bufsize
16
- _err_bufsize
17
- _no_out
18
- _no_err
19
- ]
20
-
21
- # @!attribute [r] exit_code
22
- # @return [Number]
23
- attr_reader :exit_code
24
-
25
- # @!attribute [r] started_at
26
- # @return [Time]
27
- attr_reader :started_at
28
-
29
- # @!attribute [r] finished_at
30
- # @return [Time]
31
- attr_reader :finished_at
32
-
33
- # @!attribute [r] stdout_data
34
- # @return [String]
35
- attr_reader :stdout_data
36
-
37
- # @!attribute [r] stderr_data
38
- # @return [String]
39
- attr_reader :stderr_data
40
-
41
- def initialize(sh)
42
- @sh = sh
43
- @rcmds = []
44
-
45
- # Runtime
46
- @prog_with_args = nil
47
- @exit_code = nil
48
- @started_at = nil
49
- @finished_at = nil
50
- @stdout_data = "".force_encoding(::Encoding.default_external)
51
- @stderr_data = "".force_encoding(::Encoding.default_external)
52
- @in_rd = nil
53
- @in_wr = nil
54
- @out_rd = nil
55
- @out_wr = nil
56
- @err_rd = nil
57
- @err_wr = nil
58
- @out_rd_reader = nil
59
- @err_rd_reader = nil
60
- @waiters = []
61
-
62
- # Special Kwargs - Controlling Input/Output
63
- @_in_data = nil
64
- @_in = nil
65
- @_out = nil
66
- @_err = nil
67
- @_err_to_out = false
68
- @_capture = nil
69
-
70
- # Special Kwargs - Execution
71
- @_bg = false
72
- @_env = nil
73
- @_timeout = nil
74
- @_cwd = nil
75
- @_ok_code = [0]
76
-
77
- # Special Kwargs - Performance & Optimization
78
- @_out_bufsize = 0
79
- @_err_bufsize = 0
80
- @_no_out = false
81
- @_no_err = false
82
- end
83
-
84
- # @return [Numeric, nil]
85
- def wall_time
86
- @finished_at.nil? ? nil : @finished_at - @started_at
87
- end
88
- alias_method :execution_time, :wall_time
89
-
90
- # @return [Boolean]
91
- def ok?
92
- @_ok_code.include?(@exit_code)
93
- end
94
-
95
- # @return [void]
96
- def wait(timeout: nil)
97
- wait2(timeout: timeout)
98
- handle_return_code
99
- end
100
-
101
- # @return [String]
102
- def to_s
103
- @prog_with_args
104
- end
105
-
106
- # @!visibility private
107
- def __add_running_command(cmd)
108
- @rcmds << cmd
109
- end
110
-
111
- # @!visibility private
112
- def __run(**kwargs)
113
- raise Exceptions::CommandNotFoundError, format("no commands") if @rcmds.length == 0
114
- extract_opts(**kwargs)
115
- @_bg ? run_in_background : run_in_foreground
116
- end
117
-
118
- private
119
-
120
- def extract_opts(**kwargs)
121
- kwargs.each do |k, v|
122
- raise ::ArgumentError, format("unsupported special kwarg `%s'", k) unless SPECIAL_KWARGS.include?(k.to_sym)
123
- case k.to_sym
124
- when :_in_data
125
- @_in_data = v
126
- when :_in
127
- @_in = v
128
- when :_out
129
- @_out = v
130
- when :_err
131
- @_err = v
132
- when :_err_to_out
133
- @_err_to_out = v
134
- when :_capture
135
- @_capture = v
136
- when :_bg
137
- @_bg = v
138
- when :_env
139
- @_env = v.transform_keys(&:to_s).transform_values(&:to_s)
140
- when :_timeout
141
- @_timeout = v
142
- when :_cwd
143
- @_cwd = v
144
- when :_ok_code
145
- @_ok_code = [*v]
146
- when :_out_bufsize
147
- @_out_bufsize = v
148
- when :_err_bufsize
149
- @_err_bufsize = v
150
- when :_no_out
151
- @_no_out = v
152
- when :_no_err
153
- @_no_err = v
154
- end
155
- end
156
- end
157
-
158
- def compile_redirection_args
159
- args = {}
160
-
161
- if @_in
162
- args[:in] = @_in
163
- else
164
- @in_rd, @in_wr = ::IO.pipe
165
- @in_wr.sync = true
166
- args[:in] = @in_rd.fileno
167
- end
168
-
169
- if @_out
170
- args[:out] = @_out
171
- else
172
- @out_rd, @out_wr = ::IO.pipe
173
- args[:out] = @out_wr.fileno
174
- end
175
-
176
- if @_err_to_out
177
- args[:err] = [:child, :out]
178
- elsif @_err
179
- args[:err] = @_err
180
- else
181
- @err_rd, @err_wr = ::IO.pipe
182
- args[:err] = @err_wr.fileno
183
- end
184
-
185
- args
186
- end
187
-
188
- def spawn
189
- cmds = @rcmds.map { |r| r.__spawn_arguments(env: @_env, cwd: @_cwd, redirection_args: {}) }
190
- @prog_with_args = @rcmds.map(&:__prog_with_args).join(" | ")
191
- @waiters = ::Open3.pipeline_start(*cmds, compile_redirection_args)
192
- @started_at = Time.now
193
- @in_wr&.write(@_in_data) if @_in_data
194
- @in_wr&.close
195
-
196
- if @out_rd
197
- @out_rd_reader = StreamReader.new(@out_rd, bufsize: @_capture ? @_out_bufsize : nil, &proc { |chunk|
198
- @stdout_data << chunk unless @_no_out
199
- @_capture&.call(chunk, nil)
200
- })
201
- end
202
- if @err_rd
203
- @err_rd_reader = StreamReader.new(@err_rd, bufsize: @_capture ? @_err_bufsize : nil, &proc { |chunk|
204
- @stderr_data << chunk unless @_no_err
205
- @_capture&.call(nil, chunk)
206
- })
207
- end
208
- ensure
209
- @in_rd&.close
210
- @out_wr&.close
211
- @err_wr&.close
212
- end
213
-
214
- def wait2(timeout: nil)
215
- timeout_occurred = false
216
- last_status = nil
217
-
218
- if timeout
219
- begin
220
- ::Timeout.timeout(timeout) { last_status = @waiters.map(&:value)[-1] }
221
- rescue ::Timeout::Error
222
- timeout_occurred = true
223
-
224
- failures = []
225
- @waiters.each { |w| ::Process.kill("TERM", w.pid) } # graceful stop
226
- @waiters.each { |w|
227
- _, status = nil, nil
228
- 30.times do
229
- _, status = ::Process.wait2(w.pid, ::Process::WNOHANG | ::Process::WUNTRACED)
230
- break if status
231
- sleep 0.1
232
- rescue ::Errno::ECHILD, ::Errno::ESRCH
233
- status = true
234
- end
235
- failures << w.pid if status.nil?
236
- }
237
- failures.each { |pid| ::Process.kill("KILL", pid) } # forceful stop
238
- end
239
- else
240
- last_status = @waiters.map(&:value)[-1]
241
- end
242
-
243
- @exit_code = last_status&.exitstatus
244
- @finished_at = Time.now
245
- raise Exceptions::CommandTimeoutError, "execution expired" if timeout_occurred
246
- rescue ::Errno::ECHILD, ::Errno::ESRCH
247
- raise Exceptions::CommandTimeoutError, "execution expired" if timeout_occurred
248
- ensure
249
- @out_rd_reader&.wait
250
- @err_rd_reader&.wait
251
- end
252
-
253
- def handle_return_code
254
- return if ok?
255
- message = format("\n\n RAN: %s\n\n STDOUT:\n%s\n STDERR:\n%s\n", @prog_with_args, @stdout_data, @stderr_data)
256
- raise Exceptions::CommandReturnFailureError.new(@exit_code, message)
257
- end
258
-
259
- def run_in_background
260
- spawn
261
- end
262
-
263
- def run_in_foreground
264
- spawn
265
- wait(timeout: @_timeout)
266
- end
267
- end
268
- end
@@ -1,15 +0,0 @@
1
- module Rubsh
2
- class Shell
3
- class Env
4
- attr_reader :path
5
-
6
- def initialize
7
- @path = ::ENV["PATH"].split(::File::PATH_SEPARATOR)
8
- end
9
-
10
- def path=(path)
11
- @path = [*path]
12
- end
13
- end
14
- end
15
- end