bundler 2.3.26 → 2.4.13

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 (209) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +228 -1
  3. data/README.md +3 -6
  4. data/bundler.gemspec +2 -2
  5. data/exe/bundle +1 -4
  6. data/lib/bundler/build_metadata.rb +2 -2
  7. data/lib/bundler/cli/add.rb +1 -1
  8. data/lib/bundler/cli/binstubs.rb +5 -1
  9. data/lib/bundler/cli/check.rb +1 -1
  10. data/lib/bundler/cli/common.rb +1 -0
  11. data/lib/bundler/cli/console.rb +2 -2
  12. data/lib/bundler/cli/doctor.rb +4 -6
  13. data/lib/bundler/cli/gem.rb +62 -40
  14. data/lib/bundler/cli/init.rb +2 -2
  15. data/lib/bundler/cli/install.rb +2 -3
  16. data/lib/bundler/cli/lock.rb +8 -5
  17. data/lib/bundler/cli/open.rb +6 -4
  18. data/lib/bundler/cli/outdated.rb +1 -3
  19. data/lib/bundler/cli/viz.rb +1 -1
  20. data/lib/bundler/cli.rb +45 -2
  21. data/lib/bundler/compact_index_client/cache.rb +1 -1
  22. data/lib/bundler/compact_index_client/updater.rb +40 -39
  23. data/lib/bundler/constants.rb +1 -1
  24. data/lib/bundler/current_ruby.rb +2 -0
  25. data/lib/bundler/definition.rb +99 -51
  26. data/lib/bundler/dependency.rb +13 -12
  27. data/lib/bundler/digest.rb +1 -1
  28. data/lib/bundler/dsl.rb +3 -3
  29. data/lib/bundler/endpoint_specification.rb +0 -4
  30. data/lib/bundler/env.rb +1 -1
  31. data/lib/bundler/environment_preserver.rb +3 -2
  32. data/lib/bundler/errors.rb +1 -11
  33. data/lib/bundler/fetcher/compact_index.rb +9 -11
  34. data/lib/bundler/fetcher/dependency.rb +2 -6
  35. data/lib/bundler/fetcher/downloader.rb +2 -5
  36. data/lib/bundler/fetcher.rb +4 -8
  37. data/lib/bundler/force_platform.rb +18 -0
  38. data/lib/bundler/friendly_errors.rb +0 -3
  39. data/lib/bundler/gem_version_promoter.rb +52 -86
  40. data/lib/bundler/graph.rb +3 -3
  41. data/lib/bundler/index.rb +7 -15
  42. data/lib/bundler/injector.rb +2 -2
  43. data/lib/bundler/inline.rb +8 -10
  44. data/lib/bundler/installer/parallel_installer.rb +3 -33
  45. data/lib/bundler/installer/standalone.rb +12 -8
  46. data/lib/bundler/installer.rb +9 -23
  47. data/lib/bundler/lazy_specification.rb +42 -42
  48. data/lib/bundler/lockfile_generator.rb +1 -1
  49. data/lib/bundler/lockfile_parser.rb +16 -16
  50. data/lib/bundler/man/bundle-add.1 +1 -1
  51. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  52. data/lib/bundler/man/bundle-cache.1 +3 -3
  53. data/lib/bundler/man/bundle-cache.1.ronn +2 -2
  54. data/lib/bundler/man/bundle-check.1 +1 -1
  55. data/lib/bundler/man/bundle-clean.1 +1 -1
  56. data/lib/bundler/man/bundle-config.1 +2 -2
  57. data/lib/bundler/man/bundle-config.1.ronn +1 -1
  58. data/lib/bundler/man/bundle-console.1 +1 -1
  59. data/lib/bundler/man/bundle-doctor.1 +1 -1
  60. data/lib/bundler/man/bundle-exec.1 +5 -5
  61. data/lib/bundler/man/bundle-exec.1.ronn +5 -5
  62. data/lib/bundler/man/bundle-gem.1 +27 -37
  63. data/lib/bundler/man/bundle-gem.1.ronn +5 -5
  64. data/lib/bundler/man/bundle-help.1 +1 -1
  65. data/lib/bundler/man/bundle-info.1 +1 -1
  66. data/lib/bundler/man/bundle-init.1 +5 -1
  67. data/lib/bundler/man/bundle-init.1.ronn +2 -0
  68. data/lib/bundler/man/bundle-inject.1 +1 -1
  69. data/lib/bundler/man/bundle-install.1 +1 -30
  70. data/lib/bundler/man/bundle-install.1.ronn +0 -29
  71. data/lib/bundler/man/bundle-list.1 +1 -1
  72. data/lib/bundler/man/bundle-lock.1 +1 -1
  73. data/lib/bundler/man/bundle-open.1 +22 -2
  74. data/lib/bundler/man/bundle-open.1.ronn +9 -1
  75. data/lib/bundler/man/bundle-outdated.1 +1 -1
  76. data/lib/bundler/man/bundle-platform.1 +2 -2
  77. data/lib/bundler/man/bundle-platform.1.ronn +1 -1
  78. data/lib/bundler/man/bundle-plugin.1 +1 -1
  79. data/lib/bundler/man/bundle-pristine.1 +1 -1
  80. data/lib/bundler/man/bundle-remove.1 +1 -1
  81. data/lib/bundler/man/bundle-show.1 +1 -1
  82. data/lib/bundler/man/bundle-update.1 +1 -1
  83. data/lib/bundler/man/bundle-version.1 +1 -1
  84. data/lib/bundler/man/bundle-viz.1 +1 -1
  85. data/lib/bundler/man/bundle.1 +1 -1
  86. data/lib/bundler/man/gemfile.5 +1 -1
  87. data/lib/bundler/mirror.rb +5 -7
  88. data/lib/bundler/plugin/index.rb +4 -4
  89. data/lib/bundler/plugin/installer/rubygems.rb +0 -4
  90. data/lib/bundler/plugin/installer.rb +5 -2
  91. data/lib/bundler/plugin.rb +1 -1
  92. data/lib/bundler/remote_specification.rb +2 -6
  93. data/lib/bundler/resolver/base.rb +72 -15
  94. data/lib/bundler/resolver/candidate.rb +94 -0
  95. data/lib/bundler/resolver/incompatibility.rb +15 -0
  96. data/lib/bundler/resolver/package.rb +72 -0
  97. data/lib/bundler/resolver/root.rb +25 -0
  98. data/lib/bundler/resolver/spec_group.rb +26 -36
  99. data/lib/bundler/resolver.rb +311 -278
  100. data/lib/bundler/ruby_version.rb +1 -1
  101. data/lib/bundler/rubygems_ext.rb +16 -9
  102. data/lib/bundler/rubygems_gem_installer.rb +4 -2
  103. data/lib/bundler/rubygems_integration.rb +10 -14
  104. data/lib/bundler/runtime.rb +1 -5
  105. data/lib/bundler/safe_marshal.rb +31 -0
  106. data/lib/bundler/settings.rb +1 -7
  107. data/lib/bundler/setup.rb +4 -1
  108. data/lib/bundler/shared_helpers.rb +2 -1
  109. data/lib/bundler/source/git/git_proxy.rb +214 -69
  110. data/lib/bundler/source/git.rb +17 -18
  111. data/lib/bundler/source/metadata.rb +0 -1
  112. data/lib/bundler/source/path/installer.rb +1 -22
  113. data/lib/bundler/source/path.rb +6 -6
  114. data/lib/bundler/source/rubygems.rb +19 -77
  115. data/lib/bundler/source_list.rb +8 -2
  116. data/lib/bundler/spec_set.rb +22 -14
  117. data/lib/bundler/templates/Executable +1 -1
  118. data/lib/bundler/templates/Executable.bundler +5 -10
  119. data/lib/bundler/templates/Executable.standalone +2 -0
  120. data/lib/bundler/templates/newgem/Cargo.toml.tt +7 -0
  121. data/lib/bundler/templates/newgem/Gemfile.tt +3 -0
  122. data/lib/bundler/templates/newgem/README.md.tt +6 -4
  123. data/lib/bundler/templates/newgem/Rakefile.tt +12 -1
  124. data/lib/bundler/templates/newgem/bin/console.tt +0 -4
  125. data/lib/bundler/templates/newgem/circleci/config.yml.tt +12 -0
  126. data/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +15 -0
  127. data/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt +10 -0
  128. data/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +6 -0
  129. data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +1 -1
  130. data/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +12 -0
  131. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +10 -0
  132. data/lib/bundler/templates/newgem/gitignore.tt +3 -0
  133. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +8 -0
  134. data/lib/bundler/templates/newgem/newgem.gemspec.tt +8 -2
  135. data/lib/bundler/ui/shell.rb +35 -12
  136. data/lib/bundler/ui/silent.rb +21 -5
  137. data/lib/bundler/uri_normalizer.rb +23 -0
  138. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +3 -3
  139. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -1
  140. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +3 -1
  141. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1350 -408
  142. data/lib/bundler/vendor/net-http-persistent/README.rdoc +1 -1
  143. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
  144. data/lib/bundler/vendor/pub_grub/LICENSE.txt +21 -0
  145. data/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
  146. data/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +189 -0
  147. data/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
  148. data/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb +150 -0
  149. data/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb +43 -0
  150. data/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
  151. data/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
  152. data/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb +19 -0
  153. data/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +60 -0
  154. data/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
  155. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
  156. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb +129 -0
  157. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +411 -0
  158. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +243 -0
  159. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb +178 -0
  160. data/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +31 -0
  161. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +1 -1
  162. data/lib/bundler/vendor/uri/lib/uri/common.rb +64 -16
  163. data/lib/bundler/vendor/uri/lib/uri/file.rb +7 -1
  164. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +2 -1
  165. data/lib/bundler/vendor/uri/lib/uri/generic.rb +27 -7
  166. data/lib/bundler/vendor/uri/lib/uri/http.rb +40 -2
  167. data/lib/bundler/vendor/uri/lib/uri/https.rb +2 -1
  168. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  169. data/lib/bundler/vendor/uri/lib/uri/ldaps.rb +2 -1
  170. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +2 -2
  171. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +13 -7
  172. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +10 -5
  173. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  174. data/lib/bundler/vendor/uri/lib/uri/ws.rb +1 -2
  175. data/lib/bundler/vendor/uri/lib/uri/wss.rb +2 -1
  176. data/lib/bundler/vendor/uri/lib/uri.rb +3 -2
  177. data/lib/bundler/vendored_persistent.rb +1 -33
  178. data/lib/bundler/{vendored_tmpdir.rb → vendored_pub_grub.rb} +1 -1
  179. data/lib/bundler/version.rb +5 -1
  180. data/lib/bundler/worker.rb +5 -7
  181. data/lib/bundler.rb +17 -69
  182. metadata +35 -33
  183. data/lib/bundler/templates/gems.rb +0 -5
  184. data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +0 -5
  185. data/lib/bundler/templates/newgem/travis.yml.tt +0 -6
  186. data/lib/bundler/vendor/molinillo/LICENSE +0 -9
  187. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
  188. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +0 -88
  189. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +0 -36
  190. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +0 -66
  191. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +0 -62
  192. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +0 -63
  193. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +0 -61
  194. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +0 -126
  195. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +0 -46
  196. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +0 -36
  197. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +0 -164
  198. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +0 -255
  199. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +0 -149
  200. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +0 -6
  201. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +0 -112
  202. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +0 -67
  203. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +0 -839
  204. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +0 -46
  205. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +0 -58
  206. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +0 -11
  207. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +0 -154
  208. data/lib/bundler/vendored_molinillo.rb +0 -4
  209. data/lib/bundler/version_ranges.rb +0 -122
