bundler 4.0.22 → 4.1.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/{lib/bundler/vendor/connection_pool/LICENSE → MIT.txt} +8 -6
  3. data/bundler.gemspec +23 -6
  4. data/lib/bundler/build_metadata.rb +2 -2
  5. data/lib/bundler/checksum.rb +40 -25
  6. data/lib/bundler/ci_detector.rb +1 -1
  7. data/lib/bundler/cli/add.rb +3 -4
  8. data/lib/bundler/cli/cache.rb +4 -0
  9. data/lib/bundler/cli/clean.rb +5 -0
  10. data/lib/bundler/cli/common.rb +41 -1
  11. data/lib/bundler/cli/config.rb +4 -2
  12. data/lib/bundler/cli/doctor/ssl.rb +4 -8
  13. data/lib/bundler/cli/gem.rb +0 -17
  14. data/lib/bundler/cli/info.rb +1 -1
  15. data/lib/bundler/cli/install.rb +4 -5
  16. data/lib/bundler/cli/lock.rb +15 -5
  17. data/lib/bundler/cli/open.rb +7 -1
  18. data/lib/bundler/cli/outdated.rb +16 -13
  19. data/lib/bundler/cli/pristine.rb +2 -1
  20. data/lib/bundler/cli/show.rb +5 -1
  21. data/lib/bundler/cli/update.rb +20 -11
  22. data/lib/bundler/cli.rb +15 -9
  23. data/lib/bundler/constants.rb +1 -1
  24. data/lib/bundler/definition.rb +102 -15
  25. data/lib/bundler/dependency.rb +4 -0
  26. data/lib/bundler/dsl.rb +137 -13
  27. data/lib/bundler/endpoint_specification.rb +51 -14
  28. data/lib/bundler/env.rb +7 -24
  29. data/lib/bundler/errors.rb +34 -5
  30. data/lib/bundler/fetcher/compact_index.rb +14 -5
  31. data/lib/bundler/fetcher/connection_pools.rb +150 -0
  32. data/lib/bundler/fetcher/downloader.rb +35 -16
  33. data/lib/bundler/fetcher.rb +8 -47
  34. data/lib/bundler/gem_helper.rb +1 -1
  35. data/lib/bundler/injector.rb +3 -3
  36. data/lib/bundler/inline.rb +44 -4
  37. data/lib/bundler/installer/parallel_installer.rb +27 -31
  38. data/lib/bundler/installer.rb +21 -7
  39. data/lib/bundler/lazy_specification.rb +45 -18
  40. data/lib/bundler/lockfile_generator.rb +24 -2
  41. data/lib/bundler/lockfile_parser.rb +44 -6
  42. data/lib/bundler/man/bundle-add.1 +7 -4
  43. data/lib/bundler/man/bundle-add.1.ronn +8 -4
  44. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  45. data/lib/bundler/man/bundle-cache.1 +2 -2
  46. data/lib/bundler/man/bundle-cache.1.ronn +2 -2
  47. data/lib/bundler/man/bundle-check.1 +1 -1
  48. data/lib/bundler/man/bundle-clean.1 +1 -1
  49. data/lib/bundler/man/bundle-config.1 +38 -6
  50. data/lib/bundler/man/bundle-config.1.ronn +143 -10
  51. data/lib/bundler/man/bundle-console.1 +1 -1
  52. data/lib/bundler/man/bundle-doctor.1 +1 -1
  53. data/lib/bundler/man/bundle-env.1 +1 -1
  54. data/lib/bundler/man/bundle-exec.1 +1 -1
  55. data/lib/bundler/man/bundle-fund.1 +1 -1
  56. data/lib/bundler/man/bundle-gem.1 +1 -1
  57. data/lib/bundler/man/bundle-help.1 +1 -1
  58. data/lib/bundler/man/bundle-info.1 +5 -2
  59. data/lib/bundler/man/bundle-info.1.ronn +4 -0
  60. data/lib/bundler/man/bundle-init.1 +1 -1
  61. data/lib/bundler/man/bundle-install.1 +2 -2
  62. data/lib/bundler/man/bundle-install.1.ronn +4 -4
  63. data/lib/bundler/man/bundle-issue.1 +1 -1
  64. data/lib/bundler/man/bundle-licenses.1 +1 -1
  65. data/lib/bundler/man/bundle-list.1 +1 -1
  66. data/lib/bundler/man/bundle-lock.1 +2 -2
  67. data/lib/bundler/man/bundle-lock.1.ronn +3 -2
  68. data/lib/bundler/man/bundle-open.1 +5 -2
  69. data/lib/bundler/man/bundle-open.1.ronn +4 -1
  70. data/lib/bundler/man/bundle-outdated.1 +1 -1
  71. data/lib/bundler/man/bundle-platform.1 +1 -1
  72. data/lib/bundler/man/bundle-plugin.1 +1 -1
  73. data/lib/bundler/man/bundle-pristine.1 +1 -1
  74. data/lib/bundler/man/bundle-remove.1 +1 -1
  75. data/lib/bundler/man/bundle-show.1 +5 -2
  76. data/lib/bundler/man/bundle-show.1.ronn +4 -0
  77. data/lib/bundler/man/bundle-update.1 +2 -2
  78. data/lib/bundler/man/bundle-update.1.ronn +2 -2
  79. data/lib/bundler/man/bundle-version.1 +1 -1
  80. data/lib/bundler/man/bundle.1 +1 -1
  81. data/lib/bundler/man/gemfile.5 +77 -1
  82. data/lib/bundler/man/gemfile.5.ronn +104 -0
  83. data/lib/bundler/match_metadata.rb +20 -0
  84. data/lib/bundler/match_platform.rb +25 -2
  85. data/lib/bundler/match_remote_metadata.rb +21 -6
  86. data/lib/bundler/materialization.rb +5 -2
  87. data/lib/bundler/override.rb +97 -0
  88. data/lib/bundler/plugin/dsl.rb +3 -5
  89. data/lib/bundler/plugin/events.rb +55 -13
  90. data/lib/bundler/plugin/index.rb +87 -11
  91. data/lib/bundler/plugin/installer/path.rb +1 -1
  92. data/lib/bundler/plugin/installer.rb +13 -5
  93. data/lib/bundler/plugin.rb +58 -30
  94. data/lib/bundler/remote_specification.rb +6 -3
  95. data/lib/bundler/resolver/base.rb +2 -1
  96. data/lib/bundler/resolver/incompatibility.rb +1 -1
  97. data/lib/bundler/resolver.rb +97 -23
  98. data/lib/bundler/ruby_version.rb +0 -2
  99. data/lib/bundler/rubygems_ext.rb +71 -1
  100. data/lib/bundler/rubygems_gem_installer.rb +41 -2
  101. data/lib/bundler/rubygems_integration.rb +7 -2
  102. data/lib/bundler/runtime.rb +69 -2
  103. data/lib/bundler/settings.rb +383 -56
  104. data/lib/bundler/shared_helpers.rb +2 -1
  105. data/lib/bundler/source/git/git_proxy.rb +31 -2
  106. data/lib/bundler/source/git.rb +49 -13
  107. data/lib/bundler/source/path/installer.rb +1 -1
  108. data/lib/bundler/source/rubygems/remote.rb +10 -5
  109. data/lib/bundler/source/rubygems.rb +48 -12
  110. data/lib/bundler/source/rubygems_aggregate.rb +1 -1
  111. data/lib/bundler/source_map.rb +7 -3
  112. data/lib/bundler/spec_set.rb +23 -7
  113. data/lib/bundler/stub_specification.rb +2 -1
  114. data/lib/bundler/templates/newgem/Gemfile.tt +4 -4
  115. data/lib/bundler/templates/newgem/newgem.gemspec.tt +3 -3
  116. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +1 -1
  117. data/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +1 -1
  118. data/lib/bundler/ui/shell.rb +0 -4
  119. data/lib/bundler/ui/silent.rb +0 -4
  120. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +35 -2
  121. data/lib/bundler/vendor/thor/lib/thor/base.rb +2 -1
  122. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +14 -6
  123. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +2 -0
  124. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  125. data/lib/bundler/vendor/thor/lib/thor.rb +34 -1
  126. data/lib/bundler/vendored_pub_grub.rb +5 -2
  127. data/lib/bundler/vendored_securerandom.rb +11 -8
  128. data/lib/bundler/vendored_uri.rb +14 -14
  129. data/lib/bundler/version.rb +1 -1
  130. data/lib/bundler/worker.rb +3 -2
  131. data/lib/bundler.rb +1 -1
  132. data/lib/rubygems/compact_index_client/cache.rb +122 -0
  133. data/lib/rubygems/compact_index_client/cache_file.rb +147 -0
  134. data/lib/rubygems/compact_index_client/http_fetcher.rb +90 -0
  135. data/lib/rubygems/compact_index_client/parser.rb +90 -0
  136. data/lib/rubygems/compact_index_client/updater.rb +113 -0
  137. data/lib/rubygems/compact_index_client.rb +111 -0
  138. data/lib/rubygems/cooldown_settings.rb +57 -0
  139. data/lib/rubygems/credential_store/native/linux.rb +97 -0
  140. data/lib/rubygems/credential_store/native/macos.rb +88 -0
  141. data/lib/rubygems/credential_store/native/windows.rb +130 -0
  142. data/lib/rubygems/credential_store.rb +332 -0
  143. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/assignment.rb +1 -1
  144. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +7 -7
  145. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/failure_writer.rb +1 -1
  146. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/incompatibility.rb +4 -4
  147. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/package.rb +1 -1
  148. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/partial_solution.rb +1 -1
  149. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/rubygems.rb +3 -3
  150. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/solve_failure.rb +1 -1
  151. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/static_package_source.rb +3 -3
  152. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/strategy.rb +2 -2
  153. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/term.rb +1 -1
  154. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version.rb +1 -1
  155. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_constraint.rb +3 -3
  156. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_range.rb +1 -1
  157. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_solver.rb +2 -2
  158. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_union.rb +1 -1
  159. data/lib/rubygems/vendor/pub_grub/lib/pub_grub.rb +57 -0
  160. data/lib/{bundler → rubygems}/vendor/securerandom/lib/securerandom.rb +10 -6
  161. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/common.rb +119 -119
  162. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/file.rb +13 -13
  163. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ftp.rb +24 -24
  164. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/generic.rb +132 -132
  165. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/http.rb +18 -18
  166. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/https.rb +4 -4
  167. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ldap.rb +14 -14
  168. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ldaps.rb +4 -4
  169. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/mailto.rb +21 -21
  170. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/rfc2396_parser.rb +39 -39
  171. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/rfc3986_parser.rb +14 -14
  172. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/version.rb +1 -1
  173. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ws.rb +12 -12
  174. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/wss.rb +4 -4
  175. data/lib/{bundler → rubygems}/vendor/uri/lib/uri.rb +35 -31
  176. data/lib/rubygems/yaml_serializer.rb +880 -0
  177. metadata +391 -381
  178. data/CHANGELOG.md +0 -5801
  179. data/LICENSE.md +0 -22
  180. data/README.md +0 -58
  181. data/lib/bundler/compact_index_client/cache.rb +0 -107
  182. data/lib/bundler/compact_index_client/cache_file.rb +0 -148
  183. data/lib/bundler/compact_index_client/parser.rb +0 -87
  184. data/lib/bundler/compact_index_client/updater.rb +0 -105
  185. data/lib/bundler/compact_index_client.rb +0 -92
  186. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +0 -227
  187. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +0 -3
  188. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -56
  189. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +0 -230
  190. data/lib/bundler/vendor/net-http-persistent/README.rdoc +0 -82
  191. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +0 -41
  192. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +0 -65
  193. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +0 -80
  194. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +0 -1153
  195. data/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +0 -31
  196. data/lib/bundler/vendored_persistent.rb +0 -11
  197. data/lib/bundler/yaml_serializer.rb +0 -98
  198. /data/lib/{bundler → rubygems}/vendor/pub_grub/LICENSE.txt +0 -0
  199. /data/lib/{bundler → rubygems}/vendor/securerandom/COPYING +0 -0
  200. /data/lib/{bundler → rubygems}/vendor/uri/COPYING +0 -0
