bundler 1.13.7 → 1.14.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop_todo.yml +100 -18
  4. data/.travis.yml +32 -18
  5. data/CHANGELOG.md +64 -2
  6. data/DEVELOPMENT.md +5 -3
  7. data/ISSUES.md +17 -0
  8. data/README.md +7 -0
  9. data/Rakefile +34 -23
  10. data/bin/rubocop +1 -1
  11. data/bundler.gemspec +2 -2
  12. data/exe/bundle +4 -6
  13. data/lib/bundler.rb +57 -5
  14. data/lib/bundler/cli.rb +51 -38
  15. data/lib/bundler/cli/binstubs.rb +1 -1
  16. data/lib/bundler/cli/cache.rb +1 -1
  17. data/lib/bundler/cli/check.rb +1 -1
  18. data/lib/bundler/cli/clean.rb +1 -1
  19. data/lib/bundler/cli/common.rb +30 -0
  20. data/lib/bundler/cli/doctor.rb +17 -19
  21. data/lib/bundler/cli/exec.rb +6 -0
  22. data/lib/bundler/cli/gem.rb +18 -4
  23. data/lib/bundler/cli/install.rb +9 -25
  24. data/lib/bundler/cli/lock.rb +8 -7
  25. data/lib/bundler/cli/outdated.rb +163 -56
  26. data/lib/bundler/cli/platform.rb +1 -1
  27. data/lib/bundler/cli/show.rb +1 -1
  28. data/lib/bundler/cli/update.rb +10 -23
  29. data/lib/bundler/compact_index_client.rb +108 -0
  30. data/lib/bundler/compact_index_client/cache.rb +119 -0
  31. data/lib/bundler/compact_index_client/updater.rb +88 -0
  32. data/lib/bundler/current_ruby.rb +4 -3
  33. data/lib/bundler/definition.rb +107 -17
  34. data/lib/bundler/dependency.rb +6 -0
  35. data/lib/bundler/dsl.rb +3 -2
  36. data/lib/bundler/env.rb +27 -18
  37. data/lib/bundler/errors.rb +22 -0
  38. data/lib/bundler/feature_flag.rb +32 -0
  39. data/lib/bundler/fetcher.rb +2 -2
  40. data/lib/bundler/fetcher/compact_index.rb +17 -5
  41. data/lib/bundler/fetcher/dependency.rb +1 -1
  42. data/lib/bundler/fetcher/downloader.rb +11 -0
  43. data/lib/bundler/friendly_errors.rb +28 -7
  44. data/lib/bundler/gem_helper.rb +1 -1
  45. data/lib/bundler/gem_helpers.rb +69 -1
  46. data/lib/bundler/gemdeps.rb +28 -0
  47. data/lib/bundler/index.rb +9 -4
  48. data/lib/bundler/inline.rb +3 -3
  49. data/lib/bundler/installer.rb +3 -2
  50. data/lib/bundler/installer/gem_installer.rb +2 -2
  51. data/lib/bundler/installer/parallel_installer.rb +40 -9
  52. data/lib/bundler/lazy_specification.rb +16 -1
  53. data/lib/bundler/lockfile_parser.rb +1 -2
  54. data/lib/bundler/match_platform.rb +12 -3
  55. data/lib/bundler/plugin.rb +4 -2
  56. data/lib/bundler/plugin/api.rb +2 -1
  57. data/lib/bundler/plugin/api/source.rb +1 -1
  58. data/lib/bundler/postit_trampoline.rb +12 -7
  59. data/lib/bundler/remote_specification.rb +5 -0
  60. data/lib/bundler/resolver.rb +59 -49
  61. data/lib/bundler/retry.rb +4 -1
  62. data/lib/bundler/ruby_version.rb +5 -0
  63. data/lib/bundler/rubygems_ext.rb +5 -0
  64. data/lib/bundler/rubygems_gem_installer.rb +60 -0
  65. data/lib/bundler/rubygems_integration.rb +28 -2
  66. data/lib/bundler/runtime.rb +2 -1
  67. data/lib/bundler/settings.rb +29 -5
  68. data/lib/bundler/setup.rb +1 -1
  69. data/lib/bundler/shared_helpers.rb +26 -15
  70. data/lib/bundler/source.rb +5 -0
  71. data/lib/bundler/source/git.rb +1 -1
  72. data/lib/bundler/source/git/git_proxy.rb +5 -0
  73. data/lib/bundler/source/path.rb +6 -1
  74. data/lib/bundler/source/rubygems.rb +11 -1
  75. data/lib/bundler/spec_set.rb +32 -13
  76. data/lib/bundler/templates/newgem/README.md.tt +1 -1
  77. data/lib/bundler/templates/newgem/bin/console.tt +1 -1
  78. data/lib/bundler/templates/newgem/gitignore.tt +5 -0
  79. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +1 -1
  80. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +10 -1
  81. data/lib/bundler/ui/shell.rb +4 -0
  82. data/lib/bundler/ui/silent.rb +9 -0
  83. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +7 -0
  84. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +1 -1
  85. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +2 -2
  86. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +2 -2
  87. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +62 -0
  88. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -1
  89. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +12 -1
  90. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +2 -2
  91. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +2 -2
  92. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  93. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +22 -13
  94. data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/faster.rb +1 -0
  95. data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/persistent.rb +24 -23
  96. data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/persistent/ssl_reuse.rb +2 -1
  97. data/lib/bundler/vendored_persistent.rb +9 -4
  98. data/lib/bundler/version.rb +1 -1
  99. data/lib/bundler/worker.rb +27 -5
  100. data/lib/bundler/yaml_serializer.rb +1 -1
  101. data/man/bundle-config.ronn +29 -2
  102. data/man/bundle-install.ronn +1 -1
  103. data/man/bundle-lock.ronn +47 -0
  104. data/man/bundle-outdated.ronn +107 -0
  105. data/man/bundle-update.ronn +152 -3
  106. data/man/bundle.ronn +27 -9
  107. data/man/gemfile.5.ronn +8 -0
  108. metadata +37 -31
  109. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client.rb +0 -79
  110. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client/cache.rb +0 -112
  111. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client/updater.rb +0 -80
  112. data/lib/bundler/vendor/compact_index_client/lib/compact_index_client/version.rb +0 -4
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module Bundler
3
+ class Gemdeps
4
+ def initialize(runtime)
5
+ @runtime = runtime
6
+ end
7
+
8
+ def requested_specs
9
+ @runtime.requested_specs
10
+ end
11
+
12
+ def specs
13
+ @runtime.specs
14
+ end
15
+
16
+ def dependencies
17
+ @runtime.dependencies
18
+ end
19
+
20
+ def current_dependencies
21
+ @runtime.current_dependencies
22
+ end
23
+
24
+ def requires
25
+ @runtime.requires
26
+ end
27
+ end
28
+ end
@@ -109,14 +109,19 @@ module Bundler
109
109
 