@@ -107,7 +107,7 @@ module Bundler
107
107
  ruby_engine_version = RUBY_ENGINE == "ruby" ? ruby_version : RUBY_ENGINE_VERSION.dup
108
108
  patchlevel = RUBY_PATCHLEVEL.to_s
109
109
 
110
- @ruby_version ||= RubyVersion.new(ruby_version, patchlevel, ruby_engine, ruby_engine_version)
110
+ @system ||= RubyVersion.new(ruby_version, patchlevel, ruby_engine, ruby_engine_version)
111
111
  end
112
112
 
113
113
  private
@@ -16,6 +16,7 @@ require "rubygems/specification"
16
16
  require "rubygems/source"
17
17
 
18
18
  require_relative "match_metadata"
19
+ require_relative "force_platform"
19
20
  require_relative "match_platform"
20
21
 
21
22
  # Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler
@@ -65,7 +66,9 @@ module Gem
65
66
 
66
67
  alias_method :rg_extension_dir, :extension_dir
67
68
  def extension_dir
68
- @bundler_extension_dir ||= if source.respond_to?(:extension_dir_name)
69
+ # following instance variable is already used in original method
70
+ # and that is the reason to prefix it with bundler_ and add rubocop exception
71
+ @bundler_extension_dir ||= if source.respond_to?(:extension_dir_name) # rubocop:disable Naming/MemoizedInstanceVariableName
69
72
  unique_extension_dir = [source.extension_dir_name, File.basename(full_gem_path)].uniq.join("-")