@@ -30,6 +30,54 @@ module Bundler
30
30
  @events.key?(event)
31
31
  end
32
32
 
33
+ # @!parse
34
+ # A hook called before the Gemfile is evaluated
35
+ # Includes the Gemfile path and the Lockfile path
36
+ # GEM_BEFORE_EVAL = "before-eval"
37
+ define :GEM_BEFORE_EVAL, "before-eval"
38
+
39
+ # @!parse
40
+ # A hook called after the Gemfile is evaluated
41
+ # Includes a Bundler::Definition
42
+ # GEM_AFTER_EVAL = "after-eval"
43
+ define :GEM_AFTER_EVAL, "after-eval"
44
+
45
+ # @!parse
46
+ # A hook called before any gems install
47
+ # Includes an Array of Bundler::Dependency objects
48
+ # GEM_BEFORE_INSTALL_ALL = "before-install-all"
49
+ define :GEM_BEFORE_INSTALL_ALL, "before-install-all"
50
+
51
+ # @!parse
52
+ # A hook called before each individual gem is downloaded from a remote source.
53
+ # Includes a spec-like object responding to the Gem::Specification API
54
+ # (for example, a Bundler spec proxy such as Bundler::EndpointSpecification
55
+ # or Bundler::RemoteSpecification). Does not fire when the gem is already
56
+ # present at the initial download-cache check.
57
+ # GEM_BEFORE_FETCH = "before-fetch"
58
+ define :GEM_BEFORE_FETCH, "before-fetch"
59
+
60
+ # @!parse
61
+ # A hook called after each individual gem is downloaded from a remote source.
62
+ # Includes a spec-like object responding to the Gem::Specification API
63
+ # (for example, a Bundler spec proxy such as Bundler::EndpointSpecification
64
+ # or Bundler::RemoteSpecification). Does not fire when the gem is already
65
+ # present at the initial download-cache check.
66
+ # GEM_AFTER_FETCH = "after-fetch"
67
+ define :GEM_AFTER_FETCH, "after-fetch"
68
+
69
+ # @!parse
70
+ # A hook called before a git source is fetched or checked out.
71
+ # Includes a Bundler::Source::Git reference.
72
+ # GIT_BEFORE_FETCH = "before-git-fetch"
73
+ define :GIT_BEFORE_FETCH, "before-git-fetch"
74
+
75
+ # @!parse
76
+ # A hook called after a git source is fetched or checked out.
77
+ # Includes a Bundler::Source::Git reference.
78
+ # GIT_AFTER_FETCH = "after-git-fetch"
79
+ define :GIT_AFTER_FETCH, "after-git-fetch"
80
+
33
81
  # @!parse