110
110
  # returns a list of the dependencies
111
111
  def unmet_dependency_names
112
- names = dependency_names
113
- names.delete_if {|n| n == "bundler" }
114
- names.select {|n| search(n).empty? }
112
+ dependency_names.select do |name|
113
+ name != "bundler" && search(name).empty?
114
+ end
115
115
  end
116
116
 
117
117
  def dependency_names
118
118
  names = []
119
- each {|s| names.concat(s.dependencies.map(&:name)) }
119
+ each do |spec|
120
+ spec.dependencies.each do |dep|
121
+ next if dep.type == :development
122
+ names << dep.name
123
+ end
124
+ end
120
125
  names.uniq
121
126
  end
122
127
 
@@ -41,13 +41,13 @@ def gemfile(install = false, options = {}, &gemfile)
41
41
  end
42
42
  ENV["BUNDLE_GEMFILE"] ||= "Gemfile"
43
43
 
44
- Bundler::Plugin.gemfile_install(&gemfile) if Bundler.settings[:plugins]
44
+ Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
45
45
  builder = Bundler::Dsl.new
46
46
  builder.instance_eval(&gemfile)
47
47
 
48
48
  definition = builder.to_definition(nil, true)
49
49
  def definition.lock(*); end
50
- definition.validate_ruby!
50
+ definition.validate_runtime!
51
51
 
52
52
  missing_specs = proc do
53
53
  begin
@@ -60,7 +60,7 @@ def gemfile(install = false, options = {}, &gemfile)
60
60
 
61
61
  Bundler.ui = ui if install
62
62
  if install || missing_specs.call
