bundler 2.2.11 → 2.3.26

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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +721 -5
  3. data/README.md +1 -1
  4. data/bundler.gemspec +8 -11
  5. data/exe/bundle +7 -8
  6. data/exe/bundler +1 -1
  7. data/lib/bundler/.document +1 -0
  8. data/lib/bundler/build_metadata.rb +3 -3
  9. data/lib/bundler/cli/cache.rb +1 -1
  10. data/lib/bundler/cli/check.rb +4 -2
  11. data/lib/bundler/cli/common.rb +17 -3
  12. data/lib/bundler/cli/config.rb +10 -1
  13. data/lib/bundler/cli/doctor.rb +24 -5
  14. data/lib/bundler/cli/exec.rb +1 -6
  15. data/lib/bundler/cli/gem.rb +130 -26
  16. data/lib/bundler/cli/info.rb +27 -6
  17. data/lib/bundler/cli/init.rb +5 -1
  18. data/lib/bundler/cli/install.rb +23 -54
  19. data/lib/bundler/cli/issue.rb +4 -3
  20. data/lib/bundler/cli/list.rb +7 -1
  21. data/lib/bundler/cli/lock.rb +5 -1
  22. data/lib/bundler/cli/open.rb +1 -2
  23. data/lib/bundler/cli/outdated.rb +22 -14
  24. data/lib/bundler/cli/platform.rb +2 -2
  25. data/lib/bundler/cli/remove.rb +1 -2
  26. data/lib/bundler/cli/show.rb +1 -1
  27. data/lib/bundler/cli/update.rb +17 -8
  28. data/lib/bundler/cli.rb +51 -63
  29. data/lib/bundler/compact_index_client/cache.rb +0 -9
  30. data/lib/bundler/compact_index_client/updater.rb +26 -14
  31. data/lib/bundler/compact_index_client.rb +2 -8
  32. data/lib/bundler/current_ruby.rb +17 -6
  33. data/lib/bundler/definition.rb +260 -362
  34. data/lib/bundler/dependency.rb +23 -71
  35. data/lib/bundler/digest.rb +71 -0
  36. data/lib/bundler/dsl.rb +72 -76
  37. data/lib/bundler/endpoint_specification.rb +19 -13
  38. data/lib/bundler/env.rb +1 -1
  39. data/lib/bundler/environment_preserver.rb +4 -1
  40. data/lib/bundler/errors.rb +29 -3
  41. data/lib/bundler/feature_flag.rb +0 -5
  42. data/lib/bundler/fetcher/base.rb +6 -8
  43. data/lib/bundler/fetcher/compact_index.rb +10 -15
  44. data/lib/bundler/fetcher/downloader.rb +9 -6
  45. data/lib/bundler/fetcher/index.rb +0 -27
  46. data/lib/bundler/fetcher.rb +22 -23
  47. data/lib/bundler/friendly_errors.rb +26 -36
  48. data/lib/bundler/gem_helper.rb +21 -16
  49. data/lib/bundler/gem_helpers.rb +9 -2
  50. data/lib/bundler/gem_version_promoter.rb +14 -25
  51. data/lib/bundler/index.rb +11 -46
  52. data/lib/bundler/injector.rb +18 -4
  53. data/lib/bundler/inline.rb +4 -13
  54. data/lib/bundler/installer/gem_installer.rb +16 -21
  55. data/lib/bundler/installer/parallel_installer.rb +36 -15
  56. data/lib/bundler/installer/standalone.rb +42 -10
  57. data/lib/bundler/installer.rb +25 -41
  58. data/lib/bundler/lazy_specification.rb +52 -30
  59. data/lib/bundler/lockfile_generator.rb +2 -2
  60. data/lib/bundler/lockfile_parser.rb +18 -43
  61. data/lib/bundler/man/bundle-add.1 +21 -5
  62. data/lib/bundler/man/bundle-add.1.ronn +16 -4
  63. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  64. data/lib/bundler/man/bundle-cache.1 +7 -1
  65. data/lib/bundler/man/bundle-cache.1.ronn +7 -0
  66. data/lib/bundler/man/bundle-check.1 +1 -1
  67. data/lib/bundler/man/bundle-clean.1 +2 -2
  68. data/lib/bundler/man/bundle-clean.1.ronn +1 -1
  69. data/lib/bundler/man/bundle-config.1 +49 -22
  70. data/lib/bundler/man/bundle-config.1.ronn +49 -30
  71. data/lib/bundler/man/bundle-console.1 +53 -0
  72. data/lib/bundler/man/bundle-console.1.ronn +44 -0
  73. data/lib/bundler/man/bundle-doctor.1 +1 -1
  74. data/lib/bundler/man/bundle-exec.1 +2 -2
  75. data/lib/bundler/man/bundle-exec.1.ronn +1 -1
  76. data/lib/bundler/man/bundle-gem.1 +14 -1
  77. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  78. data/lib/bundler/man/bundle-help.1 +13 -0
  79. data/lib/bundler/man/bundle-help.1.ronn +12 -0
  80. data/lib/bundler/man/bundle-info.1 +1 -1
  81. data/lib/bundler/man/bundle-init.1 +1 -1
  82. data/lib/bundler/man/bundle-inject.1 +5 -2
  83. data/lib/bundler/man/bundle-inject.1.ronn +3 -1
  84. data/lib/bundler/man/bundle-install.1 +6 -2
  85. data/lib/bundler/man/bundle-install.1.ronn +8 -2
  86. data/lib/bundler/man/bundle-list.1 +1 -1
  87. data/lib/bundler/man/bundle-lock.1 +1 -1
  88. data/lib/bundler/man/bundle-open.1 +1 -1
  89. data/lib/bundler/man/bundle-outdated.1 +3 -10
  90. data/lib/bundler/man/bundle-outdated.1.ronn +1 -10
  91. data/lib/bundler/man/bundle-platform.1 +16 -6
  92. data/lib/bundler/man/bundle-platform.1.ronn +14 -7
  93. data/lib/bundler/man/bundle-plugin.1 +81 -0
  94. data/lib/bundler/man/bundle-plugin.1.ronn +59 -0
  95. data/lib/bundler/man/bundle-pristine.1 +1 -1
  96. data/lib/bundler/man/bundle-remove.1 +1 -1
  97. data/lib/bundler/man/bundle-show.1 +1 -1
  98. data/lib/bundler/man/bundle-update.1 +5 -5
  99. data/lib/bundler/man/bundle-update.1.ronn +5 -4
  100. data/lib/bundler/man/bundle-version.1 +35 -0
  101. data/lib/bundler/man/bundle-version.1.ronn +24 -0
  102. data/lib/bundler/man/bundle-viz.1 +4 -1
  103. data/lib/bundler/man/bundle-viz.1.ronn +2 -0
  104. data/lib/bundler/man/bundle.1 +15 -10
  105. data/lib/bundler/man/bundle.1.ronn +12 -7
  106. data/lib/bundler/man/gemfile.5 +117 -80
  107. data/lib/bundler/man/gemfile.5.ronn +105 -84
  108. data/lib/bundler/man/index.txt +4 -0
  109. data/lib/bundler/match_metadata.rb +13 -0
  110. data/lib/bundler/match_platform.rb +0 -1
  111. data/lib/bundler/match_remote_metadata.rb +29 -0
  112. data/lib/bundler/plugin/api/source.rb +24 -8
  113. data/lib/bundler/plugin/index.rb +4 -1
  114. data/lib/bundler/plugin/installer/git.rb +0 -4
  115. data/lib/bundler/plugin/installer/rubygems.rb +0 -4
  116. data/lib/bundler/plugin/installer.rb +10 -10
  117. data/lib/bundler/plugin/source_list.rb +4 -0
  118. data/lib/bundler/plugin.rb +30 -8
  119. data/lib/bundler/process_lock.rb +1 -1
  120. data/lib/bundler/remote_specification.rb +10 -4
  121. data/lib/bundler/resolver/base.rb +50 -0
  122. data/lib/bundler/resolver/spec_group.rb +31 -73
  123. data/lib/bundler/resolver.rb +193 -292
  124. data/lib/bundler/retry.rb +1 -1
  125. data/lib/bundler/ruby_dsl.rb +1 -1
  126. data/lib/bundler/ruby_version.rb +5 -18
  127. data/lib/bundler/rubygems_ext.rb +160 -26
  128. data/lib/bundler/rubygems_gem_installer.rb +86 -9
  129. data/lib/bundler/rubygems_integration.rb +46 -93
  130. data/lib/bundler/runtime.rb +18 -12
  131. data/lib/bundler/self_manager.rb +168 -0
  132. data/lib/bundler/settings.rb +98 -22
  133. data/lib/bundler/setup.rb +2 -2
  134. data/lib/bundler/shared_helpers.rb +15 -31
  135. data/lib/bundler/source/git/git_proxy.rb +8 -6
  136. data/lib/bundler/source/git.rb +29 -13
  137. data/lib/bundler/source/metadata.rb +3 -7
  138. data/lib/bundler/source/path/installer.rb +1 -1
  139. data/lib/bundler/source/path.rb +3 -1
  140. data/lib/bundler/source/rubygems.rb +199 -182
  141. data/lib/bundler/source/rubygems_aggregate.rb +68 -0
  142. data/lib/bundler/source.rb +24 -4
  143. data/lib/bundler/source_list.rb +104 -60
  144. data/lib/bundler/source_map.rb +71 -0
  145. data/lib/bundler/spec_set.rb +58 -52
  146. data/lib/bundler/stub_specification.rb +13 -3
  147. data/lib/bundler/templates/Executable +2 -4
  148. data/lib/bundler/templates/Executable.bundler +8 -8
  149. data/lib/bundler/templates/Executable.standalone +2 -4
  150. data/lib/bundler/templates/Gemfile +0 -2
  151. data/lib/bundler/templates/gems.rb +0 -3
  152. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  153. data/lib/bundler/templates/newgem/README.md.tt +8 -12
  154. data/lib/bundler/templates/newgem/Rakefile.tt +15 -2
  155. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +16 -7
  156. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +5 -4
  157. data/lib/bundler/templates/newgem/newgem.gemspec.tt +19 -17
  158. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  159. data/lib/bundler/templates/newgem/standard.yml.tt +3 -0
  160. data/lib/bundler/templates/newgem/test/minitest/{newgem_test.rb.tt → test_newgem.rb.tt} +1 -1
  161. data/lib/bundler/ui/shell.rb +1 -1
  162. data/lib/bundler/vendor/.document +1 -0
  163. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  164. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  165. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  166. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  167. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  168. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  169. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  170. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +3 -3
  171. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +32 -26
  172. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  173. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -1
  174. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  175. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  176. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +5 -5
  177. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -2
  178. data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -2
  179. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
  180. data/lib/bundler/vendor/thor/lib/thor/error.rb +9 -4
  181. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +19 -1
  182. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +22 -4
  183. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  184. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  185. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  186. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +1 -1
  187. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  188. data/lib/bundler/vendor/tsort/lib/tsort.rb +452 -0
  189. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  190. data/lib/bundler/vendor/uri/lib/uri/common.rb +17 -80
  191. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -1
  192. data/lib/bundler/vendor/uri/lib/uri/generic.rb +5 -6
  193. data/lib/bundler/vendor/uri/lib/uri/http.rb +0 -1
  194. data/lib/bundler/vendor/uri/lib/uri/https.rb +0 -1
  195. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  196. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -1
  197. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +1 -14
  198. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +1 -12
  199. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  200. data/lib/bundler/vendor/uri/lib/uri/ws.rb +84 -0
  201. data/lib/bundler/vendor/uri/lib/uri/wss.rb +22 -0
  202. data/lib/bundler/vendor/uri/lib/uri.rb +0 -1
  203. data/lib/bundler/vendored_tsort.rb +4 -0
  204. data/lib/bundler/version.rb +1 -1
  205. data/lib/bundler/worker.rb +19 -4
  206. data/lib/bundler.rb +46 -39
  207. metadata +39 -12
  208. data/lib/bundler/dep_proxy.rb +0 -55
  209. data/lib/bundler/gemdeps.rb +0 -29
  210. data/lib/bundler/psyched_yaml.rb +0 -22
  211. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
