Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: #execute now accepts an optional :env hash #100

Merged
merged 1 commit into from Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,10 @@

This release ends support for ruby < 2.3.0. If you're on 2.2.x or earlier, we strongly suggest that you find the time to upgrade, because [official support for Ruby 2.2 ended on 2018-03-31](https://www.ruby-lang.org/en/news/2018/06/20/support-of-ruby-2-2-has-ended/).

#### Enhancements

* `MiniPortile.execute` now takes an optional `:env` hash, which is merged into the environment variables for the subprocess. Likely this is only useful for specialized use cases. [#99]


### 2.5.0 / 2020-02-24

Expand Down
38 changes: 25 additions & 13 deletions lib/mini_portile2/mini_portile.rb
Expand Up @@ -380,29 +380,41 @@ def extract_file(file, target)
execute('extract', [tar_exe, "#{tar_compression_switch(filename)}xf", file, "-C", target], {:cd => Dir.pwd, :initial_message => false})
end

def execute(action, command, options={})
log_out = log_file(action)
# command could be an array of args, or one string containing a command passed to the shell. See
# Process.spawn for more information.
def execute(action, command, command_opts={})
opt_message = command_opts.fetch(:initial_message, true)
opt_debug = command_opts.fetch(:debug, false)
opt_cd = command_opts.fetch(:cd) { work_path }
opt_env = command_opts.fetch(:env) { Hash.new }

Dir.chdir (options.fetch(:cd){ work_path }) do
if options.fetch(:initial_message){ true }
message "Running '#{action}' for #{@name} #{@version}... "
end
log_out = log_file(action)

Dir.chdir(opt_cd) do
output "DEBUG: env is #{opt_env.inspect}" if opt_debug
output "DEBUG: command is #{command.inspect}" if opt_debug
message "Running '#{action}' for #{@name} #{@version}... " if opt_message

if Process.respond_to?(:spawn) && ! RbConfig.respond_to?(:java)
args = [command].flatten + [{[:out, :err]=>[log_out, "a"]}]
options = {[:out, :err]=>[log_out, "a"]}
output "DEBUG: options are #{options.inspect}" if opt_debug
args = [opt_env, command, options].flatten
pid = spawn(*args)
Process.wait(pid)
else
redirected = if command.kind_of?(Array)
%Q{#{command.map(&:shellescape).join(" ")} > #{log_out.shellescape} 2>&1}
else
%Q{#{command} > #{log_out.shellescape} 2>&1}
end
env_args = opt_env.map { |k,v| "#{k}=#{v}".shellescape }.join(" ")
c = if command.kind_of?(Array)
command.map(&:shellescape).join(" ")
else
command
end
redirected = %Q{env #{env_args} #{c} > #{log_out.shellescape} 2>&1}
output "DEBUG: final command is #{redirected.inspect}" if opt_debug
system redirected
end

if $?.success?
output "OK"
output "OK" if opt_message
return true
else
if File.exist? log_out
Expand Down
39 changes: 39 additions & 0 deletions test/test_execute.rb
@@ -0,0 +1,39 @@
require_relative "helper"

class TestExecute < TestCase
def setup
super
@env = {"TEST_ENV_VAR1" => "VAR1_VALUE", "TEST_ENV_VAR2" => "VAR2_VALUE"}
@recipe = MiniPortile.new("test_execute", "1.0.0")
@log_path = @recipe.send(:tmp_path)
FileUtils.mkdir_p File.join(@log_path, "subdir") # normally created by `download`
end

def test_execute_one_big_string_arg
class << @recipe
def execute_with_env(env)
execute("testenv1",
%Q(ruby -e "puts ENV['TEST_ENV_VAR1'].inspect ; exit 0"),
{:env => env, :initial_message => false, :debug => true})
end
end

@recipe.execute_with_env(@env)

assert_equal("VAR1_VALUE".inspect, IO.read(File.join(@log_path, "testenv1.log")).chomp)
end

def test_execute_array_args
class << @recipe
def execute_with_env(env)
execute("testenv2",
["ruby", "-e", "puts ENV['TEST_ENV_VAR2'].inspect"],
{:env => env, :initial_message => false, :debug => true})
end
end

@recipe.execute_with_env(@env)

assert_equal("VAR2_VALUE".inspect, IO.read(File.join(@log_path, "testenv2.log")).chomp)
end
end