63
- installer = Bundler::Installer.install(Bundler.root, definition, :system => true)
63
+ installer = Bundler::Installer.install(Bundler.root, definition, :system => true, :inline => true)
64
64
  installer.post_install_messages.each do |name, message|
65
65
  Bundler.ui.info "Post-install message from #{name}:\n#{message}"
66
66
  end
@@ -159,6 +159,7 @@ module Bundler
159
159
  # that said, it's a rare situation (other than rake), and parallel
160
160
  # installation is SO MUCH FASTER. so we let people opt in.
161
161
  def install(options)
162
+ Bundler.rubygems.load_plugins
162
163
  force = options["force"]
163
164
  jobs = 1
164
165
  jobs = [Bundler.settings[:jobs].to_i - 1, 1].max if can_install_in_parallel?
@@ -207,11 +208,11 @@ module Bundler
207
208
  end unless Bundler.bundle_path.exist?
208
209
  rescue Errno::EEXIST
209
210
  raise PathError, "Could not install to path `#{Bundler.settings[:path]}` " \
210
- "because of an invalid symlink. Remove the symlink so the directory can be created."
211
+ "because a file already exists at that path. Either remove or rename the file so the directory can be created."
211
212
  end
212
213
 
213
214
  def resolve_if_need(options)
214
- if Bundler.default_lockfile.exist? && !options["update"]
215
+ if Bundler.default_lockfile.exist? && !options["update"] && !options[:inline]
215
216
  local = Bundler.ui.silence do
216
217
  begin
217
218
  tmpdef = Definition.build(Bundler.default_gemfile, Bundler.default_lockfile, nil)
@@ -52,12 +52,12 @@ module Bundler
52
52
  end
53
53
 
54
54
  def install
55
- spec.source.install(spec, :force => force, :ensure_builtin_gems_cached => standalone)
55
+ spec.source.install(spec, :force => force, :ensure_builtin_gems_cached => standalone, :build_args => [spec_settings])
56
56
  end
57
57
 
58
58
  def install_with_settings
59
59
  # Build arguments are global, so this is mutexed
60
- Bundler.rubygems.with_build_args([spec_settings]) { install }
60
+ Bundler.rubygems.install_with_build_args([spec_settings]) { install }
61
61
  end
62
62
 
63
63
  def out_of_space_message
@@ -47,23 +47,22 @@ module Bundler
47
47
  # sure needed dependencies have been installed.
48
48
  def dependencies_installed?(all_specs)
49
49
  installed_specs = all_specs.select(&:installed?).map(&:name)
50
- dependencies(all_specs.map(&:name)).all? {|d| installed_specs.include? d.name }
50
+ dependencies.all? {|d| installed_specs.include? d.name }
51
51
  end
52
52
 
53
53
  # Represents only the non-development dependencies, the ones that are
54
54
  # itself and are in the total list.
55
- def dependencies(all_spec_names)
55
+ def dependencies
56
56
  @dependencies ||= begin
57
- deps = all_dependencies.reject {|dep| ignorable_dependency? dep }
58
- missing = deps.reject {|dep| all_spec_names.include? dep.name }
59
- unless missing.empty?
60
- raise Bundler::LockfileError, "Your Gemfile.lock is corrupt. The following #{missing.size > 1 ? "gems are" : "gem is"} missing " \
61
- "from the DEPENDENCIES section: '#{missing.map(&:name).join('\' \'')}'"
62
- end
63
- deps
57
+ all_dependencies.reject {|dep| ignorable_dependency? dep }
64
58
  end
65
59
  end
66
60
 
61
+ def missing_lockfile_dependencies(all_spec_names)
62
+ deps = all_dependencies.reject {|dep| ignorable_dependency? dep }
63
+ deps.reject {|dep| all_spec_names.include? dep.name }
64
+ end
65
+
67
66
  # Represents all dependencies
68
67
  def all_dependencies
69
68
  @spec.dependencies
@@ -79,6 +78,8 @@ module Bundler
79
78
  [Bundler.settings[:jobs].to_i - 1, 1].max
80
79
  end
81
80
 
81
+ attr_reader :size
82
+
82
83
  def initialize(installer, all_specs, size, standalone, force)
83
84
  @installer = installer
84
85
  @size = size
@@ -88,6 +89,11 @@ module Bundler
88
89
  end
