mixlib-shellout 3.3.9 → 3.4.10

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a9ab082811bde7ebba65cb6d326ff71d9f55e6a9a8d966a9294a173c56cf35b
4
- data.tar.gz: 8eb25e4d17a30d1d1fc1e8a3f9e6fa0434dc6c692f4e461980d7cd670cbceb2e
3
+ metadata.gz: fcac251ffc6584464c8df6cc4d1583eb3d8c0d520ac987139f733baffcde3f24
4
+ data.tar.gz: 53076e837afe3d68a5c23c92186df8c44243a1432615866edf4cd527924d0918
5
5
  SHA512:
6
- metadata.gz: d0ae915100dd53a40c78f3c6dc7439d99de2684b9a057cdbbc724cf8c41997c5a279912af76f4e3b00b9b732c207f98ca9d2e3f5225b30e5aea3941c21c65646
7
- data.tar.gz: 9a4d490d87c8f9d2297c84ef7e81e844769d581b59b1bca36c8ed2a50a8a41e7909d5c788e36207b8f224002ecc7a1ad263d09b272598fce6ae16a45fe47d52f
6
+ metadata.gz: '019e84c71357cc9d3e79ce34d45f31d18d1fda1dc1f4e54a3172a26822481f873d25a1aea1f70f71cc39a84a687b4cbc4fc49b08eb7581ecac0a0c184ca7c952'
7
+ data.tar.gz: bafd1b3456b24b846346d8dc1acf1b88791fec0fc9912e84befe4554898019ae4eafbd413bf3f5b34d31fe8a946dee874b21cf73cab012c975ab8fd1a09a744c
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  #
2
3
  # Author:: Daniel DeLeo (<dan@chef.io>)
3
4
  # Copyright:: Copyright (c) Chef Software Inc.
@@ -1,5 +1,5 @@
1
1
  module Mixlib
2
2
  class ShellOut
3
- VERSION = "3.3.9".freeze
3
+ VERSION = "3.4.10".freeze
4
4
  end
5
5
  end
@@ -447,7 +447,6 @@ module Process
447
447
 
448
448
  def create_process_as_user(token, app, cmd, process_security,
449
449
  thread_security, inherit, creation_flags, env, cwd, startinfo, procinfo)
