diff --git a/lib/rubygems/commands/build_command.rb b/lib/rubygems/commands/build_command.rb index 84faef2b82e4..fff5f7c76fab 100644 --- a/lib/rubygems/commands/build_command.rb +++ b/lib/rubygems/commands/build_command.rb @@ -61,14 +61,18 @@ def usage # :nodoc: end def execute - gem_name = get_one_optional_argument || find_gemspec - build_gem(gem_name) + if build_path = options[:build_path] + Dir.chdir(build_path) { build_gem } + return + end + + build_gem end private - def find_gemspec - gemspecs = Dir.glob("*.gemspec").sort + def find_gemspec(glob = "*.gemspec") + gemspecs = Dir.glob(glob).sort if gemspecs.size > 1 alert_error "Multiple gemspecs found: #{gemspecs}, please specify one" @@ -78,28 +82,19 @@ def find_gemspec gemspecs.first end - def build_gem(gem_name) - gemspec = File.extname(gem_name) == ".gemspec" ? gem_name : "#{gem_name}.gemspec" - - if File.exist?(gemspec) - spec = Gem::Specification.load(gemspec) - - if options[:build_path] - Dir.chdir(File.dirname(gemspec)) do - spec = Gem::Specification.load(File.basename(gemspec)) - build_package(spec) - end - else - build_package(spec) - end + def build_gem + gemspec = resolve_gem_name + if gemspec + build_package(gemspec) else - alert_error "Gemspec file not found: #{gemspec}" + alert_error error_message terminate_interaction(1) end end - def build_package(spec) + def build_package(gemspec) + spec = Gem::Specification.load(gemspec) if spec Gem::Package.build( spec, @@ -112,4 +107,26 @@ def build_package(spec) terminate_interaction 1 end end + + def resolve_gem_name + return find_gemspec unless gem_name + + if File.exist?(gem_name) + gem_name + else + find_gemspec("#{gem_name}.gemspec") || find_gemspec(gem_name) + end + end + + def error_message + if gem_name + "Couldn't find a gemspec file matching '#{gem_name}' in #{Dir.pwd}" + else + "Couldn't find a gemspec file in #{Dir.pwd}" + end + end + + def gem_name + get_one_optional_argument + end end diff --git a/test/rubygems/test_gem_commands_build_command.rb b/test/rubygems/test_gem_commands_build_command.rb index 53916eb11b91..fe537780be4b 100644 --- a/test/rubygems/test_gem_commands_build_command.rb +++ b/test/rubygems/test_gem_commands_build_command.rb @@ -231,7 +231,7 @@ def test_execute_missing_file end assert_equal '', @ui.output - assert_equal "ERROR: Gemspec file not found: some_gem.gemspec\n", @ui.error + assert_equal "ERROR: Couldn't find a gemspec file matching 'some_gem' in #{@tempdir}\n", @ui.error end def test_execute_outside_dir @@ -272,6 +272,198 @@ def test_execute_outside_dir assert_equal "this is a summary", spec.summary end + def test_execute_outside_dir_with_glob_argument + gemspec_dir = File.join @tempdir, 'build_command_gem' + gemspec_file = File.join gemspec_dir, @gem.spec_name + readme_file = File.join gemspec_dir, 'README.md' + + FileUtils.mkdir_p gemspec_dir + + File.open readme_file, 'w' do |f| + f.write "My awesome gem" + end + + File.open gemspec_file, 'w' do |gs| + gs.write @gem.to_ruby + end + + @cmd.options[:build_path] = gemspec_dir + @cmd.options[:args] = ["*.gemspec"] + + use_ui @ui do + @cmd.execute + end + + output = @ui.output.split "\n" + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: some_gem", output.shift + assert_equal " Version: 2", output.shift + assert_equal " File: some_gem-2.gem", output.shift + assert_equal [], output + + gem_file = File.join gemspec_dir, File.basename(@gem.cache_file) + assert File.exist?(gem_file) + + spec = Gem::Package.new(gem_file).spec + + assert_equal "some_gem", spec.name + assert_equal "this is a summary", spec.summary + end + + def test_execute_outside_dir_no_gemspec_present + gemspec_dir = File.join @tempdir, 'build_command_gem' + gemspec_file = File.join @tempdir, @gem.spec_name + readme_file = File.join gemspec_dir, 'README.md' + + FileUtils.mkdir_p gemspec_dir + + File.open readme_file, 'w' do |f| + f.write "My awesome gem" + end + + File.open gemspec_file, 'w' do |gs| + gs.write @gem.to_ruby + end + + @cmd.options[:build_path] = gemspec_dir + @cmd.options[:args] = ["*.gemspec"] + + use_ui @ui do + assert_raises Gem::MockGemUi::TermError do + @cmd.execute + end + end + + assert_equal "", @ui.output + assert_equal "ERROR: Couldn't find a gemspec file matching '*.gemspec' in #{gemspec_dir}\n", @ui.error + + gem_file = File.join gemspec_dir, File.basename(@gem.cache_file) + refute File.exist?(gem_file) + end + + def test_execute_outside_dir_without_gem_name + gemspec_dir = File.join(@tempdir, 'build_command_gem') + gemspec_file = File.join(gemspec_dir, @gem.spec_name) + + readme_file = File.join gemspec_dir, 'README.md' + + FileUtils.mkdir_p(gemspec_dir) + + File.open readme_file, 'w' do |f| + f.write "My awesome gem" + end + + File.open(gemspec_file, "w") do |gs| + gs.write(@gem.to_ruby) + end + + @cmd.options[:build_path] = gemspec_dir + @cmd.options[:args] = [] + + use_ui @ui do + Dir.chdir(gemspec_dir) do + @cmd.execute + end + end + + output = @ui.output.split("\n") + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: some_gem", output.shift + assert_equal " Version: 2", output.shift + assert_equal " File: some_gem-2.gem", output.shift + assert_equal [], output + + gem_file = File.join gemspec_dir, File.basename(@gem.cache_file) + assert File.exist?(gem_file) + + spec = Gem::Package.new(gem_file).spec + + assert_equal "some_gem", spec.name + assert_equal "this is a summary", spec.summary + end + + def test_execute_outside_dir_with_external_gemspec + gemspec_dir = File.join @tempdir, 'gemspec_dir' + gemspec_file = File.join gemspec_dir, @gem.spec_name + + gemcode_dir = File.join @tempdir, 'build_command_gem' + readme_file = File.join gemcode_dir, 'README.md' + + FileUtils.mkdir_p gemspec_dir + FileUtils.mkdir_p gemcode_dir + + File.open readme_file, 'w' do |f| + f.write "My awesome gem in nested directory" + end + + File.open gemspec_file, 'w' do |gs| + gs.write @gem.to_ruby + end + + @cmd.options[:build_path] = gemcode_dir + @cmd.options[:args] = [gemspec_file] + + use_ui @ui do + @cmd.execute + end + + output = @ui.output.split "\n" + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: some_gem", output.shift + assert_equal " Version: 2", output.shift + assert_equal " File: some_gem-2.gem", output.shift + assert_equal [], output + + gem_file = File.join gemcode_dir, File.basename(@gem.cache_file) + assert File.exist?(gem_file) + + spec = Gem::Package.new(gem_file).spec + + assert_equal "some_gem", spec.name + assert_equal "this is a summary", spec.summary + end + + def test_execute_outside_dir_with_external_relative_gemspec + gemspec_dir = File.join @tempdir, 'gemspec_dir' + gemspec_file = File.join gemspec_dir, @gem.spec_name + + gemcode_dir = File.join @tempdir, 'build_command_gem' + readme_file = File.join gemcode_dir, 'README.md' + + FileUtils.mkdir_p gemspec_dir + FileUtils.mkdir_p gemcode_dir + + File.open readme_file, 'w' do |f| + f.write "My awesome gem in nested directory" + end + + File.open gemspec_file, 'w' do |gs| + gs.write @gem.to_ruby + end + + @cmd.options[:build_path] = gemcode_dir + @cmd.options[:args] = [File.join("..", "gemspec_dir", @gem.spec_name)] + + use_ui @ui do + @cmd.execute + end + + output = @ui.output.split "\n" + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: some_gem", output.shift + assert_equal " Version: 2", output.shift + assert_equal " File: some_gem-2.gem", output.shift + assert_equal [], output + + gem_file = File.join gemcode_dir, File.basename(@gem.cache_file) + assert File.exist?(gem_file) + + spec = Gem::Package.new(gem_file).spec + + assert_equal "some_gem", spec.name + assert_equal "this is a summary", spec.summary + end + def test_can_find_gemspecs_without_dot_gemspec gemspec_file = File.join(@tempdir, @gem.name)