89
90
 
90
91
  def call
92
+ # Since `autoload` has the potential for threading issues on 1.8.7
93
+ # TODO: remove in bundler 2.0
94
+ require "bundler/gem_remote_fetcher" if RUBY_VERSION < "1.9"
95
+
96
+ check_for_corrupt_lockfile
91
97
  enqueue_specs
92
98
  process_specs until @specs.all?(&:installed?) || @specs.any?(&:failed?)
93
99
  handle_error if @specs.any?(&:failed?)
@@ -131,6 +137,31 @@ module Bundler
131
137
  raise Bundler::InstallError, errors.map(&:to_s).join("\n\n")
132
138
  end
133
139
 
140
+ def check_for_corrupt_lockfile
141
+ missing_dependencies = @specs.map do |s|
142
+ [
143
+ s,
144
+ s.missing_lockfile_dependencies(@specs.map(&:name)),
145
+ ]
146
+ end.reject { |a| a.last.empty? }
147
+ return if missing_dependencies.empty?
148
+
149
+ warning = []
150
+ warning << "Your lockfile was created by an old Bundler that left some things out."
151
+ if @size != 1
152
+ warning << "Because of the missing DEPENDENCIES, we can only install gems one at a time, instead of installing #{@size} at a time."
153
+ @size = 1
154
+ end
155
+ warning << "You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile."
156
+ warning << "The missing gems are:"
157
+
158
+ missing_dependencies.each do |spec, missing|
159
+ warning << "* #{missing.map(&:name).join(", ")} depended upon by #{spec.name}"
160
+ end
161
+
162
+ Bundler.ui.warn(warning.join("\n"))
163
+ end
164
+
134
165
  # Keys in the remains hash represent uninstalled gems specs.
135
166
  # We enqueue all gem specs that do not have any dependencies.
136
167
  # Later we call this lambda again to install specs that depended on
@@ -6,6 +6,20 @@ require "bundler/match_platform"
6
6
  module Bundler
7
7
  class LazySpecification
8
8
  Identifier = Struct.new(:name, :version, :source, :platform, :dependencies)
9
+ class Identifier
10
+ include Comparable
11
+ def <=>(other)
12
+ return unless other.is_a?(Identifier)
13
+ [name, version, platform_string] <=> [other.name, other.version, other.platform_string]
14
+ end
15
+
16
+ protected
17
+
18
+ def platform_string
19
+ platform_string = platform.to_s
20
+ platform_string == Index::RUBY ? Index::NULL : platform_string
21
+ end
22
+ end
9
23
 
10
24
  include MatchPlatform
11
25
 
@@ -55,10 +69,11 @@ module Bundler
55
69
  end
56
70
 
57
71
  def __materialize__
72
+ search_object = Bundler.settings[:specific_platform] || Bundler.settings[:force_ruby_platform] ? self : Dependency.new(name, version)
58
73
  @specification = if source.is_a?(Source::Gemspec) && source.gemspec.name == name
59
74
  source.gemspec.tap {|s| s.source = source }
60
75
  else
61
- source.specs.search(Gem::Dependency.new(name, version)).last
76
+ source.specs.search(search_object).last
62
77
  end
63
78
  end
64
79
 
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require "strscan"
3
2
 
4
3
  # Some versions of the Bundler 1.1 RC series introduced corrupted
5
4
  # lockfiles. There were two major problems:
@@ -92,7 +91,7 @@ module Bundler
92
91
  end
93
92
  end
94
93
  @sources << @rubygems_aggregate
95
- @specs = @specs.values
94
+ @specs = @specs.values.sort_by(&:identifier)
96
95
  warn_for_outdated_bundler_version
97
96
  rescue ArgumentError => e
98
97
  Bundler.ui.debug(e)
@@ -6,9 +6,18 @@ module Bundler
6
6
  include GemHelpers
7
7
 
8
8
  def match_platform(p)
9
- Gem::Platform::RUBY == platform ||
10
- platform.nil? || p == platform ||
11
- generic(Gem::Platform.new(platform)) === p
9
+ MatchPlatform.platforms_match?(platform, p)
10
+ end
11
+
12
+ def self.platforms_match?(gemspec_platform, local_platform)
13
+ return true if gemspec_platform.nil?
14
+ return true if Gem::Platform::RUBY == gemspec_platform
15
+ return true if local_platform == gemspec_platform
16
+ gemspec_platform = Gem::Platform.new(gemspec_platform)
17
+ return true if GemHelpers.generic(gemspec_platform) === local_platform
18
+ return true if gemspec_platform === local_platform
19
+
20
+ false
12
21
  end