@@ -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
 
@@ -14,13 +15,12 @@ module Bundler
14
15
  specs.unmet_dependency_names
15
16
  end
16
17
 
17
- def version_message(spec)
18
+ def version_message(spec, locked_spec = nil)
18
19
  message = "#{spec.name} #{spec.version}"
19
20
  message += " (#{spec.platform})" if spec.platform != Gem::Platform::RUBY && !spec.platform.nil?
20
21
 
21
- if Bundler.locked_gems
22
- locked_spec = Bundler.locked_gems.specs.find {|s| s.name == spec.name }
23
- locked_spec_version = locked_spec.version if locked_spec
22
+ if locked_spec
23
+ locked_spec_version = locked_spec.version
24
24
  if locked_spec_version && spec.version != locked_spec_version
25
25
  message += Bundler.ui.add_color(" (was #{locked_spec_version})", version_color(spec.version, locked_spec_version))
26
26
  end
@@ -33,6 +33,18 @@ module Bundler
33
33
  spec.source == self
34
34
  end
35
35
 
36
+ def local!; end
37
+
38
+ def local_only!; end
39
+
40
+ def cached!; end
41
+
42
+ def remote!; end
43
+
44
+ def add_dependency_names(names)
45
+ @dependency_names = Array(dependency_names) | Array(names)
46
+ end
47
+
36
48
  # it's possible that gems from one source depend on gems from some