450
-
451
450
  bool = CreateProcessAsUserW(
452
451
  token, # User token handle
453
452
  app, # App name
@@ -479,7 +478,6 @@ module Process
479
478
 
480
479
  def create_process_with_logon(logon, domain, passwd, logon_flags, app, cmd,
481
480
  creation_flags, env, cwd, startinfo, procinfo)
482
-
483
481
  bool = CreateProcessWithLogonW(
484
482
  logon, # User
485
483
  domain, # Domain
@@ -501,7 +499,6 @@ module Process
501
499
 
502
500
  def create_process(app, cmd, process_security, thread_security, inherit,
503
501
  creation_flags, env, cwd, startinfo, procinfo)
504
-
505
502
  bool = CreateProcessW(
506
503
  app, # App name
507
504
  cmd, # Command line
@@ -1,4 +1,6 @@
1
1
  #
2
+ # frozen_string_literal: true
3
+
2
4
  # Author:: Daniel DeLeo (<dan@chef.io>)
3
5
  # Author:: John Keiser (<jkeiser@chef.io>)
4
6
  # Author:: Ho-Sheng Hsiao (<hosh@chef.io>)
@@ -24,7 +26,6 @@ require_relative "windows/core_ext"
24
26
  module Mixlib
25
27
  class ShellOut
26
28
  module Windows
27
-
28
29
  include Process::Functions
29
30
  include Process::Constants
30
31
 
@@ -44,9 +45,9 @@ module Mixlib
44
45
  raise InvalidCommandOption, "`elevated` option should be passed only with `username` and `password`."
45
46
  end
46
47
 
47
- if opts[:elevated] && opts[:elevated] != true && opts[:elevated] != false
48
- raise InvalidCommandOption, "Invalid value passed for `elevated`. Please provide true/false."
49
- end
48
+ return unless opts[:elevated] && opts[:elevated] != true && opts[:elevated] != false
49
+
50
+ raise InvalidCommandOption, "Invalid value passed for `elevated`. Please provide true/false."
50
51
  end
51
52
 
52
53
  #--
@@ -59,18 +60,17 @@ module Mixlib
59
60
  stdout_read, stdout_write = IO.pipe
60
61
  stderr_read, stderr_write = IO.pipe
61
62
  stdin_read, stdin_write = IO.pipe
62
- open_streams = [ stdout_read, stderr_read ]
63
+ open_streams = [stdout_read, stderr_read]
63
64
  @execution_time = 0
64
65
 
65
66
  begin
66
-
67
67
  #
68
68
  # Set cwd, environment, appname, etc.
69
69
  #
70
70
  app_name, command_line = command_to_run(combine_args(*command))
71
71
  create_process_args = {
72
- app_name: app_name,
73
- command_line: command_line,
72
+ app_name:,
73
+ command_line:,
74
74
  startup_info: {
75
75
  stdout: stdout_write,
76
76
  stderr: stderr_write,
@@ -110,12 +110,10 @@ module Mixlib
110
110
  @execution_time = Time.now - start_wait
111
111
  # Get process exit code
112
112
  exit_code = [0].pack("l")
113
- unless GetExitCodeProcess(process.process_handle, exit_code)
114
- raise get_last_error
115
- end
113
+ raise get_last_error unless GetExitCodeProcess(process.process_handle, exit_code)
116
114
 
117
115
  @status = ThingThatLooksSortOfLikeAProcessStatus.new
118
- @status.exitstatus = exit_code.unpack("l").first
116
+ @status.exitstatus = exit_code.unpack1("l")
119
117
 
120
118
  return self
121
119
  when WAIT_TIMEOUT
@@ -144,16 +142,13 @@ module Mixlib
144
142
  else
145
143
  raise "Unknown response from WaitForSingleObject(#{process.process_handle}, #{timeout * 1000}): #{wait_status}"
146
144
  end
147
-
148
145
  end
149
-
150
146
  ensure
151
147
  CloseHandle(process.thread_handle) if process.thread_handle
152
148
  CloseHandle(process.process_handle) if process.process_handle
153
149
  Process.unload_user_profile(token, profile) if profile
154
150
  CloseHandle(token) if token
155
151
  end
156
-
157
152
  ensure
158
153
  #
159
154
  # Consume all remaining data from the pipes until they are closed
@@ -168,6 +163,7 @@ module Mixlib
168
163
 
169
164
  class ThingThatLooksSortOfLikeAProcessStatus
170
165
  attr_accessor :exitstatus
166
+
171
167
  def success?
172
168
  exitstatus == 0
173
169
  end
@@ -183,7 +179,11 @@ module Mixlib
183
179
 
184
180
  if ready.first.include?(stdout_read)
185
181
  begin
186
- next_chunk = stdout_read.readpartial(READ_SIZE)
182
+ # The unary plus operator (+) creates a mutable copy of the string returned by readpartial.
183
+ # This is necessary because readpartial may return a frozen string, and we need to be able
184
+ # to modify the string (append to buffers, manipulate encoding, etc.) in subsequent operations.
185
+ # Without the +, attempting to modify a frozen string would raise a FrozenError.
186
+ next_chunk = +stdout_read.readpartial(READ_SIZE)
187
187
  @stdout << next_chunk
188
188
  @live_stdout << next_chunk if @live_stdout
189
189
  rescue EOFError
@@ -194,7 +194,7 @@ module Mixlib
194
194
 
195
195
  if ready.first.include?(stderr_read)
196
196
  begin
197
- next_chunk = stderr_read.readpartial(READ_SIZE)
197
+ next_chunk = +stderr_read.readpartial(READ_SIZE)
198
198
  @stderr << next_chunk
199
199
  @live_stderr << next_chunk if @live_stderr
200
200
  rescue EOFError
@@ -261,7 +261,7 @@ module Mixlib
261
261
  if exe_needs_cmd?(exe)
262
262
  run_under_cmd(command)
263
263
  else
264
- [ exe, command ]
264
+ [exe, command]
265
265
  end
266
266
  end
267
267
 
@@ -275,14 +275,14 @@ module Mixlib
275
275
  # https://github.com/chef/mixlib-shellout/pull/2#issuecomment-4837859
276
276
  # http://ss64.com/nt/syntax-esc.html
277
277
  def run_under_cmd(command)
278
- [ ENV["COMSPEC"], "cmd /c \"#{command}\"" ]
278
+ [ENV["COMSPEC"], "cmd /c \"#{command}\""]
279
279
  end
280
280
 
281
281
  # FIXME: this extracts ARGV[0] but is it correct?
282
282
  def candidate_executable_for_command(command)
283
283
  if command =~ /^\s*"(.*?)"/ || command =~ /^\s*([^\s]+)/
284
284
  # If we have quotes, do an exact match, else pick the first word ignoring the leading spaces
285
- $1
285
+ ::Regexp.last_match(1)
286
286
  else
287
287
  ""
288
288
  end
@@ -405,15 +405,15 @@ module Mixlib
405
405
  def kill_process(instance, logger)
406
406
  child_pid = instance.wmi_ole_object.processid
407
407
  logger&.debug([
408
- "killing child process #{child_pid}::",
409
- "#{instance.wmi_ole_object.Name} of parent #{pid}",
410
- ].join)
408
+ "killing child process #{child_pid}::",
409
+ "#{instance.wmi_ole_object.Name} of parent #{pid}",
410
+ ].join)
411
411
  Process.kill(:KILL, instance.wmi_ole_object.processid)
412
412
  rescue SystemCallError
413
413
  logger&.debug([
414
- "Failed to kill child process #{child_pid}::",
415
- "#{instance.wmi_ole_object.Name} of parent #{pid}",
416
- ].join)
414
+ "Failed to kill child process #{child_pid}::",
415
+ "#{instance.wmi_ole_object.Name} of parent #{pid}",
416
+ ].join)
417
417
  end
418
418
 
419
419
  def format_process(process, app_name, command_line, timeout)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  #--
2
3
  # Author:: Daniel DeLeo (<dan@chef.io>)
3
4
  # Copyright:: Copyright (c) Chef Software Inc.
@@ -170,7 +171,8 @@ module Mixlib
170
171
  # cmd = Mixlib::ShellOut.new("apachectl", "start", :user => 'www', :env => nil, :cwd => '/tmp')
171
172
  # cmd.run_command # etc.
172
173
  def initialize(*command_args)
173
- @stdout, @stderr, @process_status = "", "", ""
174
+ # Since ruby 4.0 will freeze string literals by default, we are assigning mutable strings here.
175
+ @stdout, @stderr, @process_status = String.new(""), String.new(""), String.new("")
174
176
  @live_stdout = @live_stderr = nil
175
177
  @input = nil
176
178
  @log_level = :debug
@@ -238,7 +240,7 @@ module Mixlib
238
240
  def format_for_exception
239
241
  return "Command execution failed. STDOUT/STDERR suppressed for sensitive resource" if sensitive
240
242
 
241
- msg = ""
243
+ msg = String.new
242
244
  msg << "#{@terminate_reason}\n" if @terminate_reason
243
245
  msg << "---- Begin output of #{command} ----\n"
244
246
  msg << "STDOUT: #{stdout.strip}\n"
@@ -268,7 +270,9 @@ module Mixlib
268
270
  # within +timeout+ seconds (default: 600s)
269
271
  def run_command
270
272
  if logger
271
- log_message = (log_tag.nil? ? "" : "#{@log_tag} ") << "sh(#{@command})"
273
+ prefix = log_tag.nil? ? "" : "#{@log_tag} "
274
+ log_message = prefix + "sh(#{@command})"
275
+ # log_message = (log_tag.nil? ? "" : "#{@log_tag} ") << "sh(#{@command})"
272
276
  logger.send(log_level, log_message)
273
277
  end
274
278
  super
@@ -334,11 +338,11 @@ module Mixlib
334
338
  when "returns"
335
339
  self.valid_exit_codes = Array(setting)
336
340
  when "live_stream"
337
- self.live_stdout = self.live_stderr = setting
341
+ self.live_stdout = self.live_stderr = setting.is_a?(String) ? String.new(setting) : setting
338
342
  when "live_stdout"
339
- self.live_stdout = setting
343
+ self.live_stdout = setting.is_a?(String) ? String.new(setting) : setting
340
344
  when "live_stderr"
341
- self.live_stderr = setting
345
+ self.live_stderr = setting.is_a?(String) ? String.new(setting) : setting
342
346
  when "input"
343
347
  self.input = setting
344
348
  when "logger"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixlib-shellout
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.9
4
+ version: 3.4.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef Software Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-04 00:00:00.000000000 Z
11
+ date: 2025-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-utils
@@ -50,14 +50,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: '3.0'
53
+ version: '3.1'
54
54
  required_rubygems_version: !ruby/object:Gem::Requirement
55
55
  requirements:
56
56
  - - ">="
57
57
  - !ruby/object:Gem::Version
58
58
  version: '0'
59
59
  requirements: []
60
- rubygems_version: 3.2.3
60
+ rubygems_version: 3.3.27
61
61
  signing_key:
62
62
  specification_version: 4
63
63
  summary: Run external commands on Unix or Windows