bundler 2.2.13 → 2.2.18

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +85 -5
  3. data/bundler.gemspec +2 -3
  4. data/lib/bundler.rb +1 -0
  5. data/lib/bundler/build_metadata.rb +2 -2
  6. data/lib/bundler/cli.rb +16 -35
  7. data/lib/bundler/cli/common.rb +15 -2
  8. data/lib/bundler/cli/gem.rb +9 -1
  9. data/lib/bundler/cli/outdated.rb +8 -11
  10. data/lib/bundler/compact_index_client/updater.rb +10 -6
  11. data/lib/bundler/current_ruby.rb +1 -0
  12. data/lib/bundler/definition.rb +40 -87
  13. data/lib/bundler/dsl.rb +3 -6
  14. data/lib/bundler/feature_flag.rb +0 -2
  15. data/lib/bundler/fetcher.rb +2 -1
  16. data/lib/bundler/fetcher/downloader.rb +8 -4
  17. data/lib/bundler/friendly_errors.rb +1 -1
  18. data/lib/bundler/gem_helper.rb +16 -0
  19. data/lib/bundler/index.rb +1 -2
  20. data/lib/bundler/injector.rb +2 -2
  21. data/lib/bundler/inline.rb +1 -1
  22. data/lib/bundler/installer/parallel_installer.rb +36 -15
  23. data/lib/bundler/lazy_specification.rb +6 -1
  24. data/lib/bundler/lockfile_parser.rb +2 -16
  25. data/lib/bundler/man/bundle-add.1 +1 -1
  26. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  27. data/lib/bundler/man/bundle-cache.1 +1 -1
  28. data/lib/bundler/man/bundle-check.1 +1 -1
  29. data/lib/bundler/man/bundle-clean.1 +1 -1
  30. data/lib/bundler/man/bundle-config.1 +21 -10
  31. data/lib/bundler/man/bundle-config.1.ronn +21 -11
  32. data/lib/bundler/man/bundle-doctor.1 +1 -1
  33. data/lib/bundler/man/bundle-exec.1 +1 -1
  34. data/lib/bundler/man/bundle-gem.1 +1 -1
  35. data/lib/bundler/man/bundle-info.1 +1 -1
  36. data/lib/bundler/man/bundle-init.1 +1 -1
  37. data/lib/bundler/man/bundle-inject.1 +1 -1
  38. data/lib/bundler/man/bundle-install.1 +1 -1
  39. data/lib/bundler/man/bundle-list.1 +1 -1
  40. data/lib/bundler/man/bundle-lock.1 +1 -1
  41. data/lib/bundler/man/bundle-open.1 +1 -1
  42. data/lib/bundler/man/bundle-outdated.1 +1 -1
  43. data/lib/bundler/man/bundle-platform.1 +1 -1
  44. data/lib/bundler/man/bundle-pristine.1 +1 -1
  45. data/lib/bundler/man/bundle-remove.1 +1 -1
  46. data/lib/bundler/man/bundle-show.1 +1 -1
  47. data/lib/bundler/man/bundle-update.1 +1 -1
  48. data/lib/bundler/man/bundle-viz.1 +1 -1
  49. data/lib/bundler/man/bundle.1 +1 -1
  50. data/lib/bundler/man/gemfile.5 +1 -1
  51. data/lib/bundler/plugin.rb +2 -2
  52. data/lib/bundler/plugin/api/source.rb +21 -0
  53. data/lib/bundler/resolver.rb +13 -96
  54. data/lib/bundler/resolver/spec_group.rb +0 -24
  55. data/lib/bundler/retry.rb +1 -1
  56. data/lib/bundler/rubygems_ext.rb +2 -2
  57. data/lib/bundler/settings.rb +60 -11
  58. data/lib/bundler/source.rb +15 -0
  59. data/lib/bundler/source/metadata.rb +0 -4
  60. data/lib/bundler/source/path.rb +3 -1
  61. data/lib/bundler/source/path/installer.rb +1 -1
  62. data/lib/bundler/source/rubygems.rb +37 -10
  63. data/lib/bundler/source/rubygems_aggregate.rb +64 -0
  64. data/lib/bundler/source_list.rb +37 -8
  65. data/lib/bundler/source_map.rb +58 -0
  66. data/lib/bundler/spec_set.rb +18 -5
  67. data/lib/bundler/templates/Gemfile +1 -1
  68. data/lib/bundler/templates/gems.rb +1 -1
  69. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +2 -4
  70. data/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
  71. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -1
  72. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +1 -1
  73. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +1 -1
  74. data/lib/bundler/version.rb +1 -1
  75. metadata +9 -4