34
82
  # A hook called before each individual gem is installed
35
83
  # Includes a Bundler::ParallelInstaller::SpecInstallation.
@@ -45,18 +93,18 @@ module Bundler
45
93
  # GEM_AFTER_INSTALL = "after-install"
46
94
  define :GEM_AFTER_INSTALL, "after-install"
47
95
 
48
- # @!parse
49
- # A hook called before any gems install
50
- # Includes an Array of Bundler::Dependency objects
51
- # GEM_BEFORE_INSTALL_ALL = "before-install-all"
52
- define :GEM_BEFORE_INSTALL_ALL, "before-install-all"
53
-
54
96
  # @!parse
55
97
  # A hook called after any gems install
56
98
  # Includes an Array of Bundler::Dependency objects
57
99
  # GEM_AFTER_INSTALL_ALL = "after-install-all"
58
100
  define :GEM_AFTER_INSTALL_ALL, "after-install-all"
59
101
 
102
+ # @!parse
103
+ # A hook called before any gems require
104
+ # Includes an Array of Bundler::Dependency objects.
105
+ # GEM_BEFORE_REQUIRE_ALL = "before-require-all"
106
+ define :GEM_BEFORE_REQUIRE_ALL, "before-require-all"
107
+
60
108
  # @!parse
61
109
  # A hook called before each individual gem is required
