lib/pdk/cli/exec.rb in pdk-akerl-1.9.1.1 vs lib/pdk/cli/exec.rb in pdk-akerl-1.14.0.1
- old
+ new
@@ -1,27 +1,35 @@
-require 'bundler'
-require 'childprocess'
-require 'tempfile'
-require 'tty-spinner'
-require 'tty-which'
-
-require 'pdk/util'
-require 'pdk/util/git'
-require 'pdk/util/ruby_version'
-
module PDK
module CLI
module Exec
def self.execute(*cmd)
+ require 'pdk/cli/exec/command'
+
Command.new(*cmd).execute!
end
def self.execute_with_env(env, *cmd)
+ require 'pdk/cli/exec/command'
+
Command.new(*cmd).tap { |c| c.environment = env }.execute!
end
+ def self.execute_interactive(*cmd)
+ require 'pdk/cli/exec/interactive_command'
+
+ InteractiveCommand.new(*cmd).execute!
+ end
+
+ def self.execute_interactive_with_env(env, *cmd)
+ require 'pdk/cli/exec/interactive_command'
+
+ InteractiveCommand.new(*cmd).tap { |c| c.environment = env }.execute!
+ end
+
def self.ensure_bin_present!(bin_path, bin_name)
+ require 'tty-which'
+
message = _('Unable to find `%{name}`. Check that it is installed and try again.') % {
name: bin_name,
}
raise PDK::CLI::FatalError, message unless TTY::Which.exist?(bin_path)
@@ -32,17 +40,21 @@
execute(bundle_bin, *args)
end
def self.bundle_bin
+ require 'pdk/util/ruby_version'
+
bundle_bin = Gem.win_platform? ? 'bundle.bat' : 'bundle'
vendored_bin_path = File.join('private', 'ruby', PDK::Util::RubyVersion.active_ruby_version, 'bin', bundle_bin)
try_vendored_bin(vendored_bin_path, bundle_bin)
end
def self.try_vendored_bin(vendored_bin_path, fallback)
+ require 'pdk/util'
+
unless PDK::Util.package_install?
PDK.logger.debug(_("PDK package installation not found. Trying '%{fallback}' from the system PATH instead.") % {
fallback: fallback,
})
return fallback
@@ -58,189 +70,9 @@
return fallback
end
PDK.logger.debug(_("Using '%{vendored_bin}' from PDK package.") % { vendored_bin: vendored_bin_full_path })
vendored_bin_full_path
- end
-
- # TODO: decide how/when to connect stdin to child process for things like pry
- # TODO: need a way to set callbacks on new stdout/stderr data
- class Command
- attr_reader :argv
- attr_reader :context
- attr_accessor :timeout
- attr_accessor :environment
- attr_writer :exec_group
-
- def initialize(*argv)
- @argv = argv
-
- @process = ChildProcess.build(*@argv)
- @process.leader = true
-
- @stdout = Tempfile.new('stdout').tap { |io| io.sync = true }
- @stderr = Tempfile.new('stderr').tap { |io| io.sync = true }
-
- @process.io.stdout = @stdout
- @process.io.stderr = @stderr
-
- # Default to running things in the system context.
- @context = :system
-
- # Extra environment vars to add to base set.
- @environment = {}
-
- # Register the ExecGroup when running in parallel
- @exec_group = nil
- end
-
- def context=(new_context)
- unless [:system, :module, :pwd].include?(new_context)
- raise ArgumentError, _("Expected execution context to be :system or :module but got '%{context}'.") % { context: new_context }
- end
-
- @context = new_context
- end
-
- def register_spinner(spinner, opts = {})
- return unless PDK::CLI::Util.interactive?
- @success_message = opts.delete(:success)
- @failure_message = opts.delete(:failure)
-
- @spinner = spinner
- end
-
- def add_spinner(message, opts = {})
- return unless PDK::CLI::Util.interactive?
- @success_message = opts.delete(:success)
- @failure_message = opts.delete(:failure)
-
- @spinner = TTY::Spinner.new("[:spinner] #{message}", opts.merge(PDK::CLI::Util.spinner_opts_for_platform))
- end
-
- def update_environment(additional_env)
- @environment.merge!(additional_env)
- end
-
- def execute!
- # Start spinning if configured.
- @spinner.auto_spin if @spinner
-
- # Add custom env vars.
- @environment.each do |k, v|
- @process.environment[k] = v
- end
-
- @process.environment['BUNDLE_IGNORE_CONFIG'] = '1'
-
- if [:module, :pwd].include?(context)
- @process.environment['GEM_HOME'] = PDK::Util::RubyVersion.gem_home
- @process.environment['GEM_PATH'] = PDK::Util::RubyVersion.gem_path
-
- # Make sure invocation of Ruby prefers our private installation.
- package_binpath = PDK::Util.package_install? ? File.join(PDK::Util.pdk_package_basedir, 'bin') : nil
- @process.environment['PATH'] = [
- PDK::Util::RubyVersion.bin_path,
- File.join(@process.environment['GEM_HOME'], 'bin'),
- PDK::Util::RubyVersion.gem_paths_raw.map { |gem_path| File.join(gem_path, 'bin') },
- package_binpath,
- PDK::Util.package_install? ? PDK::Util::Git.git_paths : nil,
- ENV['PATH'],
- ].compact.flatten.join(File::PATH_SEPARATOR)
-
- mod_root = PDK::Util.module_root
-
- unless mod_root
- @spinner.error if @spinner
-
- raise PDK::CLI::FatalError, _('Current working directory is not part of a module. (No metadata.json was found.)')
- end
-
- if Dir.pwd == mod_root || context == :pwd
- run_process_in_clean_env!
- else
- Dir.chdir(mod_root) do
- run_process_in_clean_env!
- end
- end
- else
- run_process!
- end
-
- # Stop spinning when done (if configured).
- stop_spinner
-
- @stdout.rewind
- @stderr.rewind
-
- process_data = {
- stdout: @stdout.read,
- stderr: @stderr.read,
- exit_code: @process.exit_code,
- duration: @duration,
- }
-
- return process_data
- ensure
- @stdout.close
- @stderr.close
- end
-
- protected
-
- def stop_spinner
- return unless @spinner
-
- # If it is a single spinner, we need to send it a success/error message
- if @process.exit_code.zero?
- @spinner.success(@success_message || '')
- else
- @spinner.error(@failure_message || '')
- end
- end
-
- def run_process_in_clean_env!
- ::Bundler.with_clean_env do
- run_process!
- end
- end
-
- def run_process!
- command_string = argv.join(' ')
-
- PDK.logger.debug(_("Executing '%{command}'") % { command: command_string })
-
- if context == :module
- PDK.logger.debug(_('Command environment:'))
- @process.environment.each do |var, val|
- PDK.logger.debug(" #{var}: #{val}")
- end
- end
-
- start_time = Time.now
-
- begin
- @process.start
- rescue ChildProcess::LaunchError => e
- raise PDK::CLI::FatalError, _("Failed to execute '%{command}': %{message}") % { command: command_string, message: e.message }
- end
-
- if timeout
- begin
- @process.poll_for_exit(timeout)
- rescue ChildProcess::TimeoutError
- @process.stop # tries increasingly harsher methods to kill the process.
- end
- else
- # Wait indfinitely if no timeout set.
- @process.wait
- end
-
- @duration = Time.now - start_time
-
- PDK.logger.debug(_("Execution of '%{command}' complete (duration: %{duration_in_seconds}s; exit code: %{exit_code})") %
- { command: command_string, duration_in_seconds: @duration, exit_code: @process.exit_code })
- end
end
end
end
end