70
73
  File.expand_path(File.join(extensions_dir, unique_extension_dir))
71
74
  else
@@ -153,12 +156,16 @@ module Gem
153
156
  end
154
157
 
155
158
  class Dependency
159
+ include ::Bundler::ForcePlatform
160
+
156
161
  attr_accessor :source, :groups
157
162
 
158
163
  alias_method :eql?, :==
159
164
 
160
165
  def force_ruby_platform
161
- false
166
+ return @force_ruby_platform if defined?(@force_ruby_platform) && !@force_ruby_platform.nil?
167
+
168
+ @force_ruby_platform = default_force_ruby_platform
162
169
  end
163
170
 
164
171
  def encode_with(coder)
@@ -198,9 +205,9 @@ module Gem
198
205
  protected
199
206
 
200
207
  def _requirements_sorted?
201
- return @_are_requirements_sorted if defined?(@_are_requirements_sorted)
208
+ return @_requirements_sorted if defined?(@_requirements_sorted)
202
209
  strings = as_list
203
- @_are_requirements_sorted = strings == strings.sort
210
+ @_requirements_sorted = strings == strings.sort
204
211
  end
205
212
 
206
213
  def _with_sorted_requirements
@@ -277,6 +284,10 @@ module Gem
277
284
  without_gnu_nor_abi_modifiers
