bundler 2.2.3 → 2.3.5

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +503 -7
  3. data/README.md +1 -1
  4. data/bundler.gemspec +2 -3
  5. data/exe/bundle +7 -8
  6. data/lib/bundler/.document +1 -0
  7. data/lib/bundler/build_metadata.rb +2 -2
  8. data/lib/bundler/cli/cache.rb +2 -1
  9. data/lib/bundler/cli/check.rb +4 -2
  10. data/lib/bundler/cli/common.rb +15 -2
  11. data/lib/bundler/cli/doctor.rb +15 -4
  12. data/lib/bundler/cli/exec.rb +1 -6
  13. data/lib/bundler/cli/gem.rb +132 -24
  14. data/lib/bundler/cli/info.rb +16 -4
  15. data/lib/bundler/cli/install.rb +12 -27
  16. data/lib/bundler/cli/issue.rb +4 -3
  17. data/lib/bundler/cli/list.rb +7 -1
  18. data/lib/bundler/cli/lock.rb +5 -1
  19. data/lib/bundler/cli/open.rb +1 -2
  20. data/lib/bundler/cli/outdated.rb +10 -11
  21. data/lib/bundler/cli/remove.rb +1 -2
  22. data/lib/bundler/cli/update.rb +17 -8
  23. data/lib/bundler/cli.rb +44 -60
  24. data/lib/bundler/compact_index_client/cache.rb +0 -9
  25. data/lib/bundler/compact_index_client/updater.rb +10 -19
  26. data/lib/bundler/compact_index_client.rb +2 -8
  27. data/lib/bundler/current_ruby.rb +5 -4
  28. data/lib/bundler/definition.rb +158 -316
  29. data/lib/bundler/dep_proxy.rb +15 -8
  30. data/lib/bundler/dependency.rb +5 -7
  31. data/lib/bundler/digest.rb +71 -0
  32. data/lib/bundler/dsl.rb +67 -66
  33. data/lib/bundler/endpoint_specification.rb +21 -11
  34. data/lib/bundler/environment_preserver.rb +4 -1
  35. data/lib/bundler/errors.rb +19 -3
  36. data/lib/bundler/feature_flag.rb +0 -5
  37. data/lib/bundler/fetcher/compact_index.rb +10 -15
  38. data/lib/bundler/fetcher/downloader.rb +9 -6
  39. data/lib/bundler/fetcher/index.rb +0 -27
  40. data/lib/bundler/fetcher.rb +10 -17
  41. data/lib/bundler/friendly_errors.rb +5 -32
  42. data/lib/bundler/gem_helper.rb +28 -21
  43. data/lib/bundler/gem_version_promoter.rb +2 -2
  44. data/lib/bundler/index.rb +8 -12
  45. data/lib/bundler/injector.rb +12 -3
  46. data/lib/bundler/inline.rb +2 -1
  47. data/lib/bundler/installer/gem_installer.rb +4 -22
  48. data/lib/bundler/installer/parallel_installer.rb +36 -15
  49. data/lib/bundler/installer/standalone.rb +29 -9
  50. data/lib/bundler/installer.rb +8 -34
  51. data/lib/bundler/lazy_specification.rb +32 -20
  52. data/lib/bundler/lockfile_generator.rb +1 -1
  53. data/lib/bundler/lockfile_parser.rb +16 -45
  54. data/{man → lib/bundler/man}/bundle-add.1 +10 -2
  55. data/lib/bundler/man/bundle-add.1.ronn +7 -1
  56. data/{man → lib/bundler/man}/bundle-binstubs.1 +1 -1
  57. data/{man → lib/bundler/man}/bundle-cache.1 +1 -1
  58. data/{man → lib/bundler/man}/bundle-check.1 +1 -1
  59. data/{man → lib/bundler/man}/bundle-clean.1 +1 -1
  60. data/{man → lib/bundler/man}/bundle-config.1 +27 -19
  61. data/lib/bundler/man/bundle-config.1.ronn +33 -25
  62. data/{man → lib/bundler/man}/bundle-doctor.1 +1 -1
  63. data/{man → lib/bundler/man}/bundle-exec.1 +1 -1
  64. data/{man → lib/bundler/man}/bundle-gem.1 +14 -1
  65. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  66. data/{man → lib/bundler/man}/bundle-info.1 +1 -1
  67. data/{man → lib/bundler/man}/bundle-init.1 +1 -1
  68. data/{man → lib/bundler/man}/bundle-inject.1 +1 -1
  69. data/{man → lib/bundler/man}/bundle-install.1 +2 -2
  70. data/lib/bundler/man/bundle-install.1.ronn +2 -2
  71. data/{man → lib/bundler/man}/bundle-list.1 +1 -1
  72. data/{man → lib/bundler/man}/bundle-lock.1 +1 -1
  73. data/{man → lib/bundler/man}/bundle-open.1 +1 -1
  74. data/{man → lib/bundler/man}/bundle-outdated.1 +1 -1
  75. data/{man → lib/bundler/man}/bundle-platform.1 +1 -1
  76. data/{man → lib/bundler/man}/bundle-pristine.1 +1 -1
  77. data/{man → lib/bundler/man}/bundle-remove.1 +1 -1
  78. data/{man → lib/bundler/man}/bundle-show.1 +1 -1
  79. data/{man → lib/bundler/man}/bundle-update.1 +5 -5
  80. data/lib/bundler/man/bundle-update.1.ronn +5 -4
  81. data/{man → lib/bundler/man}/bundle-viz.1 +1 -1
  82. data/{man → lib/bundler/man}/bundle.1 +1 -1
  83. data/{man → lib/bundler/man}/gemfile.5 +28 -2
  84. data/lib/bundler/man/gemfile.5.ronn +9 -1
  85. data/{man → lib/bundler/man}/index.txt +0 -0
  86. data/lib/bundler/plugin/api/source.rb +22 -0
  87. data/lib/bundler/plugin/index.rb +4 -1
  88. data/lib/bundler/plugin/installer.rb +10 -10
  89. data/lib/bundler/plugin/source_list.rb +4 -0
  90. data/lib/bundler/plugin.rb +28 -8
  91. data/lib/bundler/process_lock.rb +1 -1
  92. data/lib/bundler/psyched_yaml.rb +1 -13
  93. data/lib/bundler/resolver/spec_group.rb +36 -48
  94. data/lib/bundler/resolver.rb +97 -151
  95. data/lib/bundler/retry.rb +1 -1
  96. data/lib/bundler/ruby_version.rb +1 -1
  97. data/lib/bundler/rubygems_ext.rb +46 -8
  98. data/lib/bundler/rubygems_gem_installer.rb +68 -1
  99. data/lib/bundler/rubygems_integration.rb +43 -60
  100. data/lib/bundler/runtime.rb +18 -11
  101. data/lib/bundler/self_manager.rb +168 -0
  102. data/lib/bundler/settings.rb +97 -21
  103. data/lib/bundler/setup.rb +2 -2
  104. data/lib/bundler/shared_helpers.rb +6 -21
  105. data/lib/bundler/source/git/git_proxy.rb +60 -53
  106. data/lib/bundler/source/git.rb +38 -18
  107. data/lib/bundler/source/metadata.rb +1 -5
  108. data/lib/bundler/source/path/installer.rb +3 -1
  109. data/lib/bundler/source/path.rb +3 -1
  110. data/lib/bundler/source/rubygems.rb +113 -100
  111. data/lib/bundler/source/rubygems_aggregate.rb +68 -0
  112. data/lib/bundler/source.rb +21 -0
  113. data/lib/bundler/source_list.rb +100 -62
  114. data/lib/bundler/source_map.rb +58 -0
  115. data/lib/bundler/spec_set.rb +21 -34
  116. data/lib/bundler/stub_specification.rb +8 -0
  117. data/lib/bundler/templates/Executable.bundler +7 -7
  118. data/lib/bundler/templates/Gemfile +0 -2
  119. data/lib/bundler/templates/gems.rb +0 -3
  120. data/lib/bundler/templates/newgem/CHANGELOG.md.tt +5 -0
  121. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  122. data/lib/bundler/templates/newgem/README.md.tt +5 -3
  123. data/lib/bundler/templates/newgem/Rakefile.tt +15 -2
  124. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +15 -6
  125. data/lib/bundler/templates/newgem/newgem.gemspec.tt +18 -16
  126. data/lib/bundler/templates/newgem/rubocop.yml.tt +3 -0
  127. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  128. data/lib/bundler/templates/newgem/standard.yml.tt +2 -0
  129. data/lib/bundler/templates/newgem/test/minitest/{newgem_test.rb.tt → test_newgem.rb.tt} +1 -1
  130. data/lib/bundler/ui/shell.rb +1 -1
  131. data/lib/bundler/vendor/.document +1 -0
  132. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  133. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  134. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  135. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  136. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  137. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  138. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  139. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +7 -0
  140. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +11 -5
  141. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +2 -3
  142. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +2 -2
  143. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +12 -1
  144. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +11 -7
  145. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  146. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  147. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +9 -7
  148. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -2
  149. data/lib/bundler/vendor/thor/lib/thor/actions.rb +7 -3
  150. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
  151. data/lib/bundler/vendor/thor/lib/thor/error.rb +10 -5
  152. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +5 -1
  153. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +28 -9
  154. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +27 -6
  155. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +5 -1
  156. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  157. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  158. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  159. data/lib/bundler/vendor/thor/lib/thor.rb +5 -6
  160. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +1 -1
  161. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  162. data/lib/bundler/vendor/tsort/lib/tsort.rb +453 -0
  163. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  164. data/lib/bundler/vendor/uri/lib/uri/common.rb +17 -80
  165. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -1
  166. data/lib/bundler/vendor/uri/lib/uri/generic.rb +5 -6
  167. data/lib/bundler/vendor/uri/lib/uri/http.rb +0 -1
  168. data/lib/bundler/vendor/uri/lib/uri/https.rb +0 -1
  169. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  170. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -1
  171. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +1 -14
  172. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +1 -12
  173. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  174. data/lib/bundler/vendor/uri/lib/uri/ws.rb +84 -0
  175. data/lib/bundler/vendor/uri/lib/uri/wss.rb +22 -0
  176. data/lib/bundler/vendor/uri/lib/uri.rb +0 -1
  177. data/lib/bundler/vendored_tsort.rb +4 -0
  178. data/lib/bundler/version.rb +1 -1
  179. data/lib/bundler/worker.rb +19 -4
  180. data/lib/bundler.rb +29 -33
  181. metadata +54 -35
  182. data/lib/bundler/gemdeps.rb +0 -29
  183. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
