bundler 1.15.4 → 1.16.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 (251) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +43 -0
  3. data/README.md +12 -7
  4. data/exe/bundle +1 -1
  5. data/exe/bundle_ruby +4 -3
  6. data/lib/bundler.rb +47 -37
  7. data/lib/bundler/build_metadata.rb +38 -0
  8. data/lib/bundler/capistrano.rb +5 -0
  9. data/lib/bundler/cli.rb +155 -67
  10. data/lib/bundler/cli/add.rb +0 -1
  11. data/lib/bundler/cli/binstubs.rb +9 -7
  12. data/lib/bundler/cli/cache.rb +5 -4
  13. data/lib/bundler/cli/check.rb +3 -5
  14. data/lib/bundler/cli/clean.rb +5 -6
  15. data/lib/bundler/cli/common.rb +11 -2
  16. data/lib/bundler/cli/config.rb +2 -1
  17. data/lib/bundler/cli/console.rb +2 -1
  18. data/lib/bundler/cli/doctor.rb +1 -0
  19. data/lib/bundler/cli/exec.rb +2 -1
  20. data/lib/bundler/cli/gem.rb +3 -2
  21. data/lib/bundler/cli/info.rb +0 -1
  22. data/lib/bundler/cli/init.rb +17 -6
  23. data/lib/bundler/cli/inject.rb +1 -0
  24. data/lib/bundler/cli/install.rb +61 -61
  25. data/lib/bundler/cli/issue.rb +1 -1
  26. data/lib/bundler/cli/list.rb +22 -0
  27. data/lib/bundler/cli/lock.rb +0 -1
  28. data/lib/bundler/cli/open.rb +2 -2
  29. data/lib/bundler/cli/outdated.rb +13 -8
  30. data/lib/bundler/cli/package.rb +9 -6
  31. data/lib/bundler/cli/platform.rb +1 -0
  32. data/lib/bundler/cli/plugin.rb +1 -0
  33. data/lib/bundler/cli/pristine.rb +9 -2
  34. data/lib/bundler/cli/show.rb +0 -1
  35. data/lib/bundler/cli/update.rb +31 -5
  36. data/lib/bundler/cli/viz.rb +1 -0
  37. data/lib/bundler/compact_index_client.rb +1 -0
  38. data/lib/bundler/compact_index_client/cache.rb +1 -0
  39. data/lib/bundler/compact_index_client/updater.rb +3 -2
  40. data/lib/bundler/compatibility_guard.rb +14 -0
  41. data/lib/bundler/constants.rb +1 -0
  42. data/lib/bundler/current_ruby.rb +5 -4
  43. data/lib/bundler/definition.rb +140 -95
  44. data/lib/bundler/dep_proxy.rb +2 -0
  45. data/lib/bundler/dependency.rb +6 -7
  46. data/lib/bundler/deployment.rb +1 -1
  47. data/lib/bundler/deprecate.rb +1 -0
  48. data/lib/bundler/dsl.rb +97 -62
  49. data/lib/bundler/endpoint_specification.rb +9 -0
  50. data/lib/bundler/env.rb +63 -27
  51. data/lib/bundler/environment_preserver.rb +26 -6
  52. data/lib/bundler/errors.rb +1 -0
  53. data/lib/bundler/feature_flag.rb +39 -4
  54. data/lib/bundler/fetcher.rb +15 -8
  55. data/lib/bundler/fetcher/base.rb +1 -0
  56. data/lib/bundler/fetcher/compact_index.rb +2 -11
  57. data/lib/bundler/fetcher/dependency.rb +1 -0
  58. data/lib/bundler/fetcher/downloader.rb +1 -0
  59. data/lib/bundler/fetcher/index.rb +1 -0
  60. data/lib/bundler/friendly_errors.rb +2 -1
  61. data/lib/bundler/gem_helper.rb +14 -9
  62. data/lib/bundler/gem_helpers.rb +1 -0
  63. data/lib/bundler/gem_remote_fetcher.rb +1 -0
  64. data/lib/bundler/gem_tasks.rb +1 -0
  65. data/lib/bundler/gem_version_promoter.rb +1 -0
  66. data/lib/bundler/gemdeps.rb +1 -0
  67. data/lib/bundler/graph.rb +1 -0
  68. data/lib/bundler/index.rb +15 -8
  69. data/lib/bundler/injector.rb +25 -22
  70. data/lib/bundler/inline.rb +5 -7
  71. data/lib/bundler/installer.rb +93 -45
  72. data/lib/bundler/installer/gem_installer.rb +2 -0
  73. data/lib/bundler/installer/parallel_installer.rb +73 -42
  74. data/lib/bundler/installer/standalone.rb +1 -0
  75. data/lib/bundler/lazy_specification.rb +2 -1
  76. data/lib/bundler/lockfile_generator.rb +95 -0
  77. data/lib/bundler/lockfile_parser.rb +10 -4
  78. data/lib/bundler/match_platform.rb +1 -0
  79. data/lib/bundler/mirror.rb +6 -3
  80. data/lib/bundler/plugin.rb +1 -0
  81. data/lib/bundler/plugin/api/source.rb +8 -0
  82. data/lib/bundler/plugin/installer.rb +7 -6
  83. data/lib/bundler/plugin/source_list.rb +7 -8
  84. data/lib/bundler/process_lock.rb +24 -0
  85. data/lib/bundler/psyched_yaml.rb +1 -0
  86. data/lib/bundler/remote_specification.rb +1 -0
  87. data/lib/bundler/resolver.rb +138 -191
  88. data/lib/bundler/resolver/spec_group.rb +111 -0
  89. data/lib/bundler/retry.rb +1 -0
  90. data/lib/bundler/ruby_dsl.rb +1 -0
  91. data/lib/bundler/ruby_version.rb +1 -0
  92. data/lib/bundler/rubygems_ext.rb +5 -4
  93. data/lib/bundler/rubygems_gem_installer.rb +23 -0
  94. data/lib/bundler/rubygems_integration.rb +56 -27
  95. data/lib/bundler/runtime.rb +3 -5
  96. data/lib/bundler/settings.rb +177 -76
  97. data/lib/bundler/settings/validator.rb +79 -0
  98. data/lib/bundler/setup.rb +1 -0
  99. data/lib/bundler/shared_helpers.rb +86 -26
  100. data/lib/bundler/similarity_detector.rb +1 -0
  101. data/lib/bundler/source.rb +32 -0
  102. data/lib/bundler/source/gemspec.rb +1 -0
  103. data/lib/bundler/source/git.rb +21 -16
  104. data/lib/bundler/source/git/git_proxy.rb +14 -10
  105. data/lib/bundler/source/metadata.rb +63 -0
  106. data/lib/bundler/source/path.rb +8 -8
  107. data/lib/bundler/source/path/installer.rb +2 -0
  108. data/lib/bundler/source/rubygems.rb +131 -84
  109. data/lib/bundler/source/rubygems/remote.rb +3 -0
  110. data/lib/bundler/source_list.rb +75 -15
  111. data/lib/bundler/spec_set.rb +2 -1
  112. data/lib/bundler/ssl_certs/certificate_manager.rb +2 -1
  113. data/lib/bundler/stub_specification.rb +1 -0
  114. data/lib/bundler/templates/Executable +4 -0
  115. data/lib/bundler/templates/Executable.bundler +105 -0
  116. data/lib/bundler/templates/Gemfile +1 -0
  117. data/lib/bundler/templates/gems.rb +8 -0
  118. data/lib/bundler/templates/newgem/README.md.tt +1 -1
  119. data/lib/bundler/templates/newgem/gitignore.tt +0 -1
  120. data/lib/bundler/templates/newgem/newgem.gemspec.tt +4 -1
  121. data/lib/bundler/templates/newgem/rspec.tt +1 -0
  122. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +0 -2
  123. data/lib/bundler/ui.rb +1 -0
  124. data/lib/bundler/ui/rg_proxy.rb +1 -0
  125. data/lib/bundler/ui/shell.rb +15 -4
  126. data/lib/bundler/ui/silent.rb +1 -0
  127. data/lib/bundler/uri_credentials_filter.rb +1 -0
  128. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1638 -0
  129. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +2 -0
  130. data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +26 -0
  131. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +7 -0
  132. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +1 -0
  133. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +3 -2
  134. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +1 -0
  135. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +1 -0
  136. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +1 -0
  137. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +1 -0
  138. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -0
  139. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +1 -0
  140. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +1 -0
  141. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +1 -0
  142. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +3 -2
  143. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +69 -6
  144. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +2 -1
  145. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -0
  146. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +3 -1
  147. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +487 -148
  148. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +1 -0
  149. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +8 -4
  150. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
  151. data/lib/bundler/vendored_fileutils.rb +9 -0
  152. data/lib/bundler/vendored_molinillo.rb +1 -0
  153. data/lib/bundler/vendored_persistent.rb +34 -0
  154. data/lib/bundler/vendored_thor.rb +1 -0
  155. data/lib/bundler/version.rb +6 -2
  156. data/lib/bundler/version_ranges.rb +1 -0
  157. data/lib/bundler/vlad.rb +5 -0
  158. data/lib/bundler/worker.rb +1 -0
  159. data/lib/bundler/yaml_serializer.rb +3 -3
  160. data/man/bundle-add.1 +43 -0
  161. data/man/bundle-add.1.txt +40 -0
  162. data/man/bundle-binstubs.1 +40 -0
  163. data/man/bundle-binstubs.1.txt +48 -0
  164. data/man/bundle-binstubs.ronn +14 -0
  165. data/man/bundle-check.1 +31 -0
  166. data/man/bundle-check.1.txt +32 -0
  167. data/man/bundle-clean.1 +24 -0
  168. data/man/bundle-clean.1.txt +26 -0
  169. data/man/bundle-config.1 +455 -0
  170. data/man/bundle-config.1.txt +491 -0
  171. data/man/bundle-config.ronn +133 -79
  172. data/man/bundle-exec.1 +165 -0
  173. data/man/bundle-exec.1.txt +178 -0
  174. data/man/bundle-exec.ronn +7 -0
  175. data/man/bundle-gem.1 +80 -0
  176. data/man/bundle-gem.1.txt +91 -0
  177. data/man/bundle-gem.ronn +2 -1
  178. data/man/bundle-info.1 +20 -0
  179. data/man/bundle-info.1.txt +21 -0
  180. data/man/bundle-init.1 +20 -0
  181. data/man/bundle-init.1.txt +24 -0
  182. data/man/bundle-inject.1 +33 -0
  183. data/man/bundle-inject.1.txt +32 -0
  184. data/man/bundle-install.1 +305 -0
  185. data/man/bundle-install.1.txt +385 -0
  186. data/man/bundle-install.ronn +32 -32
  187. data/man/bundle-list.1 +20 -0
  188. data/man/bundle-list.1.txt +21 -0
  189. data/man/bundle-list.ronn +15 -0
  190. data/man/bundle-lock.1 +84 -0
  191. data/man/bundle-lock.1.txt +93 -0
  192. data/man/bundle-open.1 +32 -0
  193. data/man/bundle-open.1.txt +29 -0
  194. data/man/bundle-outdated.1 +151 -0
  195. data/man/bundle-outdated.1.txt +127 -0
  196. data/man/bundle-outdated.ronn +1 -1
  197. data/man/bundle-package.1 +55 -0
  198. data/man/bundle-package.1.txt +79 -0
  199. data/man/bundle-package.ronn +5 -0
  200. data/man/bundle-platform.1 +61 -0
  201. data/man/bundle-platform.1.txt +57 -0
  202. data/man/bundle-pristine.1 +34 -0
  203. data/man/bundle-pristine.1.txt +44 -0
  204. data/man/bundle-pristine.ronn +24 -3
  205. data/man/bundle-show.1 +23 -0
  206. data/man/bundle-show.1.txt +25 -0
  207. data/man/bundle-update.1 +390 -0
  208. data/man/bundle-update.1.txt +386 -0
  209. data/man/bundle-update.ronn +2 -2
  210. data/man/bundle-viz.1 +39 -0
  211. data/man/bundle-viz.1.txt +38 -0
  212. data/man/bundle-viz.ronn +5 -5
  213. data/man/bundle.1 +132 -0
  214. data/man/bundle.1.txt +113 -0
  215. data/man/bundle.ronn +5 -2
  216. data/man/gemfile.5 +679 -0
  217. data/man/gemfile.5.ronn +31 -0
  218. data/man/gemfile.5.txt +636 -0
  219. data/man/index.txt +23 -0
  220. metadata +21 -36
  221. data/.codeclimate.yml +0 -25
  222. data/.gitignore +0 -18
  223. data/.rspec +0 -3
  224. data/.rubocop.yml +0 -131
  225. data/.rubocop_todo.yml +0 -418
  226. data/.travis.yml +0 -122
  227. data/CODE_OF_CONDUCT.md +0 -42
  228. data/CONTRIBUTING.md +0 -17
  229. data/Rakefile +0 -338
  230. data/bin/rake +0 -19
  231. data/bin/rspec +0 -15
  232. data/bin/rubocop +0 -17
  233. data/bin/with_rubygems +0 -39
  234. data/bundler.gemspec +0 -48
  235. data/doc/README.md +0 -30
  236. data/doc/TROUBLESHOOTING.md +0 -64
  237. data/doc/contributing/BUG_TRIAGE.md +0 -36
  238. data/doc/contributing/COMMUNITY.md +0 -13
  239. data/doc/contributing/GETTING_HELP.md +0 -11
  240. data/doc/contributing/HOW_YOU_CAN_HELP.md +0 -27
  241. data/doc/contributing/ISSUES.md +0 -51
  242. data/doc/contributing/README.md +0 -38
  243. data/doc/development/NEW_FEATURES.md +0 -10
  244. data/doc/development/PULL_REQUESTS.md +0 -40
  245. data/doc/development/README.md +0 -19
  246. data/doc/development/RELEASING.md +0 -9
  247. data/doc/development/SETUP.md +0 -27
  248. data/doc/documentation/README.md +0 -29
  249. data/doc/documentation/VISION.md +0 -26
  250. data/doc/documentation/WRITING.md +0 -54
  251. data/task/release.rake +0 -116
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "shellwords"
3
4
  require "tempfile"