62
110
  # Includes a Bundler::Dependency.
@@ -69,17 +117,11 @@ module Bundler
69
117
  # GEM_AFTER_REQUIRE = "after-require"
70
118
  define :GEM_AFTER_REQUIRE, "after-require"
71
119
 
72
- # @!parse
73
- # A hook called before any gems require
74
- # Includes an Array of Bundler::Dependency objects.
75
- # GEM_BEFORE_REQUIRE_ALL = "before-require-all"
76
- define :GEM_BEFORE_REQUIRE_ALL, "before-require-all"
77
-
78
120
  # @!parse
79
121
  # A hook called after all gems required
80
122
  # Includes an Array of Bundler::Dependency objects.
81
123
  # GEM_AFTER_REQUIRE_ALL = "after-require-all"
82
- define :GEM_AFTER_REQUIRE_ALL, "after-require-all"
124
+ define :GEM_AFTER_REQUIRE_ALL, "after-require-all"
83
125
  end
84
126
  end
85
127
  end
@@ -163,20 +163,28 @@ module Bundler
163
163
  # @param [Pathname] index file path
164
164
  # @param [Boolean] is the index file global index
165
165
  def load_index(index_file, global = false)
166
+ base = base_for_index(global)
167
+
166
168
  SharedHelpers.filesystem_access(index_file, :read) do |index_f|