@@ -7,33 +7,34 @@ module Bundler
7
7
  autoload :Validator, File.expand_path("settings/validator", __dir__)
8
8
 
9
9
  BOOL_KEYS = %w[
10
- allow_bundler_dependency_conflicts
11
10
  allow_deployment_source_credential_changes
12
11
  allow_offline_install
13
12
  auto_clean_without_path
14
13
  auto_install
15
14
  cache_all
16
15
  cache_all_platforms
16
+ clean
17
17
  default_install_uses_path
18
18
  deployment
19
- deployment_means_frozen
20
19
  disable_checksum_validation
21
20
  disable_exec_load
22
21
  disable_local_branch_check
23
- disable_multisource
22
+ disable_local_revision_check
24
23
  disable_shared_gems
25
24
  disable_version_check
26
25
  force_ruby_platform
27
26
  forget_cli_options
28
27
  frozen
28
+ gem.changelog
29
29
  gem.coc
30
30
  gem.mit
31
+ git.allow_insecure
31
32
  global_gem_cache
32
33
  ignore_messages
33
34
  init_gems_rb
35
+ inline
34
36
  no_install
35
37
  no_prune
36
- only_update_to_newer_versions
37
38
  path_relative_to_cwd
38
39
  path.system
39
40
  plugins
@@ -43,7 +44,6 @@ module Bundler
43
44
  silence_deprecations
44
45
  silence_root_warning
45
46
  suppress_install_using_messages
46
- unlock_source_unlocks_spec
47
47
  update_requires_all_flag
48
48
  use_gem_version_promoter_for_major_updates
49
49
  ].freeze