4
5
  module Bundler
@@ -62,7 +63,7 @@ module Bundler
62
63
  begin
63
64
  @revision ||= find_local_revision
64
65
  rescue GitCommandError
65
- raise MissingGitRevisionError.new(ref, uri)
66
+ raise MissingGitRevisionError.new(ref, URICredentialsFilter.credential_filtered_uri(uri))
66
67
  end
67
68
 
68
69
  @revision
@@ -90,18 +91,21 @@ module Bundler
90
91
  end
91
92
 
92
93
  def checkout
93
- if path.exist?
94
- return if has_revision_cached?
95
- Bundler.ui.info "Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"
96
- in_path do
97
- git_retry %(fetch --force --quiet --tags #{uri_escaped_with_configured_credentials} "refs/heads/*:refs/heads/*")
98
- end
99
- else
100
- Bundler.ui.info "Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"
94
+ return if path.exist? && has_revision_cached?
95
+ extra_ref = "#{Shellwords.shellescape(ref)}:#{Shellwords.shellescape(ref)}" if ref && ref.start_with?("refs/")
96
+
97
+ Bundler.ui.info "Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"
98
+
99
+ unless path.exist?
101
100
  SharedHelpers.filesystem_access(path.dirname) do |p|
102
101
  FileUtils.mkdir_p(p)
103
102
  end
104
103
  git_retry %(clone #{uri_escaped_with_configured_credentials} "#{path}" --bare --no-hardlinks --quiet)
104
+ return unless extra_ref
105
+ end
106
+
107
+ in_path do
108
+ git_retry %(fetch --force --quiet --tags #{uri_escaped_with_configured_credentials} "refs/heads/*:refs/heads/*" #{extra_ref})
105
109
  end
106
110
  end
107
111
 
@@ -149,7 +153,7 @@ module Bundler
149
153
  end
150
154
 
151
155
  def git_retry(command)
152
- Bundler::Retry.new("`git #{command}`", GitNotAllowedError).attempts do
156
+ Bundler::Retry.new("`git #{URICredentialsFilter.credential_filtered_string(command, uri)}`", GitNotAllowedError).attempts do
153
157
  git(command)
154
158
  end
155
159
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class Source
5
+ class Metadata < Source
6
+ def specs
7
+ @specs ||= Index.build do |idx|
8
+ idx << Gem::Specification.new("ruby\0", RubyVersion.system.to_gem_version_with_patchlevel)
9
+ idx << Gem::Specification.new("rubygems\0", Gem::VERSION)
10
+
11
+ idx << Gem::Specification.new do |s|
12
+ s.name = "bundler"
13
+ s.version = VERSION
14
+ s.platform = Gem::Platform::RUBY
15
+ s.source = self
16
+ s.authors = ["bundler team"]
17
+ s.bindir = "exe"
18
+ s.executables = %w[bundle]
19
+ # can't point to the actual gemspec or else the require paths will be wrong
20
+ s.loaded_from = File.expand_path("..", __FILE__)
21
+ end
22
+ if loaded_spec = nil && Bundler.rubygems.loaded_specs("bundler")
23
+ idx << loaded_spec # this has to come after the fake gemspec, to override it
24
+ elsif local_spec = Bundler.rubygems.find_name("bundler").find {|s| s.version.to_s == VERSION }
25
+ idx << local_spec
26
+ end
27
+
28
+ idx.each {|s| s.source = self }
29
+ end
30
+ end
31
+
32
+ def cached!; end
33
+
34
+ def remote!; end
35
+
36
+ def options
37
+ {}
38
+ end
39
+
40
+ def install(spec, _opts = {})
41
+ print_using_message "Using #{version_message(spec)}"
42
+ nil
43
+ end
44
+
45
+ def to_s
46
+ "the local ruby installation"
47
+ end
48
+
49
+ def ==(other)
50
+ self.class == other.class
51
+ end
52
+ alias_method :eql?, :==
53
+
54
+ def hash
55
+ self.class.hash
56
+ end
57
+
58
+ def version_message(spec)
59
+ "#{spec.name} #{spec.version}"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bundler
3
4
  class Source
4
5
  class Path < Source
@@ -35,10 +36,12 @@ module Bundler
35
36
  end
36
37
 
37
38
  def remote!
39
+ @local_specs = nil
38
40
  @allow_remote = true
39
41
  end
40
42
 
41
43
  def cached!
44
+ @local_specs = nil
42
45
  @allow_cached = true
43
46
  end
44
47
 
@@ -74,14 +77,14 @@ module Bundler
74
77
  end
75
78
 
76
79
  def install(spec, options = {})
77
- Bundler.ui.info "Using #{version_message(spec)} from #{self}"
80
+ print_using_message "Using #{version_message(spec)} from #{self}"
78
81
  generate_bin(spec, :disable_extensions => true)
79
82
  nil # no post-install message
80
83
  end
81
84
 
82
85
  def cache(spec, custom_path = nil)
83
86
  app_cache_path = app_cache_path(custom_path)
84
- return unless Bundler.settings[:cache_all]
87
+ return unless Bundler.feature_flag.cache_all?
85
88
  return if expand(@original_path).to_s.index(root_path.to_s + "/") == 0
86
89
 
87
90
  unless @original_path.exist?
@@ -113,10 +116,6 @@ module Bundler
113
116
  Bundler.root
114
117
  end
115
118
 
116
- def is_a_path?
117
- instance_of?(Path)
118
- end
119
-
120
119
  def expanded_original_path
121
120
  @expanded_original_path ||= expand(original_path)
122
121
  end
@@ -228,7 +227,8 @@ module Bundler
228
227
  spec,
229
228
  :env_shebang => false,
230
229
  :disable_extensions => options[:disable_extensions],
231
- :build_args => options[:build_args]
230
+ :build_args => options[:build_args],
231
+ :bundler_extension_cache_path => extension_cache_path(spec)
232
232
  )
233
233
  installer.post_install
234
234
  rescue Gem::InvalidSpecificationException => e
@@ -242,7 +242,7 @@ module Bundler
242
242
  "to modify their .gemspec so it can work with `gem build`."
243
243
  end
244
244
 
245
- Bundler.ui.warn "The validation message from Rubygems was:\n #{e.message}"
245
+ Bundler.ui.warn "The validation message from RubyGems was:\n #{e.message}"
246
246
  end
247
247
  end
248
248
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bundler
3
4
  class Source
4
5
  class Path
@@ -6,6 +7,7 @@ module Bundler
6
7
  attr_reader :spec
7
8
 
8
9
  def initialize(spec, options = {})
10
+ @options = options
9
11
  @spec = spec
10
12
  @gem_dir = Bundler.rubygems.path(spec.full_gem_path)
11
13
  @wrappers = true
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "uri"
3
4
  require "rubygems/user_interaction"
4
5
 
@@ -31,6 +32,7 @@ module Bundler
31
32
  end
32
33
 
33
34
  def cached!
35
+ @specs = nil
34
36
  @allow_cached = true
35
37
  end
36
38
 
@@ -49,6 +51,7 @@ module Bundler
49
51
  end
50
52
 
51
53
  def can_lock?(spec)
54
+ return super if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
52
55
  spec.source.is_a?(Rubygems)
53
56
  end
54
57
 
@@ -69,8 +72,12 @@ module Bundler
69
72
  end
70
73
 
71
74
  def to_s
72
- remote_names = remotes.map(&:to_s).join(", ")
73
- "rubygems repository #{remote_names}"
75
+ if remotes.empty?
76
+ "locally installed gems"
77
+ else
78
+ remote_names = remotes.map(&:to_s).join(", ")
79
+ "rubygems repository #{remote_names} or installed locally"
80
+ end
74
81
  end
75
82
  alias_method :name, :to_s
76
83
 
@@ -99,8 +106,8 @@ module Bundler
99
106
  end
100
107
  end
101
108
 
102
- if installed?(spec) && (!force || spec.name.eql?("bundler"))
103
- Bundler.ui.info "Using #{version_message(spec)}"
109
+ if installed?(spec) && !force
110
+ print_using_message "Using #{version_message(spec)}"
104
111
  return nil # no post-install message
105
112
  end
106
113
 
@@ -141,7 +148,8 @@ module Bundler
141
148
  :wrappers => true,
142
149
  :env_shebang => true,
143
150
  :build_args => opts[:build_args],
144
- :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum
151
+ :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum,
152
+ :bundler_extension_cache_path => extension_cache_path(spec)
145
153
  ).install
146
154
  end
147
155
  spec.full_gem_path = installed_spec.full_gem_path
@@ -212,13 +220,21 @@ module Bundler
212
220
  @remotes.unshift(uri) unless @remotes.include?(uri)
213
221
  end
214
222
 
215
- def replace_remotes(other_remotes)
223
+ def equivalent_remotes?(other_remotes)
224
+ other_remotes.map(&method(:remove_auth)) == @remotes.map(&method(:remove_auth))
225
+ end
226
+
227
+ def replace_remotes(other_remotes, allow_equivalent = false)
216
228
  return false if other_remotes == @remotes
217
229
 
230
+ equivalent = allow_equivalent && equivalent_remotes?(other_remotes)
231
+
218
232
  @remotes = []
219
233
  other_remotes.reverse_each do |r|
220
234
  add_remote r.to_s
221
235
  end
236
+
237
+ !equivalent
222
238
  end
223
239
 
224
240
  def unmet_deps
@@ -236,6 +252,20 @@ module Bundler
236
252
  end
237
253
  end
238
254
 
255
+ def double_check_for(unmet_dependency_names, override_dupes = false, index = specs)
256
+ return unless @allow_remote
257
+ raise ArgumentError, "missing index" unless index
258
+
259
+ return unless api_fetchers.any?
260
+
261
+ unmet_dependency_names = unmet_dependency_names.call
262
+ return if !unmet_dependency_names.nil? && unmet_dependency_names.empty?
263
+
264
+ Bundler.ui.debug "Double checking for #{unmet_dependency_names || "all specs (due to the size of the request)"} in #{self}"
265
+
266
+ fetch_names(api_fetchers, unmet_dependency_names, index, override_dupes)
267
+ end
268
+
239
269
  protected
240
270
 
241
271
  def credless_remotes
@@ -276,7 +306,7 @@ module Bundler
276
306
  end
277
307
 
278
308
  def suppress_configured_credentials(remote)
279
- remote_nouser = remote.dup.tap {|uri| uri.user = uri.password = nil }.to_s
309
+ remote_nouser = remove_auth(remote)
280
310
  if remote.userinfo && remote.userinfo == Bundler.settings[remote_nouser]
281
311
  remote_nouser
282
312
  else
@@ -284,15 +314,14 @@ module Bundler
284
314
  end
285
315
  end
286
316
 
317
+ def remove_auth(remote)
318
+ remote.dup.tap {|uri| uri.user = uri.password = nil }.to_s
319
+ end
320
+
287
321
  def installed_specs
288
- @installed_specs ||= begin
289
- idx = Index.new
290
- have_bundler = false
322
+ @installed_specs ||= Index.build do |idx|
291
323
  Bundler.rubygems.all_specs.reverse_each do |spec|
292
- if spec.name == "bundler"
293
- next unless spec.version.to_s == VERSION
294
- have_bundler = true
295
- end
324
+ next if spec.name == "bundler"
296
325
  spec.source = self
297
326
  if Bundler.rubygems.spec_missing_extensions?(spec, false)
298
327
  Bundler.ui.debug "Source #{self} is ignoring #{spec} because it is missing extensions"
@@ -300,23 +329,6 @@ module Bundler
300
329
  end
301
330
  idx << spec
302
331
  end
303
-
304
- # Always have bundler locally
305
- unless have_bundler
306
- # We're running bundler directly from the source
307
- # so, let's create a fake gemspec for it (it's a path)
308
- # gemspec
309
- bundler = Gem::Specification.new do |s|
310
- s.name = "bundler"
311
- s.version = VERSION
312
- s.platform = Gem::Platform::RUBY
313
- s.source = self
314
- s.authors = ["bundler team"]
315
- s.loaded_from = File.expand_path("..", __FILE__)
316
- end
317
- idx << bundler
318
- end
319
- idx
320
332
  end
321
333
  end
322
334
 
@@ -334,9 +346,9 @@ module Bundler
334
346
  end
335
347
  idx << s
336
348
  end
337
- end
338
349
 
339
- idx
350
+ idx
351
+ end
340
352
  end
341
353
 
342
354
  def api_fetchers
@@ -348,71 +360,36 @@ module Bundler
348
360
  index_fetchers = fetchers - api_fetchers
349
361
 
350
362
  # gather lists from non-api sites
351
- index_fetchers.each do |f|
352
- Bundler.ui.info "Fetching source index from #{f.uri}"
353
- idx.use f.specs_with_retry(nil, self)
354
- end
363
+ fetch_names(index_fetchers, nil, idx, false)
355
364
 
356
365
  # because ensuring we have all the gems we need involves downloading
357
366
  # the gemspecs of those gems, if the non-api sites contain more than
358
- # about 100 gems, we treat all sites as non-api for speed.
367
+ # about 500 gems, we treat all sites as non-api for speed.
359
368
  allow_api = idx.size < API_REQUEST_LIMIT && dependency_names.size < API_REQUEST_LIMIT
360
369
  Bundler.ui.debug "Need to query more than #{API_REQUEST_LIMIT} gems." \
361
370
  " Downloading full index instead..." unless allow_api
362
371
 
363
- if allow_api
364
- api_fetchers.each do |f|
365
- Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug?
366
- idx.use f.specs_with_retry(dependency_names, self)
367
- Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
368
- end
369
-
370
- # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
371
- # sources A and B. At this point, the API request will have found all the versions of Bar in source A,
372
- # but will not have found any versions of Bar from source B, which is a problem if the requested version
373
- # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
374
- # each spec we found, we add all possible versions from all sources to the index.
375
- loop do
376
- idxcount = idx.size
377
- api_fetchers.each do |f|
378
- Bundler.ui.info "Fetching version metadata from #{f.uri}", Bundler.ui.debug?
379
- idx.use f.specs_with_retry(idx.dependency_names, self), true
380
- Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
381
- end
382
- break if idxcount == idx.size
383
- end
384
-
385
- if api_fetchers.any?
386
- # it's possible that gems from one source depend on gems from some
387
- # other source, so now we download gemspecs and iterate over those
388
- # dependencies, looking for gems we don't have info on yet.
389
- unmet = idx.unmet_dependency_names
390
-
391
- # if there are any cross-site gems we missed, get them now
392
- api_fetchers.each do |f|
393
- Bundler.ui.info "Fetching dependency metadata from #{f.uri}", Bundler.ui.debug?
394
- idx.use f.specs_with_retry(unmet, self)
395
- Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
396
- end if unmet.any?
397
- else
398
- allow_api = false
399
- end
400
- end
372
+ fetch_names(api_fetchers, allow_api && dependency_names, idx, false)
373
+ end
374
+ end
401
375
 
402
- unless allow_api
403
- api_fetchers.each do |f|
404
- Bundler.ui.info "Fetching source index from #{f.uri}"
405
- idx.use f.specs_with_retry(nil, self)
406
- end
376
+ def fetch_names(fetchers, dependency_names, index, override_dupes)
377
+ fetchers.each do |f|
378
+ if dependency_names
379
+ Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug?
380
+ index.use f.specs_with_retry(dependency_names, self), override_dupes
381
+ Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
382
+ else
383
+ Bundler.ui.info "Fetching source index from #{f.uri}"
384
+ index.use f.specs_with_retry(nil, self), override_dupes
407
385
  end
408
386
  end
409
387
  end
410
388
 
411
389
  def fetch_gem(spec)
412
390
  return false unless spec.remote
413
- uri = spec.remote.uri
391
+
414
392
  spec.fetch_platform
415
- Bundler.ui.confirm("Fetching #{version_message(spec)}")
416
393
 
417
394
  download_path = requires_sudo? ? Bundler.tmp(spec.full_name) : rubygems_dir
418
395
  gem_path = "#{rubygems_dir}/cache/#{spec.full_name}.gem"
@@ -420,7 +397,7 @@ module Bundler
420
397
  SharedHelpers.filesystem_access("#{download_path}/cache") do |p|
421
398
  FileUtils.mkdir_p(p)
422
399
  end
423
- Bundler.rubygems.download_gem(spec, uri, download_path)
400
+ download_gem(spec, download_path)
424
401
 
425
402
  if requires_sudo?
426
403
  SharedHelpers.filesystem_access("#{rubygems_dir}/cache") do |p|
@@ -457,6 +434,76 @@ module Bundler
457
434
  def cache_path
458
435
  Bundler.app_cache
459
436
  end
437
+
438
+ private
439
+
440
+ # Checks if the requested spec exists in the global cache. If it does,
441
+ # we copy it to the download path, and if it does not, we download it.
442
+ #
443
+ # @param [Specification] spec
444
+ # the spec we want to download or retrieve from the cache.
445
+ #
446
+ # @param [String] download_path
447
+ # the local directory the .gem will end up in.
448
+ #
449
+ def download_gem(spec, download_path)
450
+ local_path = File.join(download_path, "cache/#{spec.full_name}.gem")
451
+
452
+ if (cache_path = download_cache_path(spec)) && cache_path.file?
453
+ SharedHelpers.filesystem_access(local_path) do
454
+ FileUtils.cp(cache_path, local_path)
455
+ end
456
+ else
457
+ uri = spec.remote.uri
458
+ Bundler.ui.confirm("Fetching #{version_message(spec)}")
459
+ Bundler.rubygems.download_gem(spec, uri, download_path)
460
+ cache_globally(spec, local_path)
461
+ end
462
+ end
463
+
464
+ # Checks if the requested spec exists in the global cache. If it does
465
+ # not, we create the relevant global cache subdirectory if it does not
466
+ # exist and copy the spec from the local cache to the global cache.
467
+ #
468
+ # @param [Specification] spec
469
+ # the spec we want to copy to the global cache.
470
+ #
471
+ # @param [String] local_cache_path
472
+ # the local directory from which we want to copy the .gem.
473
+ #
474
+ def cache_globally(spec, local_cache_path)
475
+ return unless cache_path = download_cache_path(spec)
476
+ return if cache_path.exist?
477
+
478
+ SharedHelpers.filesystem_access(cache_path.dirname, &:mkpath)
479
+ SharedHelpers.filesystem_access(cache_path) do
480
+ FileUtils.cp(local_cache_path, cache_path)
481
+ end
482
+ end
483
+
484
+ # Returns the global cache path of the calling Rubygems::Source object.
485
+ #
486
+ # Note that the Source determines the path's subdirectory. We use this
487
+ # subdirectory in the global cache path so that gems with the same name
488
+ # -- and possibly different versions -- from different sources are saved
489
+ # to their respective subdirectories and do not override one another.
490
+ #
491
+ # @param [Gem::Specification] specification
492
+ #
493
+ # @return [Pathname] The global cache path.
494
+ #
495
+ def download_cache_path(spec)
496
+ return unless Bundler.feature_flag.global_gem_cache?
497
+ return unless remote = spec.remote
498
+ return unless cache_slug = remote.cache_slug
499
+
500
+ Bundler.user_cache.join("gems", cache_slug, spec.file_name)
501
+ end
502
+
503
+ def extension_cache_slug(spec)
504
+ return unless remote = spec.remote
505
+ remote.cache_slug
506
+ end
460
507
  end
461
508
  end
462
509
  end