167
169
  valid_file = index_f&.exist? && !index_f.size.zero?
168
170
  break unless valid_file
169
171
 
170
172
  data = index_f.read
171
173
 
172
- require_relative "../yaml_serializer"
173
- index = YAMLSerializer.load(data)
174
+ require "rubygems/yaml_serializer"
175
+ # Empty sections load as nil, e.g. from index files written by
176
+ # older Bundler versions, which dumped empty hashes as a bare key.
177
+ index = Gem::YAMLSerializer.load(data) || {}
178
+
179
+ escaping = escaping_plugins(index, base)
180
+ hooks = (index["hooks"] || {}).transform_values {|names| Array(names) - escaping }
174
181
 
175
- @commands.merge!(index["commands"])
176
- @hooks.merge!(index["hooks"])
177
- @load_paths.merge!(index["load_paths"])
178
- @plugin_paths.merge!(index["plugin_paths"])
179
- @sources.merge!(index["sources"]) unless global
182
+ @commands.merge!(owned_by(index["commands"] || {}, escaping))
183
+ # An event whose plugins all escaped is left out rather than merged in empty.
184
+ @hooks.merge!(hooks.reject {|_, names| names.empty? })
185
+ @load_paths.merge!(named(transform_index_paths(index["load_paths"]) {|p| absolutize_path(p, base) }, escaping))
186
+ @plugin_paths.merge!(named(transform_index_paths(index["plugin_paths"]) {|p| absolutize_path(p, base) }, escaping))
187
+ @sources.merge!(owned_by(index["sources"] || {}, escaping)) unless global
180
188
  end
181
189
  end
182
190
 
@@ -184,20 +192,88 @@ module Bundler
184
192
  # instance variables in YAML format. (The instance variables are supposed
185
193
  # to be only String key value pairs)
186
194
  def save_index
195
+ base = base_for_index(false)
196
+
187
197
  index = {
188
198
  "commands" => @commands,
189
199
  "hooks" => @hooks,
190
- "load_paths" => @load_paths,
191
- "plugin_paths" => @plugin_paths,
200
+ "load_paths" => transform_index_paths(@load_paths) {|p| relativize_path(p, base) },
201
+ "plugin_paths" => transform_index_paths(@plugin_paths) {|p| relativize_path(p, base) },
192
202
  "sources" => @sources,
193
203
  }
194
204
 
195
- require_relative "../yaml_serializer"
205
+ require "rubygems/yaml_serializer"
196
206
  SharedHelpers.filesystem_access(index_file) do |index_f|
197
207
  FileUtils.mkdir_p(index_f.dirname)
198
- File.open(index_f, "w") {|f| f.puts YAMLSerializer.dump(index) }
208
+ File.open(index_f, "w") {|f| f.puts Gem::YAMLSerializer.dump(index) }
209
+ end
210
+ end
211
+
212
+ def base_for_index(global)
213
+ global ? Plugin.global_root : Plugin.root
214
+ end
215
+
216
+ # A relative path only means anything inside the root, so an entry that escapes is not one Bundler installed.
217
+ def escaping_plugins(index, base)
218
+ names = []
219
+
220
+ %w[load_paths plugin_paths].each do |key|
221
+ (index[key] || {}).each do |name, value|
222
+ escapes = Array(value).any? do |path|
223
+ !Pathname.new(path).absolute? && !contained_in?(absolutize_path(path, base), base)
224
+ end
225
+
226
+ names << name if escapes
227
+ end
228
+ end
229
+
230
+ names.uniq
231
+ end
232
+
233
+ # Expanded here, not by the caller: what gets stored stays joined, because
234
+ # #installed_in_plugin_root? matches it against Plugin.root as written.
235
+ def contained_in?(path, base)
236
+ path = File.expand_path(path)
237
+ base = File.expand_path(base)
238
+
239
+ path == base || path.start_with?("#{base}#{File::SEPARATOR}")
240
+ end
241
+
242
+ # commands and sources are keyed by what they provide, load_paths and plugin_paths by the plugin.
243
+ def owned_by(mapping, names)
244
+ mapping.reject {|_, plugin| names.include?(plugin) }
245
+ end
246
+
247
+ def named(mapping, names)
248
+ mapping.reject {|plugin, _| names.include?(plugin) }
249
+ end
250
+
251
+ def transform_index_paths(paths)
252
+ return {} unless paths
253
+
254
+ paths.transform_values do |value|
255
+ if value.is_a?(Array)
256
+ value.map {|path| yield path }
257
+ else
258
+ yield value
259
+ end
199
260
  end