@@ -61,6 +61,22 @@ module Bundler
61
61
  without
62
62
  ].freeze
63
63
 
64
+ STRING_KEYS = %w[
65
+ bin
66
+ cache_path
67
+ console
68
+ gem.ci
69
+ gem.github_username
70
+ gem.linter
71
+ gem.rubocop
72
+ gem.test
73
+ gemfile
74
+ path
75
+ shebang
76
+ system_bindir
77
+ trust-policy
78
+ ].freeze
79
+
64
80
  DEFAULT_CONFIG = {
65
81
  "BUNDLE_SILENCE_DEPRECATIONS" => false,
66
82
  "BUNDLE_DISABLE_VERSION_CHECK" => true,
@@ -126,8 +142,8 @@ module Bundler
126
142
  keys = @temporary.keys | @global_config.keys | @local_config.keys | @env_config.keys
127
143
 
128
144
  keys.map do |key|
129
- key.sub(/^BUNDLE_/, "").gsub(/__/, ".").downcase
130
- end
145
+ key.sub(/^BUNDLE_/, "").gsub(/___/, "-").gsub(/__/, ".").downcase
146
+ end.sort
131
147
  end
132
148
 
133
149
  def local_overrides
@@ -173,29 +189,37 @@ module Bundler
173
189
  locations = []
174
190
 
175
191
  if value = @temporary[key]
176
- locations << "Set for the current command: #{converted_value(value, exposed_key).inspect}"
192
+ locations << "Set for the current command: #{printable_value(value, exposed_key).inspect}"
177
193
  end
178
194
 
179
195
  if value = @local_config[key]
180
- locations << "Set for your local app (#{local_config_file}): #{converted_value(value, exposed_key).inspect}"
196
+ locations << "Set for your local app (#{local_config_file}): #{printable_value(value, exposed_key).inspect}"
181
197
  end
182
198
 
183
199
  if value = @env_config[key]
184
- locations << "Set via #{key}: #{converted_value(value, exposed_key).inspect}"
200
+ locations << "Set via #{key}: #{printable_value(value, exposed_key).inspect}"
185
201
  end
186
202
 
187
203
  if value = @global_config[key]
188
- locations << "Set for the current user (#{global_config_file}): #{converted_value(value, exposed_key).inspect}"
204
+ locations << "Set for the current user (#{global_config_file}): #{printable_value(value, exposed_key).inspect}"
189
205
  end
190
206
 
191
207
  return ["You have not configured a value for `#{exposed_key}`"] if locations.empty?
192
208
  locations
193
209
  end
194
210
 
211
+ def processor_count
212
+ require "etc"
213
+ Etc.nprocessors
214
+ rescue StandardError
215
+ 1
216
+ end
217
+
195
218
  # for legacy reasons, in Bundler 2, we do not respect :disable_shared_gems
196
219
  def path
197
220
  configs.each do |_level, settings|
198
221
  path = value_for("path", settings)
222
+ path = "vendor/bundle" if value_for("deployment", settings) && path.nil?
199
223
  path_system = value_for("path.system", settings)
200
224
  disabled_shared_gems = value_for("disable_shared_gems", settings)
201
225
  next if path.nil? && path_system.nil? && disabled_shared_gems.nil?
@@ -277,9 +301,7 @@ module Bundler
277
301
  end
278
302
 
279
303
  def key_for(key)
280
- key = Settings.normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key
281
- key = key.to_s.gsub(".", "__").upcase
282
- "BUNDLE_#{key}"
304
+ self.class.key_for(key)
283
305
  end
284
306
 
285
307
  private
@@ -314,6 +336,10 @@ module Bundler
314
336
  BOOL_KEYS.include?(name.to_s) || BOOL_KEYS.include?(parent_setting_for(name.to_s))
315
337
  end
316
338
 
339
+ def is_string(name)
340
+ STRING_KEYS.include?(name.to_s) || name.to_s.start_with?("local.") || name.to_s.start_with?("mirror.") || name.to_s.start_with?("build.")
341
+ end
342
+
317
343
  def to_bool(value)
318
344
  case value
319
345
  when nil, /\A(false|f|no|n|0|)\z/i, false
@@ -331,6 +357,14 @@ module Bundler
331
357
  ARRAY_KEYS.include?(key.to_s)
332
358
  end
333
359
 
360
+ def is_credential(key)
361
+ key == "gem.push_key"
362
+ end
363
+
364
+ def is_userinfo(value)
365
+ value.include?(":")
366
+ end
367
+
334
368
  def to_array(value)
335
369
  return [] unless value
336
370
  value.split(":").map(&:to_sym)
@@ -377,15 +411,38 @@ module Bundler
377
411
  end
378
412
  end
379
413
 
414
+ def printable_value(value, key)
415
+ converted = converted_value(value, key)
416
+ return converted unless converted.is_a?(String)
417
+
418
+ if is_string(key)
419
+ converted
420
+ elsif is_credential(key)
421
+ "[REDACTED]"
422
+ elsif is_userinfo(converted)
423
+ username, pass = converted.split(":", 2)
424
+
425
+ if pass == "x-oauth-basic"
426
+ username = "[REDACTED]"
427
+ else
428
+ pass = "[REDACTED]"
429
+ end
430
+
431
+ [username, pass].join(":")
432
+ else
433
+ converted
434
+ end
435
+ end
436
+
380
437
  def global_config_file
381
438
  if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty?
382
439
  Pathname.new(ENV["BUNDLE_CONFIG"])
383
- else
384
- begin
385
- Bundler.user_bundle_path("config")
386
- rescue PermissionError, GenericSystemCallError
387
- nil
388
- end
440
+ elsif ENV["BUNDLE_USER_CONFIG"] && !ENV["BUNDLE_USER_CONFIG"].empty?
441
+ Pathname.new(ENV["BUNDLE_USER_CONFIG"])
442
+ elsif ENV["BUNDLE_USER_HOME"] && !ENV["BUNDLE_USER_HOME"].empty?
443
+ Pathname.new(ENV["BUNDLE_USER_HOME"]).join("config")
444
+ elsif Bundler.rubygems.user_home && !Bundler.rubygems.user_home.empty?
445
+ Pathname.new(Bundler.rubygems.user_home).join(".bundle/config")
389
446
  end
390
447
  end
391
448
 
@@ -399,7 +456,20 @@ module Bundler
399
456
  valid_file = file.exist? && !file.size.zero?
400
457
  return {} unless valid_file
401
458
  require_relative "yaml_serializer"
402
- YAMLSerializer.load file.read
459
+ YAMLSerializer.load(file.read).inject({}) do |config, (k, v)|
460
+ new_k = k
461
+
462
+ if k.include?("-")
463
+ Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \
464
+ "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \
465
+ "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)."
466
+
467
+ new_k = k.gsub("-", "___")
468
+ end
469
+
470
+ config[new_k] = v
471
+ config
472
+ end
403
473
  end
404
474
  end
405
475
 
@@ -416,6 +486,12 @@ module Bundler
416
486
  \z
417
487
  /ix.freeze
418
488
 
489
+ def self.key_for(key)
490
+ key = normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key
491
+ key = key.to_s.gsub(".", "__").gsub("-", "___").upcase
492
+ "BUNDLE_#{key}"
493
+ end
494
+
419
495
  # TODO: duplicates Rubygems#normalize_uri
420
496
  # TODO: is this the correct place to validate mirror URIs?
421
497
  def self.normalize_uri(uri)
data/lib/bundler/setup.rb CHANGED
@@ -9,10 +9,10 @@ if Bundler::SharedHelpers.in_bundle?
9
9
  begin
10
10
  Bundler.ui.silence { Bundler.setup }
11
11
  rescue Bundler::BundlerError => e
12
- Bundler.ui.warn "\e[31m#{e.message}\e[0m"
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 "\e[33mRun `bundle install` to install missing gems.\e[0m"
15
+ Bundler.ui.warn "Run `bundle install` to install missing gems."
16
16
  end
17
17
  exit e.status_code
18
18
  end
@@ -109,7 +109,7 @@ module Bundler
109
109
  raise VirtualProtocolError.new
110
110
  rescue Errno::ENOSPC
111
111
  raise NoSpaceOnDeviceError.new(path, action)
112
- rescue *[const_get_safely(:ENOTSUP, Errno)].compact
112
+ rescue Errno::ENOTSUP
113
113
  raise OperationNotSupportedError.new(path, action)
114
114
  rescue Errno::EEXIST, Errno::ENOENT
115
115
  raise
@@ -117,13 +117,6 @@ module Bundler
117
117
  raise GenericSystemCallError.new(e, "There was an error accessing `#{path}`.")
118
118
  end
119
119
 
120
- def const_get_safely(constant_name, namespace)
121
- const_in_namespace = namespace.constants.include?(constant_name.to_s) ||
122
- namespace.constants.include?(constant_name.to_sym)
123
- return nil unless const_in_namespace
124
- namespace.const_get(constant_name)
125
- end
126
-
127
120
  def major_deprecation(major_version, message, print_caller_location: false)
128
121
  if print_caller_location
129
122
  caller_location = caller_locations(2, 2).first
@@ -152,13 +145,6 @@ module Bundler
152
145
  Bundler.ui.warn message
153
146
  end
154
147
 
155
- def trap(signal, override = false, &block)
156
- prior = Signal.trap(signal) do
157
- block.call
158
- prior.call unless override
159
- end
160
- end
161
-
162
148
  def ensure_same_dependencies(spec, old_deps, new_deps)
163
149
  new_deps = new_deps.reject {|d| d.type == :development }
164
150
  old_deps = old_deps.reject {|d| d.type == :development }
@@ -194,11 +180,11 @@ module Bundler
194
180
  return @md5_available if defined?(@md5_available)
195
181
  @md5_available = begin
196
182
  require "openssl"
197
- OpenSSL::Digest.digest("MD5", "")
183
+ ::OpenSSL::Digest.digest("MD5", "")
198
184
  true
199
185
  rescue LoadError
200
186
  true
201
- rescue OpenSSL::Digest::DigestError
187
+ rescue ::OpenSSL::Digest::DigestError
202
188
  false
203
189
  end
204
190
  end
@@ -253,7 +239,7 @@ module Bundler
253
239
  current = File.expand_path(SharedHelpers.pwd).tap{|x| x.untaint if RUBY_VERSION < "2.7" }
254
240
 
255
241
  until !File.directory?(current) || current == previous
256
- if ENV["BUNDLE_SPEC_RUN"]
242
+ if ENV["BUNDLER_SPEC_RUN"]
257
243
  # avoid stepping above the tmp directory when testing
258
244
  gemspec = if ENV["GEM_COMMAND"]
259
245
  # for Ruby Core
@@ -327,12 +313,11 @@ module Bundler
327
313
  end
328
314
 
329
315
  def clean_load_path
330
- bundler_lib = bundler_ruby_lib
331
-
332
316
  loaded_gem_paths = Bundler.rubygems.loaded_gem_paths
333
317
 
334
318
  $LOAD_PATH.reject! do |p|
335
- next if resolve_path(p).start_with?(bundler_lib)
319
+ resolved_path = resolve_path(p)
320
+ next if $LOADED_FEATURES.any? {|lf| lf.start_with?(resolved_path) }
336
321
  loaded_gem_paths.delete(p)
337
322
  end
338
323
  $LOAD_PATH.uniq!
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "shellwords"
4
-
5
3
  module Bundler
6
4
  class Source
7
5
  class Git
@@ -17,7 +15,7 @@ module Bundler
17
15
  class GitNotAllowedError < GitError
18
16
  def initialize(command)
19
17
  msg = String.new
20
- msg << "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, "
18
+ msg << "Bundler is trying to run `#{command}` at runtime. You probably need to run `bundle install`. However, "
21
19
  msg << "this error message could probably be more useful. Please submit a ticket at https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md "
22
20
  msg << "with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}"
23
21
  super msg
@@ -27,11 +25,11 @@ module Bundler
27
25
  class GitCommandError < GitError
28
26
  attr_reader :command
29
27
 
30
- def initialize(command, path, destination_path, extra_info = nil)
28
+ def initialize(command, path, extra_info = nil)
31
29
  @command = command
32
30
 
33
31
  msg = String.new
34
- msg << "Git error: command `git #{command}` in directory #{destination_path} has failed."
32
+ msg << "Git error: command `#{command}` in directory #{path} has failed."
35
33
  msg << "\n#{extra_info}" if extra_info
36
34
  msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path.exist?
37
35
  super msg
@@ -39,9 +37,9 @@ module Bundler
39
37
  end
40
38
 
41
39
  class MissingGitRevisionError < GitCommandError
42
- def initialize(command, path, destination_path, ref, repo)
40
+ def initialize(command, destination_path, ref, repo)
43
41
  msg = "Revision #{ref} does not exist in the repository #{repo}. Maybe you misspelled it?"
44
- super command, path, destination_path, msg
42
+ super command, destination_path, msg
45
43
  end
46
44
  end
47
45
 
@@ -58,7 +56,6 @@ module Bundler
58
56
  @ref = ref
59
57
  @revision = revision
60
58
  @git = git
61
- raise GitNotInstalledError.new if allow? && !Bundler.git_present?
62
59
  end
63
60
 
64
61
  def revision
@@ -67,13 +64,13 @@ module Bundler
67
64
 
68
65
  def branch
69
66
  @branch ||= allowed_with_path do
70
- git("rev-parse --abbrev-ref HEAD", :dir => path).strip
67
+ git("rev-parse", "--abbrev-ref", "HEAD", :dir => path).strip
71
68
  end
72
69
  end
73
70
 
74
71
  def contains?(commit)
75
72
  allowed_with_path do
76
- result, status = git_null("branch --contains #{commit}", :dir => path)
73
+ result, status = git_null("branch", "--contains", commit, :dir => path)
77
74
  status.success? && result =~ /^\* (.*)$/
78
75
  end
79
76
  end
@@ -88,20 +85,22 @@ module Bundler
88
85
 
89
86
  def checkout
90
87
  return if path.exist? && has_revision_cached?
91
- extra_ref = "#{Shellwords.shellescape(ref)}:#{Shellwords.shellescape(ref)}" if ref && ref.start_with?("refs/")
88
+ extra_ref = "#{ref}:#{ref}" if ref && ref.start_with?("refs/")
92
89
 
93
90
  Bundler.ui.info "Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"
94
91
 
92
+ configured_uri = configured_uri_for(uri).to_s
93
+
95
94
  unless path.exist?
96
95
  SharedHelpers.filesystem_access(path.dirname) do |p|
97
96
  FileUtils.mkdir_p(p)
98
97
  end
99
- git_retry %(clone #{uri_escaped_with_configured_credentials} "#{path}" --bare --no-hardlinks --quiet)
98
+ git_retry "clone", "--bare", "--no-hardlinks", "--quiet", "--", configured_uri, path.to_s
100
99
  return unless extra_ref
101
100
  end
102
101
 
103
102
  with_path do
104
- git_retry %(fetch --force --quiet --tags #{uri_escaped_with_configured_credentials} "refs/heads/*:refs/heads/*" #{extra_ref}), :dir => path
103
+ git_retry(*["fetch", "--force", "--quiet", "--tags", "--", configured_uri, "refs/heads/*:refs/heads/*", extra_ref].compact, :dir => path)
105
104
  end
106
105
  end
107
106
 
@@ -115,7 +114,7 @@ module Bundler
115
114
  SharedHelpers.filesystem_access(destination) do |p|
116
115
  FileUtils.rm_rf(p)
117
116
  end
118
- git_retry %(clone --no-checkout --quiet "#{path}" "#{destination}")
117
+ git_retry "clone", "--no-checkout", "--quiet", path.to_s, destination.to_s
119
118
  File.chmod(((File.stat(destination).mode | 0o777) & ~File.umask), destination)
120
119
  rescue Errno::EEXIST => e
121
120
  file_path = e.message[%r{.*?((?:[a-zA-Z]:)?/.*)}, 1]
@@ -125,56 +124,59 @@ module Bundler
125
124
  end
126
125
  end
127
126
  # method 2
128
- git_retry %(fetch --force --quiet --tags "#{path}"), :dir => destination
127
+ git_retry "fetch", "--force", "--quiet", "--tags", path.to_s, :dir => destination
129
128
 
130
129
  begin
131
- git "reset --hard #{@revision}", :dir => destination
130
+ git "reset", "--hard", @revision, :dir => destination
132
131
  rescue GitCommandError => e
133
- raise MissingGitRevisionError.new(e.command, path, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri))
132
+ raise MissingGitRevisionError.new(e.command, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri))
134
133
  end
135
134
 
136
135
  if submodules
137
- git_retry "submodule update --init --recursive", :dir => destination
136
+ git_retry "submodule", "update", "--init", "--recursive", :dir => destination
138
137
  elsif Gem::Version.create(version) >= Gem::Version.create("2.9.0")
139
138
  inner_command = "git -C $toplevel submodule deinit --force $sm_path"
140
- inner_command = inner_command.gsub("$") { '\$' } unless Bundler::WINDOWS
141
- git_retry "submodule foreach --quiet \"#{inner_command}\"", :dir => destination
139
+ git_retry "submodule", "foreach", "--quiet", inner_command, :dir => destination
142
140
  end
143
141
  end
144
142
 
145
143
  private
146
144
 
147
- def git_null(command, dir: SharedHelpers.pwd)
145
+ def git_null(*command, dir: nil)
148
146
  check_allowed(command)
149
147
 
150
148
  out, status = SharedHelpers.with_clean_git_env do
151
- capture_and_ignore_stderr("git #{command}", :chdir => dir.to_s)
149
+ capture_and_ignore_stderr(*capture3_args_for(command, dir))
152
150
  end
153
151
 
154
152
  [URICredentialsFilter.credential_filtered_string(out, uri), status]
155
153
  end
156
154
 
157
- def git_retry(command, dir: SharedHelpers.pwd)
158
- Bundler::Retry.new("`git #{URICredentialsFilter.credential_filtered_string(command, uri)}`", GitNotAllowedError).attempts do
159
- git(command, :dir => dir)
155
+ def git_retry(*command, dir: nil)
156
+ command_with_no_credentials = check_allowed(command)
157
+
158
+ Bundler::Retry.new("`#{command_with_no_credentials}` at #{dir || SharedHelpers.pwd}").attempts do
159
+ git(*command, :dir => dir)
160
160
  end
161
161
  end
162
162
 
163
- def git(command, dir: SharedHelpers.pwd)
163
+ def git(*command, dir: nil)
164
164
  command_with_no_credentials = check_allowed(command)
165
165
 
166
166
  out, status = SharedHelpers.with_clean_git_env do
167
- capture_and_filter_stderr(uri, "git #{command}", :chdir => dir.to_s)
167
+ capture_and_filter_stderr(*capture3_args_for(command, dir))
168
168
  end
169
169
 
170
- raise GitCommandError.new(command_with_no_credentials, path, dir) unless status.success?
170
+ filtered_out = URICredentialsFilter.credential_filtered_string(out, uri)
171
+
172
+ raise GitCommandError.new(command_with_no_credentials, dir || SharedHelpers.pwd, filtered_out) unless status.success?
171
173
 
172
- URICredentialsFilter.credential_filtered_string(out, uri)
174
+ filtered_out
173
175
  end
174
176
 
175
177
  def has_revision_cached?
176
178
  return unless @revision
177
- with_path { git("cat-file -e #{@revision}", :dir => path) }
179
+ with_path { git("cat-file", "-e", @revision, :dir => path) }
178
180
  true
179
181
  rescue GitError
180
182
  false
@@ -186,24 +188,10 @@ module Bundler
186
188
 
187
189
  def find_local_revision
188
190
  allowed_with_path do
189
- git("rev-parse --verify #{Shellwords.shellescape(ref)}", :dir => path).strip
191
+ git("rev-parse", "--verify", ref || "HEAD", :dir => path).strip
190
192
  end
191
193
  rescue GitCommandError => e
192
- raise MissingGitRevisionError.new(e.command, path, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
193
- end
194
-
195
- # Escape the URI for git commands
196
- def uri_escaped_with_configured_credentials
197
- remote = configured_uri_for(uri)
198
- if Bundler::WINDOWS
199
- # Windows quoting requires double quotes only, with double quotes
200
- # inside the string escaped by being doubled.
201
- '"' + remote.gsub('"') { '""' } + '"'
202
- else
203
- # Bash requires single quoted strings, with the single quotes escaped
204
- # by ending the string, escaping the quote, and restarting the string.
205
- "'" + remote.gsub("'") { "'\\''" } + "'"
206
- end
194
+ raise MissingGitRevisionError.new(e.command, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
207
195
  end
208
196
 
209
197
  # Adds credentials to the URI as Fetcher#configured_uri_for does
@@ -219,7 +207,11 @@ module Bundler
219
207
  end
220
208
 
221
209
  def allow?
222
- @git ? @git.allow_git_ops? : true
210
+ allowed = @git ? @git.allow_git_ops? : true
211
+
212
+ raise GitNotInstalledError.new if allowed && !Bundler.git_present?
213
+
214
+ allowed
223
215
  end
224
216
 
225
217
  def with_path(&blk)
@@ -233,23 +225,38 @@ module Bundler
233
225
  end
234
226
 
235
227
  def check_allowed(command)
236
- command_with_no_credentials = URICredentialsFilter.credential_filtered_string(command, uri)
228
+ require "shellwords"
229
+ command_with_no_credentials = URICredentialsFilter.credential_filtered_string("git #{command.shelljoin}", uri)
237
230
  raise GitNotAllowedError.new(command_with_no_credentials) unless allow?
238
231
  command_with_no_credentials
239
232
  end
240
233
 
241
- def capture_and_filter_stderr(uri, cmd, chdir: SharedHelpers.pwd)
234
+ def capture_and_filter_stderr(*cmd)
242
235
  require "open3"
243
- return_value, captured_err, status = Open3.capture3(cmd, :chdir => chdir)
244
- Bundler.ui.warn URICredentialsFilter.credential_filtered_string(captured_err, uri) if uri && !captured_err.empty?
236
+ return_value, captured_err, status = Open3.capture3(*cmd)
237
+ Bundler.ui.warn URICredentialsFilter.credential_filtered_string(captured_err, uri) unless captured_err.empty?
245
238
  [return_value, status]
246
239
  end
247
240
 
248
- def capture_and_ignore_stderr(cmd, chdir: SharedHelpers.pwd)
241
+ def capture_and_ignore_stderr(*cmd)
249
242
  require "open3"
250
- return_value, _, status = Open3.capture3(cmd, :chdir => chdir)
243
+ return_value, _, status = Open3.capture3(*cmd)
251
244
  [return_value, status]
252
245
  end
246
+
247
+ def capture3_args_for(cmd, dir)
248
+ return ["git", *cmd] unless dir
249
+
250
+ if Bundler.feature_flag.bundler_3_mode? || supports_minus_c?
251
+ ["git", "-C", dir.to_s, *cmd]
252
+ else
253
+ ["git", *cmd, { :chdir => dir.to_s }]
254
+ end
255
+ end
256
+
257
+ def supports_minus_c?
258
+ @supports_minus_c ||= Gem::Version.new(version) >= Gem::Version.new("1.8.5")
259
+ end
253
260
  end
254
261
  end
255
262
  end