278
285
  end
279
286
  end
287
+
288
+ if RUBY_ENGINE == "truffleruby" && !defined?(REUSE_AS_BINARY_ON_TRUFFLERUBY)
289
+ REUSE_AS_BINARY_ON_TRUFFLERUBY = %w[libv8 libv8-node sorbet-static].freeze
290
+ end
280
291
  end
281
292
 
282
293
  Platform.singleton_class.module_eval do
@@ -338,11 +349,7 @@ module Gem
338
349
  end
339
350
 
340
351
  def glob_files_in_dir(glob, base_path)
341
- if RUBY_VERSION >= "2.5"
342
- Dir.glob(glob, :base => base_path).map! {|f| File.expand_path(f, base_path) }
343
- else
344
- Dir.glob(File.join(base_path.to_s.gsub(/[\[\]]/, '\\\\\\&'), glob)).map! {|f| File.expand_path(f) }
345
- end
352
+ Dir.glob(glob, :base => base_path).map! {|f| File.expand_path(f, base_path) }
346
353
  end
347
354
  end
348
355
  end
@@ -109,8 +109,10 @@ module Bundler
109
109
 
110
110
  def strict_rm_rf(dir)
111
111
  Bundler.rm_rf dir
112
- rescue Errno::ENOTEMPTY => e
113
- raise DirectoryRemovalError.new(e.cause, "Could not delete previous installation of `#{dir}`")
112
+ rescue StandardError => e
113
+ raise unless File.exist?(dir)
114
+
115
+ raise DirectoryRemovalError.new(e, "Could not delete previous installation of `#{dir}`")
114
116
  end
115
117
 
116
118
  def validate_bundler_checksum(checksum)
@@ -227,10 +227,14 @@ module Bundler
227
227
 
228
228
  def reverse_rubygems_kernel_mixin
229
229
  # Disable rubygems' gem activation system
230
- kernel = (class << ::Kernel; self; end)
231
- [kernel, ::Kernel].each do |k|
232
- if k.private_method_defined?(:gem_original_require)
233
- redefine_method(k, :require, k.instance_method(:gem_original_require))
230
+ if Gem.respond_to?(:discover_gems_on_require=)
231
+ Gem.discover_gems_on_require = false
232
+ else
233
+ kernel = (class << ::Kernel; self; end)
234
+ [kernel, ::Kernel].each do |k|
235
+ if k.private_method_defined?(:gem_original_require)
236
+ redefine_method(k, :require, k.instance_method(:gem_original_require))
237
+ end
234
238
  end
235
239
  end
236
240
  end
@@ -272,11 +276,7 @@ module Bundler
272
276
 
273
277
  e = Gem::LoadError.new(message)
274
278
  e.name = dep.name
275
- if e.respond_to?(:requirement=)
276
- e.requirement = dep.requirement
277
- elsif e.respond_to?(:version_requirement=)
278
- e.version_requirement = dep.requirement
279
- end
279
+ e.requirement = dep.requirement
280
280
  raise e
281
281
  end
282
282
 
@@ -453,7 +453,7 @@ module Bundler
453
453
  fetcher = gem_remote_fetcher
454
454
  fetcher.headers = { "X-Gemfile-Source" => remote.original_uri.to_s } if remote.original_uri
455
455
  string = fetcher.fetch_path(path)
456
- Bundler.load_marshal(string)
456
+ Bundler.safe_load_marshal(string)
457
457
  rescue Gem::RemoteFetcher::FetchError
458
458
  # it's okay for prerelease to fail
459
459
  raise unless name == "prerelease_specs"
@@ -508,10 +508,6 @@ module Bundler
508
508
  Gem::Package.build(spec, skip_validation)
509
509
  end
510
510
 
511
- def repository_subdirectories
512
- Gem::REPOSITORY_SUBDIRECTORIES
513
- end
514
-
515
511
  def path_separator
516
512
  Gem.path_separator
517
513
  end
@@ -300,11 +300,7 @@ module Bundler
300
300
  e = Gem::LoadError.new "You have already activated #{activated_spec.name} #{activated_spec.version}, " \
301
301
  "but your Gemfile requires #{spec.name} #{spec.version}. #{suggestion}"
302
302
  e.name = spec.name
303
- if e.respond_to?(:requirement=)
304
- e.requirement = Gem::Requirement.new(spec.version.to_s)
305
- else
306
- e.version_requirement = Gem::Requirement.new(spec.version.to_s)
307
- end
303
+ e.requirement = Gem::Requirement.new(spec.version.to_s)
308
304
  raise e