@@ -21,14 +21,10 @@ module Bundler
21
21
  @version = exemplary_spec.version
22
22
  @source = exemplary_spec.source
23
23
 
24
- @all_platforms = relevant_platforms
25
24
  @activated_platforms = relevant_platforms
26
25
  @dependencies = Hash.new do |dependencies, platforms|
27
26
  dependencies[platforms] = dependencies_for(platforms)
28
27
  end
29
- @partitioned_dependency_names = Hash.new do |partitioned_dependency_names, platforms|
30
- partitioned_dependency_names[platforms] = partitioned_dependency_names_for(platforms)
31
- end
32
28
  @specs = specs
33
29
  end
34
30
 
@@ -45,14 +41,6 @@ module Bundler
45
41
  end.flatten.compact.uniq
46
42
  end
47
43
 
48
- def activate_platform!(platform)
49
- self.activated_platforms = [platform]
50
- end
51
-
52
- def activate_all_platforms!
53
- self.activated_platforms = @all_platforms
54
- end
55
-
56
44
  def to_s
57
45
  activated_platforms_string = sorted_activated_platforms.join(", ")
58
46
  "#{name} (#{version}) (#{activated_platforms_string})"
@@ -62,10 +50,6 @@ module Bundler
62
50
  @dependencies[activated_platforms]
63
51
  end
64
52
 
65
- def partitioned_dependency_names_for_activated_platforms
66
- @partitioned_dependency_names[activated_platforms]
67
- end
68
-
69
53
  def ==(other)
70
54
  return unless other.is_a?(SpecGroup)
71
55
  name == other.name &&
@@ -100,14 +84,6 @@ module Bundler
100
84
  end.flatten
101
85
  end
102
86
 
103
- def partitioned_dependency_names_for(platforms)
104
- return @dependencies[platforms].map(&:name), [] if platforms.size == 1
105
-
106
- @dependencies[platforms].partition do |dep_proxy|
107
- @dependencies[platforms].count {|dp| dp.dep == dep_proxy.dep } == platforms.size
108
- end.map {|deps| deps.map(&:name) }
109
- end
110
-
111
87
  def __dependencies(platform)
112
88
  dependencies = []
113
89
  @specs[platform].first.dependencies.each do |dep|
data/lib/bundler/retry.rb CHANGED
@@ -49,7 +49,7 @@ module Bundler
49
49
  raise e
50
50
  end
51
51
  return true unless name
52
- Bundler.ui.info "" unless Bundler.ui.debug? # Add new line incase dots preceded this
52
+ Bundler.ui.info "" unless Bundler.ui.debug? # Add new line in case dots preceded this
53
53
  Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}", Bundler.ui.debug?
54
54
  end
55
55
 
@@ -105,7 +105,7 @@ module Gem
105
105
  end
106
106
 
107
107
  class Dependency
108
- attr_accessor :source, :groups, :all_sources
108
+ attr_accessor :source, :groups
109
109
 
110
110
  alias_method :eql?, :==
111
111
 
@@ -116,7 +116,7 @@ module Gem
116
116
  end
117
117
 
118
118
  def to_yaml_properties
119
- instance_variables.reject {|p| ["@source", "@groups", "@all_sources"].include?(p.to_s) }
119
+ instance_variables.reject {|p| ["@source", "@groups"].include?(p.to_s) }
120
120
  end
121
121
 
122
122
  def to_lock
@@ -13,6 +13,7 @@ module Bundler
13
13
  auto_install
14
14
  cache_all
15
15
  cache_all_platforms
16
+ clean
16
17
  default_install_uses_path
17
18
  deployment
18
19
  deployment_means_frozen
@@ -20,20 +21,21 @@ module Bundler
20
21
  disable_exec_load
21
22
  disable_local_branch_check
22
23
  disable_local_revision_check
23
- disable_multisource
24
24
  disable_shared_gems
25
25
  disable_version_check
26
26
  force_ruby_platform
27
27
  forget_cli_options
28
28
  frozen
29
+ gem.changelog
29
30
  gem.coc
30
31
  gem.mit
32
+ git.allow_insecure
31
33
  global_gem_cache
32
34
  ignore_messages
33
35
  init_gems_rb
36
+ inline
34
37
  no_install
35
38
  no_prune
36
- only_update_to_newer_versions
37
39
  path_relative_to_cwd
38
40
  path.system
39
41
  plugins
@@ -61,6 +63,22 @@ module Bundler
61
63
  without
62
64
  ].freeze
63
65
 