37
49
  # other source, so now we download gemspecs and iterate over those
38
50
  # dependencies, looking for gems we don't have info on yet.
@@ -42,6 +54,10 @@ module Bundler
42
54
  specs.dependency_names
43
55
  end
44
56
 
57
+ def spec_names
58
+ specs.spec_names
59
+ end
60
+
45
61
  def include?(other)
46
62
  other == self
47
63
  end
@@ -50,6 +66,10 @@ module Bundler
50
66
  "#<#{self.class}:0x#{object_id} #{self}>"
51
67
  end
52
68
 
69
+ def identifier
70
+ to_s
71
+ end
72
+
53
73
  def path?
54
74
  instance_of?(Bundler::Source::Path)
55
75
  end
@@ -5,24 +5,49 @@ module Bundler
5
5
  attr_reader :path_sources,
6
6
  :git_sources,
7
7
  :plugin_sources,
8
- :global_rubygems_source,
8
+ :global_path_source,
9
9
  :metadata_source
10
10
 
11
+ def global_rubygems_source
12
+ @global_rubygems_source ||= rubygems_aggregate_class.new("allow_local" => true)
13
+ end
14
+
11
15
  def initialize
12
16
  @path_sources = []
13
17
  @git_sources = []
14
18
  @plugin_sources = []