309
305
  end
310
306
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ module SafeMarshal
5
+ ALLOWED_CLASSES = [
6
+ Array,
7
+ FalseClass,
8
+ Gem::Specification,
9
+ Gem::Version,
10
+ Hash,
11
+ String,
12
+ Symbol,
13
+ Time,
14
+ TrueClass,
15
+ ].freeze
16
+
17
+ ERROR = "Unexpected class %s present in marshaled data. Only %s are allowed."
18
+
19
+ PROC = proc do |object|
20
+ object.tap do
21
+ unless ALLOWED_CLASSES.include?(object.class)
22
+ raise TypeError, format(ERROR, object.class, ALLOWED_CLASSES.join(", "))
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.proc
28
+ PROC
29
+ end
30
+ end
31
+ end
@@ -277,12 +277,6 @@ module Bundler
277
277
  end
278
278
  end
279
279
 
280
- def allow_sudo?
281
- key = key_for(:path)
282
- path_configured = @temporary.key?(key) || @local_config.key?(key)
283
- !path_configured
284
- end
285
-
286
280
  def ignore_config?
287
281
  ENV["BUNDLE_IGNORE_CONFIG"]
288
282
  end
@@ -501,7 +495,7 @@ module Bundler
501
495
  uri = $2
502
496
  suffix = $3
503
497
  end
504
- uri = "#{uri}/" unless uri.end_with?("/")
498
+ uri = URINormalizer.normalize_suffix(uri)
505
499
  require_relative "vendored_uri"
506
500
  uri = Bundler::URI(uri)
507
501
  unless uri.absolute?
data/lib/bundler/setup.rb CHANGED
@@ -12,7 +12,10 @@ if Bundler::SharedHelpers.in_bundle?
12
12
  Bundler.ui.error e.message
13
13
  Bundler.ui.warn e.backtrace.join("\n") if ENV["DEBUG"]
14
14
  if e.is_a?(Bundler::GemNotFound)
15
- Bundler.ui.warn "Run `bundle install` to install missing gems."
15
+ suggested_cmd = "bundle install"
16
+ original_gemfile = Bundler.original_env["BUNDLE_GEMFILE"]
17
+ suggested_cmd += " --gemfile #{original_gemfile}" if original_gemfile
18
+ Bundler.ui.warn "Run `#{suggested_cmd}` to install missing gems."
16
19
  end
17
20
  exit e.status_code
18
21
  end
@@ -160,7 +160,7 @@ module Bundler
160
160
  " (was expecting #{old_deps.map(&:to_s)}, but the real spec has #{new_deps.map(&:to_s)})"
161
161
  raise APIResponseMismatchError,
162
162
  "Downloading #{spec.full_name} revealed dependencies not in the API or the lockfile (#{extra_deps.join(", ")})." \
163
- "\nEither installing with `--full-index` or running `bundle update #{spec.name}` should fix the problem."
163
+ "\nRunning `bundle update #{spec.name}` should fix the problem."
164
164
  end
165
165
 
166
166
  def pretty_dependency(dep)
@@ -284,6 +284,7 @@ module Bundler
284
284
  Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", exe_file
285
285
  Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", find_gemfile.to_s
286
286
  Bundler::SharedHelpers.set_env "BUNDLER_VERSION", Bundler::VERSION
287
+ Bundler::SharedHelpers.set_env "BUNDLER_SETUP", File.expand_path("setup", __dir__) unless RUBY_VERSION < "2.7"
287
288
  end
288
289
 
289
290
  def set_path
@@ -28,10 +28,10 @@ module Bundler
28
28
  def initialize(command, path, extra_info = nil)
29
29
  @command = command
30
30
 
31
- msg = String.new
32
- msg << "Git error: command `#{command}` in directory #{path} has failed."
31
+ msg = String.new("Git error: command `#{command}`")
32
+ msg << " in directory #{path}" if path
33
+ msg << " has failed."
33
34
  msg << "\n#{extra_info}" if extra_info
34
- msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path.exist?
35
35
  super msg
36
36
  end
37
37
  end
@@ -47,23 +47,27 @@ module Bundler
47
47
  # All actions required by the Git source is encapsulated in this
48
48
  # object.
49
49
  class GitProxy
50
- attr_accessor :path, :uri, :ref
50
+ attr_accessor :path, :uri, :branch, :tag, :ref, :explicit_ref
51
51
  attr_writer :revision
52
52
 
53
- def initialize(path, uri, ref, revision = nil, git = nil)
53
+ def initialize(path, uri, options = {}, revision = nil, git = nil)
54
54
  @path = path
55
55
  @uri = uri
56
- @ref = ref
56
+ @branch = options["branch"]
57
+ @tag = options["tag"]
58
+ @ref = options["ref"]
59
+ @explicit_ref = branch || tag || ref
57
60
  @revision = revision