66
+ STRING_KEYS = %w[
67
+ bin
68
+ cache_path
69
+ console
70
+ gem.ci
71
+ gem.github_username
72
+ gem.linter
73
+ gem.rubocop
74
+ gem.test
75
+ gemfile
76
+ path
77
+ shebang
78
+ system_bindir
79
+ trust-policy
80
+ ].freeze
81
+
64
82
  DEFAULT_CONFIG = {
65
83
  "BUNDLE_SILENCE_DEPRECATIONS" => false,
66
84
  "BUNDLE_DISABLE_VERSION_CHECK" => true,
@@ -126,8 +144,8 @@ module Bundler
126
144
  keys = @temporary.keys | @global_config.keys | @local_config.keys | @env_config.keys
127
145
 
128
146
  keys.map do |key|
129
- key.sub(/^BUNDLE_/, "").gsub(/__/, ".").downcase
130
- end
147
+ key.sub(/^BUNDLE_/, "").gsub(/___/, "-").gsub(/__/, ".").downcase
148
+ end.sort
131
149
  end
132
150
 
133
151
  def local_overrides
@@ -173,19 +191,19 @@ module Bundler
173
191
  locations = []
174
192
 
175
193
  if value = @temporary[key]
176
- locations << "Set for the current command: #{converted_value(value, exposed_key).inspect}"
194
+ locations << "Set for the current command: #{printable_value(value, exposed_key).inspect}"
177
195
  end
178
196
 
179
197
  if value = @local_config[key]
180
- locations << "Set for your local app (#{local_config_file}): #{converted_value(value, exposed_key).inspect}"
198
+ locations << "Set for your local app (#{local_config_file}): #{printable_value(value, exposed_key).inspect}"
181
199
  end
182
200
 
183
201
  if value = @env_config[key]
184
- locations << "Set via #{key}: #{converted_value(value, exposed_key).inspect}"
202
+ locations << "Set via #{key}: #{printable_value(value, exposed_key).inspect}"
185
203
  end
186
204
 
187
205
  if value = @global_config[key]
188
- locations << "Set for the current user (#{global_config_file}): #{converted_value(value, exposed_key).inspect}"
206
+ locations << "Set for the current user (#{global_config_file}): #{printable_value(value, exposed_key).inspect}"
189
207
  end
190
208
 
191
209
  return ["You have not configured a value for `#{exposed_key}`"] if locations.empty?
@@ -277,9 +295,7 @@ module Bundler
277
295
  end
278
296
 
279
297
  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}"
298
+ self.class.key_for(key)
283
299
  end
284
300
 
285
301
  private
@@ -314,6 +330,10 @@ module Bundler
314
330
  BOOL_KEYS.include?(name.to_s) || BOOL_KEYS.include?(parent_setting_for(name.to_s))
315
331
  end
316
332
 
333
+ def is_string(name)
334
+ STRING_KEYS.include?(name.to_s) || name.to_s.start_with?("local.") || name.to_s.start_with?("mirror.") || name.to_s.start_with?("build.")
335
+ end
336
+
317
337
  def to_bool(value)
318
338
  case value
319
339
  when nil, /\A(false|f|no|n|0|)\z/i, false
@@ -331,6 +351,14 @@ module Bundler
331
351
  ARRAY_KEYS.include?(key.to_s)
332
352
  end
333
353
 
354
+ def is_credential(key)
355
+ key == "gem.push_key"
356
+ end
357
+
358
+ def is_userinfo(value)
359
+ value.include?(":")
360
+ end
361
+
334
362
  def to_array(value)
335
363
  return [] unless value
336
364
  value.split(":").map(&:to_sym)
@@ -377,6 +405,21 @@ module Bundler
377
405
  end
378
406
  end
379
407
 
408
+ def printable_value(value, key)
409
+ converted = converted_value(value, key)
410
+ return converted unless converted.is_a?(String)
411
+
412
+ if is_string(key)
413
+ converted
414
+ elsif is_credential(key)
415
+ "[REDACTED]"
416
+ elsif is_userinfo(converted)
417
+ converted.gsub(/:.*$/, ":[REDACTED]")
418
+ else
419
+ converted
420
+ end
421
+ end
422
+
380
423
  def global_config_file
381
424
  if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty?
382
425
  Pathname.new(ENV["BUNDLE_CONFIG"])
@@ -416,6 +459,12 @@ module Bundler
416
459
  \z
417
460
  /ix.freeze
418
461
 
462
+ def self.key_for(key)
463
+ key = normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key
464
+ key = key.to_s.gsub(".", "__").gsub("-", "___").upcase
465
+ "BUNDLE_#{key}"
466
+ end
467
+
419
468
  # TODO: duplicates Rubygems#normalize_uri