13
22
  end
14
23
  end
@@ -62,7 +62,9 @@ module Bundler
62
62
 
63
63
  save_plugins plugins, installed_specs, builder.inferred_plugins
64
64
  rescue => e
65
- Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"
65
+ unless e.is_a?(GemfileError)
66
+ Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"
67
+ end
66
68
  raise
67
69
  end
68
70
 
@@ -158,7 +160,7 @@ module Bundler
158
160
  #
159
161
  # @param [String] event
160
162
  def hook(event, *args, &arg_blk)
161
- return unless Bundler.settings[:plugins]
163
+ return unless Bundler.feature_flag.plugins?
162
164
 
163
165
  plugins = index.hook_plugins(event)
164
166
  return unless plugins.any?
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require "bundler/plugin/api/source"
3
2
 
4
3
  module Bundler
5
4
  # This is the interfacing class represents the API that we intend to provide
@@ -24,6 +23,8 @@ module Bundler
24
23
  # and hooks).
25
24
  module Plugin
26
25
  class API
26
+ autoload :Source, "bundler/plugin/api/source"
27
+
27
28
  # The plugins should declare that they handle a command through this helper.
28
29
  #
29
30
  # @param [String] command being handled by them
@@ -93,7 +93,7 @@ module Bundler
93
93
  # It should be called in `install` after the plugin is done placing the
94
94
  # gem at correct install location.
95
95
  #
96
- # It also runs Gem hooks `post_install`, `post_build` and `post_install`
96
+ # It also runs Gem hooks `pre_install`, `post_build` and `post_install`
97
97
  #
98
98
  # Note: Do not override if you don't know what you are doing.
99
99
  def post_install(spec, disable_exts = false)
@@ -1,13 +1,18 @@
1
1
  # frozen_string_literal: true
2
- if ENV["BUNDLE_ENABLE_TRAMPOLINE"]
3
2
 
4
- module BundlerVendoredPostIt; end
5
- require "bundler/vendor/postit/lib/postit"
6
- require "rubygems"
3
+ module BundlerVendoredPostIt; end
4
+ require "bundler/vendor/postit/lib/postit"
5
+ require "rubygems"
7
6
 
8
- environment = BundlerVendoredPostIt::PostIt::Environment.new([])
9
- version = Gem::Requirement.new(environment.bundler_version)
7
+ environment = BundlerVendoredPostIt::PostIt::Environment.new([])
8
+ version = Gem::Requirement.new(environment.bundler_version)
9
+ if version.requirements.size == 1 && version.requirements.first.first == "=" # version.exact?
10
+ if version.requirements.first.last.segments.first >= 2
11
+ ENV["BUNDLE_TRAMPOLINE_FORCE"] = "true"
12
+ end
13
+ end
10
14
 
15
+ if ENV["BUNDLE_TRAMPOLINE_FORCE"] && !ENV["BUNDLE_TRAMPOLINE_DISABLE"]
11
16
  installed_version =
12
17
  if defined?(Bundler::VERSION)
13
18
  Bundler::VERSION
@@ -65,4 +70,4 @@ You're running Bundler #{installed_version} but this project uses #{running_vers
65
70
  abort "The running bundler (#{running_version}) does not match the required `#{version}`"
66
71
  end
67
72
 
68
- end # unless ENV["BUNDLE_ENABLE_TRAMPOLINE"]
73
+ end # if ENV["BUNDLE_TRAMPOLINE_FORCE"] && !ENV["BUNDLE_TRAMPOLINE_DISABLE"]
@@ -81,5 +81,10 @@ module Bundler
81
81
  def method_missing(method, *args, &blk)
82
82
  _remote_specification.send(method, *args, &blk)
83
83
  end
84
+
85
+ def respond_to?(method, include_all = false)
86
+ super || _remote_specification.respond_to?(method, include_all)
87
+ end
88
+ public :respond_to?
84
89
  end
85
90
  end
@@ -66,48 +66,39 @@ module Bundler
66
66
  end
