diff options
author | Andre Arko <andre@arko.net> | 2015-01-24 12:45:08 -0800 |
---|---|---|
committer | Andre Arko <andre@arko.net> | 2015-01-24 12:45:42 -0800 |
commit | a78e2d1aaf51a95faa19b6f1442dd1b632c4d30d (patch) | |
tree | 163b34deb64e533cc8c28780bd31b91bf7617f19 | |
parent | 6f53d616b642e3baeb36464567253a5dfa5a7bef (diff) | |
parent | 0aa8345b143e45d587124832f6949d7957eaa618 (diff) | |
download | bundler-a78e2d1aaf51a95faa19b6f1442dd1b632c4d30d.tar.gz |
Merge tag 'v1.7.12'
Version 1.7.12
Conflicts:
CHANGELOG.md
lib/bundler/fetcher.rb
spec/cache/platform_spec.rb
-rw-r--r-- | CHANGELOG.md | 38 | ||||
-rw-r--r-- | lib/bundler/dependency.rb | 5 | ||||
-rw-r--r-- | lib/bundler/fetcher.rb | 82 | ||||
-rw-r--r-- | lib/bundler/source_list.rb | 4 | ||||
-rw-r--r-- | lib/bundler/version.rb | 2 | ||||
-rw-r--r-- | man/gemfile.5.ronn | 6 | ||||
-rw-r--r-- | spec/install/gems/dependency_api_spec.rb | 11 | ||||
-rw-r--r-- | spec/install/gems/sources_spec.rb | 32 | ||||
-rw-r--r-- | spec/support/artifice/endpoint_api_forbidden.rb | 11 |
9 files changed, 136 insertions, 55 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 19474b76fe..e2b35d7477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,28 @@ Features: Documentation: - add missing Gemfile global `path` explanation (@agenteo) +## 1.7.12 (2015-01-08) + +Bugfixes: + + - Always send credentials for sources, fixing private Gemfury gems (#3342, @TimMoore) + +## 1.7.11 (2015-01-04) + +Bugfixes: + + - Recognize `:mri_22` and `:mingw_22`, rather than just `:ruby_22` (#3328, @myabc) + +## 1.7.10 (2014-12-29) + +Bugfixes: + + - Fix source blocks sometimes causing deployment mode to fail wrongly (#3298, @TimMoore) + +Features(?): + + - Support `platform :mri_22` and related version bits (#3309, @thomasfedb) + ## 1.7.9 (2014-12-09) Bugfixes: @@ -28,7 +50,7 @@ Bugfixes: Bugfixes: - - Hide credentials while warning about gems with ambiguous sources (#3256, @tmoore) + - Hide credentials while warning about gems with ambiguous sources (#3256, @TimMoore) ## 1.7.7 (2014-11-19) @@ -48,14 +70,14 @@ Bugfixes: Bugfixes: - - Fix --deployment with source blocks and non-alphabetical gems (#3224, @tmoore) + - Fix --deployment with source blocks and non-alphabetical gems (#3224, @TimMoore) - Vendor CA chain to validate new rubygems.org HTTPS certificate (@indirect) ## 1.7.4 (2014-10-19) Bugfixes: - - Allow --deployment after `pack` while using source blocks (#3167, @tmoore) + - Allow --deployment after `pack` while using source blocks (#3167, @TimMoore) - Use dependency API even when HTTP credentials are in ENV (#3191, @fvaleur) - Silence warnings (including root warning) in --quiet mode (#3186, @indirect) - Stop asking gem servers for gems already found locally (#2909, @dubek) @@ -78,23 +100,23 @@ Bugfixes: Bugfixes: - Install gems from one source needed by gems in another source (@indirect) - - Install the same gem versions even after some are installed (@tmoore) + - Install the same gem versions even after some are installed (@TimMoore) - Download specs only when installing from servers (@indirect) ## 1.7.0 (2014-08-13) Security: - - Fix for CVE-2013-0334, installing gems from an unexpected source (@tmoore) + - Fix for CVE-2013-0334, installing gems from an unexpected source (@TimMoore) Features: - - Gemfile `source` calls now take a block containing gems from that source (@tmoore) - - Added the `:source` option to `gem` to specify a source (@tmoore) + - Gemfile `source` calls now take a block containing gems from that source (@TimMoore) + - Added the `:source` option to `gem` to specify a source (@TimMoore) Bugfixes: - - Warn on ambiguous gems available from more than one source (@tmoore) + - Warn on ambiguous gems available from more than one source (@TimMoore) ## 1.6.7 (2014-10-19) diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb index 38e44d24ab..6a9284fd56 100644 --- a/lib/bundler/dependency.rb +++ b/lib/bundler/dependency.rb @@ -20,6 +20,7 @@ module Bundler :mri_19 => Gem::Platform::RUBY, :mri_20 => Gem::Platform::RUBY, :mri_21 => Gem::Platform::RUBY, + :mri_22 => Gem::Platform::RUBY, :rbx => Gem::Platform::RUBY, :jruby => Gem::Platform::JAVA, :jruby_18 => Gem::Platform::JAVA, @@ -38,9 +39,11 @@ module Bundler :mingw_19 => Gem::Platform::MINGW, :mingw_20 => Gem::Platform::MINGW, :mingw_21 => Gem::Platform::MINGW, + :mingw_22 => Gem::Platform::MINGW, :x64_mingw => Gem::Platform::X64_MINGW, :x64_mingw_20 => Gem::Platform::X64_MINGW, - :x64_mingw_21 => Gem::Platform::X64_MINGW + :x64_mingw_21 => Gem::Platform::X64_MINGW, + :x64_mingw_22 => Gem::Platform::X64_MINGW }.freeze def initialize(name, version, options = {}, &blk) diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb index 143594db0b..c13d848bd8 100644 --- a/lib/bundler/fetcher.rb +++ b/lib/bundler/fetcher.rb @@ -106,8 +106,7 @@ module Bundler @api_timeout = 10 # How long to wait for each API call @max_retries = 3 # How many retries for the API call - @remote_uri = Bundler::Source.mirror_for(remote_uri) - @anonymizable_uri = AnonymizableURI.new(@remote_uri.dup) unless @remote_uri.nil? + @anonymizable_uri = resolve_remote_uri(remote_uri) Socket.do_not_reverse_lookup = true connection # create persistent connection @@ -115,14 +114,14 @@ module Bundler def connection @connection ||= begin - needs_ssl = @remote_uri.scheme == "https" || + needs_ssl = remote_uri.scheme == "https" || Bundler.settings[:ssl_verify_mode] || Bundler.settings[:ssl_client_cert] raise SSLError if needs_ssl && !defined?(OpenSSL::SSL) con = Net::HTTP::Persistent.new 'bundler', :ENV - if @remote_uri.scheme == "https" + if remote_uri.scheme == "https" con.verify_mode = (Bundler.settings[:ssl_verify_mode] || OpenSSL::SSL::VERIFY_PEER) con.cert_store = bundler_cert_store @@ -141,7 +140,7 @@ module Bundler end def uri - @anonymizable_uri.without_credentials unless @anonymizable_uri.nil? + @anonymizable_uri.without_credentials end # fetch a gem specification @@ -149,7 +148,7 @@ module Bundler spec = spec - [nil, 'ruby', ''] spec_file_name = "#{spec.join '-'}.gemspec" - uri = URI.parse("#{@remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") + uri = URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") if uri.scheme == 'file' Bundler.load_marshal Gem.inflate(Gem.read_binary(uri.path)) elsif cached_spec_path = gemspec_cached_path(spec_file_name) @@ -187,7 +186,7 @@ module Bundler end end - specs[@remote_uri].each do |name, version, platform, dependencies| + specs[remote_uri].each do |name, version, platform, dependencies| next if name == 'bundler' spec = nil if dependencies @@ -219,7 +218,7 @@ module Bundler Bundler.ui.info ".", false end - return {@remote_uri => last_spec_list} if query_list.empty? + return {remote_uri => last_spec_list} if query_list.empty? remote_specs = Bundler::Retry.new("dependency api", AUTH_ERRORS).attempts do fetch_dependency_remote_specs(query_list) @@ -236,24 +235,18 @@ module Bundler end def use_api - _use_api(true) - rescue AuthenticationRequiredError - retry_with_auth{_use_api(false)} - end - - def _use_api(reraise_auth_error = false) return @use_api if defined?(@use_api) - if @remote_uri.scheme == "file" || Bundler::Fetcher.disable_endpoint + if remote_uri.scheme == "file" || Bundler::Fetcher.disable_endpoint @use_api = false elsif fetch(dependency_api_uri) @use_api = true end rescue NetworkDownError => e raise HTTPError, e.message - rescue AuthenticationRequiredError => e - raise e if reraise_auth_error - false + rescue AuthenticationRequiredError + # We got a 401 from the server. Don't fall back to the full index, just fail. + raise rescue HTTPError @use_api = false end @@ -298,8 +291,8 @@ module Bundler response.body when Net::HTTPRequestEntityTooLarge raise FallbackError, response.body - when Net::HTTPUnauthorized, Net::HTTPForbidden - raise AuthenticationRequiredError, "#{response.class}: #{response.body}" + when Net::HTTPUnauthorized + raise AuthenticationRequiredError, remote_uri else raise HTTPError, "#{response.class}: #{response.body}" end @@ -359,16 +352,20 @@ module Bundler # fetch from modern index: specs.4.8.gz def fetch_all_remote_specs old_sources = Bundler.rubygems.sources - Bundler.rubygems.sources = [@remote_uri.to_s] + Bundler.rubygems.sources = [remote_uri.to_s] Bundler.rubygems.fetch_all_remote_specs rescue Gem::RemoteFetcher::FetchError, OpenSSL::SSL::SSLError => e case e.message when /certificate verify failed/ raise CertificateFailureError.new(uri) - when /401|403/ - # Gemfury uses a 403 for unauthenticated requests instead of a 401, so retry auth - # on both. - retry_with_auth { fetch_all_remote_specs } + when /401/ + raise AuthenticationRequiredError, remote_uri + when /403/ + if remote_uri.userinfo + raise BadAuthenticationError, remote_uri + else + raise AuthenticationRequiredError, remote_uri + end else Bundler.ui.trace e raise HTTPError, "Could not fetch specs from #{uri}" @@ -405,36 +402,35 @@ module Bundler store end - # Attempt to retry with HTTP authentication, if it's appropriate to do so. Yields to a block; - # the caller should use this to re-attempt the failing request with the altered `@remote_uri`. - def retry_with_auth - # Authentication has already been attempted and failed. - raise BadAuthenticationError.new(uri) if @remote_uri.user - - auth = Bundler.settings[uri.host] - auth ||= Bundler.settings[uri.to_s] - - # Authentication isn't provided at all, by "bundle config" or in the URI. - raise AuthenticationRequiredError.new(uri.host) if auth.nil? + private - @remote_uri.user, @remote_uri.password = *auth.split(":", 2) - @anonymizable_uri = AnonymizableURI.new(@remote_uri.dup) - yield + def resolve_remote_uri(uri) + add_configured_credentials(Bundler::Source.mirror_for(uri)) end - private + def add_configured_credentials(uri) + auth = Bundler.settings[uri.to_s] + if auth + uri = uri.dup + uri.user, uri.password = *auth.split(":", 2) + end + AnonymizableURI.new(uri) + end def fetch_uri @fetch_uri ||= begin - if @remote_uri.host == "rubygems.org" - uri = @remote_uri.dup + if remote_uri.host == "rubygems.org" + uri = remote_uri.dup uri.host = "bundler.rubygems.org" uri else - @remote_uri + remote_uri end end end + def remote_uri + @anonymizable_uri.original_uri + end end end diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb index 04f81814df..3ca6d4ad66 100644 --- a/lib/bundler/source_list.rb +++ b/lib/bundler/source_list.rb @@ -65,10 +65,10 @@ module Bundler replacement_rubygems = replacement_sources.detect { |s| s.is_a?(Source::Rubygems) } - @rubygems_aggregate = replacement_rubygems + @rubygems_aggregate = replacement_rubygems if replacement_rubygems # Return true if there were changes - all_sources.to_set != replacement_sources.to_set || + lock_sources.to_set != replacement_sources.to_set || rubygems_remotes.to_set != replacement_rubygems.remotes.to_set end diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb index 2c7e7af949..a4cb873e32 100644 --- a/lib/bundler/version.rb +++ b/lib/bundler/version.rb @@ -2,5 +2,5 @@ module Bundler # We're doing this because we might write tests that deal # with other versions of bundler and we are unsure how to # handle this better. - VERSION = "1.7.9" unless defined?(::Bundler::VERSION) + VERSION = "1.7.12" unless defined?(::Bundler::VERSION) end diff --git a/man/gemfile.5.ronn b/man/gemfile.5.ronn index e6284478a1..876c927380 100644 --- a/man/gemfile.5.ronn +++ b/man/gemfile.5.ronn @@ -193,6 +193,8 @@ There are a number of `Gemfile` platforms: _mri_ `AND` version 2.0 * `mri_21`: _mri_ `AND` version 2.1 + * `mri_22`: + _mri_ `AND` version 2.2 * `rbx`: Same as _ruby_, but only Rubinius (not MRI) * `jruby`: @@ -209,12 +211,16 @@ There are a number of `Gemfile` platforms: _mingw_ `AND` version 2.0 * `mingw_21`: _mingw_ `AND` version 2.1 + * `mingw_22`: + _mingw_ `AND` version 2.2 * `x64_mingw`: Windows 64 bit 'mingw32' platform (aka RubyInstaller x64) * `x64_mingw_20`: _x64_mingw_ `AND` version 2.0 * `x64_mingw_21`: _x64_mingw_ `AND` version 2.1 + * `x64_mingw_22`: + _x64_mingw_ `AND` version 2.2 As with groups, you can specify one or more platforms: diff --git a/spec/install/gems/dependency_api_spec.rb b/spec/install/gems/dependency_api_spec.rb index 8a625b2493..d0c769e0fb 100644 --- a/spec/install/gems/dependency_api_spec.rb +++ b/spec/install/gems/dependency_api_spec.rb @@ -163,6 +163,17 @@ describe "gemcutter's dependency API" do should_be_installed "rack 1.0.0" end + it "falls back when the API URL returns 403 Forbidden" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle :install, :verbose => true, :artifice => "endpoint_api_forbidden" + expect(out).to include("Fetching source index from #{source_uri}") + should_be_installed "rack 1.0.0" + end + it "handles host redirects" do gemfile <<-G source "#{source_uri}" diff --git a/spec/install/gems/sources_spec.rb b/spec/install/gems/sources_spec.rb index 0caf6806d6..68f3fd3713 100644 --- a/spec/install/gems/sources_spec.rb +++ b/spec/install/gems/sources_spec.rb @@ -239,6 +239,38 @@ describe "bundle install with gems on multiple sources" do expect(out).to include("Could not find gem 'not_in_repo1 (>= 0) ruby'") end end + + context "with an existing lockfile" do + before do + system_gems "rack-0.9.1", "rack-1.0.0" + + lockfile <<-L + GEM + remote: file:#{gem_repo1} + remote: file:#{gem_repo3} + specs: + rack (0.9.1) + + PLATFORMS + ruby + + DEPENDENCIES + rack! + L + + gemfile <<-G + source "file://#{gem_repo1}" + source "file://#{gem_repo3}" do + gem 'rack' + end + G + end + + # Reproduction of https://github.com/bundler/bundler/issues/3298 + it "does not unlock the installed gem on exec" do + should_be_installed("rack 0.9.1") + end + end end context "when an older version of the same gem also ships with Ruby" do diff --git a/spec/support/artifice/endpoint_api_forbidden.rb b/spec/support/artifice/endpoint_api_forbidden.rb new file mode 100644 index 0000000000..f9d28c0470 --- /dev/null +++ b/spec/support/artifice/endpoint_api_forbidden.rb @@ -0,0 +1,11 @@ +require File.expand_path("../endpoint", __FILE__) + +Artifice.deactivate + +class EndpointApiForbidden < Endpoint + get "/api/v1/dependencies" do + halt 403 + end +end + +Artifice.activate_with(EndpointApiForbidden) |