420
469
  # TODO: is this the correct place to validate mirror URIs?
421
470
  def self.normalize_uri(uri)
@@ -7,6 +7,7 @@ module Bundler
7
7
  autoload :Metadata, File.expand_path("source/metadata", __dir__)
8
8
  autoload :Path, File.expand_path("source/path", __dir__)
9
9
  autoload :Rubygems, File.expand_path("source/rubygems", __dir__)
10
+ autoload :RubygemsAggregate, File.expand_path("source/rubygems_aggregate", __dir__)
10
11
 
11
12
  attr_accessor :dependency_names
12
13
 
@@ -33,6 +34,16 @@ module Bundler
33
34
  spec.source == self
34
35
  end
35
36
 
37
+ def local!; end
38
+
39
+ def cached!; end
40
+
41
+ def remote!; end
42
+
43
+ def add_dependency_names(names)
44
+ @dependency_names = Array(dependency_names) | Array(names)
45
+ end
46
+
36
47
  # it's possible that gems from one source depend on gems from some
37
48
  # other source, so now we download gemspecs and iterate over those
38
49
  # dependencies, looking for gems we don't have info on yet.
@@ -42,6 +53,10 @@ module Bundler
42
53
  specs.dependency_names
43
54
  end
44
55
 
56
+ def spec_names
57
+ specs.spec_names
58
+ end
59
+
45
60
  def include?(other)
46
61
  other == self
47
62
  end
@@ -33,10 +33,6 @@ module Bundler
33
33
  end
34
34
  end
35
35
 
36
- def cached!; end
37
-
38
- def remote!; end
39
-
40
36
  def options
41
37
  {}
42
38
  end
@@ -82,7 +82,9 @@ module Bundler
82
82
  end
83
83
 
84
84
  def install(spec, options = {})
85
- print_using_message "Using #{version_message(spec)} from #{self}"
85
+ using_message = "Using #{version_message(spec)} from #{self}"
86
+ using_message += " and installing its executables" unless spec.executables.empty?
87
+ print_using_message using_message
86
88
  generate_bin(spec, :disable_extensions => true)
87
89
  nil # no post-install message
88
90
  end
@@ -35,7 +35,7 @@ module Bundler
35
35
  run_hooks(:post_build)
36
36
  end
37
37
 
38
- generate_bin unless spec.executables.nil? || spec.executables.empty?
38
+ generate_bin unless spec.executables.empty?
39
39
 
40
40
  run_hooks(:post_install)
41
41
  ensure
@@ -20,17 +20,29 @@ module Bundler
20
20
  @dependency_names = []
21
21
  @allow_remote = false
22
22
  @allow_cached = false
23
+ @allow_local = options["allow_local"] || false
23
24
  @caches = [cache_path, *Bundler.rubygems.gem_cache]
24
25
 
25
- Array(options["remotes"] || []).reverse_each {|r| add_remote(r) }
26
+ Array(options["remotes"]).reverse_each {|r| add_remote(r) }
27
+ end
28
+
29
+ def local!
30
+ return if @allow_local
31
+
32
+ @specs = nil
33
+ @allow_local = true
26
34
  end
27
35
 
28
36
  def remote!
37
+ return if @allow_remote
38
+
29
39
  @specs = nil
30
40
  @allow_remote = true
31
41
  end
32
42
 
33
43
  def cached!
44
+ return if @allow_cached
45
+
34
46
  @specs = nil
35
47
  @allow_cached = true
36
48
  end
@@ -49,8 +61,12 @@ module Bundler
49
61
  o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty?
50
62
  end
51
63
 
64
+ def disable_multisource?
65
+ @remotes.size <= 1
66
+ end
67
+
52
68
  def can_lock?(spec)
53
- return super if Bundler.feature_flag.disable_multisource?
69
+ return super if disable_multisource?
54
70
  spec.source.is_a?(Rubygems)
55
71
  end
56
72
 
@@ -87,7 +103,7 @@ module Bundler
87
103
  # small_idx.use large_idx.
88
104
  idx = @allow_remote ? remote_specs.dup : Index.new
89
105
  idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote
90
- idx.use(installed_specs, :override_dupes)
106
+ idx.use(installed_specs, :override_dupes) if @allow_local
91
107
  idx
92
108
  end
93
109
  end
@@ -243,8 +259,16 @@ module Bundler
243
259
  !equivalent
244
260
  end
245
261
 