15
19
  @global_rubygems_source = nil
16
- @rubygems_aggregate = rubygems_aggregate_class.new
20
+ @global_path_source = nil
17
21
  @rubygems_sources = []
18
22
  @metadata_source = Source::Metadata.new
23
+
24
+ @merged_gem_lockfile_sections = false
25
+ end
26
+
27
+ def merged_gem_lockfile_sections?
28
+ @merged_gem_lockfile_sections
29
+ end
30
+
31
+ def merged_gem_lockfile_sections!(replacement_source)
32
+ @merged_gem_lockfile_sections = true
33
+ @global_rubygems_source = replacement_source
34
+ end
35
+
36
+ def aggregate_global_source?
37
+ global_rubygems_source.multiple_remotes?
38
+ end
39
+
40
+ def implicit_global_source?
41
+ global_rubygems_source.no_remotes?
19
42
  end
20
43
 
21
44
  def add_path_source(options = {})
22
45
  if options["gemspec"]
23
46
  add_source_to_list Source::Gemspec.new(options), path_sources
24
47
  else
25
- add_source_to_list Source::Path.new(options), path_sources
48
+ path_source = add_source_to_list Source::Path.new(options), path_sources
49
+ @global_path_source ||= path_source if options["global"]
50
+ path_source
26
51
  end
27
52
  end
28
53
 
@@ -33,32 +58,31 @@ module Bundler
33
58
  end
34
59
 
35
60
  def add_rubygems_source(options = {})
36
- add_source_to_list Source::Rubygems.new(options), @rubygems_sources
61
+ new_source = Source::Rubygems.new(options)
62
+ return @global_rubygems_source if @global_rubygems_source == new_source
63
+
64
+ add_source_to_list new_source, @rubygems_sources
37
65
  end
38
66
 
39
67
  def add_plugin_source(source, options = {})
40
68
  add_source_to_list Plugin.source(source).new(options), @plugin_sources
41
69
  end
42
70
 
43
- def global_rubygems_source=(uri)
44
- if Bundler.feature_flag.disable_multisource?
45
- @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
46
- end
47
- add_rubygems_remote(uri)
48
- end
49
-
50
- def add_rubygems_remote(uri)
51
- return if Bundler.feature_flag.disable_multisource?
52
- @rubygems_aggregate.add_remote(uri)
53
- @rubygems_aggregate
71
+ def add_global_rubygems_remote(uri)
72
+ global_rubygems_source.add_remote(uri)
73
+ global_rubygems_source
54
74
  end
55
75
 
56
76
  def default_source
57
- global_rubygems_source || @rubygems_aggregate
77
+ global_path_source || global_rubygems_source
58
78
  end
59
79
 
60
80
  def rubygems_sources
61
- @rubygems_sources + [default_source]
81
+ non_global_rubygems_sources + [global_rubygems_source]
82
+ end
83
+
84
+ def non_global_rubygems_sources
85
+ @rubygems_sources
62
86
  end
63
87
 
64
88
  def rubygems_remotes
@@ -69,37 +93,55 @@ module Bundler
69
93
  path_sources + git_sources + plugin_sources + rubygems_sources + [metadata_source]
70
94
  end
71
95
 
96
+ def non_default_explicit_sources
97
+ all_sources - [default_source, metadata_source]
98
+ end
99
+
72
100
  def get(source)
73
- source_list_for(source).find {|s| equal_source?(source, s) || equivalent_source?(source, s) }
101
+ source_list_for(source).find {|s| equivalent_source?(source, s) }
102
+ end
103
+
104
+ def get_with_fallback(source)
105
+ get(source) || default_source
74
106
  end
