diff --git a/lib/foreman/cli.rb b/lib/foreman/cli.rb index 2f69b21..6ecf2c2 100644 --- a/lib/foreman/cli.rb +++ b/lib/foreman/cli.rb @@ -75,10 +75,19 @@ class Foreman::CLI < Thor def run(*args) load_environment! + + if File.exist?(procfile) + engine.load_procfile(procfile) + end + pid = fork do begin engine.env.each { |k,v| ENV[k] = v } - exec args.shelljoin + if args.size == 1 && process = engine.process(args.first) + process.exec(:env => engine.env) + else + exec args.shelljoin + end rescue Errno::EACCES error "not executable: #{args.first}" rescue Errno::ENOENT diff --git a/lib/foreman/process.rb b/lib/foreman/process.rb index c395a6d..6ea3893 100644 --- a/lib/foreman/process.rb +++ b/lib/foreman/process.rb @@ -21,6 +21,21 @@ class Foreman::Process @options[:env] ||= {} end + # Get environment-expanded command for a +Process+ + # + # @param [Hash] custom_env ({}) Environment variables to merge with defaults + # + # @return [String] The expanded command + # + def expanded_command(custom_env={}) + env = @options[:env].merge(custom_env) + expanded_command = command.dup + env.each do |key, val| + expanded_command.gsub!("$#{key}", val) + end + expanded_command + end + # Run a +Process+ # # @param [Hash] options @@ -31,16 +46,12 @@ class Foreman::Process # @returns [Fixnum] pid The +pid+ of the process # def run(options={}) - env = options[:env] ? @options[:env].merge(options[:env]) : @options[:env] + env = @options[:env].merge(options[:env] || {}) output = options[:output] || $stdout if Foreman.windows? Dir.chdir(cwd) do - expanded_command = command.dup - env.each do |key, val| - expanded_command.gsub!("$#{key}", val) - end - Process.spawn env, expanded_command, :out => output, :err => output + Process.spawn env, expanded_command(env), :out => output, :err => output end elsif Foreman.jruby? require "posix/spawn" @@ -52,7 +63,7 @@ class Foreman::Process $stderr.reopen output env.each { |k,v| ENV[k] = v } wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}" - exec wrapped_command + Kernel.exec wrapped_command end else wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}" @@ -60,6 +71,20 @@ class Foreman::Process end end + # Exec a +Process+ + # + # @param [Hash] options + # + # @option options :env ({}) Environment variables to set for this execution + # + # @return Does not return + def exec(options={}) + env = @options[:env].merge(options[:env] || {}) + env.each { |k, v| ENV[k] = v } + Dir.chdir(cwd) + Kernel.exec expanded_command(env) + end + # Send a signal to this +Process+ # # @param [String] signal The signal to send diff --git a/spec/foreman/cli_spec.rb b/spec/foreman/cli_spec.rb index 595da0e..717ab52 100644 --- a/spec/foreman/cli_spec.rb +++ b/spec/foreman/cli_spec.rb @@ -73,6 +73,10 @@ describe "Foreman::CLI", :fakefs do forked_foreman("run #{resource_path("bin/env FOO")} -e #{resource_path(".env")}").should == "bar\n" end + it "can run a command from the Procfile" do + forked_foreman("run -f #{resource_path("Procfile")} test").should == "testing\n" + end + it "exits with the same exit code as the command" do fork_and_get_exitstatus("run echo 1").should == 0 fork_and_get_exitstatus("run date 'invalid_date'").should == 1