200
261
  end
262
+
263
+ def relativize_path(path, base)
264
+ pathname = Pathname.new(path)
265
+ return path unless pathname.absolute?
266
+
267
+ return path unless contained_in?(pathname.to_s, base)
268
+
269
+ pathname.relative_path_from(Pathname.new(base)).to_s
270
+ end
271
+
272
+ def absolutize_path(path, base)
273
+ pathname = Pathname.new(path)
274
+ pathname = Pathname.new(base).join(pathname) unless pathname.absolute?
275
+ pathname.to_s
276
+ end
201
277
  end
202
278
  end
203
279
  end
@@ -5,7 +5,7 @@ module Bundler
5
5
  class Installer
6
6
  class Path < Bundler::Source::Path
7
7
  def root
8
- SharedHelpers.in_bundle? ? Bundler.root : Plugin.root
8
+ Plugin.root
9
9
  end
10
10
 
11
11
  def eql?(other)
@@ -32,12 +32,18 @@ module Bundler
32
32
  #
33
33
  # @param [Definition] definition object
34
34
  # @return [Hash] map of names to their specs they are installed with
35
- def install_definition(definition)
35
+ def install_definition(definition, latest = false)
36
36
  def definition.lock(*); end
37
- definition.remotely!
37
+
38
+ if latest || definition.missing_specs?
39
+ definition.remotely!
40
+ else
41
+ definition.with_cache!
42
+ end
43
+
38
44
  specs = definition.specs
39
45
 
40
- install_from_specs specs
46
+ install_from_specs(specs)
41
47
  end
42
48
 
43
49
  private
@@ -89,14 +95,14 @@ module Bundler
89
95
  end
90
96
 
91
97
  def install_all_sources(names, version, source_list, source = nil)
92
- deps = names.map {|name| Dependency.new(name, version, { "source" => source }) }
98
+ deps = names.map {|name| Dependency.new(name, version, { "source" => source, "plugin" => true }) }
93
99
 
94
100
  Bundler.configure_gem_home_and_path(Plugin.root)
95
101
 
96
102
  Bundler.settings.temporary(deployment: false, frozen: false) do
97
103
  definition = Definition.new(nil, deps, source_list, true)
98
104
 
99
- install_definition(definition)
105
+ install_definition(definition, true)
100
106
  end
101
107
  end
102
108
 
@@ -110,6 +116,8 @@ module Bundler
110
116
  paths = {}
111
117
 
112
118
  specs.each do |spec|
119
+ next if spec.name == "bundler"
120
+
113
121
  spec.source.download(spec)
114
122
  spec.source.install(spec)
115
123
 
@@ -18,6 +18,14 @@ module Bundler
18
18
 
19
19
  PLUGIN_FILE_NAME = "plugins.rb"
20
20
 
21
+ # Module-level flag set while .gemfile_install parses the Gemfile and
22
+ # consulted by .from_lock to substitute plugin sources with
23
+ # UnloadedSource. It relies on definitions being built one at a time in
24
+ # a single thread; if they are ever built concurrently or reentrantly,
25
+ # this needs to be replaced by explicit state passed down to the
26
+ # lockfile parser.
27
+ @gemfile_parse = false
28
+
21
29
  module_function
22
30
 
23
31
  def reset!
@@ -27,6 +35,7 @@ module Bundler
27
35
  @commands = {}
28
36
  @hooks_by_event = Hash.new {|h, k| h[k] = [] }
29
37
  @loaded_plugin_names = []
38
+ @index = nil
30
39
  end
31
40
 
32
41
  reset!
@@ -41,7 +50,7 @@ module Bundler
41
50
 
42
51
  specs = Installer.new.install(names, options)
43
52
 
44
- save_plugins names, specs
53
+ save_plugins specs.slice(*names)
45
54
  rescue PluginError
46
55
  specs_to_delete = specs.select {|k, _v| names.include?(k) && !index.commands.values.include?(k) }
47
56
  specs_to_delete.each_value {|spec| Bundler.rm_rf(spec.full_gem_path) }
