bundler 2.3.14 → 2.3.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64817a3760b34f35e53aea5e788049373a97d786d75921aa67fbd6a676eb5bcb
4
- data.tar.gz: 584ecd0d1b0a738a7de9e95f9cdbfef0ca3e8ac00f2a928fd5e23b4777b073e7
3
+ metadata.gz: 364d4bc2c2c1f342aa034417b9e30074317878931bf34e90ddf6c42d3ae539c2
4
+ data.tar.gz: dad782afd5246e703b67d004c7282a89132f0ebe699d8e8306387fb8db179193
5
5
  SHA512:
6
- metadata.gz: 5397e12203b667c6870f7ee605c7ad2b43c31af5716c45c2376577cc5a2a2be93b1e48ae36eab6e23f7b49e1942a21d9e8c3c04d2ea8d18606fd3e4ea2b4f1ac
7
- data.tar.gz: 1db7fcf817b82739a0b6867e532705fec37e82b571103b9e2b688374f208f4d5ce9e9daad3bdd0062abddfb9025190953535c100c3365c0b3109e993efdb1ea6
6
+ metadata.gz: 463cc7534f4164ae4d2e4c67d1ed57dcc9a40494c496f0b06e11ac8f2b3599ea0dbc74be8772a98abb2d09c119db2da8f1d85cde6bafe83319051de3e24a46f2
7
+ data.tar.gz: 61b997e77634dc3a7d812adb805f899bb8bbae48bd25aad2884906c818d21853e76fd0db8bfbd95ee79689c25567e346e9c468fbe1321768c2614518f0e78356
data/CHANGELOG.md CHANGED
@@ -1,3 +1,49 @@
1
+ # 2.3.17 (June 29, 2022)
2
+
3
+ ## Enhancements:
4
+
5
+ - Add support for platform `:x64_mingw` to correctly lookup "x64-mingw-ucrt" [#5649](https://github.com/rubygems/rubygems/pull/5649)
6
+ - Fix some errors being printed twice in `--verbose` mode [#5654](https://github.com/rubygems/rubygems/pull/5654)
7
+ - Fix extension paths in generated standalone script [#5632](https://github.com/rubygems/rubygems/pull/5632)
8
+
9
+ ## Bug fixes:
10
+
11
+ - Raise if ruby platform is forced and there are no ruby variants [#5495](https://github.com/rubygems/rubygems/pull/5495)
12
+ - Fix `bundle package --no-install` no longer skipping install [#5639](https://github.com/rubygems/rubygems/pull/5639)
13
+
14
+ ## Performance:
15
+
16
+ - Improve performance of `Bundler::SpecSet#for` by using hash lookup of handled deps [#5537](https://github.com/rubygems/rubygems/pull/5537)
17
+
18
+ ## Documentation:
19
+
20
+ - Fix formatting issue in `bundle add` man page [#5642](https://github.com/rubygems/rubygems/pull/5642)
21
+
22
+ # 2.3.16 (June 15, 2022)
23
+
24
+ ## Performance:
25
+
26
+ - Improve performance of installing gems from gem server sources [#5614](https://github.com/rubygems/rubygems/pull/5614)
27
+
28
+ # 2.3.15 (June 1, 2022)
29
+
30
+ ## Enhancements:
31
+
32
+ - Show better error when previous installation fails to be removed [#5564](https://github.com/rubygems/rubygems/pull/5564)
33
+ - Show exception cause in bug report template [#5563](https://github.com/rubygems/rubygems/pull/5563)
34
+
35
+ ## Bug fixes:
36
+
37
+ - Fix `bundle remove` by invalidating cached `Bundle.definition` [#5443](https://github.com/rubygems/rubygems/pull/5443)
38
+ - Fix generated standalone script when it includes default gems [#5586](https://github.com/rubygems/rubygems/pull/5586)
39
+ - Skip duplicated dependency warning for gemspec dev deps [#5587](https://github.com/rubygems/rubygems/pull/5587)
40
+ - Give better conflict resolution advice [#5581](https://github.com/rubygems/rubygems/pull/5581)
41
+ - Fix crash when commenting out a mirror in configuration [#5576](https://github.com/rubygems/rubygems/pull/5576)
42
+ - Fix crash when installing gems with symlinks [#5570](https://github.com/rubygems/rubygems/pull/5570)
43
+ - Ignore `Errno::EROFS` errors when creating `bundler.lock` [#5580](https://github.com/rubygems/rubygems/pull/5580)
44
+ - Ignore `Errno::EPERM` errors when creating `bundler.lock` [#5579](https://github.com/rubygems/rubygems/pull/5579)
45
+ - Fix crash when printing resolution conflicts on metadata requirements [#5562](https://github.com/rubygems/rubygems/pull/5562)
46
+
1
47
  # 2.3.14 (May 18, 2022)
2
48
 
3
49
  ## Bug fixes:
@@ -4,8 +4,8 @@ module Bundler
4
4
  # Represents metadata from when the Bundler gem was built.
5
5
  module BuildMetadata
6
6
  # begin ivars
7
- @built_at = "2022-05-18".freeze
8
- @git_commit_sha = "467ad58a7c".freeze
7
+ @built_at = "2022-06-29".freeze
8
+ @git_commit_sha = "539b20c172".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -78,7 +78,7 @@ module Bundler
78
78
  end
79
79
 
80
80
  def x64_mingw?
81
- Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64"
81
+ Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os.start_with?("mingw") && Bundler.local_platform.cpu == "x64"
82
82
  end
83
83
 
84
84
  (KNOWN_MINOR_VERSIONS + KNOWN_MAJOR_VERSIONS).each do |version|
@@ -255,20 +255,18 @@ module Bundler
255
255
  #
256
256
  # @return [SpecSet] resolved dependencies
257
257
  def resolve
258
- @resolve ||= begin
259
- if Bundler.frozen_bundle?
260
- Bundler.ui.debug "Frozen, using resolution from the lockfile"
261
- @locked_specs
262
- elsif !unlocking? && nothing_changed?
263
- Bundler.ui.debug("Found no changes, using resolution from the lockfile")
264
- SpecSet.new(filter_specs(@locked_specs, @dependencies.select {|dep| @locked_specs[dep].any? }))
265
- else
266
- last_resolve = converge_locked_specs
267
- # Run a resolve against the locally available gems
268
- Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
269
- expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, true)
270
- Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
271
- end
258
+ @resolve ||= if Bundler.frozen_bundle?
259
+ Bundler.ui.debug "Frozen, using resolution from the lockfile"
260
+ @locked_specs
261
+ elsif !unlocking? && nothing_changed?
262
+ Bundler.ui.debug("Found no changes, using resolution from the lockfile")
263
+ SpecSet.new(filter_specs(@locked_specs, @dependencies.select {|dep| @locked_specs[dep].any? }))
264
+ else
265
+ last_resolve = converge_locked_specs
266
+ # Run a resolve against the locally available gems
267
+ Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
268
+ expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, true)
269
+ Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
272
270
  end
273
271
  end
274
272
 
@@ -735,12 +733,10 @@ module Bundler
735
733
  end
736
734
 
737
735
  def metadata_dependencies
738
- @metadata_dependencies ||= begin
739
- [
740
- Dependency.new("Ruby\0", RubyVersion.system.gem_version),
741
- Dependency.new("RubyGems\0", Gem::VERSION),
742
- ]
743
- end
736
+ @metadata_dependencies ||= [
737
+ Dependency.new("Ruby\0", RubyVersion.system.gem_version),
738
+ Dependency.new("RubyGems\0", Gem::VERSION),
739
+ ]
744
740
  end
745
741
 
746
742
  def expand_dependencies(dependencies, remote = false)
@@ -9,6 +9,7 @@ module Bundler
9
9
  attr_reader :autorequire
10
10
  attr_reader :groups, :platforms, :gemfile, :git, :github, :branch, :ref
11
11
 
12
+ # rubocop:disable Naming/VariableNumber
12
13
  PLATFORM_MAP = {
13
14
  :ruby => Gem::Platform::RUBY,
14
15
  :ruby_18 => Gem::Platform::RUBY,
@@ -91,6 +92,7 @@ module Bundler
91
92
  :x64_mingw_30 => Gem::Platform::X64_MINGW,
92
93
  :x64_mingw_31 => Gem::Platform::X64_MINGW,
93
94
  }.freeze
95
+ # rubocop:enable Naming/VariableNumber
94
96
 
95
97
  def initialize(name, version, options = {}, &blk)
96
98
  type = options["type"] || :runtime
@@ -120,7 +122,7 @@ module Bundler
120
122
  end
121
123
 
122
124
  def expanded_platforms
123
- @expanded_platforms ||= @platforms.map {|pl| PLATFORM_MAP[pl] }.compact.uniq
125
+ @expanded_platforms ||= @platforms.map {|pl| PLATFORM_MAP[pl] }.compact.flatten.uniq
124
126
  end
125
127
 
126
128
  def should_include?
data/lib/bundler/dsl.rb CHANGED
@@ -124,19 +124,17 @@ module Bundler
124
124
  raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \
125
125
  "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \
126
126
  "#{update_prompt}"
127
+ elsif current.source != dep.source
128
+ return if dep.type == :development
129
+ raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
130
+ "You specified that #{dep.name} (#{dep.requirement}) should come from " \
131
+ "#{current.source || "an unspecified source"} and #{dep.source}\n"
127
132
  else
128
133
  Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \
129
134
  "You should probably keep only one of them.\n" \
130
135
  "Remove any duplicate entries and specify the gem only once.\n" \
131
136
  "While it's not a problem now, it could cause errors if you change the version of one of them later."
132
137
  end
133
-
134
- if current.source != dep.source
135
- return if dep.type == :development
136
- raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
137
- "You specified that #{dep.name} (#{dep.requirement}) should come from " \
138
- "#{current.source || "an unspecified source"} and #{dep.source}\n"
139
- end
140
138
  end
141
139
  end
142
140
 
@@ -513,9 +511,7 @@ module Bundler
513
511
  # be raised.
514
512
  #
515
513
  def contents
516
- @contents ||= begin
517
- dsl_path && File.exist?(dsl_path) && File.read(dsl_path)
518
- end
514
+ @contents ||= dsl_path && File.exist?(dsl_path) && File.read(dsl_path)
519
515
  end
520
516
 
521
517
  # The message of the exception reports the content of podspec for the
@@ -41,12 +41,14 @@ module Bundler
41
41
  class GemspecError < BundlerError; status_code(14); end
42
42
  class InvalidOption < BundlerError; status_code(15); end
43
43
  class ProductionError < BundlerError; status_code(16); end
44
+
44
45
  class HTTPError < BundlerError
45
46
  status_code(17)
46
47
  def filter_uri(uri)
47
48
  URICredentialsFilter.credential_filtered_uri(uri)
48
49
  end
49
50
  end
51
+
50
52
  class RubyVersionMismatch < BundlerError; status_code(18); end
51
53
  class SecurityError < BundlerError; status_code(19); end
52
54
  class LockfileError < BundlerError; status_code(20); end
@@ -79,10 +81,6 @@ module Bundler
79
81
  case @permission_type
80
82
  when :create
81
83
  "executable permissions for all parent directories and write permissions for `#{parent_folder}`"
82
- when :delete
83
- permissions = "executable permissions for all parent directories and write permissions for `#{parent_folder}`"
84
- permissions += ", and the same thing for all subdirectories inside #{@path}" if File.directory?(@path)
85
- permissions
86
84
  else
87
85
  "#{@permission_type} permissions for that path"
88
86
  end
@@ -172,4 +170,16 @@ module Bundler
172
170
 
173
171
  status_code(32)
174
172
  end
173
+
174
+ class DirectoryRemovalError < BundlerError
175
+ def initialize(orig_exception, msg)
176
+ full_message = "#{msg}.\n" \
177
+ "The underlying error was #{orig_exception.class}: #{orig_exception.message}, with backtrace:\n" \
178
+ " #{orig_exception.backtrace.join("\n ")}\n\n" \
179
+ "Bundler Error Backtrace:"
180
+ super(full_message)
181
+ end
182
+
183
+ status_code(36)
184
+ end
175
185
  end
@@ -19,14 +19,12 @@ module Bundler
19
19
  end
20
20
 
21
21
  def fetch_uri
22
- @fetch_uri ||= begin
23
- if remote_uri.host == "rubygems.org"
24
- uri = remote_uri.dup
25
- uri.host = "index.rubygems.org"
26
- uri
27
- else
28
- remote_uri
29
- end
22
+ @fetch_uri ||= if remote_uri.host == "rubygems.org"
23
+ uri = remote_uri.dup
24
+ uri.host = "index.rubygems.org"
25
+ uri
26
+ else
27
+ remote_uri
30
28
  end
31
29
  end
32
30
 
@@ -20,6 +20,7 @@ module Bundler
20
20
  class TooManyRequestsError < HTTPError; end
21
21
  # This error is raised if the API returns a 413 (only printed in verbose)
22
22
  class FallbackError < HTTPError; end
23
+
23
24
  # This is the error raised if OpenSSL fails the cert verification
24
25
  class CertificateFailureError < HTTPError
25
26
  def initialize(remote_uri)
@@ -33,6 +34,7 @@ module Bundler
33
34
  " sources and change 'https' to 'http'."
34
35
  end
35
36
  end
37
+
36
38
  # This is the error raised when a source is HTTPS and OpenSSL didn't load
37
39
  class SSLError < HTTPError
38
40
  def initialize(msg = nil)
@@ -42,6 +44,7 @@ module Bundler
42
44
  "using RVM are available at rvm.io/packages/openssl."
43
45
  end
44
46
  end
47
+
45
48
  # This error is raised if HTTP authentication is required, but not provided.
46
49
  class AuthenticationRequiredError < HTTPError
47
50
  def initialize(remote_uri)
@@ -52,6 +55,7 @@ module Bundler
52
55
  "or by storing the credentials in the `#{Settings.key_for(remote_uri)}` environment variable"
53
56
  end
54
57
  end
58
+
55
59
  # This error is raised if HTTP authentication is provided, but incorrect.
56
60
  class BadAuthenticationError < HTTPError
57
61
  def initialize(remote_uri)
@@ -29,8 +29,11 @@ module Bundler
29
29
  Bundler.ui.error error.message
30
30
  Bundler.ui.trace error.orig_exception
31
31
  when BundlerError
32
- Bundler.ui.error error.message, :wrap => true
33
- Bundler.ui.trace error
32
+ if Bundler.ui.debug?
33
+ Bundler.ui.trace error
34
+ else
35
+ Bundler.ui.error error.message, :wrap => true
36
+ end
34
37
  when Thor::Error
35
38
  Bundler.ui.error error.message
36
39
  when LoadError
@@ -65,8 +68,7 @@ module Bundler
65
68
  --- ERROR REPORT TEMPLATE -------------------------------------------------------
66
69
 
67
70
  ```
68
- #{e.class}: #{e.message}
69
- #{e.backtrace && e.backtrace.join("\n ").chomp}
71
+ #{exception_message(e)}
70
72
  ```
71
73
 
72
74
  #{Bundler::Env.report}
@@ -85,6 +87,21 @@ module Bundler
85
87
  EOS
86
88
  end
87
89
 
90
+ def exception_message(error)
91
+ message = serialized_exception_for(error)
92
+ cause = error.cause
93
+ return message unless cause
94
+
95
+ message + serialized_exception_for(cause)
96
+ end
97
+
98
+ def serialized_exception_for(e)
99
+ <<-EOS.gsub(/^ {8}/, "")
100
+ #{e.class}: #{e.message}
101
+ #{e.backtrace && e.backtrace.join("\n ").chomp}
102
+ EOS
103
+ end
104
+
88
105
  def issues_url(exception)
89
106
  message = exception.message.lines.first.tr(":", " ").chomp
90
107
  message = message.split("-").first if exception.is_a?(Errno)
@@ -10,6 +10,7 @@ module Bundler
10
10
  [Gem::Platform.new("universal-mingw32"), Gem::Platform.new("universal-mingw32")],
11
11
  [Gem::Platform.new("x64-mingw32"), Gem::Platform.new("x64-mingw32")],
12
12
  [Gem::Platform.new("x86_64-mingw32"), Gem::Platform.new("x64-mingw32")],
13
+ [Gem::Platform.new("x64-mingw-ucrt"), Gem::Platform.new("x64-mingw-ucrt")],
13
14
  [Gem::Platform.new("mingw32"), Gem::Platform.new("x86-mingw32")],
14
15
  ].freeze
15
16
 
data/lib/bundler/index.rb CHANGED
@@ -192,11 +192,7 @@ module Bundler
192
192
  specs += base if base
193
193
  found = specs.select do |spec|
194
194
  next true if spec.source.is_a?(Source::Gemspec)
195
- if base # allow all platforms when searching from a lockfile
196
- dependency.matches_spec?(spec)
197
- else
198
- dependency.matches_spec?(spec) && Gem::Platform.match_spec?(spec)
199
- end
195
+ dependency.matches_spec?(spec)
200
196
  end
201
197
 
202
198
  found
@@ -72,6 +72,10 @@ module Bundler
72
72
 
73
73
  deps.each {|dep| Bundler.ui.confirm "#{SharedHelpers.pretty_dependency(dep, false)} was removed." }
74
74
  end
75
+
76
+ # Invalidate the cached Bundler.definition.
77
+ # This prevents e.g. `bundle remove ...` from using outdated information.
78
+ Bundler.reset_paths!
75
79
  end
76
80
 
77
81
  private
@@ -38,12 +38,7 @@ def gemfile(install = false, options = {}, &gemfile)
38
38
  raise ArgumentError, "Unknown options: #{opts.keys.join(", ")}" unless opts.empty?
39
39
 
40
40
  begin
41
- old_root = Bundler.method(:root)
42
- bundler_module = class << Bundler; self; end
43
- bundler_module.send(:remove_method, :root)
44
- def Bundler.root
45
- Bundler::SharedHelpers.pwd.expand_path
46
- end
41
+ Bundler.instance_variable_set(:@bundle_path, Pathname.new(Gem.dir))
47
42
  old_gemfile = ENV["BUNDLE_GEMFILE"]
48
43
  Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", "Gemfile"
49
44
 
@@ -71,11 +66,6 @@ def gemfile(install = false, options = {}, &gemfile)
71
66
  runtime.setup.require
72
67
  end
73
68
  ensure
74
- if bundler_module
75
- bundler_module.send(:remove_method, :root)
76
- bundler_module.send(:define_method, :root, old_root)
77
- end
78
-
79
69
  if old_gemfile
80
70
  ENV["BUNDLE_GEMFILE"] = old_gemfile
81
71
  else
@@ -12,6 +12,7 @@ module Bundler
12
12
  end
13
13
  File.open File.join(bundler_path, "setup.rb"), "w" do |file|
14
14
  file.puts "require 'rbconfig'"
15
+ file.puts define_path_helpers
15
16
  file.puts reverse_rubygems_kernel_mixin
16
17
  paths.each do |path|
17
18
  if Pathname.new(path).absolute?
@@ -29,14 +30,20 @@ module Bundler
29
30
  @specs.map do |spec|
30
31
  next if spec.name == "bundler"
31
32
  Array(spec.require_paths).map do |path|
32
- gem_path(path, spec).sub(version_dir, '#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}')
33
+ gem_path(path, spec).
34
+ sub(version_dir, '#{RUBY_ENGINE}/#{Gem.ruby_api_version}').
35
+ sub(extensions_dir, 'extensions/\k<platform>/#{Gem.extension_api_version}')
33
36
  # This is a static string intentionally. It's interpolated at a later time.
34
37
  end
35
38
  end.flatten.compact
36
39
  end
37
40
 
38
41
  def version_dir
39
- "#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}"
42
+ "#{RUBY_ENGINE}/#{Gem.ruby_api_version}"
43
+ end
44
+
45
+ def extensions_dir
46
+ %r{extensions/(?<platform>[^/]+)/#{Regexp.escape(Gem.extension_api_version)}}
40
47
  end
41
48
 
42
49
  def bundler_path
@@ -55,6 +62,26 @@ module Bundler
55
62
  raise Gem::InvalidSpecificationException.new(error_message)
56
63
  end
57
64
 
65
+ def define_path_helpers
66
+ <<~'END'
67
+ unless defined?(Gem)
68
+ module Gem
69
+ def self.ruby_api_version
70
+ RbConfig::CONFIG["ruby_version"]
71
+ end
72
+
73
+ def self.extension_api_version
74
+ if 'no' == RbConfig::CONFIG['ENABLE_SHARED']
75
+ "#{ruby_api_version}-static"
76
+ else
77
+ ruby_api_version
78
+ end
79
+ end
80
+ end
81
+ end
82
+ END
83
+ end
84
+
58
85
  def reverse_rubygems_kernel_mixin
59
86
  <<~END
60
87
  kernel = (class << ::Kernel; self; end)
@@ -66,7 +66,7 @@ module Bundler
66
66
  # require paths and save them in a `setup.rb` file. See `bundle standalone --help` for more
67
67
  # information.
68
68
  def run(options)
69
- create_bundle_path
69
+ Bundler.create_bundle_path
70
70
 
71
71
  ProcessLock.lock do
72
72
  if Bundler.frozen_bundle?
@@ -262,15 +262,6 @@ module Bundler
262
262
  end
263
263
  end
264
264
 
265
- def create_bundle_path
266
- SharedHelpers.filesystem_access(Bundler.bundle_path.to_s) do |p|
267
- Bundler.mkdir_p(p)
268
- end unless Bundler.bundle_path.exist?
269
- rescue Errno::EEXIST
270
- raise PathError, "Could not install to path `#{Bundler.bundle_path}` " \
271
- "because a file already exists at that path. Either remove or rename the file so the directory can be created."
272
- end
273
-
274
265
  # returns whether or not a re-resolve was needed
275
266
  def resolve_if_needed(options)
276
267
  if !@definition.unlocking? && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
@@ -84,7 +84,7 @@ module Bundler
84
84
  else
85
85
  ruby_platform_materializes_to_ruby_platform? ? self : Dependency.new(name, version)
86
86
  end
87
- platform_object = Gem::Platform.new(platform)
87
+ platform_object = ruby_platform_materializes_to_ruby_platform? ? Gem::Platform.new(platform) : Gem::Platform.local
88
88
  candidates = source.specs.search(search_object)
89
89
  same_platform_candidates = candidates.select do |spec|
90
90
  MatchPlatform.platforms_match?(spec.platform, platform_object)
@@ -152,7 +152,7 @@ module Bundler
152
152
  # explicitly add a more specific platform.
153
153
  #
154
154
  def ruby_platform_materializes_to_ruby_platform?
155
- !Bundler.most_specific_locked_platform?(Gem::Platform::RUBY) || Bundler.settings[:force_ruby_platform]
155
+ !Bundler.most_specific_locked_platform?(generic_local_platform) || Bundler.settings[:force_ruby_platform]
156
156
  end
157
157
  end
158
158
  end
@@ -41,7 +41,7 @@ Specify version requirements(s) for the added gem\.
41
41
  Specify the group(s) for the added gem\. Multiple groups should be separated by commas\.
42
42
  .
43
43
  .TP
44
- \fB\-\-source\fR, , \fB\-s\fR
44
+ \fB\-\-source\fR, \fB\-s\fR
45
45
  Specify the source for the added gem\.
46
46
  .
47
47
  .TP
@@ -27,7 +27,7 @@ bundle add rails --group "development, test"
27
27
  * `--group`, `-g`:
28
28
  Specify the group(s) for the added gem. Multiple groups should be separated by commas.
29
29
 
30
- * `--source`, , `-s`:
30
+ * `--source`, `-s`:
31
31
  Specify the source for the added gem.
32
32
 
33
33
  * `--require`, `-r`:
@@ -15,7 +15,6 @@ module Bundler
15
15
  return true if Gem::Platform::RUBY == gemspec_platform
16
16
  return true if local_platform == gemspec_platform
17
17
  gemspec_platform = Gem::Platform.new(gemspec_platform)
18
- return true if GemHelpers.generic(gemspec_platform) === local_platform
19
18
  return true if gemspec_platform === local_platform
20
19
 
21
20
  false
@@ -258,7 +258,7 @@ module Bundler
258
258
  @dependencies |= Array(names)
259
259
  end
260
260
 
261
- # Note: Do not override if you don't know what you are doing.
261
+ # NOTE: Do not override if you don't know what you are doing.
262
262
  def can_lock?(spec)
263
263
  spec.source == self
264
264
  end
@@ -285,7 +285,7 @@ module Bundler
285
285
  end
286
286
  alias_method :identifier, :to_s
287
287
 
288
- # Note: Do not override if you don't know what you are doing.
288
+ # NOTE: Do not override if you don't know what you are doing.
289
289
  def include?(other)
290
290
  other == self
291
291
  end
@@ -294,7 +294,7 @@ module Bundler
294
294
  SharedHelpers.digest(:SHA1).hexdigest(uri)
295
295
  end
296
296
 
297
- # Note: Do not override if you don't know what you are doing.
297
+ # NOTE: Do not override if you don't know what you are doing.
298
298
  def gem_install_dir
299
299
  Bundler.install_path
300
300
  end
@@ -12,7 +12,7 @@ module Bundler
12
12
  yield
13
13
  f.flock(File::LOCK_UN)
14
14
  end
15
- rescue Errno::EACCES, Errno::ENOLCK, Errno::ENOTSUP
15
+ rescue Errno::EACCES, Errno::ENOLCK, Errno::ENOTSUP, Errno::EPERM, Errno::EROFS
16
16
  # In the case the user does not have access to
17
17
  # create the lock file or is using NFS where
18
18
  # locks are not available we skip locking.
@@ -19,13 +19,15 @@ module Bundler
19
19
  # collection of gemspecs is returned. Otherwise, nil is returned.
20
20
  def self.resolve(requirements, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
21
21
  base = SpecSet.new(base) unless base.is_a?(SpecSet)
22
- resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
22
+ metadata_requirements, regular_requirements = requirements.partition {|dep| dep.name.end_with?("\0") }
23
+ resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms, metadata_requirements)
23
24
  result = resolver.start(requirements)
24
- SpecSet.new(SpecSet.new(result).for(requirements.reject {|dep| dep.name.end_with?("\0") }))
25
+ SpecSet.new(SpecSet.new(result).for(regular_requirements))
25
26
  end
26
27
 
27
- def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
28
+ def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms, metadata_requirements)
28
29
  @source_requirements = source_requirements
30
+ @metadata_requirements = metadata_requirements
29
31
  @base = base
30
32
  @resolver = Molinillo::Resolver.new(self, self)
31
33
  @search_for = {}
@@ -231,19 +233,17 @@ module Bundler
231
233
  # before dependencies that are unconstrained
232
234
  def amount_constrained(dependency)
233
235
  @amount_constrained ||= {}
234
- @amount_constrained[dependency.name] ||= begin
235
- if (base = @base[dependency.name]) && !base.empty?
236
- dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1
237
- else
238
- all = index_for(dependency).search(dependency.name).size
236
+ @amount_constrained[dependency.name] ||= if (base = @base[dependency.name]) && !base.empty?
237
+ dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1
238
+ else
239
+ all = index_for(dependency).search(dependency.name).size
239
240
 
240
- if all <= 1
241
- all - 1_000_000
242
- else
243
- search = search_for(dependency)
244
- search = @prerelease_specified[dependency.name] ? search.count : search.count {|s| !s.version.prerelease? }
245
- search - all
246
- end
241
+ if all <= 1
242
+ all - 1_000_000
243
+ else
244
+ search = search_for(dependency)
245
+ search = @prerelease_specified[dependency.name] ? search.count : search.count {|s| !s.version.prerelease? }
246
+ search - all
247
247
  end
248
248
  end
249
249
  end
@@ -284,7 +284,7 @@ module Bundler
284
284
  if specs_matching_requirement.any?
285
285
  specs = specs_matching_requirement
286
286
  matching_part = requirement_label
287
- requirement_label = "#{requirement_label} #{requirement.__platform}"
287
+ requirement_label = "#{requirement_label}' with platform '#{requirement.__platform}"
288
288
  end
289
289
 
290
290
  message = String.new("Could not find gem '#{requirement_label}'#{extra_message} in #{source}#{cache_message}.\n")
@@ -344,8 +344,6 @@ module Bundler
344
344
  trees.sort_by! {|t| t.reverse.map(&:name) }
345
345
  end
346
346
 
347
- metadata_requirements = {}
348
-
349
347
  o << trees.map do |tree|
350
348
  t = "".dup
351
349
  depth = 2
@@ -354,7 +352,6 @@ module Bundler
354
352
  base_tree_name = base_tree.name
355
353
 
356
354
  if base_tree_name.end_with?("\0")
357
- metadata_requirements[base_tree_name] = base_tree
358
355
  t = nil
359
356
  else
360
357
  tree.each do |req|
@@ -393,10 +390,10 @@ module Bundler
393
390
  end
394
391
  end
395
392
  elsif name.end_with?("\0")
396
- o << %(\n Current #{name} version:\n #{SharedHelpers.pretty_dependency(metadata_requirements[name])}\n\n)
393
+ o << %(\n Current #{name} version:\n #{SharedHelpers.pretty_dependency(@metadata_requirements.find {|req| req.name == name })}\n\n)
397
394
  elsif conflict.locked_requirement
398
395
  o << "\n"
399
- o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
396
+ o << %(Deleting your #{name_for_locking_dependency_source} file and running `bundle install` will rebuild your snapshot from scratch, using only\n)
400
397
  o << %(the gems in your Gemfile, which may resolve the conflict.\n)
401
398
  elsif !conflict.existing
402
399
  o << "\n"
@@ -216,11 +216,12 @@ module Gem
216
216
  require "rubygems/platform"
217
217
 
218
218
  class Platform
219
- JAVA = Gem::Platform.new("java") unless defined?(JAVA)
220
- MSWIN = Gem::Platform.new("mswin32") unless defined?(MSWIN)
221
- MSWIN64 = Gem::Platform.new("mswin64") unless defined?(MSWIN64)
222
- MINGW = Gem::Platform.new("x86-mingw32") unless defined?(MINGW)
223
- X64_MINGW = Gem::Platform.new("x64-mingw32") unless defined?(X64_MINGW)
219
+ JAVA = Gem::Platform.new("java")
220
+ MSWIN = Gem::Platform.new("mswin32")
221
+ MSWIN64 = Gem::Platform.new("mswin64")
222
+ MINGW = Gem::Platform.new("x86-mingw32")
223
+ X64_MINGW = [Gem::Platform.new("x64-mingw32"),
224
+ Gem::Platform.new("x64-mingw-ucrt")].freeze
224
225
  end
225
226
 
226
227
  Platform.singleton_class.module_eval do
@@ -90,17 +90,20 @@ module Bundler
90
90
  end
91
91
  end
92
92
 
93
+ def spec
94
+ if Bundler.rubygems.provides?("< 3.3.12") # RubyGems implementation rescues and re-raises errors before 3.3.12 and we don't want that
95
+ @package.spec
96
+ else
97
+ super
98
+ end
99
+ end
100
+
93
101
  private
94
102
 
95
103
  def strict_rm_rf(dir)
96
- # FileUtils.rm_rf should probably rise in case of permission issues like
97
- # `rm -rf` does. However, it fails to delete the folder silently due to
98
- # https://github.com/ruby/fileutils/issues/57. It should probably be fixed
99
- # inside `fileutils` but for now I`m checking whether the folder was
100
- # removed after it completes, and raising otherwise.
101
- FileUtils.rm_rf dir
102
-
103
- raise PermissionError.new(dir, :delete) if File.directory?(dir)
104
+ Bundler.rm_rf dir
105
+ rescue Errno::ENOTEMPTY => e
106
+ raise DirectoryRemovalError.new(e.cause, "Could not delete previous installation of `#{dir}`")
104
107
  end
105
108
 
106
109
  def validate_bundler_checksum(checksum)
@@ -203,20 +203,9 @@ module Bundler
203
203
  EXT_LOCK
204
204
  end
205
205
 
206
- def spec_from_gem(path, policy = nil)
207
- require "rubygems/security"
208
- require "psych"
209
- gem_from_path(path, security_policies[policy]).spec
210
- rescue Exception, Gem::Exception, Gem::Security::Exception => e # rubocop:disable Lint/RescueException
211
- if e.is_a?(Gem::Security::Exception) ||
212
- e.message =~ /unknown trust policy|unsigned gem/i ||
213
- e.message =~ /couldn't verify (meta)?data signature/i
214
- raise SecurityError,
215
- "The gem #{File.basename(path, ".gem")} can't be installed because " \
216
- "the security policy didn't allow it, with the message: #{e.message}"
217
- else
218
- raise e
219
- end
206
+ def spec_from_gem(path)
207
+ require "rubygems/package"
208
+ Gem::Package.new(path).spec
220
209
  end
221
210
 
222
211
  def build_gem(gem_dir, spec)
@@ -514,13 +503,6 @@ module Bundler
514
503
  Gem::RemoteFetcher.new(proxy)
515
504
  end
516
505
 
517
- def gem_from_path(path, policy = nil)
518
- require "rubygems/package"
519
- p = Gem::Package.new(path)
520
- p.security_policy = policy if policy
521
- p
522
- end
523
-
524
506
  def build(spec, skip_validation = false)
525
507
  require "rubygems/package"
526
508
  Gem::Package.build(spec, skip_validation)
@@ -487,7 +487,7 @@ module Bundler
487
487
  /ix.freeze
488
488
 
489
489
  def self.key_for(key)
490
- key = normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key
490
+ key = normalize_uri(key).to_s if key.is_a?(String) && key.start_with?("http", "mirror.http")
491
491
  key = key.to_s.gsub(".", "__").gsub("-", "___").upcase
492
492
  "BUNDLE_#{key}"
493
493
  end
@@ -219,13 +219,11 @@ module Bundler
219
219
  # across different projects, this cache will be shared.
220
220
  # When using local git repos, this is set to the local repo.
221
221
  def cache_path
222
- @cache_path ||= begin
223
- if Bundler.requires_sudo? || Bundler.feature_flag.global_gem_cache?
224
- Bundler.user_cache
225
- else
226
- Bundler.bundle_path.join("cache", "bundler")
227
- end.join("git", git_scope)
228
- end
222
+ @cache_path ||= if Bundler.requires_sudo? || Bundler.feature_flag.global_gem_cache?
223
+ Bundler.user_cache
224
+ else
225
+ Bundler.bundle_path.join("cache", "bundler")
226
+ end.join("git", git_scope)
229
227
  end
230
228
 
231
229
  def app_cache_dirname
@@ -139,13 +139,9 @@ module Bundler
139
139
  force = options[:force]
140
140
  ensure_builtin_gems_cached = options[:ensure_builtin_gems_cached]
141
141
 
142
- if ensure_builtin_gems_cached && spec.default_gem?
143
- if !cached_path(spec)
144
- cached_built_in_gem(spec) unless spec.remote
145
- force = true
146
- else
147
- spec.loaded_from = loaded_from(spec)
148
- end
142
+ if ensure_builtin_gems_cached && spec.default_gem? && !cached_path(spec)
143
+ cached_built_in_gem(spec) unless spec.remote
144
+ force = true
149
145
  end
150
146
 
151
147
  if installed?(spec) && !force
@@ -153,84 +149,92 @@ module Bundler
153
149
  return nil # no post-install message
154
150
  end
155
151
 
156
- # Download the gem to get the spec, because some specs that are returned
157
- # by rubygems.org are broken and wrong.
158
152
  if spec.remote
159
153
  # Check for this spec from other sources
160
- uris = [spec.remote.anonymized_uri]
161
- uris += remotes_for_spec(spec).map(&:anonymized_uri)
162
- uris.uniq!
154
+ uris = [spec.remote, *remotes_for_spec(spec)].map(&:anonymized_uri).uniq
163
155
  Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1
164
156
 
165
157
  path = fetch_gem(spec, options[:previous_spec])
166
- begin
167
- s = Bundler.rubygems.spec_from_gem(path, Bundler.settings["trust-policy"])
168
- spec.__swap__(s)
158
+ else
159
+ path = cached_gem(spec)
160
+ raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
161
+ end
162
+
163
+ return if Bundler.settings[:no_install]
164
+
165
+ if requires_sudo?
166
+ install_path = Bundler.tmp(spec.full_name)
167
+ bin_path = install_path.join("bin")
168
+ else
169
+ install_path = rubygems_dir
170
+ bin_path = Bundler.system_bindir
171
+ end
172
+
173
+ Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
174
+
175
+ require_relative "../rubygems_gem_installer"
176
+
177
+ installer = Bundler::RubyGemsGemInstaller.at(
178
+ path,
179
+ :security_policy => Bundler.rubygems.security_policies[Bundler.settings["trust-policy"]],
180
+ :install_dir => install_path.to_s,
181
+ :bin_dir => bin_path.to_s,
182
+ :ignore_dependencies => true,
183
+ :wrappers => true,
184
+ :env_shebang => true,
185
+ :build_args => options[:build_args],
186
+ :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum,
187
+ :bundler_extension_cache_path => extension_cache_path(spec)
188
+ )
189
+
190
+ if spec.remote
191
+ s = begin
192
+ installer.spec
169
193
  rescue Gem::Package::FormatError
170
194
  Bundler.rm_rf(path)
171
195
  raise
196
+ rescue Gem::Security::Exception => e
197
+ raise SecurityError,
198
+ "The gem #{File.basename(path, ".gem")} can't be installed because " \
199
+ "the security policy didn't allow it, with the message: #{e.message}"
172
200
  end
201
+
202
+ spec.__swap__(s)
173
203
  end
174
204
 
175
- unless Bundler.settings[:no_install]
176
- message = "Installing #{version_message(spec, options[:previous_spec])}"
177
- message += " with native extensions" if spec.extensions.any?
178
- Bundler.ui.confirm message
205
+ message = "Installing #{version_message(spec, options[:previous_spec])}"
206
+ message += " with native extensions" if spec.extensions.any?
207
+ Bundler.ui.confirm message
179
208
 
180
- path = cached_gem(spec)
181
- raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
182
- if requires_sudo?
183
- install_path = Bundler.tmp(spec.full_name)
184
- bin_path = install_path.join("bin")
185
- else
186
- install_path = rubygems_dir
187
- bin_path = Bundler.system_bindir
188
- end
209
+ installed_spec = installer.install
189
210
 
190
- Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
191
-
192
- require_relative "../rubygems_gem_installer"
193
-
194
- installed_spec = Bundler::RubyGemsGemInstaller.at(
195
- path,
196
- :install_dir => install_path.to_s,
197
- :bin_dir => bin_path.to_s,
198
- :ignore_dependencies => true,
199
- :wrappers => true,
200
- :env_shebang => true,
201
- :build_args => options[:build_args],
202
- :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum,
203
- :bundler_extension_cache_path => extension_cache_path(spec)
204
- ).install
205
- spec.full_gem_path = installed_spec.full_gem_path
206
-
207
- # SUDO HAX
208
- if requires_sudo?
209
- Bundler.rubygems.repository_subdirectories.each do |name|
210
- src = File.join(install_path, name, "*")
211
- dst = File.join(rubygems_dir, name)
212
- if name == "extensions" && Dir.glob(src).any?
213
- src = File.join(src, "*/*")
214
- ext_src = Dir.glob(src).first
215
- ext_src.gsub!(src[0..-6], "")
216
- dst = File.dirname(File.join(dst, ext_src))
217
- end
218
- SharedHelpers.filesystem_access(dst) do |p|
219
- Bundler.mkdir_p(p)
220
- end
221
- Bundler.sudo "cp -R #{src} #{dst}" if Dir[src].any?
211
+ spec.full_gem_path = installed_spec.full_gem_path
212
+ spec.loaded_from = installed_spec.loaded_from
213
+
214
+ # SUDO HAX
215
+ if requires_sudo?
216
+ Bundler.rubygems.repository_subdirectories.each do |name|
217
+ src = File.join(install_path, name, "*")
218
+ dst = File.join(rubygems_dir, name)
219
+ if name == "extensions" && Dir.glob(src).any?
220
+ src = File.join(src, "*/*")
221
+ ext_src = Dir.glob(src).first
222
+ ext_src.gsub!(src[0..-6], "")
223
+ dst = File.dirname(File.join(dst, ext_src))
222
224
  end
225
+ SharedHelpers.filesystem_access(dst) do |p|
226
+ Bundler.mkdir_p(p)
227
+ end
228
+ Bundler.sudo "cp -R #{src} #{dst}" if Dir[src].any?
229
+ end
223
230
 
224
- spec.executables.each do |exe|
225
- SharedHelpers.filesystem_access(Bundler.system_bindir) do |p|
226
- Bundler.mkdir_p(p)
227
- end
228
- Bundler.sudo "cp -R #{install_path}/bin/#{exe} #{Bundler.system_bindir}/"
231
+ spec.executables.each do |exe|
232
+ SharedHelpers.filesystem_access(Bundler.system_bindir) do |p|
233
+ Bundler.mkdir_p(p)
229
234
  end
235
+ Bundler.sudo "cp -R #{install_path}/bin/#{exe} #{Bundler.system_bindir}/"
230
236
  end
231
- installed_spec.loaded_from = loaded_from(spec)
232
237
  end
233
- spec.loaded_from = loaded_from(spec)
234
238
 
235
239
  spec.post_install_message
236
240
  ensure
@@ -348,10 +352,6 @@ module Bundler
348
352
  end
349
353
  end
350
354
 
351
- def loaded_from(spec)
352
- "#{rubygems_dir}/specifications/#{spec.full_name}.gemspec"
353
- end
354
-
355
355
  def cached_gem(spec)
356
356
  if spec.default_gem?
357
357
  cached_built_in_gem(spec)
@@ -364,10 +364,14 @@ module Bundler
364
364
  global_cache_path = download_cache_path(spec)
365
365
  @caches << global_cache_path if global_cache_path
366
366
 
367
- possibilities = @caches.map {|p| "#{p}/#{spec.file_name}" }
367
+ possibilities = @caches.map {|p| package_path(p, spec) }
368
368
  possibilities.find {|p| File.exist?(p) }
369
369
  end
370
370
 
371
+ def package_path(cache_path, spec)
372
+ "#{cache_path}/#{spec.file_name}"
373
+ end
374
+
371
375
  def normalize_uri(uri)
372
376
  uri = uri.to_s
373
377
  uri = "#{uri}/" unless uri =~ %r{/$}
@@ -459,12 +463,11 @@ module Bundler
459
463
  end
460
464
 
461
465
  def fetch_gem(spec, previous_spec = nil)
462
- return false unless spec.remote
463
-
464
466
  spec.fetch_platform
465
467
 
466
468
  cache_path = download_cache_path(spec) || default_cache_path_for(rubygems_dir)
467
- gem_path = "#{cache_path}/#{spec.file_name}"
469
+ gem_path = package_path(cache_path, spec)
470
+ return gem_path if File.exist?(gem_path)
468
471
 
469
472
  if requires_sudo?
470
473
  download_path = Bundler.tmp(spec.full_name)
@@ -482,7 +485,7 @@ module Bundler
482
485
  SharedHelpers.filesystem_access(cache_path) do |p|
483
486
  Bundler.mkdir_p(p)
484
487
  end
485
- Bundler.sudo "mv #{download_cache_path}/#{spec.file_name} #{gem_path}"
488
+ Bundler.sudo "mv #{package_path(download_cache_path, spec)} #{gem_path}"
486
489
  end
487
490
 
488
491
  gem_path
@@ -499,7 +502,7 @@ module Bundler
499
502
  end
500
503
 
501
504
  def rubygems_dir
502
- Bundler.rubygems.gem_dir
505
+ Bundler.bundle_path
503
506
  end
504
507
 
505
508
  def default_cache_path_for(dir)
@@ -12,17 +12,19 @@ module Bundler
12
12
  end
13
13
 
14
14
  def for(dependencies, check = false, match_current_platform = false)
15
- handled = []
15
+ # dep.name => [list, of, deps]
16
+ handled = Hash.new {|h, k| h[k] = [] }
16
17
  deps = dependencies.dup
17
18
  specs = []
18
19
 
19
20
  loop do
20
21
  break unless dep = deps.shift
21
- next if handled.any? {|d| d.name == dep.name && (match_current_platform || d.__platform == dep.__platform) } || dep.name == "bundler"
22
+ next if handled[dep.name].any? {|d| match_current_platform || d.__platform == dep.__platform } || dep.name == "bundler"
22
23
 
23
- handled << dep
24
+ # use a hash here to ensure constant lookup time in the `any?` call above
25
+ handled[dep.name] << dep
24
26
 
25
- specs_for_dep = spec_for_dependency(dep, match_current_platform)
27
+ specs_for_dep = specs_for_dependency(dep, match_current_platform)
26
28
  if specs_for_dep.any?
27
29
  specs.concat(specs_for_dep)
28
30
 
@@ -171,12 +173,13 @@ module Bundler
171
173
  @specs.sort_by(&:name).each {|s| yield s }
172
174
  end
173
175
 
174
- def spec_for_dependency(dep, match_current_platform)
175
- specs_for_platforms = lookup[dep.name]
176
+ def specs_for_dependency(dep, match_current_platform)
177
+ specs_for_name = lookup[dep.name]
176
178
  if match_current_platform
177
- GemHelpers.select_best_platform_match(specs_for_platforms.select {|s| Gem::Platform.match_spec?(s) }, Bundler.local_platform)
179
+ GemHelpers.select_best_platform_match(specs_for_name.select {|s| Gem::Platform.match_spec?(s) }, Bundler.local_platform)
178
180
  else
179
- GemHelpers.select_best_platform_match(specs_for_platforms, dep.__platform)
181
+ specs_for_name_and_platform = GemHelpers.select_best_platform_match(specs_for_name, dep.__platform)
182
+ specs_for_name_and_platform.any? ? specs_for_name_and_platform : specs_for_name
180
183
  end
181
184
  end
182
185
 
@@ -64,9 +64,11 @@ module Bundler
64
64
  end
65
65
 
66
66
  def full_gem_path
67
- # deleted gems can have their stubs return nil, so in that case grab the
68
- # expired path from the full spec
69
- stub.full_gem_path || method_missing(:full_gem_path)
67
+ stub.full_gem_path
68
+ end
69
+
70
+ def full_gem_path=(path)
71
+ stub.full_gem_path = path
70
72
  end
71
73
 
72
74
  def full_require_paths
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "2.3.14".freeze
4
+ VERSION = "2.3.17".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= VERSION.split(".").first.to_i
data/lib/bundler.rb CHANGED
@@ -97,6 +97,17 @@ module Bundler
97
97
  @bundle_path ||= Pathname.new(configured_bundle_path.path).expand_path(root)
98
98
  end
99
99
 
100
+ def create_bundle_path
101
+ SharedHelpers.filesystem_access(bundle_path.to_s) do |p|
102
+ mkdir_p(p)
103
+ end unless bundle_path.exist?
104
+
105
+ @bundle_path = bundle_path.realpath
106
+ rescue Errno::EEXIST
107
+ raise PathError, "Could not install to path `#{bundle_path}` " \
108
+ "because a file already exists at that path. Either remove or rename the file so the directory can be created."
109
+ end
110
+
100
111
  def configured_bundle_path
101
112
  @configured_bundle_path ||= settings.path.tap(&:validate!)
102
113
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.14
4
+ version: 2.3.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - André Arko
@@ -22,7 +22,7 @@ authors:
22
22
  autorequire:
23
23
  bindir: exe
24
24
  cert_chain: []
25
- date: 2022-05-18 00:00:00.000000000 Z
25
+ date: 2022-06-29 00:00:00.000000000 Z
26
26
  dependencies: []
27
27
  description: Bundler manages an application's dependencies through its entire life,
28
28
  across many machines, systematically and repeatably
@@ -369,7 +369,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
369
369
  - !ruby/object:Gem::Version
370
370
  version: 2.5.2
371
371
  requirements: []
372
- rubygems_version: 3.3.14
372
+ rubygems_version: 3.3.17
373
373
  signing_key:
374
374
  specification_version: 4
375
375
  summary: The best way to manage your application's dependencies