diff --git a/bin/producer b/bin/producer index 6de0817..3885ec6 100755 --- a/bin/producer +++ b/bin/producer @@ -2,4 +2,4 @@ require 'producer/core' -Producer::Core::CLI.new(ARGV).run! +Producer::Core::CLI.run!(ARGV) diff --git a/lib/producer/core/cli.rb b/lib/producer/core/cli.rb index abb5366..6309f6a 100644 --- a/lib/producer/core/cli.rb +++ b/lib/producer/core/cli.rb @@ -1,24 +1,34 @@ module Producer module Core class CLI + ArgumentError = Class.new(::ArgumentError) + USAGE = "Usage: #{File.basename $0} recipe_file" + class << self + def run!(arguments, output: $stderr) + begin + cli = new(arguments) + rescue ArgumentError + output.puts USAGE + exit 64 + end + cli.run! + end + end + attr_reader :arguments, :stdout def initialize(arguments, stdout: $stdout) + raise ArgumentError unless arguments.any? @arguments = arguments @stdout = stdout end def run! - check_arguments! interpreter.process recipe.tasks end - def check_arguments! - print_usage_and_exit(64) unless @arguments.length == 1 - end - def env @env ||= Env.new end @@ -30,14 +40,6 @@ module Producer def interpreter @interpreter ||= Interpreter.new end - - private - - def print_usage_and_exit(status) - @stdout.puts USAGE - - exit status - end end end end diff --git a/spec/producer/core/cli_spec.rb b/spec/producer/core/cli_spec.rb index 8b2a30d..6acb77d 100644 --- a/spec/producer/core/cli_spec.rb +++ b/spec/producer/core/cli_spec.rb @@ -11,12 +11,50 @@ module Producer::Core subject(:cli) { CLI.new(arguments, stdout: stdout) } + describe '.run!' do + let(:output) { StringIO.new } + subject(:run) { described_class.run! arguments, output: output } + + it 'builds a new CLI with given arguments' do + expect(CLI).to receive(:new).with(arguments).and_call_original + run + end + + it 'runs the CLI' do + cli = double 'cli' + allow(CLI).to receive(:new) { cli } + expect(cli).to receive :run! + run + end + + context 'when recipe argument is missing' do + let(:arguments) { [] } + + it 'exits with a return status of 64' do + expect { run }.to raise_error(SystemExit) { |e| + expect(e.status).to eq 64 + } + end + + it 'prints the usage' do + trap_exit { run } + expect(output.string).to match /\AUsage: .+/ + end + end + end + describe '#initialize' do subject(:cli) { CLI.new(arguments) } it 'assigns $stdout as the default standard output' do expect(cli.stdout).to be $stdout end + + context 'without arguments' do + let(:arguments) { [] } + + specify { expect { cli }.to raise_error described_class::ArgumentError } + end end describe '#arguments' do @@ -32,11 +70,6 @@ module Producer::Core end describe '#run!' do - it 'checks the arguments' do - expect(cli).to receive :check_arguments! - cli.run! - end - it 'processes the tasks with the interpreter' do allow(cli.recipe).to receive(:tasks) { [:some_task] } expect(cli.interpreter).to receive(:process).with [:some_task] @@ -44,29 +77,6 @@ module Producer::Core end end - describe '#check_arguments!' do - context 'when recipe argument is provided' do - it 'does not raise any error' do - expect { cli.check_arguments! }.to_not raise_error - end - end - - context 'when recipe argument is missing' do - let(:arguments) { [] } - - it 'exits with a return status of 64' do - expect { cli.check_arguments! }.to raise_error(SystemExit) { |e| - expect(e.status).to eq 64 - } - end - - it 'prints the usage' do - trap_exit { cli.check_arguments! } - expect(stdout.string).to match /\AUsage: .+/ - end - end - end - describe '#env' do it 'builds an environment with the current recipe' do expect(Env).to receive :new