58
61
  @git = git
62
+ @commit_ref = nil
59
63
  end
60
64
 
61
65
  def revision
62
- @revision ||= find_local_revision
66
+ @revision ||= allowed_with_path { find_local_revision }
63
67
  end
64
68
 
65
- def branch
66
- @branch ||= allowed_with_path do
69
+ def current_branch
70
+ @current_branch ||= allowed_with_path do
67
71
  git("rev-parse", "--abbrev-ref", "HEAD", :dir => path).strip
68
72
  end
69
73
  end
@@ -76,36 +80,26 @@ module Bundler
76
80
  end
77
81
 
78
82
  def version
79
- git("--version").match(/(git version\s*)?((\.?\d+)+).*/)[2]
83
+ @version ||= full_version.match(/((\.?\d+)+).*/)[1]
80
84
  end
81
85
 
82
86
  def full_version
83
- git("--version").sub("git version", "").strip
87
+ @full_version ||= git("--version").sub(/git version\s*/, "").strip
84
88
  end
85
89
 
86
90
  def checkout
87
- return if path.exist? && has_revision_cached?
88
- extra_ref = "#{ref}:#{ref}" if ref && ref.start_with?("refs/")
89
-
90
- Bundler.ui.info "Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"
91
+ return if has_revision_cached?
91
92
 
92
- configured_uri = configured_uri_for(uri).to_s
93
+ Bundler.ui.info "Fetching #{credential_filtered_uri}"
93
94
 
94
- unless path.exist?
95
- SharedHelpers.filesystem_access(path.dirname) do |p|
96
- FileUtils.mkdir_p(p)
97
- end
98
- git_retry "clone", "--bare", "--no-hardlinks", "--quiet", "--", configured_uri, path.to_s
99
- return unless extra_ref
100
- end
95
+ extra_fetch_needed = clone_needs_extra_fetch?
96
+ unshallow_needed = clone_needs_unshallow?
97
+ return unless extra_fetch_needed || unshallow_needed
101
98
 
102
- with_path do
103
- git_retry(*["fetch", "--force", "--quiet", "--tags", "--", configured_uri, "refs/heads/*:refs/heads/*", extra_ref].compact, :dir => path)
104
- end
99
+ git_remote_fetch(unshallow_needed ? ["--unshallow"] : depth_args)
105
100
  end
106
101
 
107
102
  def copy_to(destination, submodules = false)
108
- # method 1
109
103
  unless File.exist?(destination.join(".git"))
110
104
  begin
111
105
  SharedHelpers.filesystem_access(destination.dirname) do |p|
@@ -114,7 +108,7 @@ module Bundler
114
108
  SharedHelpers.filesystem_access(destination) do |p|
115
109
  FileUtils.rm_rf(p)
116
110
  end
117
- git_retry "clone", "--no-checkout", "--quiet", path.to_s, destination.to_s
111
+ git "clone", "--no-checkout", "--quiet", path.to_s, destination.to_s
118
112
  File.chmod(((File.stat(destination).mode | 0o777) & ~File.umask), destination)
119
113
  rescue Errno::EEXIST => e
120
114
  file_path = e.message[%r{.*?((?:[a-zA-Z]:)?/.*)}, 1]
@@ -123,14 +117,10 @@ module Bundler
123
117
  "this file and try again."
124
118
  end
125
119
  end
126
- # method 2
127
- git_retry "fetch", "--force", "--quiet", "--tags", path.to_s, :dir => destination
128
120
 
129
- begin
130
- git "reset", "--hard", @revision, :dir => destination
131
- rescue GitCommandError => e
132
- raise MissingGitRevisionError.new(e.command, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri))
133
- end
121
+ git "fetch", "--force", "--quiet", *extra_fetch_args, :dir => destination if @commit_ref
122
+
123
+ git "reset", "--hard", @revision, :dir => destination
134
124
 
135
125
  if submodules
136
126
  git_retry "submodule", "update", "--init", "--recursive", :dir => destination
@@ -142,14 +132,116 @@ module Bundler
142
132
 
143
133
  private
144
134
 