@@ -101,29 +110,44 @@ module Bundler
101
110
  #
102
111
  # @param [Pathname] gemfile path
103
112
  # @param [Proc] block that can be evaluated for (inline) Gemfile
104
- def gemfile_install(gemfile = nil, &inline)
105
- Bundler.settings.temporary(frozen: false, deployment: false) do
106
- builder = DSL.new
107
- if block_given?
108
- builder.instance_eval(&inline)
109
- else
110
- builder.eval_gemfile(gemfile)
111
- end
112
- builder.check_primary_source_safety
113
- definition = builder.to_definition(nil, true)
114
-
115
- return if definition.dependencies.empty?
113
+ def gemfile_install(gemfile = nil, lockfile = nil, unlock = {}, &inline)
114
+ @gemfile_parse = true
115
+ Bundler.configure
116
+ builder = DSL.new
117
+ if block_given?
118
+ builder.instance_eval(&inline)
119
+ else
120
+ builder.eval_gemfile(gemfile)
121
+ end
122
+ builder.check_primary_source_safety
116
123
 
117
- plugins = definition.dependencies.map(&:name)
118
- installed_specs = Installer.new.install_definition(definition)
124
+ plugins = builder.dependencies.map(&:name)
125
+ return if plugins.empty?
119
126
 
120
- save_plugins plugins, installed_specs, builder.inferred_plugins
127
+ # skip the update if unlocking specific gems, but none of them are plugins
128
+ # declared in the Gemfile
129
+ if unlock.is_a?(Hash) && unlock[:gems] && !unlock[:gems].empty? &&
130
+ (unlock[:gems] & plugins).empty?
131
+ unlock = {}
121
132
  end
133
+
134
+ # resolve remotely when unlocking, so that plugins can be updated.
135
+ # Definition#initialize consumes the unlock hash, so this must be decided
136
+ # before building the definition.
137
+ updating = unlock == true || (unlock.is_a?(Hash) && !unlock.empty?)
138
+
139
+ definition = builder.to_definition(lockfile, unlock)
140
+
141
+ installed_specs = Installer.new.install_definition(definition, updating)
142
+
143
+ save_plugins installed_specs.slice(*plugins), builder.inferred_plugins
122
144
  rescue RuntimeError => e
123
145
  unless e.is_a?(GemfileError)
124
146
  Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"
125
147
  end
126
148
  raise
149
+ ensure
150
+ @gemfile_parse = false
127
151
  end
128
152
 
129
153
  # The index object used to store the details about the plugin
@@ -184,12 +208,17 @@ module Bundler
184
208
 
185
209
  # Checks if any plugin declares the source
186
210
  def source?(name)
187
- !index.source_plugin(name.to_s).nil?
211
+ !!source_plugin(name)
212
+ end
213
+
214
+ # Returns the plugin that handles the source +name+ if any
215
+ def source_plugin(name)
216
+ index.source_plugin(name.to_s)
188
217
  end
189
218
 
190
219
  # @return [Class] that handles the source. The class includes API::Source
191
220
  def source(name)
192
- raise UnknownSourceError, "Source #{name} not found" unless source? name
221
+ raise UnknownSourceError, "Source #{name} not found" unless source_plugin(name)
193
222
 
194
223
  load_plugin(index.source_plugin(name)) unless @sources.key? name
195
224
 
@@ -201,6 +230,9 @@ module Bundler
201
230
  # type passed in locked_opts
202
231
  def from_lock(locked_opts)
203
232
  opts = locked_opts.merge("uri" => locked_opts["remote"])
233
+ # when reading the lockfile while doing the plugin-install-from-gemfile phase,
234
+ # we need to ignore any plugin sources
235
+ return UnloadedSource.new(opts) if @gemfile_parse
204
236
  # use an inert placeholder when the plugin handling this source is not
205
237
  # installed, so that the lockfile can still be parsed
206
238
  return UnloadedSource.new(opts) unless source?(locked_opts["type"])
@@ -243,7 +275,9 @@ module Bundler
243
275
  #
244
276
  # @return [String, nil] installed path
245
277
  def installed?(plugin)
246
- Index.new.installed?(plugin)
278
+ (path = index.installed?(plugin)) &&
279
+ index.plugin_path(plugin).join(PLUGIN_FILE_NAME).file? &&
280
+ path
247
281
  end
248
282
 
249
283
  # @return [true, false] whether the plugin is loaded