75
107
 
76
108
  def lock_sources
77
- lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
78
- if Bundler.feature_flag.disable_multisource?
79
- lock_sources + rubygems_sources.sort_by(&:to_s)
109
+ lock_other_sources + lock_rubygems_sources
110
+ end
111
+
112
+ def lock_other_sources
113
+ (path_sources + git_sources + plugin_sources).sort_by(&:identifier)
114
+ end
115
+
116
+ def lock_rubygems_sources
117
+ if merged_gem_lockfile_sections?
118
+ [combine_rubygems_sources]
80
119
  else
81
- lock_sources << combine_rubygems_sources
120
+ rubygems_sources.sort_by(&:identifier)
82
121
  end
83
122
  end
84
123
 
85
124
  # Returns true if there are changes
86
125
  def replace_sources!(replacement_sources)
87
- return true if replacement_sources.empty?
126
+ return false if replacement_sources.empty?
88
127
 
89
- [path_sources, git_sources, plugin_sources].each do |source_list|
90
- source_list.map! do |source|
91
- replacement_sources.find {|s| s == source } || source
92
- end
93
- end
128
+ @rubygems_sources, @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
129
+ @global_rubygems_source = global_replacement_source(replacement_sources)
130
+
131
+ different_sources?(lock_sources, replacement_sources)
132
+ end
133
+
134
+ # Returns true if there are changes
135
+ def expired_sources?(replacement_sources)
136
+ return false if replacement_sources.empty?
94
137
 
95
- replacement_rubygems = !Bundler.feature_flag.disable_multisource? &&
96
- replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
97
- @rubygems_aggregate = replacement_rubygems if replacement_rubygems
138
+ lock_sources = dup_with_replaced_sources(replacement_sources).lock_sources
98
139
 
99
- return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
100
- return true if replacement_rubygems && rubygems_remotes.sort_by(&:to_s) != replacement_rubygems.remotes.sort_by(&:to_s)
140
+ different_sources?(lock_sources, replacement_sources)
141
+ end
101
142
 
102
- false
143
+ def local_only!
144
+ all_sources.each(&:local_only!)
103
145
  end
104
146
 
105
147
  def cached!
@@ -110,11 +152,33 @@ module Bundler
110
152
  all_sources.each(&:remote!)
111
153
  end
112
154
 
113
- def rubygems_primary_remotes
114
- @rubygems_aggregate.remotes
155
+ private
156
+
157
+ def dup_with_replaced_sources(replacement_sources)
158
+ new_source_list = dup
159
+ new_source_list.replace_sources!(replacement_sources)
160
+ new_source_list
115
161
  end
116
162
 
117
- private
163
+ def map_sources(replacement_sources)
164
+ [@rubygems_sources, @path_sources, @git_sources, @plugin_sources].map do |sources|
165
+ sources.map do |source|
166
+ replacement_sources.find {|s| s == source } || source
167
+ end
168
+ end
169
+ end
170
+
171
+ def global_replacement_source(replacement_sources)
172
+ replacement_source = replacement_sources.find {|s| s == global_rubygems_source }
173
+ return global_rubygems_source unless replacement_source
174
+
175
+ replacement_source.local!
176
+ replacement_source
177
+ end
178
+
179
+ def different_sources?(lock_sources, replacement_sources)
180
+ !equivalent_sources?(lock_sources, replacement_sources)
181
+ end
118
182
 
119
183
  def rubygems_aggregate_class
120
184
  Source::Rubygems
@@ -150,32 +214,12 @@ module Bundler
150
214
  end
151
215
  end
152
216
 
153
- def equal_sources?(lock_sources, replacement_sources)
154
- lock_sources.sort_by(&:to_s) == replacement_sources.sort_by(&:to_s)
155
- end
156
-
157
- def equal_source?(source, other_source)
158
- source == other_source
159
- end
160
-
161
- def equivalent_source?(source, other_source)
162
- return false unless Bundler.settings[:allow_deployment_source_credential_changes] && source.is_a?(Source::Rubygems)
163
-
164
- equivalent_rubygems_sources?([source], [other_source])
165
- end
166
-
167
217
  def equivalent_sources?(lock_sources, replacement_sources)
168
- return false unless Bundler.settings[:allow_deployment_source_credential_changes]
169
-
170
- lock_rubygems_sources, lock_other_sources = lock_sources.partition {|s| s.is_a?(Source::Rubygems) }
171
- replacement_rubygems_sources, replacement_other_sources = replacement_sources.partition {|s| s.is_a?(Source::Rubygems) }
172
-
173
- equivalent_rubygems_sources?(lock_rubygems_sources, replacement_rubygems_sources) && equal_sources?(lock_other_sources, replacement_other_sources)
218
+ lock_sources.sort_by(&:identifier) == replacement_sources.sort_by(&:identifier)
174
219
  end