145
- def git_null(*command, dir: nil)
146
- check_allowed(command)
135
+ def git_remote_fetch(args)
136
+ command = ["fetch", "--force", "--quiet", "--no-tags", *args, "--", configured_uri, refspec].compact
137
+ command_with_no_credentials = check_allowed(command)
138
+
139
+ Bundler::Retry.new("`#{command_with_no_credentials}` at #{path}", [MissingGitRevisionError]).attempts do
140
+ out, err, status = capture(command, path)
141
+ return out if status.success?
142
+
143
+ if err.include?("couldn't find remote ref") || err.include?("not our ref")
144
+ raise MissingGitRevisionError.new(command_with_no_credentials, path, commit || explicit_ref, credential_filtered_uri)
145
+ else
146
+ raise GitCommandError.new(command_with_no_credentials, path, err)
147
+ end
148
+ end
149
+ end
150
+
151
+ def clone_needs_extra_fetch?
152
+ return true if path.exist?
153
+
154
+ SharedHelpers.filesystem_access(path.dirname) do |p|
155
+ FileUtils.mkdir_p(p)
156
+ end
157
+
158
+ command = ["clone", "--bare", "--no-hardlinks", "--quiet", *extra_clone_args, "--", configured_uri, path.to_s]
159
+ command_with_no_credentials = check_allowed(command)
160
+
161
+ Bundler::Retry.new("`#{command_with_no_credentials}`", [MissingGitRevisionError]).attempts do
162
+ _, err, status = capture(command, nil)
163
+ return extra_ref if status.success?
164
+
165
+ if err.include?("Could not find remote branch")
166
+ raise MissingGitRevisionError.new(command_with_no_credentials, nil, explicit_ref, credential_filtered_uri)
167
+ else
168
+ raise GitCommandError.new(command_with_no_credentials, path, err)
169
+ end
170
+ end
171
+ end
172
+
173
+ def clone_needs_unshallow?
174
+ return false unless path.join("shallow").exist?
175
+ return true if full_clone?
176
+
177
+ @revision && @revision != head_revision
178
+ end
179
+
180
+ def extra_ref
181
+ return false if not_pinned?
182
+ return true unless full_clone?
183
+
184
+ ref.start_with?("refs/")
185
+ end
186
+
187
+ def depth
188
+ return @depth if defined?(@depth)
189
+
190
+ @depth = if !supports_fetching_unreachable_refs?
191
+ nil
192
+ elsif not_pinned? || pinned_to_full_sha?
193
+ 1
194
+ elsif ref.include?("~")
195
+ parsed_depth = ref.split("~").last
196
+ parsed_depth.to_i + 1
197
+ end
198
+ end
199
+
200
+ def refspec
201
+ if commit
202
+ @commit_ref = "refs/#{commit}-sha"
203
+ return "#{commit}:#{@commit_ref}"
204
+ end
205
+
206
+ reference = fully_qualified_ref
207
+
208
+ reference ||= if ref.include?("~")
209
+ ref.split("~").first
210
+ elsif ref.start_with?("refs/")
211
+ ref
212
+ else
213
+ "refs/*"
214
+ end
215
+
216
+ "#{reference}:#{reference}"
217
+ end
218
+
219
+ def commit
220
+ @commit ||= pinned_to_full_sha? ? ref : @revision
221
+ end
147
222
 
148
- out, status = SharedHelpers.with_clean_git_env do
149
- capture_and_ignore_stderr(*capture3_args_for(command, dir))
223
+ def fully_qualified_ref
224
+ if branch
225
+ "refs/heads/#{branch}"
226
+ elsif tag
227
+ "refs/tags/#{tag}"
228
+ elsif ref.nil?
229
+ "refs/heads/#{current_branch}"
150
230
  end
231
+ end
232
+
233
+ def not_pinned?
234
+ branch || tag || ref.nil?
235
+ end
236
+
237
+ def pinned_to_full_sha?
238
+ ref =~ /\A\h{40}\z/
239
+ end
240
+
241
+ def git_null(*command, dir: nil)
242
+ check_allowed(command)
151
243
 
152
- [URICredentialsFilter.credential_filtered_string(out, uri), status]
244
+ capture(command, dir, :ignore_err => true)
153
245
  end
154
246
 
155
247
  def git_retry(*command, dir: nil)
@@ -163,49 +255,62 @@ module Bundler
163
255
  def git(*command, dir: nil)
164
256
  command_with_no_credentials = check_allowed(command)
165
257
 
166
- out, status = SharedHelpers.with_clean_git_env do
167
- capture_and_filter_stderr(*capture3_args_for(command, dir))
168
- end
258
+ out, err, status = capture(command, dir)
169
259
 
170
- filtered_out = URICredentialsFilter.credential_filtered_string(out, uri)
260
+ raise GitCommandError.new(command_with_no_credentials, dir || SharedHelpers.pwd, err) unless status.success?
171
261
 
172
- raise GitCommandError.new(command_with_no_credentials, dir || SharedHelpers.pwd, filtered_out) unless status.success?
262
+ Bundler.ui.warn err unless err.empty?
173
263
 
174
- filtered_out
264
+ out
175
265
  end
176
266
 
177
267
  def has_revision_cached?
178
- return unless @revision
179
- with_path { git("cat-file", "-e", @revision, :dir => path) }
268
+ return unless @revision && path.exist?
269
+ git("cat-file", "-e", @revision, :dir => path)
180
270
  true
181
271
  rescue GitError
182
272
  false
183
273
  end
184
274
 