67
67
  end
68
68
 
69
- ALL = Bundler::Dependency::PLATFORM_MAP.values.uniq.freeze
70
-
71
69
  class SpecGroup < Array
72
70
  include GemHelpers
73
71
 
74
- attr_reader :activated, :required_by
72
+ attr_reader :activated
75
73
 
76
74
  def initialize(a)
77
75
  super
78
- @required_by = []
79
- @activated = []
76
+ @required_by = []
77
+ @activated_platforms = []
80
78
  @dependencies = nil
81
- @specs = {}
82
-
83
- ALL.each do |p|
84
- @specs[p] = reverse.find {|s| s.match_platform(p) }
79
+ @specs = Hash.new do |specs, platform|
80
+ specs[platform] = select_best_platform_match(self, platform)
85
81
  end
86
82
  end
87
83
 
88
84
  def initialize_copy(o)
89
85
  super
90
- @required_by = o.required_by.dup
91
- @activated = o.activated.dup
86
+ @activated_platforms = o.activated.dup
92
87
  end
93
88
 
94
89
  def to_specs
95
- specs = {}
96
-
97
- @activated.each do |p|
90
+ @activated_platforms.map do |p|
98
91
  next unless s = @specs[p]
99
- platform = generic(Gem::Platform.new(s.platform))
100
- next if specs[platform]
101
-
102
- lazy_spec = LazySpecification.new(name, version, platform, source)
92
+ lazy_spec = LazySpecification.new(name, version, s.platform, source)
103
93
  lazy_spec.dependencies.replace s.dependencies
104
- specs[platform] = lazy_spec
105
- end
106
- specs.values
94
+ lazy_spec
95
+ end.compact
107
96
  end
108
97
 
109
98
  def activate_platform!(platform)
110
- @activated << platform if !@activated.include?(platform) && for?(platform, nil)
99
+ return unless for?(platform)
100
+ return if @activated_platforms.include?(platform)
101
+ @activated_platforms << platform
111
102
  end
112
103
 
113
104
  def name
@@ -122,17 +113,9 @@ module Bundler
122
113
  @source ||= first.source
123
114
  end
124
115
 
125
- def for?(platform, ruby_version)
116
+ def for?(platform)
126
117
  spec = @specs[platform]
127
- return false unless spec
128
-
129
- return true if ruby_version.nil?
130
- # Only allow endpoint specifications since they won't hit the network to
131
- # fetch the full gemspec when calling required_ruby_version
132
- return true if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
133
- return true if spec.required_ruby_version.nil?
134
-
135
- spec.required_ruby_version.satisfied_by?(ruby_version.to_gem_version_with_patchlevel)
118
+ !spec.nil?
136
119
  end
137
120
 
138
121
  def to_s
@@ -140,7 +123,11 @@ module Bundler
140
123
  end
141
124
 
142
125
  def dependencies_for_activated_platforms
143
- @activated.map {|p| __dependencies[p] }.flatten
126
+ dependencies = @activated_platforms.map {|p| __dependencies[p] }
127
+ metadata_dependencies = @activated_platforms.map do |platform|
128
+ metadata_dependencies(@specs[platform], platform)
129
+ end
130
+ dependencies.concat(metadata_dependencies).flatten
144
131
  end
145
132
 
146
133
  def platforms_for_dependency_named(dependency)
@@ -150,18 +137,31 @@ module Bundler
150
137
  private
151
138
 
152
139
  def __dependencies
153
- @dependencies ||= begin
154
- dependencies = {}
155
- ALL.each do |p|
156
- next unless spec = @specs[p]
157
- dependencies[p] = []
140
+ @dependencies = Hash.new do |dependencies, platform|
141
+ dependencies[platform] = []
142
+ if spec = @specs[platform]
158
143
  spec.dependencies.each do |dep|
159
144
  next if dep.type == :development
160
- dependencies[p] << DepProxy.new(dep, p)
145
+ dependencies[platform] << DepProxy.new(dep, platform)
161
146
  end
162
147
  end
