diff options
-rw-r--r-- | lib/bundler.rb | 4 | ||||
-rw-r--r-- | lib/bundler/definition.rb | 51 | ||||
-rw-r--r-- | lib/bundler/dsl.rb | 26 | ||||
-rw-r--r-- | lib/bundler/index.rb | 10 | ||||
-rw-r--r-- | lib/bundler/lazy_specification.rb | 10 | ||||
-rw-r--r-- | lib/bundler/lockfile_parser.rb | 6 | ||||
-rw-r--r-- | lib/bundler/source/gemspec.rb | 4 | ||||
-rw-r--r-- | lib/bundler/source/path.rb | 4 | ||||
-rw-r--r-- | spec/commands/package_spec.rb | 2 | ||||
-rw-r--r-- | spec/install/gemfile/gemspec_spec.rb | 146 | ||||
-rw-r--r-- | spec/install/gemfile/path_spec.rb | 2 | ||||
-rw-r--r-- | spec/support/builders.rb | 2 | ||||
-rw-r--r-- | spec/support/helpers.rb | 1 |
13 files changed, 230 insertions, 38 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb index c73c07af3a..98f8123466 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -131,7 +131,9 @@ module Bundler def locked_gems @locked_gems ||= - if Bundler.default_lockfile.exist? + if defined?(@definition) && @definition + definition.locked_gems + elsif Bundler.default_lockfile.exist? lock = Bundler.read_file(Bundler.default_lockfile) LockfileParser.new(lock) end diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 10e8e517f9..36bb9f2ef8 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -7,7 +7,15 @@ module Bundler class Definition include GemHelpers - attr_reader :dependencies, :platforms, :ruby_version, :locked_deps, :gem_version_promoter, :requires + attr_reader( + :dependencies, + :gem_version_promoter, + :locked_deps, + :locked_gems, + :platforms, + :requires, + :ruby_version + ) # Given a gemfile and lockfile creates a Bundler definition # @@ -60,15 +68,15 @@ module Bundler if lockfile && File.exist?(lockfile) @lockfile_contents = Bundler.read_file(lockfile) - locked = LockfileParser.new(@lockfile_contents) - @platforms = locked.platforms - @locked_bundler_version = locked.bundler_version - @locked_ruby_version = locked.ruby_version + @locked_gems = LockfileParser.new(@lockfile_contents) + @platforms = @locked_gems.platforms + @locked_bundler_version = @locked_gems.bundler_version + @locked_ruby_version = @locked_gems.ruby_version if unlock != true - @locked_deps = locked.dependencies - @locked_specs = SpecSet.new(locked.specs) - @locked_sources = locked.sources + @locked_deps = @locked_gems.dependencies + @locked_specs = SpecSet.new(@locked_gems.specs) + @locked_sources = @locked_gems.sources else @unlock = {} @locked_deps = [] @@ -78,6 +86,7 @@ module Bundler else @unlock = {} @platforms = [] + @locked_gems = nil @locked_deps = [] @locked_specs = SpecSet.new([]) @locked_sources = [] @@ -512,14 +521,14 @@ module Bundler # Check if the specs of the given source changed # according to the locked source. def specs_changed?(source) - locked = @locked_sources.find(source) + locked = @locked_sources.find {|s| s == source } - !locked || dependencies_for_source_changed?(source) || specs_for_source_changed?(source) + !locked || dependencies_for_source_changed?(source, locked) || specs_for_source_changed?(source) end - def dependencies_for_source_changed?(source) + def dependencies_for_source_changed?(source, locked_source = source) deps_for_source = @dependencies.select {|s| s.source == source } - locked_deps_for_source = @locked_deps.select {|s| s.source == source } + locked_deps_for_source = @locked_deps.select {|s| s.source == locked_source } Set.new(deps_for_source) != Set.new(locked_deps_for_source) end @@ -557,9 +566,22 @@ module Bundler end end + def converge_path_source_to_gemspec_source(source) + return source unless source.instance_of?(Source::Path) + gemspec_source = sources.path_sources.find {|s| s.is_a?(Source::Gemspec) && s.as_path_source == source } + gemspec_source || source + end + def converge_sources changes = false + @locked_sources.map! do |source| + converge_path_source_to_gemspec_source(source) + end + @locked_specs.each do |spec| + spec.source &&= converge_path_source_to_gemspec_source(spec.source) + end + # Get the Rubygems sources from the Gemfile.lock locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) } # Get the Rubygems remotes from the Gemfile @@ -604,6 +626,9 @@ module Bundler elsif dep.source dep.source = sources.get(dep.source) end + if dep.source.is_a?(Source::Gemspec) + dep.platforms.concat(@platforms.map {|p| Dependency::REVERSE_PLATFORM_MAP[p] }.flatten(1)).uniq! + end end Set.new(@dependencies) != Set.new(@locked_deps) end @@ -655,7 +680,7 @@ module Bundler # then we unlock it. # Path sources have special logic - if s.source.instance_of?(Source::Path) + if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec) other = s.source.specs[s].first # If the spec is no longer in the path source, unlock it. This diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb index 5577f40c26..b064c80d4c 100644 --- a/lib/bundler/dsl.rb +++ b/lib/bundler/dsl.rb @@ -50,22 +50,22 @@ module Bundler end def gemspec(opts = nil) - path = opts && opts[:path] || "." - glob = opts && opts[:glob] - name = opts && opts[:name] || "{,*}" - development_group = opts && opts[:development_group] || :development + opts ||= {} + path = opts[:path] || "." + glob = opts[:glob] + name = opts[:name] + development_group = opts[:development_group] || :development expanded_path = gemfile_root.join(path) - gemspecs = Dir[File.join(expanded_path, "#{name}.gemspec")] + gemspecs = Dir[File.join(expanded_path, "{,*}.gemspec")].map {|g| Bundler.load_gemspec(g) }.compact + gemspecs.reject! {|s| s.name != name } if name + Index.sort_specs(gemspecs) + specs_by_name_and_version = gemspecs.group_by {|s| [s.name, s.version] } - case gemspecs.size + case specs_by_name_and_version.size when 1 - spec = Bundler.load_gemspec(gemspecs.first) - - unless spec - raise InvalidOption, "There was an error loading the gemspec at " \ - "#{file}. Make sure you can build the gem, then try again" - end + specs = specs_by_name_and_version.values.first + spec = specs.find {|s| s.match_platform(Gem::Platform.local) } || specs.first @gemspecs << spec @@ -74,7 +74,7 @@ module Bundler group(development_group) do spec.development_dependencies.each do |dep| - gem dep.name, *(dep.requirement.as_list + [:type => :development, :platforms => gem_platforms]) + gem dep.name, *(dep.requirement.as_list + [:type => :development]) end end when 0 diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb index f0ee411df8..4529c57279 100644 --- a/lib/bundler/index.rb +++ b/lib/bundler/index.rb @@ -67,12 +67,20 @@ module Bundler end end - results.sort_by do |s| + sort_specs(results) + end + + def self.sort_specs(specs) + specs.sort_by do |s| platform_string = s.platform.to_s [s.version, platform_string == RUBY ? NULL : platform_string] end end + def sort_specs(specs) + self.class.sort_specs(specs) + end + def local_search(query, base = nil) case query when Gem::Specification, RemoteSpecification, LazySpecification, EndpointSpecification then search_by_spec(query) diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb index ccaa791cc8..36ff5c59ed 100644 --- a/lib/bundler/lazy_specification.rb +++ b/lib/bundler/lazy_specification.rb @@ -5,6 +5,8 @@ require "bundler/match_platform" module Bundler class LazySpecification + Identifier = Struct.new(:name, :version, :source, :platform, :dependencies) + include MatchPlatform attr_reader :name, :version, :dependencies, :platform @@ -61,11 +63,15 @@ module Bundler end def to_s - @__to_s ||= "#{name} (#{version})" + @__to_s ||= if platform == Gem::Platform::RUBY || platform.nil? + "#{name} (#{version})" + else + "#{name} (#{version}-#{platform})" + end end def identifier - @__identifier ||= [name, version, source, platform, dependencies].hash + @__identifier ||= Identifier.new(name, version, source, platform, dependencies) end private diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb index d5b2844079..90da4ac608 100644 --- a/lib/bundler/lockfile_parser.rb +++ b/lib/bundler/lockfile_parser.rb @@ -207,8 +207,10 @@ module Bundler def parse_spec(line) if line =~ NAME_VERSION_4 name = $1 - version = Gem::Version.new($2) - platform = $3 ? Gem::Platform.new($3) : Gem::Platform::RUBY + version = $2 + platform = $3 + version = Gem::Version.new(version) + platform = platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY @current_spec = LazySpecification.new(name, version, platform) @current_spec.source = @current_source diff --git a/lib/bundler/source/gemspec.rb b/lib/bundler/source/gemspec.rb index 37e9a43945..05e613277f 100644 --- a/lib/bundler/source/gemspec.rb +++ b/lib/bundler/source/gemspec.rb @@ -8,6 +8,10 @@ module Bundler super @gemspec = options["gemspec"] end + + def as_path_source + Path.new(options) + end end end end diff --git a/lib/bundler/source/path.rb b/lib/bundler/source/path.rb index 3c4d914fb3..69bb0c1af2 100644 --- a/lib/bundler/source/path.rb +++ b/lib/bundler/source/path.rb @@ -11,7 +11,7 @@ module Bundler DEFAULT_GLOB = "{,*,*/*}.gemspec".freeze def initialize(options) - @options = options + @options = options.dup @glob = options["glob"] || DEFAULT_GLOB @allow_cached = false @@ -60,7 +60,7 @@ module Bundler end def eql?(other) - return unless other.class == Path || other.class == Gemspec + return unless other.class == self.class expanded_path == expand(other.path) && version == other.version end diff --git a/spec/commands/package_spec.rb b/spec/commands/package_spec.rb index 9c722b3491..83b56f304e 100644 --- a/spec/commands/package_spec.rb +++ b/spec/commands/package_spec.rb @@ -127,7 +127,7 @@ describe "bundle package" do source "file://#{gem_repo1}" gem 'rack' gemspec :name => 'mygem' - gemspec :name => 'mygem_client' + gemspec :name => 'mygem_test' D bundle! "package --all" diff --git a/spec/install/gemfile/gemspec_spec.rb b/spec/install/gemfile/gemspec_spec.rb index f860f55f13..454dbcf8c2 100644 --- a/spec/install/gemfile/gemspec_spec.rb +++ b/spec/install/gemfile/gemspec_spec.rb @@ -67,7 +67,7 @@ describe "bundle install from an existing gemspec" do it "should raise if there are too many gemspecs available" do build_lib("foo", :path => tmp.join("foo")) do |s| - s.write("foo2.gemspec", "") + s.write("foo2.gemspec", build_spec("foo", "4.0").first.to_ruby) end error = install_gemfile(<<-G, :expect_err => true) @@ -196,7 +196,17 @@ describe "bundle install from an existing gemspec" do before do build_lib("foo", :path => tmp.join("foo")) do |s| s.add_dependency "rack", "=1.0.0" - s.platform = platform if explicit_platform + end + + if explicit_platform + create_file( + tmp.join("foo", "foo-#{platform}.gemspec"), + build_spec("foo", "1.0", platform) do + dep "rack", "=1.0.0" + @spec.authors = "authors" + @spec.summary = "summary" + end.first.to_ruby + ) end gemfile <<-G @@ -266,5 +276,137 @@ describe "bundle install from an existing gemspec" do end end end + + context "bundled for ruby and jruby" do + let(:platform_specific_type) { :runtime } + let(:dependency) { "platform_specific" } + before do + build_repo2 do + build_gem "indirect_platform_specific" do |s| + s.add_runtime_dependency "platform_specific" + end + end + + build_lib "foo", :path => "." do |s| + if platform_specific_type == :runtime + s.add_runtime_dependency dependency + elsif platform_specific_type == :development + s.add_development_dependency dependency + else + raise "wrong dependency type #{platform_specific_type}, can only be :development or :runtime" + end + end + + %w(ruby jruby).each do |platform| + simulate_platform(platform) do + install_gemfile <<-G + source "file://#{gem_repo2}" + gemspec + G + end + end + end + + context "on ruby" do + before do + simulate_platform("ruby") + bundle :install + end + + context "as a runtime dependency" do + it "keeps java dependencies in the lockfile" do + should_be_installed "foo 1.0", "platform_specific 1.0 RUBY" + expect(lockfile).to eq strip_whitespace(<<-L) + PATH + remote: . + specs: + foo (1.0) + platform_specific + + GEM + remote: file:#{gem_repo2}/ + specs: + platform_specific (1.0) + platform_specific (1.0-java) + + PLATFORMS + java + ruby + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + + context "as a development dependency" do + let(:platform_specific_type) { :development } + + it "keeps java dependencies in the lockfile" do + should_be_installed "foo 1.0", "platform_specific 1.0 RUBY" + expect(lockfile).to eq strip_whitespace(<<-L) + PATH + remote: . + specs: + foo (1.0) + + GEM + remote: file:#{gem_repo2}/ + specs: + platform_specific (1.0) + platform_specific (1.0-java) + + PLATFORMS + java + ruby + + DEPENDENCIES + foo! + platform_specific + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + + context "with an indirect platform-specific development dependency" do + let(:platform_specific_type) { :development } + let(:dependency) { "indirect_platform_specific" } + + it "keeps java dependencies in the lockfile" do + should_be_installed "foo 1.0", "indirect_platform_specific 1.0", "platform_specific 1.0 RUBY" + expect(lockfile).to eq strip_whitespace(<<-L) + PATH + remote: . + specs: + foo (1.0) + + GEM + remote: file:#{gem_repo2}/ + specs: + indirect_platform_specific (1.0) + platform_specific + platform_specific (1.0) + platform_specific (1.0-java) + + PLATFORMS + java + ruby + + DEPENDENCIES + foo! + indirect_platform_specific + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + end + end end end diff --git a/spec/install/gemfile/path_spec.rb b/spec/install/gemfile/path_spec.rb index 9f2893a01c..d3910748cc 100644 --- a/spec/install/gemfile/path_spec.rb +++ b/spec/install/gemfile/path_spec.rb @@ -241,7 +241,7 @@ describe "bundle install with explicit source paths" do it "raises if there are multiple gemspecs" do build_lib "foo", "1.0", :path => lib_path("foo") do |s| - s.write "bar.gemspec" + s.write "bar.gemspec", build_spec("bar", "1.0").first.to_ruby end install_gemfile <<-G diff --git a/spec/support/builders.rb b/spec/support/builders.rb index 3c10cba757..6ed3a2904e 100644 --- a/spec/support/builders.rb +++ b/spec/support/builders.rb @@ -395,6 +395,8 @@ module Spec s.name = name s.version = Gem::Version.new(v) s.platform = platform + s.authors = ["no one in particular"] + s.summary = "a gemspec used only for testing" DepBuilder.run(s, &block) if block_given? end end diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb index 0293f08716..0d2338df90 100644 --- a/spec/support/helpers.rb +++ b/spec/support/helpers.rb @@ -217,6 +217,7 @@ module Spec opts[:retry] ||= 0 bundle :install, opts end + bang :install_gemfile def lock_gemfile(*args) gemfile(*args) |