175
220
 
176
- def equivalent_rubygems_sources?(lock_sources, replacement_sources)
177
- actual_remotes = replacement_sources.map(&:remotes).flatten.uniq
178
- lock_sources.all? {|s| s.equivalent_remotes?(actual_remotes) }
221
+ def equivalent_source?(source, other_source)
222
+ source == other_source
179
223
  end
180
224
  end
181
225
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class SourceMap
5
+ attr_reader :sources, :dependencies, :locked_specs
6
+
7
+ def initialize(sources, dependencies, locked_specs)
8
+ @sources = sources
9
+ @dependencies = dependencies
10
+ @locked_specs = locked_specs
11
+ end
12
+
13
+ def pinned_spec_names(skip = nil)
14
+ direct_requirements.reject {|_, source| source == skip }.keys
15
+ end
16
+
17
+ def all_requirements
18
+ requirements = direct_requirements.dup
19
+
20
+ unmet_deps = sources.non_default_explicit_sources.map do |source|
21
+ (source.spec_names - pinned_spec_names).each do |indirect_dependency_name|
22
+ previous_source = requirements[indirect_dependency_name]
23
+ if previous_source.nil?
24
+ requirements[indirect_dependency_name] = source
25
+ else
26
+ no_ambiguous_sources = Bundler.feature_flag.bundler_3_mode?
27
+
28
+ msg = ["The gem '#{indirect_dependency_name}' was found in multiple relevant sources."]
29
+ msg.concat [previous_source, source].map {|s| " * #{s}" }.sort
30
+ msg << "You #{no_ambiguous_sources ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
31
+ msg = msg.join("\n")
32
+
33
+ raise SecurityError, msg if no_ambiguous_sources
34
+ Bundler.ui.warn "Warning: #{msg}"
35
+ end
36
+ end
37
+
38
+ source.unmet_deps
39
+ end
40
+
41
+ sources.default_source.add_dependency_names(unmet_deps.flatten - requirements.keys)
42
+
43
+ requirements
44
+ end
45
+
46
+ def direct_requirements
47
+ @direct_requirements ||= begin
48
+ requirements = {}
49
+ default = sources.default_source
50
+ dependencies.each do |dep|
51
+ dep_source = dep.source || default
52
+ dep_source.add_dependency_names(dep.name)
53
+ requirements[dep.name] = dep_source
54
+ end
55
+ requirements
56
+ end
57
+ end
58
+
59
+ def locked_requirements
60
+ @locked_requirements ||= begin
61
+ requirements = {}
62
+ locked_specs.each do |locked_spec|
63
+ source = locked_spec.source
64
+ source.add_dependency_names(locked_spec.name)
65
+ requirements[locked_spec.name] = source
66
+ end
67
+ requirements
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,56 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "tsort"
3
+ require_relative "vendored_tsort"
4
4
 
5
5
  module Bundler
6
6
  class SpecSet
7
7
  include Enumerable
8
8
  include TSort
9
9
 
10
- def initialize(specs)
10
+ attr_reader :incomplete_specs
11
+
12
+ def initialize(specs, incomplete_specs = [])
11
13
  @specs = specs
14
+ @incomplete_specs = incomplete_specs
12
15
  end
13
16
 
14
- def for(dependencies, skip = [], check = false, match_current_platform = false, raise_on_missing = true)
15
- handled = []
16
- deps = dependencies.dup
17
+ def for(dependencies, check = false, platforms = [nil])
18
+ handled = ["bundler"].product(platforms).map {|k| [k, true] }.to_h
19
+ deps = dependencies.product(platforms)
17
20
  specs = []
18
- skip += ["bundler"]
19
21
 
20
22
  loop do
21
23
  break unless dep = deps.shift
22
- next if handled.include?(dep) || skip.include?(dep.name)
23
24
 
24
- handled << dep
25
+ name = dep[0].name
26
+ platform = dep[1]
27
+
28
+ key = [name, platform]
29
+ next if handled.key?(key)
25
30
 
26
- specs_for_dep = spec_for_dependency(dep, match_current_platform)
31
+ handled[key] = true
32
+
33
+ specs_for_dep = specs_for_dependency(*dep)
27
34
  if specs_for_dep.any?
28
- specs += specs_for_dep
35
+ specs.concat(specs_for_dep)
29
36
 
30
37
  specs_for_dep.first.dependencies.each do |d|
31
38
  next if d.type == :development
