diff --git a/lib/foreman/cli.rb b/lib/foreman/cli.rb index 0e82a04..cb259c0 100644 --- a/lib/foreman/cli.rb +++ b/lib/foreman/cli.rb @@ -5,15 +5,23 @@ require "thor" require "yaml" class Foreman::CLI < Thor - + class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile" - + desc "start", "Start the application" method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env" method_option :port, :type => :numeric, :aliases => "-p" method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"' + class << self + # Hackery. Take the run method away from Thor so that we can redefine it. + def is_thor_reserved_word?(word, type) + return false if word == 'run' + super + end + end + def start check_procfile! engine.start @@ -53,7 +61,20 @@ class Foreman::CLI < Thor error "no processes defined" unless engine.procfile.entries.length > 0 display "valid procfile detected (#{engine.procfile.process_names.join(', ')})" end + + desc "run COMMAND", "Run a command using your application's environment" + def run(*args) + engine.apply_environment! + begin + exec args.join(" ") + rescue Errno::EACCES + error "not executable: #{args.first}" + rescue Errno::ENOENT + error "command not found: #{args.first}" + end + end + private ###################################################################### def check_procfile! @@ -87,5 +108,4 @@ private ###################################################################### defaults = YAML::load_file(".foreman") || {} Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options)) end - end diff --git a/spec/foreman/cli_spec.rb b/spec/foreman/cli_spec.rb index 2250d08..8b9285f 100644 --- a/spec/foreman/cli_spec.rb +++ b/spec/foreman/cli_spec.rb @@ -89,5 +89,54 @@ describe "Foreman::CLI" do end end end + + describe "run" do + describe "with a valid Procfile" do + before { write_procfile } + + describe "and a command" do + let(:command) { ["ls", "-l"] } + + before(:each) do + stub(subject).exec + end + + it "should load the environment file" do + write_env + preserving_env do + subject.run *command + ENV["FOO"].should == "bar" + end + + ENV["FOO"].should be_nil + end + + it "should runute the command as a string" do + mock(subject).exec(command.join(" ")) + subject.run *command + end + end + + describe "and a non-existent command" do + let(:command) { "iuhtngrglhulhdfg" } + + it "should print an error" do + mock_error(subject, "command not found: #{command}") do + subject.run command + end + end + end + + describe "and a non-executable command" do + let(:command) { __FILE__ } + + it "should print an error" do + mock_error(subject, "not executable: #{command}") do + subject.run command + end + end + end + end + end end diff --git a/spec/helper_spec.rb b/spec/helper_spec.rb new file mode 100644 index 0000000..6fd5efe --- /dev/null +++ b/spec/helper_spec.rb @@ -0,0 +1,18 @@ +require "spec_helper" + +describe "spec helpers" do + describe "#preserving_env" do + after { ENV.delete "FOO" } + + it "should remove added environment vars" do + preserving_env { ENV["FOO"] = "baz" } + ENV["FOO"].should == nil + end + + it "should reset modified environment vars" do + ENV["FOO"] = "bar" + preserving_env { ENV["FOO"] = "baz"} + ENV["FOO"].should == "bar" + end + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5a901bc..e22bd7a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -63,6 +63,16 @@ def example_export_file(filename) data end +def preserving_env + old_env = ENV.to_hash + begin + yield + ensure + ENV.clear + ENV.update(old_env) + end +end + RSpec.configure do |config| config.color_enabled = true config.include FakeFS::SpecHelpers