@@ -253,19 +287,11 @@ module Bundler
253
287
 
254
288
  # Post installation processing and registering with index
255
289
  #
256
- # @param [Array<String>] plugins list to be installed
257
290
  # @param [Hash] specs of plugins mapped to installation path (currently they
258
291
  # contain all the installed specs, including plugins)
259
292
  # @param [Array<String>] names of inferred source plugins that can be ignored
260
- def save_plugins(plugins, specs, optional_plugins = [])
261
- plugins.each do |name|
262
- spec = specs[name]
263
-
264
- # It's possible that the `plugin` found in the Gemfile don't appear in the specs. For instance when
265
- # calling `BUNDLE_WITHOUT=default bundle install`, the plugins will not get installed.
266
- next if spec.nil?
267
- next if index.up_to_date?(spec)
268
-
293
+ def save_plugins(specs, optional_plugins = [])
294
+ specs.each do |name, spec|
269
295
  save_plugin(name, spec, optional_plugins.include?(name))
270
296
  end
271
297
  end
@@ -290,6 +316,8 @@ module Bundler
290
316
  #
291
317
  # @raise [PluginInstallError] if validation or registration raises any error
292
318
  def save_plugin(name, spec, optional_plugin = false)
319
+ return if index.up_to_date?(spec)
320
+
293
321
  validate_plugin! Pathname.new(spec.full_gem_path)
294
322
  installed = register_plugin(name, spec, optional_plugin)
295
323
  Bundler.ui.info "Installed plugin #{name}" if installed
@@ -325,7 +353,7 @@ module Bundler
325
353
  raise MalformattedPlugin, "#{e.class}: #{e.message}"
326
354
  end
327
355
 
328
- if optional_plugin && @sources.keys.any? {|s| source? s }
356
+ if optional_plugin && @sources.keys.any? {|s| source_plugin(s) }
329
357
  Bundler.rm_rf(path)
330
358
  false
331
359
  else
@@ -10,11 +10,11 @@ module Bundler
10
10
  include MatchPlatform
11
11
  include Comparable
12
12
 
13
- attr_reader :name, :version, :platform
13
+ attr_reader :name, :version, :platform, :content_address
14
14
  attr_writer :dependencies
15
15
  attr_accessor :source, :remote, :locked_platform, :created_at
16
16
 
17
- def initialize(name, version, platform, spec_fetcher)
17
+ def initialize(name, version, platform, spec_fetcher, content_address: nil)
18
18
  @name = name
19
19
  @version = Gem::Version.create version
20
20
  @original_platform = platform || Gem::Platform::RUBY
@@ -22,6 +22,7 @@ module Bundler
22
22
  @spec_fetcher = spec_fetcher
23
23
  @dependencies = nil
24
24
  @locked_platform = nil
25
+ @content_address = content_address
25
26
  end
26
27
 
27
28
  def insecurely_materialized?
@@ -35,7 +36,9 @@ module Bundler
35
36
  end
36
37
 
37
38
  def full_name
38
- @full_name ||= if @platform == Gem::Platform::RUBY
39
+ @full_name ||= if Gem::ContentAddress.content_addressed?(self, validate_ruby_abi: false)
40
+ "#{@name}-#{@version}-#{@content_address}"
41
+ elsif @platform == Gem::Platform::RUBY
39
42
  "#{@name}-#{@version}"
40
43
  else
41
44
  "#{@name}-#{@version}-#{@platform}"
@@ -5,9 +5,10 @@ require_relative "package"
5
5
  module Bundler
6
6
  class Resolver
7
7
  class Base
8
- attr_reader :packages, :requirements, :source_requirements, :locked_specs
8
+ attr_reader :packages, :requirements, :source_requirements, :locked_specs, :overrides
9
9
 
10
10
  def initialize(source_requirements, dependencies, base, platforms, options)
11
+ @overrides = options.delete(:overrides) || []
11
12
  @explicit_unlocks = options.delete(:explicit_unlocks) || []
12
13
  @source_requirements = source_requirements
13
14
  @locked_specs = options[:locked_specs]
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Bundler
4
4
  class Resolver
5
- class Incompatibility < PubGrub::Incompatibility
5
+ class Incompatibility < Gem::PubGrub::Incompatibility
6
6
  attr_reader :extended_explanation
7
7
 
8
8
  def initialize(terms, cause:, custom_explanation: nil, extended_explanation: nil)