32
- d = DepProxy.get_proxy(d, dep.__platform) unless match_current_platform
33
- deps << d
39
+ deps << [d, dep[1]]
34
40
  end
35
41
  elsif check
36
- return false
37
- elsif raise_on_missing
38
- others = lookup[dep.name] if match_current_platform
39
- message = "Unable to find a spec satisfying #{dep} in the set. Perhaps the lockfile is corrupted?"
40
- message += " Found #{others.join(", ")} that did not match the current platform." if others && !others.empty?
41
- raise GemNotFound, message
42
+ @incomplete_specs += lookup[name]
42
43
  end
43
44
  end
44
45
 
45
- if spec = lookup["bundler"].first
46
- specs << spec
47
- end
48
-
49
- check ? true : SpecSet.new(specs)
50
- end
51
-
52
- def valid_for?(deps)
53
- self.for(deps, [], true)
46
+ specs
54
47
  end
55
48
 
56
49
  def [](key)
@@ -64,6 +57,12 @@ module Bundler
64
57
  @sorted = nil
65
58
  end
66
59
 
60
+ def delete(spec)
61
+ @specs.delete(spec)
62
+ @lookup = nil
63
+ @sorted = nil
64
+ end
65
+
67
66
  def sort!
68
67
  self
69
68
  end
@@ -76,39 +75,35 @@ module Bundler
76
75
  lookup.dup
77
76
  end
78
77
 
79
- def materialize(deps, missing_specs = nil)
80
- materialized = self.for(deps, [], false, true, !missing_specs).to_a
81
- deps = materialized.map(&:name).uniq
82
- materialized.map! do |s|
83
- next s unless s.is_a?(LazySpecification)
84
- s.source.dependency_names = deps if s.source.respond_to?(:dependency_names=)
85
- spec = s.__materialize__
86
- unless spec
87
- unless missing_specs
88
- raise GemNotFound, "Could not find #{s.full_name} in any of the sources"
89
- end
90
- missing_specs << s
91
- end
92
- spec
93
- end
94
- SpecSet.new(missing_specs ? materialized.compact : materialized)
78
+ def materialize(deps)
79
+ materialized = self.for(deps, true)
80
+
81
+ SpecSet.new(materialized, incomplete_specs)
95
82
  end
96
83
 
97
84
  # Materialize for all the specs in the spec set, regardless of what platform they're for
98
85
  # This is in contrast to how for does platform filtering (and specifically different from how `materialize` calls `for` only for the current platform)
99
86
  # @return [Array<Gem::Specification>]
100
87
  def materialized_for_all_platforms
101
- names = @specs.map(&:name).uniq
102
88
  @specs.map do |s|
103
89
  next s unless s.is_a?(LazySpecification)
104
- s.source.dependency_names = names if s.source.respond_to?(:dependency_names=)
105
90
  s.source.remote!
106
- spec = s.__materialize__
91
+ spec = s.materialize_for_installation
107
92
  raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
108
93
  spec
109
94
  end
110
95
  end
111
96
 
97
+ def incomplete_ruby_specs?(deps)
98
+ self.for(deps, true, [Gem::Platform::RUBY])
99
+
100
+ @incomplete_specs.any?
101
+ end
102
+
103
+ def missing_specs
104
+ @specs.select {|s| s.is_a?(LazySpecification) }
105
+ end
106
+
112
107
  def merge(set)
113
108
  arr = sorted.dup
114
109
  set.each do |set_spec|
@@ -119,10 +114,20 @@ module Bundler
119
114
  SpecSet.new(arr)
120
115
  end
121
116
 
117
+ def -(other)
118
+ SpecSet.new(to_a - other.to_a)
119
+ end
120
+
122
121
  def find_by_name_and_platform(name, platform)
123
122
  @specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
124
123
  end
125
124
 
125
+ def delete_by_name_and_version(name, version)
126
+ @specs.reject! {|spec| spec.name == name && spec.version == version }
127
+ @lookup = nil
128
+ @sorted = nil
129
+ end
130
+
126
131
  def what_required(spec)
127
132
  unless req = find {|s| s.dependencies.any? {|d| d.type == :runtime && d.name == spec.name } }
128
133
  return [spec]
@@ -171,7 +176,7 @@ module Bundler
171
176
  def lookup
172
177
  @lookup ||= begin
173
178
  lookup = Hash.new {|h, k| h[k] = [] }
174
- Index.sort_specs(@specs).reverse_each do |s|
179
+ @specs.each do |s|
175
180
  lookup[s.name] << s
176
181
  end
177
182
  lookup
@@ -183,12 +188,13 @@ module Bundler
183
188
  @specs.sort_by(&:name).each {|s| yield s }
184
189
  end
185
190
 