185
- def remove_cache
186
- FileUtils.rm_rf(path)
275
+ def find_local_revision
276
+ return head_revision if explicit_ref.nil?
277
+
278
+ find_revision_for(explicit_ref)
187
279
  end
188
280
 
189
- def find_local_revision
190
- allowed_with_path do
191
- git("rev-parse", "--verify", ref || "HEAD", :dir => path).strip
192
- end
281
+ def head_revision
282
+ verify("HEAD")
283
+ end
284
+
285
+ def find_revision_for(reference)
286
+ verify(reference)
193
287
  rescue GitCommandError => e
194
- raise MissingGitRevisionError.new(e.command, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
288
+ raise MissingGitRevisionError.new(e.command, path, reference, credential_filtered_uri)
289
+ end
290
+
291
+ def verify(reference)
292
+ git("rev-parse", "--verify", reference, :dir => path).strip
195
293
  end
196
294
 
197
- # Adds credentials to the URI as Fetcher#configured_uri_for does
198
- def configured_uri_for(uri)
199
- if /https?:/ =~ uri
295
+ # Adds credentials to the URI
296
+ def configured_uri
297
+ if /https?:/.match?(uri)
200
298
  remote = Bundler::URI(uri)
201
299
  config_auth = Bundler.settings[remote.to_s] || Bundler.settings[remote.host]
202
300
  remote.userinfo ||= config_auth
203
301
  remote.to_s
302
+ elsif File.exist?(uri)
303
+ "file://#{uri}"
204
304
  else
205
- uri
305
+ uri.to_s
206
306
  end
207
307
  end
208
308
 
309
+ # Removes credentials from the URI
310
+ def credential_filtered_uri
311
+ URICredentialsFilter.credential_filtered_uri(uri)
312
+ end
313
+
209
314
  def allow?
210
315
  allowed = @git ? @git.allow_git_ops? : true
211
316
 
@@ -231,17 +336,17 @@ module Bundler
231
336
  command_with_no_credentials
232
337
  end
233
338
 
234
- def capture_and_filter_stderr(*cmd)
235
- require "open3"
236
- return_value, captured_err, status = Open3.capture3(*cmd)
237
- Bundler.ui.warn URICredentialsFilter.credential_filtered_string(captured_err, uri) unless captured_err.empty?
238
- [return_value, status]
239
- end
339
+ def capture(cmd, dir, ignore_err: false)
340
+ SharedHelpers.with_clean_git_env do
341
+ require "open3"
342
+ out, err, status = Open3.capture3(*capture3_args_for(cmd, dir))
240
343
 
241
- def capture_and_ignore_stderr(*cmd)
242
- require "open3"
243
- return_value, _, status = Open3.capture3(*cmd)
244
- [return_value, status]
344
+ filtered_out = URICredentialsFilter.credential_filtered_string(out, uri)
345
+ return [filtered_out, status] if ignore_err
346
+
347
+ filtered_err = URICredentialsFilter.credential_filtered_string(err, uri)
348
+ [filtered_out, filtered_err, status]
349
+ end
245
350
  end
246
351
 
247
352
  def capture3_args_for(cmd, dir)
@@ -254,9 +359,49 @@ module Bundler
254
359
  end
255
360
  end
256
361
 
362
+ def extra_clone_args
363
+ args = depth_args
364
+ return [] if args.empty?
365
+
366
+ args += ["--single-branch"]
367
+ args.unshift("--no-tags") if supports_cloning_with_no_tags?
368
+
369
+ # If there's a locked revision, no need to clone any specific branch
370
+ # or tag, since we will end up checking out that locked revision
371
+ # anyways.
372
+ return args if @revision
373
+
374
+ args += ["--branch", branch || tag] if branch || tag
375
+ args
376
+ end
377
+
378
+ def depth_args
379
+ return [] if full_clone?
380
+
381
+ ["--depth", depth.to_s]
382
+ end
383
+
384
+ def extra_fetch_args
385
+ extra_args = [path.to_s, *depth_args]
386
+ extra_args.push(@commit_ref)
387
+ extra_args
388
+ end
389
+
390
+ def full_clone?
391
+ depth.nil?
392
+ end
393
+
257
394
  def supports_minus_c?
258
395
  @supports_minus_c ||= Gem::Version.new(version) >= Gem::Version.new("1.8.5")
259
396
  end
397
+
398
+ def supports_fetching_unreachable_refs?
399
+ @supports_fetching_unreachable_refs ||= Gem::Version.new(version) >= Gem::Version.new("2.5.0")
400
+ end
401
+
402
+ def supports_cloning_with_no_tags?
403
+ @supports_cloning_with_no_tags ||= Gem::Version.new(version) >= Gem::Version.new("2.14.0-rc0")
404
+ end
260
405
  end
261
406
  end
262
407
  end