diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 208f21c74b9..d5054e80547 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -242,6 +242,13 @@ def show(gem_name = nil) # TODO: 2.0 remove `bundle list` map %w(list) => "show" + desc "info GEM [OPTIONS]", "Show information for the given gem" + method_option "path", :type => :boolean, :banner => "Print full path to gem" + def info(gem_name) + require "bundler/cli/info" + Info.new(options, gem_name).run + end + desc "binstubs GEM [OPTIONS]", "Install the binstubs of the listed gem" long_desc <<-D Generate binstubs for executables in [GEM]. Binstubs are put into bin, diff --git a/lib/bundler/cli/info.rb b/lib/bundler/cli/info.rb new file mode 100644 index 00000000000..4465fba9d41 --- /dev/null +++ b/lib/bundler/cli/info.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true +require "bundler/cli/common" + +module Bundler + class CLI::Info + attr_reader :gem_name, :options + def initialize(options, gem_name) + @options = options + @gem_name = gem_name + end + + def run + spec = spec_for_gem(gem_name) + + spec_not_found(gem_name) unless spec + return print_gem_path(spec) if @options[:path] + print_gem_info(spec) + end + + private + + def spec_for_gem(gem_name) + spec = Bundler.definition.specs.find {|s| s.name == gem_name } + spec || default_gem_spec(gem_name) + end + + def default_gem_spec(gem_name) + return unless Gem::Specification.respond_to?(:find_all_by_name) + gem_spec = Gem::Specification.find_all_by_name(gem_name).last + return gem_spec if gem_spec && gem_spec.respond_to?(:default_gem?) && gem_spec.default_gem? + end + + def spec_not_found(gem_name) + raise GemNotFound, Bundler::CLI::Common.gem_not_found_message(gem_name, Bundler.definition.dependencies) + end + + def print_gem_path(spec) + Bundler.ui.info spec.full_gem_path + end + + def print_gem_info(spec) + gem_info = String.new + gem_info << " * #{spec.name} (#{spec.version}#{spec.git_version})\n" + gem_info << "\tSummary: #{spec.summary}\n" if spec.summary + gem_info << "\tHomepage: #{spec.homepage}\n" if spec.homepage + gem_info << "\tPath: #{spec.full_gem_path}\n" + gem_info << "\tDefault Gem: yes" if spec.respond_to?(:default_gem?) && spec.default_gem? + Bundler.ui.info gem_info + end + end +end diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb index b21693a32ba..752c5e9c555 100644 --- a/lib/bundler/cli/install.rb +++ b/lib/bundler/cli/install.rb @@ -78,7 +78,7 @@ def run relative_path = absolute_path.sub(File.expand_path(".") + File::SEPARATOR, "." + File::SEPARATOR) Bundler.ui.confirm "Bundled gems are installed into #{relative_path}." else - Bundler.ui.confirm "Use `bundle show [gemname]` to see where a bundled gem is installed." + Bundler.ui.confirm "Use `bundle info [gemname]` to see where a bundled gem is installed." end Bundler::CLI::Common.output_post_install_messages installer.post_install_messages diff --git a/man/bundle-info.ronn b/man/bundle-info.ronn new file mode 100644 index 00000000000..47e457aa3c8 --- /dev/null +++ b/man/bundle-info.ronn @@ -0,0 +1,17 @@ +bundle-info(1) -- Show information for the given gem in your bundle +========================================================================= + +## SYNOPSIS + +`bundle info` [GEM] + [--path] + +## DESCRIPTION + +Print the basic information about the provided GEM such as homepage, version, +path and summary. + +## OPTIONS + +* `--path`: +Print the path of the given gem diff --git a/spec/commands/info_spec.rb b/spec/commands/info_spec.rb new file mode 100644 index 00000000000..b37de765e4c --- /dev/null +++ b/spec/commands/info_spec.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true +require "spec_helper" + +RSpec.describe "bundle info" do + context "info from specific gem in gemfile" do + before do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rails" + G + end + + it "prints information about the current gem" do + bundle "info rails" + expect(out).to include "* rails (2.3.2) +\tSummary: This is just a fake gem for testing +\tHomepage: http://example.com" + expect(out).to match(%r{Path\: .*\/rails\-2\.3\.2}) + end + + context "given a gem that is not installed" do + it "prints missing gem error" do + bundle "info foo" + expect(out).to eq "Could not find gem 'foo'." + end + end + + context "given a default gem shippped in ruby" do + it "prints information about the default gem", :if => (RUBY_VERSION >= "2.0") do + bundle "info rdoc" + expect(out).to include("* rdoc") + expect(out).to include("Default Gem: yes") + end + end + + context "when gem does not have homepage" do + before do + build_repo1 do + build_gem "rails", "2.3.2" do |s| + s.executables = "rails" + s.summary = "Just another test gem" + end + end + end + + it "excludes the homepage field from the output" do + expect(out).to_not include("Homepage:") + end + end + + context "given --path option" do + it "prints the path to the gem" do + bundle "info rails" + expect(out).to match(%r{.*\/rails\-2\.3\.2}) + end + end + end +end diff --git a/spec/install/post_bundle_message_spec.rb b/spec/install/post_bundle_message_spec.rb index 69f9256c070..4453e4190f9 100644 --- a/spec/install/post_bundle_message_spec.rb +++ b/spec/install/post_bundle_message_spec.rb @@ -14,7 +14,7 @@ G end - let(:bundle_show_message) { "Use `bundle show [gemname]` to see where a bundled gem is installed." } + let(:bundle_show_message) { "Use `bundle info [gemname]` to see where a bundled gem is installed." } let(:bundle_deployment_message) { "Bundled gems are installed into ./vendor" } let(:bundle_complete_message) { "Bundle complete!" } let(:bundle_updated_message) { "Bundle updated!" }