163
- dependencies
148
+ dependencies[platform]
149
+ end
150
+ end
151
+
152
+ def metadata_dependencies(spec, platform)
153
+ return [] unless spec
154
+ # Only allow endpoint specifications since they won't hit the network to
155
+ # fetch the full gemspec when calling required_ruby_version
156
+ return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
157
+ dependencies = []
158
+ if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
159
+ dependencies << DepProxy.new(Gem::Dependency.new("ruby\0", spec.required_ruby_version), platform)
164
160
  end
161
+ if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
162
+ dependencies << DepProxy.new(Gem::Dependency.new("rubygems\0", spec.required_rubygems_version), platform)
163
+ end
164
+ dependencies
165
165
  end
166
166
  end
167
167
 
@@ -175,30 +175,34 @@ module Bundler
175
175
  # ==== Returns
176
176
  # <GemBundle>,nil:: If the list of dependencies can be resolved, a
177
177
  # collection of gemspecs is returned. Otherwise, nil is returned.
178
- def self.resolve(requirements, index, source_requirements = {}, base = [], ruby_version = nil, gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [])
178
+ def self.resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [])
179
179
  base = SpecSet.new(base) unless base.is_a?(SpecSet)
180
- resolver = new(index, source_requirements, base, ruby_version, gem_version_promoter, additional_base_requirements)
180
+ resolver = new(index, source_requirements, base, gem_version_promoter, additional_base_requirements)
181
181
  result = resolver.start(requirements)
182
182
  SpecSet.new(result)
183
183
  end
184
184
 
185
- def initialize(index, source_requirements, base, ruby_version, gem_version_promoter, additional_base_requirements)
185
+ def initialize(index, source_requirements, base, gem_version_promoter, additional_base_requirements)
186
186
  @index = index
187
187
  @source_requirements = source_requirements
188
188
  @base = base
189
189
  @resolver = Molinillo::Resolver.new(self, self)
190
190
  @search_for = {}
191
191
  @base_dg = Molinillo::DependencyGraph.new
192
- @base.each {|ls| @base_dg.add_vertex(ls.name, Dependency.new(ls.name, ls.version), true) }
192
+ @base.each do |ls|
193
+ dep = Dependency.new(ls.name, ls.version)
194
+ @base_dg.add_vertex(ls.name, DepProxy.new(dep, ls.platform), true)
195
+ end
193
196
  additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
194
- @ruby_version = ruby_version
195
197
  @gem_version_promoter = gem_version_promoter
196
198
  end
197
199
 
198
200
  def start(requirements)
199
201
  verify_gemfile_dependencies_are_found!(requirements)
200
202
  dg = @resolver.resolve(requirements, @base_dg)
201
- dg.map(&:payload).map(&:to_specs).flatten
203
+ dg.map(&:payload).
204
+ reject {|sg| sg.name.end_with?("\0") }.
205
+ map(&:to_specs).flatten
202
206
  rescue Molinillo::VersionConflict => e
203
207
  raise VersionConflict.new(e.conflicts.keys.uniq, e.message)
204
208
  rescue Molinillo::CircularDependencyError => e
@@ -279,7 +283,7 @@ module Bundler
279
283
  @gem_version_promoter.sort_versions(dependency, spec_groups)
280
284
  end
281
285
  end
282
- search.select {|sg| sg.for?(platform, @ruby_version) }.each {|sg| sg.activate_platform!(platform) }
286
+ search.select {|sg| sg.for?(platform) }.each {|sg| sg.activate_platform!(platform) }
283
287
  end
284
288
 
285
289
  def index_for(dependency)
@@ -303,7 +307,8 @@ module Bundler
303
307
  end
304
308
 
305
309
  def requirement_satisfied_by?(requirement, activated, spec)
306
- requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
310
+ return false unless requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
311
+ spec.activate_platform!(requirement.__platform) || spec.for?(requirement.__platform)
307
312
  end
308
313
 
309
314
  def sort_dependencies(dependencies, activated, conflicts)
@@ -360,8 +365,13 @@ module Bundler
360
365
  "Source does not contain any versions of '#{requirement}'"
361
366
  end
362
367
  else
368
+ cache_message = begin
369
+ " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
370
+ rescue GemfileNotFound
371
+ nil
372
+ end
363
373
  message = "Could not find gem '#{requirement}' in any of the gem sources " \
364
- "listed in your Gemfile or available on this machine."
374
+ "listed in your Gemfile#{cache_message}."
365
375
  end
366
376
  raise GemNotFound, message
367
377
  end