diff options
author | Homu <homu@barosl.com> | 2016-06-29 08:17:33 +0900 |
---|---|---|
committer | Homu <homu@barosl.com> | 2016-06-29 08:17:33 +0900 |
commit | c5e161a2ea28feef7a1314dcfd03d0d54d1e4f1c (patch) | |
tree | c52b489a8d31653b374bbec9d5debbbdfedd78d4 | |
parent | bd8982c525bd79302d4551e1ad0053722de4b0b6 (diff) | |
parent | baa71129d0b9db353fd95f667e050f3839ef1cdb (diff) | |
download | bundler-c5e161a2ea28feef7a1314dcfd03d0d54d1e4f1c.tar.gz |
Auto merge of #4714 - bundler:seg-no-aggregate, r=indirect
[2.0] Remove RubyGems Aggregate & support transitive source pinning
Closes https://github.com/bundler/bundler/issues/3671.
Closes https://github.com/bundler/bundler/pull/3696.
Closes #4059.
29 files changed, 595 insertions, 317 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 275f4ee8ac..ab754ae24d 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -218,6 +218,27 @@ module Bundler dependency_names -= pinned_spec_names(source.specs) dependency_names.push(*source.unmet_deps).uniq! end + + # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both + # sources A and B. At this point, the API request will have found all the versions of Bar in source A, + # but will not have found any versions of Bar from source B, which is a problem if the requested version + # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for + # each spec we found, we add all possible versions from all sources to the index. + loop do + idxcount = idx.size + sources.all_sources.each do |source| + names = :names # do this so we only have to traverse to get dependency_names from the index once + unmet_dependency_names = proc do + if names == :names + names = dependency_names.+(idx.dependency_names).uniq unless idx.size > Source::Rubygems::API_REQUEST_LIMIT + else + names + end + end + source.double_check_for(unmet_dependency_names, :override_dupes) + end + break if idxcount == idx.size + end end end @@ -225,8 +246,8 @@ module Bundler # spec, even if (say) a git gem is not checked out. def rubygems_index @rubygems_index ||= Index.build do |idx| - sources.rubygems_sources.each do |rubygems| - idx.add_source rubygems.specs + sources.rubygems_sources.each do |s| + idx.add_source s.specs end end end @@ -496,19 +517,6 @@ module Bundler def converge_sources changes = false - # Get the Rubygems sources from the gems.locked - locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) } - # Get the Rubygems remotes from the gems.rb - actual_remotes = sources.rubygems_remotes - - # If there is a Rubygems source in both - if !locked_gem_sources.empty? && !actual_remotes.empty? - locked_gem_sources.each do |locked_gem| - # Merge the remotes from the gems.rb into the gems.locked - changes |= locked_gem.replace_remotes(actual_remotes) - end - end - # Replace the sources from the gems.rb with the sources from the gems.locked, # if they exist in the gems.locked and are `==`. If you can't find an equivalent # source in the gems.locked, use the one from the gems.rb. @@ -654,10 +662,11 @@ module Bundler # Record the specs available in each gem's source, so that those # specs will be available later when the resolver knows where to # look for that gemspec (or its dependencies) - source_requirements = {} + default = sources.default_source + source_requirements = { :default => default } dependencies.each do |dep| - next unless dep.source - source_requirements[dep.name] = dep.source.specs + next unless source = dep.source || default + source_requirements[dep.name] = source end source_requirements end diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb index aaa0eab06d..abfa1337ab 100644 --- a/lib/bundler/dsl.rb +++ b/lib/bundler/dsl.rb @@ -132,7 +132,7 @@ module Bundler with_source(@sources.add_rubygems_source("remotes" => source), &blk) else check_primary_source_safety(@sources) - @sources.add_rubygems_remote(source) + @sources.global_rubygems_remote = source end end @@ -150,6 +150,16 @@ module Bundler end def path(path, options = {}, &blk) + unless block_given? + msg = "You can no longer specify a path source by itself. Instead, \n" \ + "either use the :path option on a gem, or specify the gems that \n" \ + "bundler should find in the path source by passing a block to \n" \ + "the path method, like: \n\n" \ + " path 'dir/containing/rails' do\n" \ + " gem 'rails'\n" \ + " end" + raise DeprecatedError, msg + end source_options = normalize_hash(options).merge("path" => Pathname.new(path), "root_path" => gemfile_root) source = @sources.add_path_source(source_options) with_source(source, &blk) @@ -384,8 +394,8 @@ module Bundler end end - def check_primary_source_safety(source) - return unless source.rubygems_primary_remotes.any? + def check_primary_source_safety(source_list) + return if source_list.global_rubygems_source.nil? raise GemspecError, "This #{SharedHelpers.gemfile_name} contains multiple primary sources. " \ "Each source after the first must include a block to indicate which gems " \ diff --git a/lib/bundler/fetcher/downloader.rb b/lib/bundler/fetcher/downloader.rb index 204e33387e..5a638a4b27 100644 --- a/lib/bundler/fetcher/downloader.rb +++ b/lib/bundler/fetcher/downloader.rb @@ -31,7 +31,7 @@ module Bundler when Net::HTTPUnauthorized raise AuthenticationRequiredError, uri.host when Net::HTTPNotFound - raise FallbackError, "Net::HTTPNotFound" + raise FallbackError, "Net::HTTPNotFound (#{uri})" else raise HTTPError, "#{response.class}#{": #{response.body}" unless response.body.empty?}" end diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb index f2defe1cff..833276b251 100644 --- a/lib/bundler/index.rb +++ b/lib/bundler/index.rb @@ -98,6 +98,7 @@ module Bundler specs.values.each do |spec_sets| spec_sets.values.each(&blk) end + sources.each {|s| s.each(&blk) } end # returns a list of the dependencies diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb index 5d450fcefc..57e6372f02 100644 --- a/lib/bundler/lockfile_parser.rb +++ b/lib/bundler/lockfile_parser.rb @@ -62,8 +62,6 @@ module Bundler @state = nil @specs = {} - @rubygems_aggregate = Source::Rubygems.new - if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/) raise LockfileError, "Your #{SharedHelpers.lockfile_name} contains merge conflicts.\n" \ "Run `git checkout HEAD -- #{SharedHelpers.lockfile_name}` first to get a clean lock." @@ -87,7 +85,6 @@ module Bundler send("parse_#{@state}", line) end end - @sources << @rubygems_aggregate @specs = @specs.values warn_for_outdated_bundler_version rescue ArgumentError => e @@ -129,23 +126,10 @@ module Bundler @type = line when SPECS case @type - when PATH - @current_source = TYPES[@type].from_lock(@opts) - @sources << @current_source - when GIT - @current_source = TYPES[@type].from_lock(@opts) - # Strip out duplicate GIT sections - if @sources.include?(@current_source) - @current_source = @sources.find {|s| s == @current_source } - else - @sources << @current_source - end when GEM - Array(@opts["remote"]).each do |url| - @rubygems_aggregate.add_remote(url) - end - @current_source = @rubygems_aggregate + @opts["remotes"] = @opts.delete("remote") end + add_source(TYPES[@type].from_lock(@opts)) when OPTIONS value = $2 value = true if value == "true" @@ -164,6 +148,16 @@ module Bundler end end + def add_source(source) + # Strip out duplicate sections + if @sources.include?(source) && !source.instance_of?(Bundler::Source::Path) + @current_source = @sources.find {|s| s == @current_source } + else + @current_source = source + @sources << @current_source + end + end + NAME_VERSION = '(?! )(.*?)(?: \(([^-]*)(?:-(.*))?\))?'.freeze NAME_VERSION_2 = /^ {2}#{NAME_VERSION}(!)?$/ NAME_VERSION_4 = /^ {4}#{NAME_VERSION}$/ diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index 742087b206..3c5d2bc462 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -54,11 +54,20 @@ module Bundler o << %(the gems in your #{SharedHelpers.gemfile_name}, which may resolve the conflict.\n) elsif !conflict.existing o << "\n" + + relevant_sources = if conflict.requirement.source + [conflict.requirement.source] + elsif conflict.requirement.all_sources + conflict.requirement.all_sources + else + raise "no source set for #{conflict}" + end.compact.uniq + if conflict.requirement_trees.first.size > 1 - o << "Could not find gem '#{conflict.requirement}', which is required by " - o << "gem '#{conflict.requirement_trees.first[-2]}', in any of the sources." + o << "Could not find gem '#{printable_dep(conflict.requirement)}', which is required by " + o << "gem '#{printable_dep(conflict.requirement_trees.first[-2])}', in any of the relevant sources:\n #{relevant_sources * "\n "}\n" else - o << "Could not find gem '#{conflict.requirement}' in any of the sources\n" + o << "Could not find gem '#{printable_dep(conflict.requirement)}' in any of the relevant sources:\n #{relevant_sources * "\n "}\n" end end o @@ -259,7 +268,17 @@ module Bundler platform = dependency.__platform dependency = dependency.dep unless dependency.is_a? Gem::Dependency search = @search_for[dependency] ||= begin - index = @source_requirements[dependency.name] || @index + index = Index.build do |idx| + if source = @source_requirements[dependency.name] + idx.add_source source.specs + elsif dependency.all_sources + dependency.all_sources.each {|s| idx.add_source(s.specs) if s } + else + idx.add_source @source_requirements[:default].specs + end + end + # source = @source_requirements[dependency.name] + # index = (source && source.specs) || @index results = index.search(dependency, @base[dependency.name]) if vertex = @base_dg.vertex_named(dependency.name) locked_requirement = vertex.payload.requirement @@ -303,8 +322,19 @@ module Bundler requirement.matches_spec?(spec) end + def relevant_sources_for_vertex(vertex) + if vertex.root? + [@source_requirements[vertex.name]] + else + vertex.recursive_predecessors.map do |v| + @source_requirements[v.name] + end << @source_requirements[:default] + end + end + def sort_dependencies(dependencies, activated, conflicts) dependencies.sort_by do |dependency| + dependency.all_sources = relevant_sources_for_vertex(activated.vertex_named(dependency.name)) name = name_for(dependency) [ activated.vertex_named(name).payload ? 0 : 1, @@ -336,26 +366,26 @@ module Bundler def verify_gemfile_dependencies_are_found!(requirements) requirements.each do |requirement| - next if requirement.name == "bundler" + name = requirement.name + next if name == "bundler" next unless search_for(requirement).empty? - if (base = @base[requirement.name]) && !base.empty? + if (base = @base[name]) && !base.empty? version = base.first.version message = "You have requested:\n" \ - " #{requirement.name} #{requirement.requirement}\n\n" \ - "The bundle currently has #{requirement.name} locked at #{version}.\n" \ - "Try running `bundle update #{requirement.name}`\n\n" \ + " #{name} #{requirement.requirement}\n\n" \ + "The bundle currently has #{name} locked at #{version}.\n" \ + "Try running `bundle update #{name}`\n\n" \ "If you are updating multiple gems in your Gemfile at once,\n" \ "try passing them all to `bundle update`" - elsif requirement.source - name = requirement.name - specs = @source_requirements[name][name] + elsif source = @source_requirements[name] + specs = source.specs[name] versions_with_platforms = specs.map {|s| [s.version, s.platform] } - message = String.new("Could not find gem '#{requirement}' in #{requirement.source}.\n") + message = String.new("Could not find gem '#{requirement}' in #{source}.\n") message << if versions_with_platforms.any? - "Source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}" + "The source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}" else - "Source does not contain any versions of '#{requirement}'" + "The source does not contain any versions of '#{requirement}'." end else message = "Could not find gem '#{requirement}' in any of the gem sources " \ @@ -370,7 +400,8 @@ module Bundler version = vwp.first platform = vwp.last version_platform_str = String.new(version.to_s) - version_platform_str << " #{platform}" unless platform.nil? + version_platform_str << " #{platform}" unless platform.nil? || platform == Gem::Platform::RUBY + version_platform_str end version_platform_strs.join(", ") end diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index 2f36c29cd9..94f502ad51 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -112,7 +112,7 @@ module Gem end class Dependency - attr_accessor :source, :groups + attr_accessor :source, :groups, :all_sources alias_method :eql?, :== diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb index eee4ade45b..56ce30af10 100644 --- a/lib/bundler/source.rb +++ b/lib/bundler/source.rb @@ -29,6 +29,12 @@ module Bundler spec.source == self end + # it's possible that gems from one source depend on gems from some + # other source, so now we download gemspecs and iterate over those + # dependencies, looking for gems we don't have info on yet. + def double_check_for(*) + end + def include?(other) other == self end diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb index 6b09173130..602b4386a3 100644 --- a/lib/bundler/source/rubygems.rb +++ b/lib/bundler/source/rubygems.rb @@ -48,10 +48,6 @@ module Bundler o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty? end - def can_lock?(spec) - spec.source.is_a?(Rubygems) - end - def options { "remotes" => @remotes.map(&:to_s) } end @@ -69,8 +65,12 @@ module Bundler end def to_s - remote_names = remotes.map(&:to_s).join(", ") - "rubygems repository #{remote_names}" + if remotes.empty? + "locally installed gems" + else + remote_names = remotes.map(&:to_s).join(", ") + "rubygems repository #{remote_names} or installed locally" + end end alias_method :name, :to_s @@ -234,6 +234,20 @@ module Bundler end end + def double_check_for(unmet_dependency_names, override_dupes = false, index = specs) + return unless @allow_remote + raise ArgumentError, "missing index" unless index + + return unless api_fetchers.any? + + unmet_dependency_names = unmet_dependency_names.call + Bundler.ui.debug "#{self}: 2x check for #{unmet_dependency_names}" + + return if unmet_dependency_names && unmet_dependency_names.empty? + + fetch_names(api_fetchers, unmet_dependency_names, index, override_dupes) + end + protected def credless_remotes @@ -337,62 +351,28 @@ module Bundler index_fetchers = fetchers - api_fetchers # gather lists from non-api sites - index_fetchers.each do |f| - Bundler.ui.info "Fetching source index from #{f.uri}" - idx.use f.specs_with_retry(nil, self) - end + fetch_names(index_fetchers, nil, idx, false) # because ensuring we have all the gems we need involves downloading # the gemspecs of those gems, if the non-api sites contain more than - # about 100 gems, we treat all sites as non-api for speed. + # about 500 gems, we treat all sites as non-api for speed. allow_api = idx.size < API_REQUEST_LIMIT && dependency_names.size < API_REQUEST_LIMIT Bundler.ui.debug "Need to query more than #{API_REQUEST_LIMIT} gems." \ " Downloading full index instead..." unless allow_api - if allow_api - api_fetchers.each do |f| - Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug? - idx.use f.specs_with_retry(dependency_names, self) - Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over - end - - # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both - # sources A and B. At this point, the API request will have found all the versions of Bar in source A, - # but will not have found any versions of Bar from source B, which is a problem if the requested version - # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for - # each spec we found, we add all possible versions from all sources to the index. - loop do - idxcount = idx.size - api_fetchers.each do |f| - Bundler.ui.info "Fetching version metadata from #{f.uri}", Bundler.ui.debug? - idx.use f.specs_with_retry(idx.dependency_names, self), true - Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over - end - break if idxcount == idx.size - end - - if api_fetchers.any? - # it's possible that gems from one source depend on gems from some - # other source, so now we download gemspecs and iterate over those - # dependencies, looking for gems we don't have info on yet. - unmet = idx.unmet_dependency_names - - # if there are any cross-site gems we missed, get them now - api_fetchers.each do |f| - Bundler.ui.info "Fetching dependency metadata from #{f.uri}", Bundler.ui.debug? - idx.use f.specs_with_retry(unmet, self) - Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over - end if unmet.any? - else - allow_api = false - end - end + fetch_names(api_fetchers, allow_api && dependency_names, idx, false) + end + end - unless allow_api - api_fetchers.each do |f| - Bundler.ui.info "Fetching source index from #{f.uri}" - idx.use f.specs_with_retry(nil, self) - end + def fetch_names(fetchers, dependency_names, index, override_dupes) + fetchers.each do |f| + if dependency_names + Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug? + index.use f.specs_with_retry(dependency_names, self), override_dupes + Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over + else + Bundler.ui.info "Fetching source index from #{f.uri}" + index.use f.specs_with_retry(nil, self), override_dupes end end end diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb index d1c3c8c170..d63c8129d1 100644 --- a/lib/bundler/source_list.rb +++ b/lib/bundler/source_list.rb @@ -4,13 +4,15 @@ require "set" module Bundler class SourceList attr_reader :path_sources, - :git_sources + :git_sources, + :global_rubygems_source def initialize - @path_sources = [] - @git_sources = [] - @rubygems_aggregate = Source::Rubygems.new - @rubygems_sources = [] + @path_sources = [] + @git_sources = [] + @global_rubygems_source = nil + @rubygems_local = Source::Rubygems.new + @rubygems_sources = [] end def add_path_source(options = {}) @@ -27,13 +29,16 @@ module Bundler add_source_to_list Source::Rubygems.new(options), @rubygems_sources end - def add_rubygems_remote(uri) - @rubygems_aggregate.add_remote(uri) - @rubygems_aggregate + def global_rubygems_remote=(uri) + @global_rubygems_source = Source::Rubygems.new("remotes" => uri) + end + + def default_source + @global_rubygems_source || @rubygems_local end def rubygems_sources - @rubygems_sources + [@rubygems_aggregate] + @rubygems_sources + [default_source] end def rubygems_remotes @@ -44,13 +49,12 @@ module Bundler path_sources + git_sources + rubygems_sources end - def get(source) - source_list_for(source).find {|s| source == s } + def lock_sources + rubygems_sources.sort_by(&:to_s) + git_sources.sort_by(&:to_s) + path_sources.sort_by(&:to_s) end - def lock_sources - lock_sources = (path_sources + git_sources).sort_by(&:to_s) - lock_sources << combine_rubygems_sources + def get(source) + source_list_for(source).find {|s| source == s } end def replace_sources!(replacement_sources) @@ -79,10 +83,6 @@ module Bundler all_sources.each(&:remote!) end - def rubygems_primary_remotes - @rubygems_aggregate.remotes - end - private def add_source_to_list(source, list) diff --git a/lib/bundler/stub_specification.rb b/lib/bundler/stub_specification.rb index f4ee7d0644..557852bdec 100644 --- a/lib/bundler/stub_specification.rb +++ b/lib/bundler/stub_specification.rb @@ -11,8 +11,8 @@ module Bundler attr_accessor :stub - def to_yaml - _remote_specification.to_yaml + def encode_with(*args) + _remote_specification.encode_with(*args) end private diff --git a/spec/bundler/fetcher/downloader_spec.rb b/spec/bundler/fetcher/downloader_spec.rb index 04793d2a9c..f7631ef408 100644 --- a/spec/bundler/fetcher/downloader_spec.rb +++ b/spec/bundler/fetcher/downloader_spec.rb @@ -89,7 +89,7 @@ describe Bundler::Fetcher::Downloader do let(:http_response) { Net::HTTPNotFound.new("1.1", 404, "Not Found") } it "should raise a Bundler::Fetcher::FallbackError with Net::HTTPNotFound" do - expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::FallbackError, "Net::HTTPNotFound") + expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::FallbackError, "Net::HTTPNotFound (#{uri})") end end diff --git a/spec/bundler/source_list_spec.rb b/spec/bundler/source_list_spec.rb index d724141bfa..d2395b30e4 100644 --- a/spec/bundler/source_list_spec.rb +++ b/spec/bundler/source_list_spec.rb @@ -8,8 +8,6 @@ describe Bundler::SourceList do subject(:source_list) { Bundler::SourceList.new } - let(:rubygems_aggregate) { Bundler::Source::Rubygems.new } - describe "adding sources" do before do source_list.add_path_source("path" => "/existing/path/to/gem") @@ -108,36 +106,41 @@ describe Bundler::SourceList do end end - describe "#add_rubygems_remote" do + describe "#global_rubygems_remote=" do before do - @returned_source = source_list.add_rubygems_remote("https://rubygems.org/") + source_list.global_rubygems_remote = "https://rubygems.org/" + @returned_source = source_list.global_rubygems_source end it "returns the aggregate rubygems source" do expect(@returned_source).to be_instance_of(Bundler::Source::Rubygems) + expect(source_list.rubygems_sources).to end_with @returned_source end - it "adds the provided remote to the beginning of the aggregate source" do - source_list.add_rubygems_remote("https://othersource.org") - expect(@returned_source.remotes.first).to eq(URI("https://othersource.org/")) + it "resets the global source" do + source_list.global_rubygems_remote = "https://othersource.org" + new_global = source_list.global_rubygems_source + expect(new_global.remotes.first).to eq(URI("https://othersource.org/")) + expect(source_list.global_rubygems_source).to eq(new_global) + expect(source_list.rubygems_sources).not_to include(@returned_source) end end end describe "#all_sources" do it "includes the aggregate rubygems source when rubygems sources have been added" do - source_list.add_git_source("uri" => "git://host/path.git") - source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) - source_list.add_path_source("path" => "/path/to/gem") + git = source_list.add_git_source("uri" => "git://host/path.git") + rubygems = source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) + path = source_list.add_path_source("path" => "/path/to/gem") - expect(source_list.all_sources).to include rubygems_aggregate + expect(source_list.all_sources).to include(git, rubygems, path) end it "includes the aggregate rubygems source when no rubygems sources have been added" do source_list.add_git_source("uri" => "git://host/path.git") source_list.add_path_source("path" => "/path/to/gem") - expect(source_list.all_sources).to include rubygems_aggregate + expect(source_list.all_sources).to include source_list.default_source end it "returns sources of the same type in the reverse order that they were added" do @@ -165,29 +168,29 @@ describe Bundler::SourceList do Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]), Bundler::Source::Rubygems.new("remotes" => ["https://fourth-rubygems.org"]), Bundler::Source::Rubygems.new("remotes" => ["https://fifth-rubygems.org"]), - rubygems_aggregate, + source_list.default_source, ] end end describe "#path_sources" do it "returns an empty array when no path sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") + source_list.add_rubygems_source("remotes" => "https://rubygems.org") source_list.add_git_source("uri" => "git://host/path.git") expect(source_list.path_sources).to be_empty end it "returns path sources in the reverse order that they were added" do source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_remote("https://fifth-rubygems.org") + source_list.add_rubygems_source("remotes" => "https://fifth-rubygems.org") source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") + source_list.add_rubygems_source("remotes" => "https://fourth-rubygems.org") source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") + source_list.add_rubygems_source("remotes" => "https://third-rubygems.org") source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") + source_list.add_rubygems_source("remotes" => "https://second-rubygems.org") source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") + source_list.add_rubygems_source("remotes" => "https://first-rubygems.org") source_list.add_git_source("uri" => "git://first-git.org/path.git") expect(source_list.path_sources).to eq [ @@ -200,7 +203,7 @@ describe Bundler::SourceList do describe "#git_sources" do it "returns an empty array when no git sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") + source_list.add_rubygems_source("remotes" => "https://rubygems.org") source_list.add_path_source("path" => "/path/to/gem") expect(source_list.git_sources).to be_empty @@ -208,15 +211,15 @@ describe Bundler::SourceList do it "returns git sources in the reverse order that they were added" do source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_remote("https://fifth-rubygems.org") + source_list.add_rubygems_source("remotes" => "https://fifth-rubygems.org") source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") + source_list.add_rubygems_source("remotes" => "https://fourth-rubygems.org") source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") + source_list.add_rubygems_source("remotes" => "https://third-rubygems.org") source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") + source_list.add_rubygems_source("remotes" => "https://second-rubygems.org") source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") + source_list.add_rubygems_source("remotes" => "https://first-rubygems.org") source_list.add_git_source("uri" => "git://first-git.org/path.git") expect(source_list.git_sources).to eq [ @@ -230,17 +233,17 @@ describe Bundler::SourceList do describe "#rubygems_sources" do it "includes the aggregate rubygems source when rubygems sources have been added" do source_list.add_git_source("uri" => "git://host/path.git") - source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) + rg = source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) source_list.add_path_source("path" => "/path/to/gem") - expect(source_list.rubygems_sources).to include rubygems_aggregate + expect(source_list.rubygems_sources).to end_with(rg, source_list.default_source) end it "returns only the aggregate rubygems source when no rubygems sources have been added" do source_list.add_git_source("uri" => "git://host/path.git") source_list.add_path_source("path" => "/path/to/gem") - expect(source_list.rubygems_sources).to eq [rubygems_aggregate] + expect(source_list.rubygems_sources).to eq [source_list.default_source] end it "returns rubygems sources in the reverse order that they were added" do @@ -262,7 +265,7 @@ describe Bundler::SourceList do Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]), Bundler::Source::Rubygems.new("remotes" => ["https://fourth-rubygems.org"]), Bundler::Source::Rubygems.new("remotes" => ["https://fifth-rubygems.org"]), - rubygems_aggregate, + source_list.default_source, ] end end @@ -270,7 +273,7 @@ describe Bundler::SourceList do describe "#get" do context "when it includes an equal source" do let(:rubygems_source) { Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"]) } - before { @equal_source = source_list.add_rubygems_remote("https://rubygems.org") } + before { @equal_source = source_list.add_rubygems_source("remotes" => "https://rubygems.org") } it "returns the equal source" do expect(source_list.get(rubygems_source)).to be @equal_source @@ -301,18 +304,17 @@ describe Bundler::SourceList do source_list.add_git_source("uri" => "git://first-git.org/path.git") expect(source_list.lock_sources).to eq [ + Bundler::Source::Rubygems.new, + Bundler::Source::Rubygems.new("remotes" => "https://duplicate-rubygems.org"), + Bundler::Source::Rubygems.new("remotes" => "https://first-rubygems.org"), + Bundler::Source::Rubygems.new("remotes" => "https://second-rubygems.org"), + Bundler::Source::Rubygems.new("remotes" => "https://third-rubygems.org"), Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"), Bundler::Source::Path.new("path" => "/first/path/to/gem"), Bundler::Source::Path.new("path" => "/second/path/to/gem"), Bundler::Source::Path.new("path" => "/third/path/to/gem"), - Bundler::Source::Rubygems.new("remotes" => [ - "https://duplicate-rubygems.org", - "https://first-rubygems.org", - "https://second-rubygems.org", - "https://third-rubygems.org", - ]), ] end end @@ -343,7 +345,7 @@ describe Bundler::SourceList do end describe "#cached!" do - let(:rubygems_source) { source_list.add_rubygems_remote("https://rubygems.org") } + let(:rubygems_source) { source_list.add_rubygems_source("remotes" => "https://rubygems.org") } let(:git_source) { source_list.add_git_source("uri" => "git://host/path.git") } let(:path_source) { source_list.add_path_source("path" => "/path/to/gem") } @@ -356,7 +358,7 @@ describe Bundler::SourceList do end describe "#remote!" do - let(:rubygems_source) { source_list.add_rubygems_remote("https://rubygems.org") } + let(:rubygems_source) { source_list.add_rubygems_source("remotes" => "https://rubygems.org") } let(:git_source) { source_list.add_git_source("uri" => "git://host/path.git") } let(:path_source) { source_list.add_path_source("path" => "/path/to/gem") } diff --git a/spec/cache/gems_spec.rb b/spec/cache/gems_spec.rb index 7f0a914947..ed9c3440a8 100644 --- a/spec/cache/gems_spec.rb +++ b/spec/cache/gems_spec.rb @@ -9,6 +9,7 @@ describe "bundle cache" do G system_gems "rack-1.0.0" + should_be_installed "rack 1.0.0" bundle :cache end @@ -29,7 +30,7 @@ describe "bundle cache" do it "uses the cache as a source when installing gems with --local" do system_gems [] - bundle "install --local" + bundle! "install --local" should_be_installed("rack 1.0.0") end diff --git a/spec/commands/exec_spec.rb b/spec/commands/exec_spec.rb index 051644ed60..3e4d55c42f 100644 --- a/spec/commands/exec_spec.rb +++ b/spec/commands/exec_spec.rb @@ -451,7 +451,8 @@ describe "bundle exec" do let(:exit_code) { Bundler::GemNotFound.new.status_code } let(:expected) { "" } let(:expected_err) { <<-EOS.strip } -\e[31mCould not find gem 'rack (= 2)' in any of the gem sources listed in your gems.rb or available on this machine.\e[0m +\e[31mCould not find gem 'rack (= 2)' in locally installed gems. +The source contains 'rack' at: 0.9.1, 1.0.0\e[0m \e[33mRun `bundle install` to install missing gems.\e[0m EOS diff --git a/spec/commands/lock_spec.rb b/spec/commands/lock_spec.rb index 5b2b465192..ea6f3219bb 100644 --- a/spec/commands/lock_spec.rb +++ b/spec/commands/lock_spec.rb @@ -85,7 +85,8 @@ describe "bundle lock" do it "does not fetch remote specs when using the --local option" do bundle "lock --update --local", :expect_err => true - expect(err).to include("sources listed in your gems.rb or available on this machine") + expect(err).to include("or installed locally."). + and include("The source does not contain any versions of 'rails'.") end it "writes to a custom location using --lockfile" do diff --git a/spec/install/gemfile/git_spec.rb b/spec/install/gemfile/git_spec.rb index b7abba63bb..52f939ebc2 100644 --- a/spec/install/gemfile/git_spec.rb +++ b/spec/install/gemfile/git_spec.rb @@ -82,7 +82,7 @@ describe "bundle install with git sources" do gem "foo", "1.1", :git => "#{lib_path("foo-1.0")}" G - expect(err).to include("Source contains 'foo' at: 1.0 ruby") + expect(err).to include("The source contains 'foo' at: 1.0") end it "complains with version and platform if pinned specs don't exist in the git repo" do @@ -98,7 +98,7 @@ describe "bundle install with git sources" do end G - expect(err).to include("Source contains 'only_java' at: 1.0 java") + expect(err).to include("The source contains 'only_java' at: 1.0 java") end it "complains with multiple versions and platforms if pinned specs don't exist in the git repo" do @@ -119,7 +119,7 @@ describe "bundle install with git sources" do end G - expect(err).to include("Source contains 'only_java' at: 1.0 java, 1.1 java") + expect(err).to include("The source contains 'only_java' at: 1.0 java, 1.1 java") end it "still works after moving the application directory" do diff --git a/spec/install/gemfile/path_spec.rb b/spec/install/gemfile/path_spec.rb index fd5e799048..2adacf4dca 100644 --- a/spec/install/gemfile/path_spec.rb +++ b/spec/install/gemfile/path_spec.rb @@ -6,8 +6,9 @@ describe "bundle install with explicit source paths" do build_lib "foo" install_gemfile <<-G - path "#{lib_path("foo-1.0")}" - gem 'foo' + path "#{lib_path("foo-1.0")}" do + gem 'foo' + end G should_be_installed("foo 1.0") @@ -273,8 +274,9 @@ describe "bundle install with explicit source paths" do end install_gemfile <<-G - path "#{lib_path("foo-1.0")}" - gem 'foo' + path "#{lib_path("foo-1.0")}" do + gem 'foo' + end G bundle "exec foobar" diff --git a/spec/install/gemfile/sources_spec.rb b/spec/install/gemfile/sources_spec.rb index 206dfa44be..0697974fbe 100644 --- a/spec/install/gemfile/sources_spec.rb +++ b/spec/install/gemfile/sources_spec.rb @@ -30,7 +30,7 @@ describe "bundle install with gems on multiple sources" do it "errors when disable_multisource is set" do bundle "config disable_multisource true" - bundle :install + bundle :install, :expect_err => true expect(err).to include("Each source after the first must include a block") expect(exitstatus).to eq(14) if exitstatus end @@ -59,6 +59,10 @@ describe "bundle install with gems on multiple sources" do build_gem "rack", "1.0.0" do |s| s.write "lib/rack.rb", "RACK = 'FAIL'" end + + build_gem "rack-obama" do |s| + s.add_dependency "rack" + end end gemfile <<-G @@ -72,7 +76,7 @@ describe "bundle install with gems on multiple sources" do end it "installs the gems without any warning" do - bundle :install + bundle! :install expect(out).not_to include("Warning") should_be_installed("rack-obama 1.0.0", "rack 1.0.0") end @@ -86,6 +90,10 @@ describe "bundle install with gems on multiple sources" do build_gem "rack", "1.0.0" do |s| s.write "lib/rack.rb", "RACK = 'FAIL'" end + + build_gem "rack-obama" do |s| + s.add_dependency "rack" + end end gemfile <<-G @@ -96,13 +104,13 @@ describe "bundle install with gems on multiple sources" do end it "installs the gems without any warning" do - bundle :install + bundle! :install expect(out).not_to include("Warning") should_be_installed("rack-obama 1.0.0", "rack 1.0.0") end end - context "with an indirect dependency" do + context "when a pinned gem has an indirect dependency" do before do build_repo gem_repo3 do build_gem "depends_on_rack", "1.0.1" do |s| @@ -150,7 +158,17 @@ describe "bundle install with gems on multiple sources" do it "installs from the same source without any warning" do bundle :install - expect(out).not_to include("Warning") + + expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.") + expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") + should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0") + + # when there is already a lock file, and the gems are missing, so try again + system_gems [] + bundle :install + + expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.") + expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0") end end @@ -218,6 +236,207 @@ describe "bundle install with gems on multiple sources" do end end + context "installing with dependencies from a monorepo" do + def should_be_installed_from_source(names_and_sources) + names_and_sources.each do |full_name, source| + name, version = full_name.split(" ", 2) + constant_name = Spec::Builders.constantize(name) + run! <<-RUBY + begin + require '#{name}' + puts begin + #{constant_name} + rescue NameError + #{name[0].upcase + name[1..-1]}::VERSION + end + rescue LoadError, NameError + puts '-' + end + + begin + require '#{name}/source' + puts #{constant_name}_SOURCE + rescue LoadError, NameError + puts '-' + end + RUBY + actual_version, actual_source = out.split("\n") + expect(actual_version).to eq(version), "Expected #{name} to be at version #{version}, instead was at #{actual_version}" + expect(actual_source).to eq(source || "-"), "#{full_name} came from #{actual_source.inspect} instead of #{source.inspect}" + end + end + + before do + build_lib "actionpack", "2.3.2", :path => lib_path("rails-2.3.2/actionpack") do |s| + s.write "lib/#{s.name}/source.rb", "#{Spec::Builders.constantize(s.name)}_SOURCE = 'rails-git'" + s.add_dependency "activesupport", "2.3.2" + end + build_lib "activerecord", "2.3.2", :path => lib_path("rails-2.3.2/activerecord") do |s| + s.write "lib/#{s.name}/source.rb", "#{Spec::Builders.constantize(s.name)}_SOURCE = 'rails-git'" + s.add_dependency "activesupport", "2.3.2" + end + build_lib "actionmailer", "2.3.2", :path => lib_path("rails-2.3.2/actionmailer") do |s| + s.write "lib/#{s.name}/source.rb", "#{Spec::Builders.constantize(s.name)}_SOURCE = 'rails-git'" + s.add_dependency "activesupport", "2.3.2" + end + build_lib "activeresource", "2.3.2", :path => lib_path("rails-2.3.2/activeresource") do |s| + s.write "lib/#{s.name}/source.rb", "#{Spec::Builders.constantize(s.name)}_SOURCE = 'rails-git'" + s.add_dependency "activesupport", "2.3.2" + end + build_lib "activesupport", "2.3.2", :path => lib_path("rails-2.3.2/activesupport") do |s| + s.write "lib/#{s.name}/source.rb", "#{Spec::Builders.constantize(s.name)}_SOURCE = 'rails-git'" + end + build_git "rails", "2.3.2" do |s| + s.write "lib/#{s.name}/source.rb", "#{Spec::Builders.constantize(s.name)}_SOURCE = 'rails-git'" + s.executables = "rails" + s.add_dependency "rake", "10.0.2" + s.add_dependency "actionpack", s.version + s.add_dependency "activerecord", s.version + s.add_dependency "actionmailer", s.version + s.add_dependency "activeresource", s.version + end + end + + context "when depending on rails via git without a rubygems source" do + before do + build_lib "rake", "10.0.2" do |s| + s.write "lib/rake/source.rb", "RAKE_SOURCE = 'rake-git'" + end + install_gemfile <<-G + gem "rake", :path => #{lib_path("rake-10.0.2").to_s.dump} + gem "rails", :git => #{lib_path("rails-2.3.2").to_s.dump} + G + end + + it "pulls all dependencies from the rails repo" do + should_be_installed_from_source("actionmailer 2.3.2" => "rails-git", + "actionpack 2.3.2" => "rails-git", + "activerecord 2.3.2" => "rails-git", + "activeresource 2.3.2" => "rails-git", + "activesupport 2.3.2" => "rails-git", + "rails 2.3.2" => "rails-git", + "rake 10.0.2" => "rake-git") + end + end + + context "when depending on rails via git with a rubygems source" do + before do + install_gemfile <<-G + source "file://#{gem_repo1}/" + gem "rails", :git => #{lib_path("rails-2.3.2").to_s.dump} + G + end + + it "pulls all dependencies from the rails repo" do + should_be_installed_from_source("actionmailer 2.3.2" => "rails-git", + "actionpack 2.3.2" => "rails-git", + "activerecord 2.3.2" => "rails-git", + "activeresource 2.3.2" => "rails-git", + "activesupport 2.3.2" => "rails-git", + "rails 2.3.2" => "rails-git", + "rake 10.0.2" => nil) + end + end + + context "when depending on rails via git with a rubygems source and a transitive dep is made explicit" do + before do + install_gemfile <<-G + source "file://#{gem_repo1}/" + gem "rails", :git => #{lib_path("rails-2.3.2").to_s.dump} + gem "actionmailer" + G + end + + it "pulls all dependencies from the rails repo" do + should_be_installed_from_source("actionmailer 2.3.2" => nil, + "actionpack 2.3.2" => "rails-git", + "activerecord 2.3.2" => "rails-git", + "activeresource 2.3.2" => "rails-git", + "activesupport 2.3.2" => nil, + "rails 2.3.2" => "rails-git", + "rake 10.0.2" => nil) + end + end + end + + context "when a top-level gem has an indirect dependency" do + before do + build_repo gem_repo2 do + build_gem "depends_on_rack", "1.0.1" do |s| + s.add_dependency "rack" + end + end + + build_repo gem_repo3 do + build_gem "unrelated_gem", "1.0.0" + end + + gemfile <<-G + source "file://#{gem_repo2}" + + gem "depends_on_rack" + + source "file://#{gem_repo3}" do + gem "unrelated_gem" + end + G + end + + context "and the dependency is only in the top-level source" do + before do + update_repo gem_repo2 do + build_gem "rack", "1.0.0" + end + end + + it "installs all gems without warning" do + bundle :install + expect(out).not_to include("Warning") + expect(err).not_to include("Warning") + should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") + end + end + + context "and the dependency is only in a pinned source" do + before do + update_repo gem_repo3 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + end + end + + it "does not find the dependency" do + bundle :install, :expect_err => true + expect(err).to include strip_whitespace(<<-E).strip + Could not find gem 'rack', which is required by gem 'depends_on_rack', in any of the relevant sources: + rubygems repository file:#{gem_repo2}/ or installed locally + E + end + end + + context "and the dependency is in both the top-level and a pinned source" do + before do + update_repo gem_repo2 do + build_gem "rack", "1.0.0" + end + + update_repo gem_repo3 do + build_gem "rack", "1.0.0" do |s| + s.write "lib/rack.rb", "RACK = 'FAIL'" + end + end + end + + it "installs the dependency from the top-level source without warning" do + bundle :install, :expect_err => true + expect(out).not_to include("Warning") + expect(err).not_to include("Warning") + should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") + end + end + end + context "with a gem that is only found in the wrong source" do before do build_repo gem_repo3 do diff --git a/spec/install/gems/compact_index_spec.rb b/spec/install/gems/compact_index_spec.rb index f2a9042cb8..1cd0f370ab 100644 --- a/spec/install/gems/compact_index_spec.rb +++ b/spec/install/gems/compact_index_spec.rb @@ -222,8 +222,6 @@ The checksum of /versions does not match the checksum provided by the server! So end it "fetches again when more dependencies are found in subsequent sources" do - pending "This test only passed with multiple primary sources. We need to " \ - "fix it to work with pinned sources, too." build_repo2 do build_gem "back_deps" do |s| s.add_dependency "foo" @@ -256,7 +254,6 @@ The checksum of /versions does not match the checksum provided by the server! So end end - pending "this should not be ambiguous. rack 1.2 should come from the extra source." gemfile <<-G source "#{source_uri}" do; end source "#{source_uri}/extra" @@ -267,7 +264,6 @@ The checksum of /versions does not match the checksum provided by the server! So end it "considers all possible versions of dependencies from all api gem sources" do - pending "this is currently broken with a pinned source. we need to fix it." # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0 # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other @@ -293,7 +289,6 @@ The checksum of /versions does not match the checksum provided by the server! So end it "prints API output properly with back deps" do - pending "back deps are currently broken with pinned sources :'(" build_repo2 do build_gem "back_deps" do |s| s.add_dependency "foo" @@ -315,7 +310,6 @@ The checksum of /versions does not match the checksum provided by the server! So end it "does not fetch every spec if the index of gems is large when doing back deps" do - pending "back deps: still broken" build_repo2 do build_gem "back_deps" do |s| s.add_dependency "foo" @@ -352,7 +346,6 @@ The checksum of /versions does not match the checksum provided by the server! So end it "fetches again when more dependencies are found in subsequent sources using --deployment" do - pending "back deps also broken in deployment mode" build_repo2 do build_gem "back_deps" do |s| s.add_dependency "foo" diff --git a/spec/install/gems/resolving_spec.rb b/spec/install/gems/resolving_spec.rb index 49d160063d..d6f83a20d9 100644 --- a/spec/install/gems/resolving_spec.rb +++ b/spec/install/gems/resolving_spec.rb @@ -4,14 +4,14 @@ require "spec_helper" describe "bundle install with gem sources" do describe "install time dependencies" do it "installs gems with implicit rake dependencies" do - install_gemfile <<-G + install_gemfile! <<-G source "file://#{gem_repo1}" gem "with_implicit_rake_dep" gem "another_implicit_rake_dep" gem "rake" G - run <<-R + run! <<-R require 'implicit_rake_dep' require 'another_implicit_rake_dep' puts IMPLICIT_RAKE_DEP @@ -32,7 +32,7 @@ describe "bundle install with gem sources" do f.write Gem.deflate(Marshal.dump(spec)) end - install_gemfile <<-G + install_gemfile! <<-G source "file://#{gem_repo2}" gem "actionpack", "2.3.2" G @@ -42,7 +42,7 @@ describe "bundle install with gem sources" do describe "with crazy rubygem plugin stuff" do it "installs plugins" do - install_gemfile <<-G + install_gemfile! <<-G source "file://#{gem_repo1}" gem "net_b" G @@ -51,7 +51,7 @@ describe "bundle install with gem sources" do end it "installs plugins depended on by other plugins" do - install_gemfile <<-G + install_gemfile! <<-G source "file://#{gem_repo1}" gem "net_a" G @@ -60,7 +60,7 @@ describe "bundle install with gem sources" do end it "installs multiple levels of dependencies" do - install_gemfile <<-G + install_gemfile! <<-G source "file://#{gem_repo1}" gem "net_c" gem "net_e" diff --git a/spec/install/post_bundle_message_spec.rb b/spec/install/post_bundle_message_spec.rb index 4e89d32432..6be21f35a8 100644 --- a/spec/install/post_bundle_message_spec.rb +++ b/spec/install/post_bundle_message_spec.rb @@ -95,12 +95,13 @@ describe "post bundle message" do describe "with misspelled or non-existent gem name" do it "should report a helpful error message" do - install_gemfile <<-G + install_gemfile <<-G, :expect_err => true source "file://#{gem_repo1}" gem "rack" gem "not-a-gem", :group => :development G - expect(err).to include("Could not find gem 'not-a-gem' in any of the gem sources listed in your gems.rb or available on this machine.") + expect(err).to include("Could not find gem 'not-a-gem' in rubygems repository"). + and include("or installed locally.\nThe source does not contain any versions of 'not-a-gem'.") end end end diff --git a/spec/lock/lockfile_spec.rb b/spec/lock/lockfile_spec.rb index e6b4ba34d1..4b961bc371 100644 --- a/spec/lock/lockfile_spec.rb +++ b/spec/lock/lockfile_spec.rb @@ -30,16 +30,16 @@ describe "the lockfile format" do it "updates the lockfile's bundler version if current ver. is newer" do lockfile <<-L - GIT - remote: git://github.com/nex3/haml.git - revision: 8a2271f - specs: - GEM remote: file://#{gem_repo1}/ specs: rack (1.0.0) + GIT + remote: git://github.com/nex3/haml.git + revision: 8a2271f + specs: + PLATFORMS #{generic_local_platform} @@ -359,18 +359,21 @@ describe "the lockfile format" do G end - it "generates a lockfile wihout credentials for a configured source" do + it "generates a lockfile without credentials for a configured source" do bundle "config http://localgemserver.test/ user:pass" install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) - source "http://localgemserver.test/" + source "http://user:pass@othergemserver.test/" gem "rack-obama", ">= 1.0" - source "http://user:pass@othergemserver.test/" do; end + source "http://localgemserver.test/" do; end G lockfile_should_be <<-G GEM remote: http://localgemserver.test/ + specs: + + GEM remote: http://user:pass@othergemserver.test/ specs: rack (1.0.0) @@ -423,15 +426,15 @@ describe "the lockfile format" do G lockfile_should_be <<-G + GEM + specs: + GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("master")} specs: foo (1.0) - GEM - specs: - PLATFORMS #{generic_local_platform} @@ -457,16 +460,16 @@ describe "the lockfile format" do G lockfile <<-L - GIT - remote: git://github.com/nex3/haml.git - revision: 8a2271f - specs: - GEM remote: file://#{gem_repo1}/ specs: rack (1.0.0) + GIT + remote: git://github.com/nex3/haml.git + revision: 8a2271f + specs: + PLATFORMS #{not_local} @@ -492,15 +495,15 @@ describe "the lockfile format" do G lockfile_should_be <<-G + GEM + specs: + GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("master")} specs: foo (1.0) - GEM - specs: - PLATFORMS #{generic_local_platform} @@ -521,6 +524,9 @@ describe "the lockfile format" do G lockfile_should_be <<-G + GEM + specs: + GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("omg")} @@ -528,9 +534,6 @@ describe "the lockfile format" do specs: foo (1.0) - GEM - specs: - PLATFORMS #{generic_local_platform} @@ -551,6 +554,9 @@ describe "the lockfile format" do G lockfile_should_be <<-G + GEM + specs: + GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("omg")} @@ -558,9 +564,6 @@ describe "the lockfile format" do specs: foo (1.0) - GEM - specs: - PLATFORMS #{generic_local_platform} @@ -580,14 +583,14 @@ describe "the lockfile format" do G lockfile_should_be <<-G + GEM + specs: + PATH remote: #{lib_path("foo-1.0")} specs: foo (1.0) - GEM - specs: - PLATFORMS #{generic_local_platform} @@ -612,6 +615,11 @@ describe "the lockfile format" do G lockfile_should_be <<-G + GEM + remote: file:#{gem_repo1}/ + specs: + rack (1.0.0) + GIT remote: #{lib_path("bar-1.0")} revision: #{bar.ref_for("master")} @@ -623,11 +631,6 @@ describe "the lockfile format" do specs: foo (1.0) - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - PLATFORMS #{generic_local_platform} @@ -797,24 +800,25 @@ describe "the lockfile format" do build_lib "foo", :path => bundled_app("foo") install_gemfile <<-G - path "foo" - gem "foo" + path "foo" do + gem "foo" + end G lockfile_should_be <<-G + GEM + specs: + PATH remote: foo specs: foo (1.0) - GEM - specs: - PLATFORMS #{generic_local_platform} DEPENDENCIES - foo + foo! BUNDLED WITH #{Bundler::VERSION} @@ -825,24 +829,25 @@ describe "the lockfile format" do build_lib "foo", :path => bundled_app(File.join("..", "foo")) install_gemfile <<-G - path "../foo" - gem "foo" + path "../foo" do + gem "foo" + end G lockfile_should_be <<-G + GEM + specs: + PATH remote: ../foo specs: foo (1.0) - GEM - specs: - PLATFORMS #{generic_local_platform} DEPENDENCIES - foo + foo! BUNDLED WITH #{Bundler::VERSION} @@ -853,24 +858,25 @@ describe "the lockfile format" do build_lib "foo", :path => bundled_app("foo") install_gemfile <<-G - path File.expand_path("../foo", __FILE__) - gem "foo" + path File.expand_path("../foo", __FILE__) do + gem "foo" + end G lockfile_should_be <<-G + GEM + specs: + PATH remote: foo specs: foo (1.0) - GEM - specs: - PLATFORMS #{generic_local_platform} DEPENDENCIES - foo + foo! BUNDLED WITH #{Bundler::VERSION} @@ -885,14 +891,14 @@ describe "the lockfile format" do G lockfile_should_be <<-G + GEM + specs: + PATH remote: ../foo specs: foo (1.0) - GEM - specs: - PLATFORMS #{generic_local_platform} @@ -1172,6 +1178,10 @@ describe "the lockfile format" do # Create a gems.locked that has duplicate GIT sections lockfile <<-L + GEM + remote: file:#{gem_repo1}/ + specs: + GIT remote: #{lib_path("omg")} revision: #{revision} @@ -1186,10 +1196,6 @@ describe "the lockfile format" do specs: omg (1.0) - GEM - remote: file:#{gem_repo1}/ - specs: - PLATFORMS #{local} @@ -1206,6 +1212,10 @@ describe "the lockfile format" do # Confirm that duplicate specs do not appear expect(File.read(bundled_app("gems.locked"))).to eq(strip_whitespace(<<-L)) + GEM + remote: file:#{gem_repo1}/ + specs: + GIT remote: #{lib_path("omg")} revision: #{revision} @@ -1213,10 +1223,6 @@ describe "the lockfile format" do specs: omg (1.0) - GEM - remote: file:#{gem_repo1}/ - specs: - PLATFORMS #{local} diff --git a/spec/resolver/basic_spec.rb b/spec/resolver/basic_spec.rb index cb5bc45597..861fa6e35a 100644 --- a/spec/resolver/basic_spec.rb +++ b/spec/resolver/basic_spec.rb @@ -100,7 +100,7 @@ describe "Resolving" do deps << Bundler::DepProxy.new(d, "ruby") end - got = Bundler::Resolver.resolve(deps, @index, {}, [], Bundler::RubyVersion.new("1.8.7", nil, nil, nil)) + got = Bundler::Resolver.resolve(deps, @index, { :default => double(:specs => @index) }, [], Bundler::RubyVersion.new("1.8.7", nil, nil, nil)) got = got.map(&:full_name).sort expect(got).to eq(%w(foo-1.0.0 bar-1.0.0).sort) end diff --git a/spec/runtime/inline_spec.rb b/spec/runtime/inline_spec.rb index dc429bf5c0..32686efa45 100644 --- a/spec/runtime/inline_spec.rb +++ b/spec/runtime/inline_spec.rb @@ -53,8 +53,9 @@ describe "bundler/inline#gemfile" do it "requires the gems" do script <<-RUBY gemfile do - path "#{lib_path}" - gem "two" + path "#{lib_path}" do + gem "two" + end end RUBY @@ -63,8 +64,9 @@ describe "bundler/inline#gemfile" do script <<-RUBY, :expect_err => true gemfile do - path "#{lib_path}" - gem "eleven" + path "#{lib_path}" do + gem "eleven" + end end puts "success" @@ -116,8 +118,9 @@ describe "bundler/inline#gemfile" do it "raises an exception if passed unknown arguments" do script <<-RUBY, :expect_err => true gemfile(true, :arglebargle => true) do - path "#{lib_path}" - gem "two" + path "#{lib_path}" do + gem "two" + end end puts "success" @@ -131,8 +134,9 @@ describe "bundler/inline#gemfile" do require 'bundler' options = { :ui => Bundler::UI::Shell.new } gemfile(false, options) do - path "#{lib_path}" - gem "two" + path "#{lib_path}" do + gem "two" + end end puts "OKAY" if options.key?(:ui) RUBY @@ -162,8 +166,9 @@ describe "bundler/inline#gemfile" do it "raises an exception if passed unknown arguments" do script <<-RUBY, :expect_err => true gemfile(true, :arglebargle => true) do - path "#{lib_path}" - gem "two" + path "#{lib_path}" do + gem "two" + end end puts "success" @@ -177,8 +182,9 @@ describe "bundler/inline#gemfile" do require 'bundler' options = { :ui => Bundler::UI::Shell.new } gemfile(false, options) do - path "#{lib_path}" - gem "two" + path "#{lib_path}" do + gem "two" + end end puts "OKAY" if options.key?(:ui) RUBY diff --git a/spec/runtime/require_spec.rb b/spec/runtime/require_spec.rb index c9cb10eedf..676a2a9cea 100644 --- a/spec/runtime/require_spec.rb +++ b/spec/runtime/require_spec.rb @@ -39,15 +39,16 @@ describe "Bundler.require" do end gemfile <<-G - path "#{lib_path}" - gem "one", :group => :bar, :require => %w[baz qux] - gem "two" - gem "three", :group => :not - gem "four", :require => false - gem "five" - gem "six", :group => "string" - gem "seven", :group => :not - gem "eight", :require => true, :group => :require_true + path "#{lib_path}" do + gem "one", :group => :bar, :require => %w[baz qux] + gem "two" + gem "three", :group => :not + gem "four", :require => false + gem "five" + gem "six", :group => "string" + gem "seven", :group => :not + gem "eight", :require => true, :group => :require_true + end G end @@ -88,8 +89,9 @@ describe "Bundler.require" do it "raises an exception if a require is specified but the file does not exist" do gemfile <<-G - path "#{lib_path}" - gem "two", :require => 'fail' + path "#{lib_path}" do + gem "two", :require => 'fail' + end G load_error_run <<-R, "fail" @@ -105,8 +107,9 @@ describe "Bundler.require" do end gemfile <<-G - path "#{lib_path}" - gem "faulty" + path "#{lib_path}" do + gem "faulty" + end G run "Bundler.require", :expect_err => true @@ -120,8 +123,9 @@ describe "Bundler.require" do end gemfile <<-G - path "#{lib_path}" - gem "faulty" + path "#{lib_path}" do + gem "faulty" + end G run "Bundler.require", :expect_err => true @@ -135,8 +139,9 @@ describe "Bundler.require" do end gemfile <<-G - path "#{lib_path}" - gem "loadfuuu" + path "#{lib_path}" do + gem "loadfuuu" + end G cmd = <<-RUBY @@ -161,8 +166,9 @@ describe "Bundler.require" do it "requires gem names that are namespaced" do gemfile <<-G - path '#{lib_path}' - gem 'jquery-rails' + path "#{lib_path}" do + gem "jquery-rails" + end G run "Bundler.require" @@ -174,8 +180,9 @@ describe "Bundler.require" do s.write "lib/brcrypt.rb", "BCrypt = '1.0.0'" end gemfile <<-G - path "#{lib_path}" - gem "bcrypt-ruby" + path "#{lib_path}" do + gem "bcrypt-ruby" + end G cmd = <<-RUBY @@ -189,8 +196,9 @@ describe "Bundler.require" do it "does not mangle explictly given requires" do gemfile <<-G - path "#{lib_path}" - gem 'jquery-rails', :require => 'jquery-rails' + path "#{lib_path}" do + gem 'jquery-rails', :require => 'jquery-rails' + end G load_error_run <<-R, "jquery-rails" @@ -205,8 +213,9 @@ describe "Bundler.require" do end gemfile <<-G - path "#{lib_path}" - gem "load-fuuu" + path "#{lib_path}" do + gem "load-fuuu" + end G cmd = <<-RUBY @@ -228,8 +237,9 @@ describe "Bundler.require" do lib_path("load-fuuu-1.0.0/lib/load-fuuu.rb").rmtree gemfile <<-G - path "#{lib_path}" - gem "load-fuuu" + path "#{lib_path}" do + gem "load-fuuu" + end G cmd = <<-RUBY @@ -285,9 +295,10 @@ describe "Bundler.require" do it "works when the gems are in the Gemfile in the correct order" do gemfile <<-G - path "#{lib_path}" - gem "two" - gem "one" + path "#{lib_path}" do + gem "two" + gem "one" + end G run "Bundler.require" @@ -325,9 +336,10 @@ describe "Bundler.require" do it "fails when the gems are in the Gemfile in the wrong order" do gemfile <<-G - path "#{lib_path}" - gem "one" - gem "two" + path "#{lib_path}" do + gem "one" + gem "two" + end G run "Bundler.require" diff --git a/spec/runtime/setup_spec.rb b/spec/runtime/setup_spec.rb index e89d5b3a0e..319f752be2 100644 --- a/spec/runtime/setup_spec.rb +++ b/spec/runtime/setup_spec.rb @@ -367,9 +367,9 @@ describe "Bundler.setup" do end gemfile <<-G - path "#{lib_path("rack-1.0.0")}" - source "file://#{gem_repo1}" - gem "rack" + path "#{lib_path("rack-1.0.0")}" do + gem "rack" + end G run "require 'rack'" diff --git a/spec/support/indexes.rb b/spec/support/indexes.rb index acace96886..2fdc1f23f4 100644 --- a/spec/support/indexes.rb +++ b/spec/support/indexes.rb @@ -16,12 +16,15 @@ module Spec def resolve @platforms ||= ["ruby"] deps = [] + default_source = instance_double("Bundler::Source::Rubygems", :specs => @index) + source_requirements = { :default => default_source } @deps.each do |d| @platforms.each do |p| + source_requirements[d.name] = d.source = default_source deps << Bundler::DepProxy.new(d, p) end end - Bundler::Resolver.resolve(deps, @index) + Bundler::Resolver.resolve(deps, @index, source_requirements) end def should_resolve_as(specs) diff --git a/spec/update/git_spec.rb b/spec/update/git_spec.rb index 8c68b56010..8424161a7f 100644 --- a/spec/update/git_spec.rb +++ b/spec/update/git_spec.rb @@ -334,17 +334,17 @@ describe "bundle update" do bundle "update --source bar" lockfile_should_be <<-G + GEM + remote: file:#{gem_repo2}/ + specs: + rack (1.0.0) + GIT remote: #{@git.path} revision: #{ref} specs: foo (2.0) - GEM - remote: file:#{gem_repo2}/ - specs: - rack (1.0.0) - PLATFORMS ruby |