186
- def spec_for_dependency(dep, match_current_platform)
187
- specs_for_platforms = lookup[dep.name]
188
- if match_current_platform
189
- GemHelpers.select_best_platform_match(specs_for_platforms, Bundler.local_platform)
191
+ def specs_for_dependency(dep, platform)
192
+ specs_for_name = lookup[dep.name]
193
+ if platform.nil?
194
+ matching_specs = specs_for_name.map {|s| s.materialize_for_installation if Gem::Platform.match_spec?(s) }.compact
195
+ GemHelpers.sort_best_platform_match(matching_specs, Bundler.local_platform)
190
196
  else
191
- GemHelpers.select_best_platform_match(specs_for_platforms, dep.__platform)
197
+ GemHelpers.select_best_platform_match(specs_for_name, dep.force_ruby_platform ? Gem::Platform::RUBY : platform)
192
198
  end
193
199
  end
194
200
 
@@ -26,11 +26,19 @@ module Bundler
26
26
 
27
27
  # @!group Stub Delegates
28
28
 
29
+ def manually_installed?
30
+ # This is for manually installed gems which are gems that were fixed in place after a
31
+ # failed installation. Once the issue was resolved, the user then manually created
32
+ # the gem specification using the instructions provided by `gem help install`
33
+ installed_by_version == Gem::Version.new(0)
34
+ end
35
+
29
36
  # This is defined directly to avoid having to loading the full spec
30
37
  def missing_extensions?
31
38
  return false if default_gem?
32
39
  return false if extensions.empty?
33
40
  return false if File.exist? gem_build_complete_path
41
+ return false if manually_installed?
34
42
 
35
43
  true
36
44
  end
@@ -56,9 +64,11 @@ module Bundler
56
64
  end
57
65
 
58
66
  def full_gem_path
59
- # deleted gems can have their stubs return nil, so in that case grab the
60
- # expired path from the full spec
61
- 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
62
72
  end
63
73
 
64
74
  def full_require_paths
@@ -8,11 +8,9 @@
8
8
  # this file is here to facilitate running it.
9
9
  #
10
10
 
11
- require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../<%= relative_gemfile_path %>",
13
- Pathname.new(__FILE__).realpath)
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("<%= relative_gemfile_path %>", __dir__)
14
12
 
15
- bundle_binstub = File.expand_path("../bundle", __FILE__)
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
16
14
 
17
15
  if File.file?(bundle_binstub)
18
16
  if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
@@ -41,7 +41,7 @@ m = Module.new do
41
41
  gemfile = ENV["BUNDLE_GEMFILE"]
42
42
  return gemfile if gemfile && !gemfile.empty?
43
43
 
44
- File.expand_path("../<%= relative_gemfile_path %>", __FILE__)
44
+ File.expand_path("<%= relative_gemfile_path %>", __dir__)
45
45
  end
46
46
 
47
47
  def lockfile
@@ -60,20 +60,20 @@ m = Module.new do
60
60
  Regexp.last_match(1)
61
61
  end
62
62
 
63
- def bundler_version
64
- @bundler_version ||=
63
+ def bundler_requirement
64
+ @bundler_requirement ||=
65
65
  env_var_version || cli_arg_version ||
66
- lockfile_version
66
+ bundler_requirement_for(lockfile_version)
67
67
  end
68
68
 
69
- def bundler_requirement
70
- return "#{Gem::Requirement.default}.a" unless bundler_version
69
+ def bundler_requirement_for(version)
70
+ return "#{Gem::Requirement.default}.a" unless version
71
71
 
72
- bundler_gem_version = Gem::Version.new(bundler_version)
72
+ bundler_gem_version = Gem::Version.new(version)
73
73
 
74
74
  requirement = bundler_gem_version.approximate_recommendation
75
75
 
76
- return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
76
+ return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0")
77
77
 
78
78
  requirement += ".a" if bundler_gem_version.prerelease?
79
79
 
@@ -6,9 +6,7 @@
6
6
  # this file is here to facilitate running it.
7
7
  #
8
8
 
9
- require "pathname"
10
- path = Pathname.new(__FILE__)
11
- $:.unshift File.expand_path "../<%= standalone_path %>", path.realpath
9
+ $:.unshift File.expand_path "<%= standalone_path %>", __dir__
12
10
 
13
11
  require "bundler/setup"
14
- load File.expand_path "../<%= executable_path %>", path.realpath
12
+ load File.expand_path "<%= executable_path %>", __dir__
@@ -2,6 +2,4 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
6
-
7
5
  # gem "rails"
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # A sample gems.rb
4
3
  source "https://rubygems.org"
5
4
 
6
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
7
-
8
5
  # gem "rails"