262
+ def spec_names
263
+ if @allow_remote && dependency_api_available?
264
+ remote_specs.spec_names
265
+ else
266
+ []
267
+ end
268
+ end
269
+
246
270
  def unmet_deps
247
- if @allow_remote && api_fetchers.any?
271
+ if @allow_remote && dependency_api_available?
248
272
  remote_specs.unmet_dependency_names
249
273
  else
250
274
  []
@@ -260,7 +284,7 @@ module Bundler
260
284
 
261
285
  def double_check_for(unmet_dependency_names)
262
286
  return unless @allow_remote
263
- return unless api_fetchers.any?
287
+ return unless dependency_api_available?
264
288
 
265
289
  unmet_dependency_names = unmet_dependency_names.call
266
290
  unless unmet_dependency_names.nil?
@@ -282,17 +306,20 @@ module Bundler
282
306
  remote_specs.each do |spec|
283
307
  case spec
284
308
  when EndpointSpecification, Gem::Specification, StubSpecification, LazySpecification
285
- names.concat(spec.runtime_dependencies)
309
+ names.concat(spec.runtime_dependencies.map(&:name))
286
310
  when RemoteSpecification # from the full index
287
311
  return nil
288
312
  else
289
313
  raise "unhandled spec type (#{spec.inspect})"
290
314
  end
291
315
  end
292
- names.map!(&:name) if names
293
316
  names
294
317
  end
295
318
 
319
+ def dependency_api_available?
320
+ api_fetchers.any?
321
+ end
322
+
296
323
  protected
297
324
 
298
325
  def credless_remotes
@@ -365,7 +392,7 @@ module Bundler
365
392
 
366
393
  def cached_specs
367
394
  @cached_specs ||= begin
368
- idx = installed_specs.dup
395
+ idx = @allow_local ? installed_specs.dup : Index.new
369
396
 
370
397
  Dir["#{cache_path}/*.gem"].each do |gemfile|
371
398
  next if gemfile =~ /^bundler\-[\d\.]+?\.gem/
@@ -407,11 +434,11 @@ module Bundler
407
434
  def fetch_names(fetchers, dependency_names, index, override_dupes)
408
435
  fetchers.each do |f|
409
436
  if dependency_names
410
- Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug?
437
+ Bundler.ui.info "Fetching gem metadata from #{URICredentialsFilter.credential_filtered_uri(f.uri)}", Bundler.ui.debug?
411
438
  index.use f.specs_with_retry(dependency_names, self), override_dupes
412
439
  Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
413
440
  else
414
- Bundler.ui.info "Fetching source index from #{f.uri}"
441
+ Bundler.ui.info "Fetching source index from #{URICredentialsFilter.credential_filtered_uri(f.uri)}"
415
442
  index.use f.specs_with_retry(nil, self), override_dupes
416
443
  end
417
444
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class Source
5
+ class RubygemsAggregate
6
+ attr_reader :source_map, :sources
7
+
8
+ def initialize(sources, source_map)
9
+ @sources = sources
10
+ @source_map = source_map
11
+
12
+ @index = build_index
13
+ end
14
+
15
+ def specs
16
+ @index
17
+ end
18
+
19
+ def to_s
20
+ "any of the sources"
21
+ end
22
+
23
+ private
24
+
25
+ def build_index
26
+ Index.build do |idx|
27
+ dependency_names = source_map.pinned_spec_names
28
+
29
+ sources.all_sources.each do |source|
30
+ source.dependency_names = dependency_names - source_map.pinned_spec_names(source)
31
+ idx.add_source source.specs
32
+ dependency_names.concat(source.unmet_deps).uniq!
33
+ end
34
+
35
+ double_check_for_index(idx, dependency_names)
36
+ end
37
+ end
38
+
39
+ # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
40
+ # sources A and B. At this point, the API request will have found all the versions of Bar in source A,
41
+ # but will not have found any versions of Bar from source B, which is a problem if the requested version
42
+ # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
43
+ # each spec we found, we add all possible versions from all sources to the index.
44
+ def double_check_for_index(idx, dependency_names)
45
+ pinned_names = source_map.pinned_spec_names
46
+
47
+ names = :names # do this so we only have to traverse to get dependency_names from the index once
48
+ unmet_dependency_names = lambda do
49
+ return names unless names == :names
50
+ new_names = sources.all_sources.map(&:dependency_names_to_double_check)
51
+ return names = nil if new_names.compact!
52
+ names = new_names.flatten(1).concat(dependency_names)
53
+ names.uniq!
54
+ names -= pinned_names
55
+ names
56
+ end
57
+
58
+ sources.all_sources.each do |source|
59
+ source.double_check_for(unmet_dependency_names)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end