bundler 1.15.1 → 1.17.3

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 (294) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +320 -0
  3. data/README.md +17 -8
  4. data/bundler.gemspec +25 -9
  5. data/exe/bundle +1 -6
  6. data/exe/bundle_ruby +4 -3
  7. data/lib/bundler/build_metadata.rb +53 -0
  8. data/lib/bundler/capistrano.rb +5 -0
  9. data/lib/bundler/cli/add.rb +15 -6
  10. data/lib/bundler/cli/binstubs.rb +17 -9
  11. data/lib/bundler/cli/cache.rb +5 -4
  12. data/lib/bundler/cli/check.rb +3 -5
  13. data/lib/bundler/cli/clean.rb +5 -6
  14. data/lib/bundler/cli/common.rb +11 -2
  15. data/lib/bundler/cli/config.rb +2 -1
  16. data/lib/bundler/cli/console.rb +2 -1
  17. data/lib/bundler/cli/doctor.rb +48 -1
  18. data/lib/bundler/cli/exec.rb +6 -5
  19. data/lib/bundler/cli/gem.rb +13 -8
  20. data/lib/bundler/cli/info.rb +0 -1
  21. data/lib/bundler/cli/init.rb +18 -6
  22. data/lib/bundler/cli/inject.rb +1 -0
  23. data/lib/bundler/cli/install.rb +64 -77
  24. data/lib/bundler/cli/issue.rb +1 -1
  25. data/lib/bundler/cli/list.rb +58 -0
  26. data/lib/bundler/cli/lock.rb +0 -1
  27. data/lib/bundler/cli/open.rb +2 -2
  28. data/lib/bundler/cli/outdated.rb +20 -9
  29. data/lib/bundler/cli/package.rb +9 -6
  30. data/lib/bundler/cli/platform.rb +1 -0
  31. data/lib/bundler/cli/plugin.rb +1 -0
  32. data/lib/bundler/cli/pristine.rb +20 -6
  33. data/lib/bundler/cli/remove.rb +18 -0
  34. data/lib/bundler/cli/show.rb +0 -1
  35. data/lib/bundler/cli/update.rb +35 -7
  36. data/lib/bundler/cli/viz.rb +4 -0
  37. data/lib/bundler/cli.rb +234 -90
  38. data/lib/bundler/compact_index_client/cache.rb +1 -2
  39. data/lib/bundler/compact_index_client/updater.rb +35 -7
  40. data/lib/bundler/compact_index_client.rb +1 -0
  41. data/lib/bundler/compatibility_guard.rb +14 -0
  42. data/lib/bundler/constants.rb +1 -0
  43. data/lib/bundler/current_ruby.rb +13 -5
  44. data/lib/bundler/definition.rb +192 -139
  45. data/lib/bundler/dep_proxy.rb +3 -1
  46. data/lib/bundler/dependency.rb +9 -9
  47. data/lib/bundler/deployment.rb +1 -1
  48. data/lib/bundler/deprecate.rb +15 -3
  49. data/lib/bundler/dsl.rb +115 -64
  50. data/lib/bundler/endpoint_specification.rb +10 -1
  51. data/lib/bundler/env.rb +90 -29
  52. data/lib/bundler/environment_preserver.rb +27 -6
  53. data/lib/bundler/errors.rb +1 -0
  54. data/lib/bundler/feature_flag.rb +46 -4
  55. data/lib/bundler/fetcher/base.rb +1 -0
  56. data/lib/bundler/fetcher/compact_index.rb +2 -11
  57. data/lib/bundler/fetcher/dependency.rb +2 -1
  58. data/lib/bundler/fetcher/downloader.rb +11 -5
  59. data/lib/bundler/fetcher/index.rb +3 -2
  60. data/lib/bundler/fetcher.rb +18 -11
  61. data/lib/bundler/friendly_errors.rb +6 -1
  62. data/lib/bundler/gem_helper.rb +19 -10
  63. data/lib/bundler/gem_helpers.rb +1 -0
  64. data/lib/bundler/gem_remote_fetcher.rb +1 -0
  65. data/lib/bundler/gem_tasks.rb +1 -0
  66. data/lib/bundler/gem_version_promoter.rb +17 -2
  67. data/lib/bundler/gemdeps.rb +1 -0
  68. data/lib/bundler/graph.rb +1 -0
  69. data/lib/bundler/index.rb +8 -8
  70. data/lib/bundler/injector.rb +192 -30
  71. data/lib/bundler/inline.rb +10 -10
  72. data/lib/bundler/installer/gem_installer.rb +12 -2
  73. data/lib/bundler/installer/parallel_installer.rb +78 -42
  74. data/lib/bundler/installer/standalone.rb +1 -0
  75. data/lib/bundler/installer.rb +138 -53
  76. data/lib/bundler/lazy_specification.rb +3 -2
  77. data/lib/bundler/lockfile_generator.rb +95 -0
  78. data/lib/bundler/lockfile_parser.rb +10 -4
  79. data/lib/bundler/match_platform.rb +1 -0
  80. data/lib/bundler/mirror.rb +8 -5
  81. data/lib/bundler/plugin/api/source.rb +9 -2
  82. data/lib/bundler/plugin/events.rb +61 -0
  83. data/lib/bundler/plugin/index.rb +7 -2
  84. data/lib/bundler/plugin/installer.rb +7 -6
  85. data/lib/bundler/plugin/source_list.rb +7 -8
  86. data/lib/bundler/plugin.rb +13 -5
  87. data/lib/bundler/process_lock.rb +24 -0
  88. data/lib/bundler/psyched_yaml.rb +10 -0
  89. data/lib/bundler/remote_specification.rb +10 -1
  90. data/lib/bundler/resolver/spec_group.rb +106 -0
  91. data/lib/bundler/resolver.rb +158 -195
  92. data/lib/bundler/retry.rb +1 -0
  93. data/lib/bundler/ruby_dsl.rb +1 -0
  94. data/lib/bundler/ruby_version.rb +2 -1
  95. data/lib/bundler/rubygems_ext.rb +5 -4
  96. data/lib/bundler/rubygems_gem_installer.rb +31 -1
  97. data/lib/bundler/rubygems_integration.rb +71 -32
  98. data/lib/bundler/runtime.rb +11 -9
  99. data/lib/bundler/settings/validator.rb +102 -0
  100. data/lib/bundler/settings.rb +213 -86
  101. data/lib/bundler/setup.rb +4 -7
  102. data/lib/bundler/shared_helpers.rb +131 -26
  103. data/lib/bundler/similarity_detector.rb +1 -0
  104. data/lib/bundler/source/gemspec.rb +1 -0
  105. data/lib/bundler/source/git/git_proxy.rb +21 -11
  106. data/lib/bundler/source/git.rb +24 -19
  107. data/lib/bundler/source/metadata.rb +62 -0
  108. data/lib/bundler/source/path/installer.rb +2 -0
  109. data/lib/bundler/source/path.rb +11 -7
  110. data/lib/bundler/source/rubygems/remote.rb +8 -2
  111. data/lib/bundler/source/rubygems.rb +161 -84
  112. data/lib/bundler/source.rb +36 -0
  113. data/lib/bundler/source_list.rb +75 -15
  114. data/lib/bundler/spec_set.rb +12 -6
  115. data/lib/bundler/ssl_certs/certificate_manager.rb +2 -1
  116. data/lib/bundler/stub_specification.rb +1 -0
  117. data/lib/bundler/templates/.document +1 -0
  118. data/lib/bundler/templates/Executable +12 -0
  119. data/lib/bundler/templates/Executable.bundler +105 -0
  120. data/lib/bundler/templates/Gemfile +3 -0
  121. data/lib/bundler/templates/gems.rb +8 -0
  122. data/lib/bundler/templates/newgem/Gemfile.tt +2 -0
  123. data/lib/bundler/templates/newgem/README.md.tt +1 -1
  124. data/lib/bundler/templates/newgem/gitignore.tt +0 -1
  125. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +1 -0
  126. data/lib/bundler/templates/newgem/newgem.gemspec.tt +12 -3
  127. data/lib/bundler/templates/newgem/rspec.tt +1 -0
  128. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +0 -2
  129. data/lib/bundler/templates/newgem/{.travis.yml.tt → travis.yml.tt} +2 -0
  130. data/lib/bundler/ui/rg_proxy.rb +1 -0
  131. data/lib/bundler/ui/shell.rb +17 -4
  132. data/lib/bundler/ui/silent.rb +1 -0
  133. data/lib/bundler/ui.rb +1 -0
  134. data/lib/bundler/uri_credentials_filter.rb +1 -0
  135. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1638 -0
  136. data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +26 -0
  137. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +7 -0
  138. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +1 -0
  139. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +1 -0
  140. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +1 -0
  141. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +1 -0
  142. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +1 -0
  143. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -0
  144. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +1 -0
  145. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +1 -0
  146. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +1 -0
  147. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +15 -4
  148. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +3 -2
  149. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +75 -7
  150. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +2 -1
  151. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -0
  152. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +3 -1
  153. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +491 -148
  154. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +1 -0
  155. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +8 -4
  156. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +2 -0
  157. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +3 -1
  158. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +1 -0
  159. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +1 -0
  160. data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +9 -1
  161. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +45 -8
  162. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +9 -3
  163. data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -3
  164. data/lib/bundler/vendor/thor/lib/thor/base.rb +27 -4
  165. data/lib/bundler/vendor/thor/lib/thor/command.rb +9 -7
  166. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +12 -0
  167. data/lib/bundler/vendor/thor/lib/thor/group.rb +1 -1
  168. data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +2 -0
  169. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +5 -5
  170. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +6 -5
  171. data/lib/bundler/vendor/thor/lib/thor/runner.rb +6 -4
  172. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +10 -9
  173. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  174. data/lib/bundler/vendor/thor/lib/thor.rb +25 -8
  175. data/lib/bundler/vendored_fileutils.rb +9 -0
  176. data/lib/bundler/vendored_molinillo.rb +1 -0
  177. data/lib/bundler/vendored_persistent.rb +35 -0
  178. data/lib/bundler/vendored_thor.rb +1 -0
  179. data/lib/bundler/version.rb +6 -2
  180. data/lib/bundler/version_ranges.rb +1 -0
  181. data/lib/bundler/vlad.rb +5 -0
  182. data/lib/bundler/worker.rb +1 -0
  183. data/lib/bundler/yaml_serializer.rb +3 -3
  184. data/lib/bundler.rb +86 -52
  185. data/man/bundle-add.1 +18 -3
  186. data/man/bundle-add.1.txt +26 -14
  187. data/man/bundle-add.ronn +13 -2
  188. data/man/bundle-binstubs.1 +11 -1
  189. data/man/bundle-binstubs.1.txt +33 -18
  190. data/man/bundle-binstubs.ronn +15 -1
  191. data/man/bundle-check.1 +4 -4
  192. data/man/bundle-check.1.txt +15 -14
  193. data/man/bundle-check.ronn +3 -3
  194. data/man/bundle-clean.1 +1 -1
  195. data/man/bundle-clean.1.txt +10 -10
  196. data/man/bundle-config.1 +129 -29
  197. data/man/bundle-config.1.txt +285 -174
  198. data/man/bundle-config.ronn +167 -88
  199. data/man/bundle-doctor.1 +44 -0
  200. data/man/bundle-doctor.1.txt +44 -0
  201. data/man/bundle-doctor.ronn +33 -0
  202. data/man/bundle-exec.1 +6 -3
  203. data/man/bundle-exec.1.txt +78 -71
  204. data/man/bundle-exec.ronn +10 -3
  205. data/man/bundle-gem.1 +4 -4
  206. data/man/bundle-gem.1.txt +41 -40
  207. data/man/bundle-gem.ronn +3 -2
  208. data/man/bundle-info.1 +1 -1
  209. data/man/bundle-info.1.txt +8 -8
  210. data/man/bundle-init.1 +9 -4
  211. data/man/bundle-init.1.txt +23 -13
  212. data/man/bundle-init.ronn +15 -4
  213. data/man/bundle-inject.1 +4 -4
  214. data/man/bundle-inject.1.txt +10 -10
  215. data/man/bundle-inject.ronn +3 -3
  216. data/man/bundle-install.1 +31 -28
  217. data/man/bundle-install.1.txt +205 -194
  218. data/man/bundle-install.ronn +44 -35
  219. data/man/bundle-list.1 +50 -0
  220. data/man/bundle-list.1.txt +43 -0
  221. data/man/bundle-list.ronn +33 -0
  222. data/man/bundle-lock.1 +1 -1
  223. data/man/bundle-lock.1.txt +47 -47
  224. data/man/bundle-lock.ronn +1 -1
  225. data/man/bundle-open.1 +1 -1
  226. data/man/bundle-open.1.txt +7 -7
  227. data/man/bundle-outdated.1 +7 -3
  228. data/man/bundle-outdated.1.txt +40 -36
  229. data/man/bundle-outdated.ronn +6 -2
  230. data/man/bundle-package.1 +6 -3
  231. data/man/bundle-package.1.txt +44 -39
  232. data/man/bundle-package.ronn +7 -2
  233. data/man/bundle-platform.1 +1 -1
  234. data/man/bundle-platform.1.txt +13 -13
  235. data/man/bundle-pristine.1 +21 -3
  236. data/man/bundle-pristine.1.txt +33 -10
  237. data/man/bundle-pristine.ronn +24 -3
  238. data/man/bundle-remove.1 +31 -0
  239. data/man/bundle-remove.1.txt +34 -0
  240. data/man/bundle-remove.ronn +23 -0
  241. data/man/bundle-show.1 +3 -3
  242. data/man/bundle-show.1.txt +14 -12
  243. data/man/bundle-show.ronn +3 -2
  244. data/man/bundle-update.1 +13 -9
  245. data/man/bundle-update.1.txt +133 -130
  246. data/man/bundle-update.ronn +21 -17
  247. data/man/bundle-viz.1 +7 -7
  248. data/man/bundle-viz.1.txt +17 -15
  249. data/man/bundle-viz.ronn +6 -6
  250. data/man/bundle.1 +31 -32
  251. data/man/bundle.1.txt +63 -75
  252. data/man/bundle.ronn +35 -47
  253. data/man/gemfile.5 +44 -8
  254. data/man/gemfile.5.ronn +54 -8
  255. data/man/gemfile.5.txt +218 -165
  256. data/man/index.txt +25 -15
  257. metadata +36 -44
  258. data/.codeclimate.yml +0 -25
  259. data/.gitignore +0 -18
  260. data/.rspec +0 -3
  261. data/.rubocop.yml +0 -131
  262. data/.rubocop_todo.yml +0 -418
  263. data/.travis.yml +0 -122
  264. data/CODE_OF_CONDUCT.md +0 -42
  265. data/CONTRIBUTING.md +0 -17
  266. data/Rakefile +0 -346
  267. data/bin/rake +0 -19
  268. data/bin/rspec +0 -15
  269. data/bin/rubocop +0 -17
  270. data/bin/with_rubygems +0 -39
  271. data/doc/README.md +0 -30
  272. data/doc/TROUBLESHOOTING.md +0 -64
  273. data/doc/contributing/BUG_TRIAGE.md +0 -36
  274. data/doc/contributing/COMMUNITY.md +0 -13
  275. data/doc/contributing/GETTING_HELP.md +0 -11
  276. data/doc/contributing/HOW_YOU_CAN_HELP.md +0 -27
  277. data/doc/contributing/ISSUES.md +0 -51
  278. data/doc/contributing/README.md +0 -38
  279. data/doc/development/NEW_FEATURES.md +0 -10
  280. data/doc/development/PULL_REQUESTS.md +0 -40
  281. data/doc/development/README.md +0 -19
  282. data/doc/development/RELEASING.md +0 -9
  283. data/doc/development/SETUP.md +0 -29
  284. data/doc/documentation/README.md +0 -29
  285. data/doc/documentation/VISION.md +0 -26
  286. data/doc/documentation/WRITING.md +0 -54
  287. data/lib/bundler/postit_trampoline.rb +0 -73
  288. data/lib/bundler/vendor/postit/lib/postit/environment.rb +0 -44
  289. data/lib/bundler/vendor/postit/lib/postit/installer.rb +0 -28
  290. data/lib/bundler/vendor/postit/lib/postit/parser.rb +0 -21
  291. data/lib/bundler/vendor/postit/lib/postit/setup.rb +0 -12
  292. data/lib/bundler/vendor/postit/lib/postit/version.rb +0 -3
  293. data/lib/bundler/vendor/postit/lib/postit.rb +0 -15
  294. data/task/release.rake +0 -116
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "bundler/plugin/api"
3
4
 
4
5
  module Bundler
5
6
  module Plugin
6
7
  autoload :DSL, "bundler/plugin/dsl"
8
+ autoload :Events, "bundler/plugin/events"
7
9
  autoload :Index, "bundler/plugin/index"
8
10
  autoload :Installer, "bundler/plugin/installer"
9
11
  autoload :SourceList, "bundler/plugin/source_list"
@@ -65,7 +67,7 @@ module Bundler
65
67
  installed_specs = Installer.new.install_definition(definition)
66
68
 
67
69
  save_plugins plugins, installed_specs, builder.inferred_plugins
68
- rescue => e
70
+ rescue RuntimeError => e
69
71
  unless e.is_a?(GemfileError)
70
72
  Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"
71
73
  end
@@ -79,8 +81,8 @@ module Bundler
79
81
 
80
82
  # The directory root for all plugin related data
81
83
  #
82
- # Points to root in app_config_path if ran in an app else points to the one
83
- # in user_bundle_path
84
+ # If run in an app, points to local root, in app_config_path
85
+ # Otherwise, points to global root, in Bundler.user_bundle_path("plugin")
84
86
  def root
85
87
  @root ||= if SharedHelpers.in_bundle?
86
88
  local_root
@@ -95,7 +97,7 @@ module Bundler
95
97
 
96
98
  # The global directory root for all plugin related data
97
99
  def global_root
98
- Bundler.user_bundle_path.join("plugin")
100
+ Bundler.user_bundle_path("plugin")
99
101
  end
100
102
 
101
103
  # The cache directory for plugin stuffs
@@ -154,6 +156,9 @@ module Bundler
154
156
  # To be called via the API to register a hooks and corresponding block that
155
157
  # will be called to handle the hook
156
158
  def add_hook(event, &block)
159
+ unless Events.defined_event?(event)
160
+ raise ArgumentError, "Event '#{event}' not defined in Bundler::Plugin::Events"
161
+ end
157
162
  @hooks_by_event[event.to_s] << block
158
163
  end
159
164
 
@@ -165,6 +170,9 @@ module Bundler
165
170
  # @param [String] event
166
171
  def hook(event, *args, &arg_blk)
167
172
  return unless Bundler.feature_flag.plugins?
173
+ unless Events.defined_event?(event)
174
+ raise ArgumentError, "Event '#{event}' not defined in Bundler::Plugin::Events"
175
+ end
168
176
 
169
177
  plugins = index.hook_plugins(event)
170
178
  return unless plugins.any?
@@ -263,7 +271,7 @@ module Bundler
263
271
  load path.join(PLUGIN_FILE_NAME)
264
272
 
265
273
  @loaded_plugin_names << name
266
- rescue => e
274
+ rescue RuntimeError => e
267
275
  Bundler.ui.error "Failed loading plugin #{name}: #{e.message}"
268
276
  raise
269
277
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class ProcessLock
5
+ def self.lock(bundle_path = Bundler.bundle_path)
6
+ lock_file_path = File.join(bundle_path, "bundler.lock")
7
+ has_lock = false
8
+
9
+ File.open(lock_file_path, "w") do |f|
10
+ f.flock(File::LOCK_EX)
11
+ has_lock = true
12
+ yield
13
+ f.flock(File::LOCK_UN)
14
+ end
15
+ rescue Errno::EACCES, Errno::ENOLCK, *[SharedHelpers.const_get_safely(:ENOTSUP, Errno)].compact
16
+ # In the case the user does not have access to
17
+ # create the lock file or is using NFS where
18
+ # locks are not available we skip locking.
19
+ yield
20
+ ensure
21
+ FileUtils.rm_f(lock_file_path) if has_lock
22
+ end
23
+ end
24
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Psych could be a gem, so try to ask for it
3
4
  begin
4
5
  gem "psych"
@@ -25,3 +26,12 @@ module Bundler
25
26
  YamlLibrarySyntaxError = ::ArgumentError
26
27
  end
27
28
  end
29
+
30
+ require "bundler/deprecate"
31
+ begin
32
+ Bundler::Deprecate.skip_during do
33
+ require "rubygems/safe_yaml"
34
+ end
35
+ rescue LoadError
36
+ # it's OK if the file isn't there
37
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "uri"
3
4
 
4
5
  module Bundler
@@ -73,7 +74,15 @@ module Bundler
73
74
  end
74
75
 
75
76
  def dependencies
76
- @dependencies || method_missing(:dependencies)
77
+ @dependencies ||= begin
78
+ deps = method_missing(:dependencies)
79
+
80
+ # allow us to handle when the specs dependencies are an array of array of string
81
+ # see https://github.com/bundler/bundler/issues/5797
82
+ deps = deps.map {|d| d.is_a?(Gem::Dependency) ? d : Gem::Dependency.new(*d) }
83
+
84
+ deps
85
+ end
77
86
  end
78
87
 
79
88
  def git_version
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class Resolver
5
+ class SpecGroup
6
+ include GemHelpers
7
+
8
+ attr_accessor :name, :version, :source
9
+ attr_accessor :ignores_bundler_dependencies
10
+
11
+ def initialize(all_specs)
12
+ raise ArgumentError, "cannot initialize with an empty value" unless exemplary_spec = all_specs.first
13
+ @name = exemplary_spec.name
14
+ @version = exemplary_spec.version
15
+ @source = exemplary_spec.source
16
+
17
+ @activated_platforms = []
18
+ @dependencies = nil
19
+ @specs = Hash.new do |specs, platform|
20
+ specs[platform] = select_best_platform_match(all_specs, platform)
21
+ end
22
+ @ignores_bundler_dependencies = true
23
+ end
24
+
25
+ def to_specs
26
+ @activated_platforms.map do |p|
27
+ next unless s = @specs[p]
28
+ lazy_spec = LazySpecification.new(name, version, s.platform, source)
29
+ lazy_spec.dependencies.replace s.dependencies
30
+ lazy_spec
31
+ end.compact
32
+ end
33
+
34
+ def activate_platform!(platform)
35
+ return unless for?(platform)
36
+ return if @activated_platforms.include?(platform)
37
+ @activated_platforms << platform
38
+ end
39
+
40
+ def for?(platform)
41
+ spec = @specs[platform]
42
+ !spec.nil?
43
+ end
44
+
45
+ def to_s
46
+ @to_s ||= "#{name} (#{version})"
47
+ end
48
+
49
+ def dependencies_for_activated_platforms
50
+ dependencies = @activated_platforms.map {|p| __dependencies[p] }
51
+ metadata_dependencies = @activated_platforms.map do |platform|
52
+ metadata_dependencies(@specs[platform], platform)
53
+ end
54
+ dependencies.concat(metadata_dependencies).flatten
55
+ end
56
+
57
+ def ==(other)
58
+ return unless other.is_a?(SpecGroup)
59
+ name == other.name &&
60
+ version == other.version &&
61
+ source == other.source
62
+ end
63
+
64
+ def eql?(other)
65
+ name.eql?(other.name) &&
66
+ version.eql?(other.version) &&
67
+ source.eql?(other.source)
68
+ end
69
+
70
+ def hash
71
+ to_s.hash ^ source.hash
72
+ end
73
+
74
+ private
75
+
76
+ def __dependencies
77
+ @dependencies = Hash.new do |dependencies, platform|
78
+ dependencies[platform] = []
79
+ if spec = @specs[platform]
80
+ spec.dependencies.each do |dep|
81
+ next if dep.type == :development
82
+ next if @ignores_bundler_dependencies && dep.name == "bundler".freeze
83
+ dependencies[platform] << DepProxy.new(dep, platform)
84
+ end
85
+ end
86
+ dependencies[platform]
87
+ end
88
+ end
89
+
90
+ def metadata_dependencies(spec, platform)
91
+ return [] unless spec
92
+ # Only allow endpoint specifications since they won't hit the network to
93
+ # fetch the full gemspec when calling required_ruby_version
94
+ return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
95
+ dependencies = []
96
+ if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
97
+ dependencies << DepProxy.new(Gem::Dependency.new("ruby\0", spec.required_ruby_version), platform)
98
+ end
99
+ if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
100
+ dependencies << DepProxy.new(Gem::Dependency.new("rubygems\0", spec.required_rubygems_version), platform)
101
+ end
102
+ dependencies
103
+ end
104
+ end
105
+ end
106
+ end
@@ -1,178 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bundler
3
4
  class Resolver
4
5
  require "bundler/vendored_molinillo"
5
-
6
- class Molinillo::VersionConflict
7
- def printable_dep(dep)
8
- if dep.is_a?(Bundler::Dependency)
9
- DepProxy.new(dep, dep.platforms.join(", ")).to_s.strip
10
- else
11
- dep.to_s
12
- end
13
- end
14
-
15
- def message
16
- conflicts.sort.reduce(String.new) do |o, (name, conflict)|
17
- o << %(\nBundler could not find compatible versions for gem "#{name}":\n)
18
- if conflict.locked_requirement
19
- o << %( In snapshot (#{Bundler.default_lockfile.basename}):\n)
20
- o << %( #{printable_dep(conflict.locked_requirement)}\n)
21
- o << %(\n)
22
- end
23
- o << %( In Gemfile:\n)
24
- trees = conflict.requirement_trees
25
-
26
- maximal = 1.upto(trees.size).map do |size|
27
- trees.map(&:last).flatten(1).combination(size).to_a
28
- end.flatten(1).select do |deps|
29
- Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
30
- end.min_by(&:size)
31
- trees.reject! {|t| !maximal.include?(t.last) } if maximal
32
-
33
- o << trees.sort_by {|t| t.reverse.map(&:name) }.map do |tree|
34
- t = String.new
35
- depth = 2
36
- tree.each do |req|
37
- t << " " * depth << req.to_s
38
- unless tree.last == req
39
- if spec = conflict.activated_by_name[req.name]
40
- t << %( was resolved to #{spec.version}, which)
41
- end
42
- t << %( depends on)
43
- end
44
- t << %(\n)
45
- depth += 1
46
- end
47
- t
48
- end.join("\n")
49
-
50
- if name == "bundler"
51
- o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
52
- other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new Bundler::VERSION)
53
- end
54
-
55
- if name == "bundler" && other_bundler_required
56
- o << "\n"
57
- o << "This Gemfile requires a different version of Bundler.\n"
58
- o << "Perhaps you need to update Bundler by running `gem install bundler`?\n"
59
- end
60
- if conflict.locked_requirement
61
- o << "\n"
62
- o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
63
- o << %(the gems in your Gemfile, which may resolve the conflict.\n)
64
- elsif !conflict.existing
65
- o << "\n"
66
- if conflict.requirement_trees.first.size > 1
67
- o << "Could not find gem '#{conflict.requirement}', which is required by "
68
- o << "gem '#{conflict.requirement_trees.first[-2]}', in any of the sources."
69
- else
70
- o << "Could not find gem '#{conflict.requirement}' in any of the sources\n"
71
- end
72
- end
73
- o
74
- end.strip
75
- end
76
- end
77
-
78
- class SpecGroup < Array
79
- include GemHelpers
80
-
81
- attr_reader :activated
82
-
83
- def initialize(a)
84
- super
85
- @required_by = []
86
- @activated_platforms = []
87
- @dependencies = nil
88
- @specs = Hash.new do |specs, platform|
89
- specs[platform] = select_best_platform_match(self, platform)
90
- end
91
- end
92
-
93
- def initialize_copy(o)
94
- super
95
- @activated_platforms = o.activated.dup
96
- end
97
-
98
- def to_specs
99
- @activated_platforms.map do |p|
100
- next unless s = @specs[p]
101
- lazy_spec = LazySpecification.new(name, version, s.platform, source)
102
- lazy_spec.dependencies.replace s.dependencies
103
- lazy_spec
104
- end.compact
105
- end
106
-
107
- def activate_platform!(platform)
108
- return unless for?(platform)
109
- return if @activated_platforms.include?(platform)
110
- @activated_platforms << platform
111
- end
112
-
113
- def name
114
- @name ||= first.name
115
- end
116
-
117
- def version
118
- @version ||= first.version
119
- end
120
-
121
- def source
122
- @source ||= first.source
123
- end
124
-
125
- def for?(platform)
126
- spec = @specs[platform]
127
- !spec.nil?
128
- end
129
-
130
- def to_s
131
- "#{name} (#{version})"
132
- end
133
-
134
- def dependencies_for_activated_platforms
135
- dependencies = @activated_platforms.map {|p| __dependencies[p] }
136
- metadata_dependencies = @activated_platforms.map do |platform|
137
- metadata_dependencies(@specs[platform], platform)
138
- end
139
- dependencies.concat(metadata_dependencies).flatten
140
- end
141
-
142
- def platforms_for_dependency_named(dependency)
143
- __dependencies.select {|_, deps| deps.map(&:name).include? dependency }.keys
144
- end
145
-
146
- private
147
-
148
- def __dependencies
149
- @dependencies = Hash.new do |dependencies, platform|
150
- dependencies[platform] = []
151
- if spec = @specs[platform]
152
- spec.dependencies.each do |dep|
153
- next if dep.type == :development
154
- dependencies[platform] << DepProxy.new(dep, platform)
155
- end
156
- end
157
- dependencies[platform]
158
- end
159
- end
160
-
161
- def metadata_dependencies(spec, platform)
162
- return [] unless spec
163
- # Only allow endpoint specifications since they won't hit the network to
164
- # fetch the full gemspec when calling required_ruby_version
165
- return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
166
- dependencies = []
167
- if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
168
- dependencies << DepProxy.new(Gem::Dependency.new("ruby\0", spec.required_ruby_version), platform)
169
- end
170
- if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
171
- dependencies << DepProxy.new(Gem::Dependency.new("rubygems\0", spec.required_rubygems_version), platform)
172
- end
173
- dependencies
174
- end
175
- end
6
+ require "bundler/resolver/spec_group"
176
7
 
177
8
  # Figures out the best possible configuration of gems that satisfies
178
9
  # the list of passed dependencies and any child dependencies without
@@ -206,16 +37,23 @@ module Bundler
206
37
  additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
207
38
  @platforms = platforms
208
39
  @gem_version_promoter = gem_version_promoter
40
+ @allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts?
41
+ @lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
42
+ @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
209
43
  end
210
44
 
211
45
  def start(requirements)
46
+ @gem_version_promoter.prerelease_specified = @prerelease_specified = {}
47
+ requirements.each {|dep| @prerelease_specified[dep.name] ||= dep.prerelease? }
48
+
212
49
  verify_gemfile_dependencies_are_found!(requirements)
213
50
  dg = @resolver.resolve(requirements, @base_dg)
214
51
  dg.map(&:payload).
215
52
  reject {|sg| sg.name.end_with?("\0") }.
216
53
  map(&:to_specs).flatten
217
54
  rescue Molinillo::VersionConflict => e
218
- raise VersionConflict.new(e.conflicts.keys.uniq, e.message)
55
+ message = version_conflict_message(e)
56
+ raise VersionConflict.new(e.conflicts.keys.uniq, message)
219
57
  rescue Molinillo::CircularDependencyError => e
220
58
  names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
221
59
  raise CyclicDependencyError, "Your bundle requires gems that depend" \
@@ -266,9 +104,18 @@ module Bundler
266
104
  search = @search_for[dependency] ||= begin
267
105
  index = index_for(dependency)
268
106
  results = index.search(dependency, @base[dependency.name])
107
+
269
108
  if vertex = @base_dg.vertex_named(dependency.name)
270
109
  locked_requirement = vertex.payload.requirement
271
110
  end
111
+
112
+ if !@prerelease_specified[dependency.name] && (!@use_gvp || locked_requirement.nil?)
113
+ # Move prereleases to the beginning of the list, so they're considered
114
+ # last during resolution.
115
+ pre, results = results.partition {|spec| spec.version.prerelease? }
116
+ results = pre + results
117
+ end
118
+
272
119
  spec_groups = if results.any?
273
120
  nested = []
274
121
  results.each do |spec|
@@ -281,14 +128,16 @@ module Bundler
281
128
  end
282
129
  nested.reduce([]) do |groups, (version, specs)|
283
130
  next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
284
- groups << SpecGroup.new(specs)
131
+ spec_group = SpecGroup.new(specs)
132
+ spec_group.ignores_bundler_dependencies = @allow_bundler_dependency_conflicts
133
+ groups << spec_group
285
134
  end
286
135
  else
287
136
  []
288
137
  end
289
138
  # GVP handles major itself, but it's still a bit risky to trust it with it
290
139
  # until we get it settled with new behavior. For 2.x it can take over all cases.
291
- if @gem_version_promoter.major?
140
+ if !@use_gvp
292
141
  spec_groups
293
142
  else
294
143
  @gem_version_promoter.sort_versions(dependency, spec_groups)
@@ -298,7 +147,20 @@ module Bundler
298
147
  end
299
148
 
300
149
  def index_for(dependency)
301
- @source_requirements[dependency.name] || @index
150
+ source = @source_requirements[dependency.name]
151
+ if source
152
+ source.specs
153
+ elsif @lockfile_uses_separate_rubygems_sources
154
+ Index.build do |idx|
155
+ if dependency.all_sources
156
+ dependency.all_sources.each {|s| idx.add_source(s.specs) if s }
157
+ else
158
+ idx.add_source @source_requirements[:default].specs
159
+ end
160
+ end
161
+ else
162
+ @index
163
+ end
302
164
  end
303
165
 
304
166
  def name_for(dependency)
@@ -323,19 +185,45 @@ module Bundler
323
185
  true
324
186
  end
325
187
 
188
+ def relevant_sources_for_vertex(vertex)
189
+ if vertex.root?
190
+ [@source_requirements[vertex.name]]
191
+ elsif @lockfile_uses_separate_rubygems_sources
192
+ vertex.recursive_predecessors.map do |v|
193
+ @source_requirements[v.name]
194
+ end << @source_requirements[:default]
195
+ end
196
+ end
197
+
326
198
  def sort_dependencies(dependencies, activated, conflicts)
327
199
  dependencies.sort_by do |dependency|
200
+ dependency.all_sources = relevant_sources_for_vertex(activated.vertex_named(dependency.name))
328
201
  name = name_for(dependency)
202
+ vertex = activated.vertex_named(name)
329
203
  [
330
204
  @base_dg.vertex_named(name) ? 0 : 1,
331
- activated.vertex_named(name).payload ? 0 : 1,
205
+ vertex.payload ? 0 : 1,
206
+ vertex.root? ? 0 : 1,
332
207
  amount_constrained(dependency),
333
208
  conflicts[name] ? 0 : 1,
334
- activated.vertex_named(name).payload ? 0 : search_for(dependency).count,
209
+ vertex.payload ? 0 : search_for(dependency).count,
210
+ self.class.platform_sort_key(dependency.__platform),
335
211
  ]
336
212
  end
337
213
  end
338
214
 
215
+ # Sort platforms from most general to most specific
216
+ def self.sort_platforms(platforms)
217
+ platforms.sort_by do |platform|
218
+ platform_sort_key(platform)
219
+ end
220
+ end
221
+
222
+ def self.platform_sort_key(platform)
223
+ return ["", "", ""] if Gem::Platform::RUBY == platform
224
+ platform.to_a.map {|part| part || "" }
225
+ end
226
+
339
227
  private
340
228
 
341
229
  # returns an integer \in (-\infty, 0]
@@ -355,7 +243,8 @@ module Bundler
355
243
  if all <= 1
356
244
  all - 1_000_000
357
245
  else
358
- search = search_for(dependency).size
246
+ search = search_for(dependency)
247
+ search = @prerelease_specified[dependency.name] ? search.count : search.count {|s| !s.version.prerelease? }
359
248
  search - all
360
249
  end
361
250
  end
@@ -364,32 +253,34 @@ module Bundler
364
253
 
365
254
  def verify_gemfile_dependencies_are_found!(requirements)
366
255
  requirements.each do |requirement|
367
- next if requirement.name == "bundler"
256
+ name = requirement.name
257
+ next if name == "bundler"
368
258
  next unless search_for(requirement).empty?
369
- if (base = @base[requirement.name]) && !base.empty?
259
+
260
+ cache_message = begin
261
+ " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
262
+ rescue GemfileNotFound
263
+ nil
264
+ end
265
+
266
+ if (base = @base[name]) && !base.empty?
370
267
  version = base.first.version
371
268
  message = "You have requested:\n" \
372
- " #{requirement.name} #{requirement.requirement}\n\n" \
373
- "The bundle currently has #{requirement.name} locked at #{version}.\n" \
374
- "Try running `bundle update #{requirement.name}`\n\n" \
269
+ " #{name} #{requirement.requirement}\n\n" \
270
+ "The bundle currently has #{name} locked at #{version}.\n" \
271
+ "Try running `bundle update #{name}`\n\n" \
375
272
  "If you are updating multiple gems in your Gemfile at once,\n" \
376
273
  "try passing them all to `bundle update`"
377
- elsif requirement.source
378
- name = requirement.name
379
- specs = @source_requirements[name][name]
274
+ elsif source = @source_requirements[name]
275
+ specs = source.specs[name]
380
276
  versions_with_platforms = specs.map {|s| [s.version, s.platform] }
381
- message = String.new("Could not find gem '#{requirement}' in #{requirement.source}.\n")
277
+ message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source}#{cache_message}.\n")
382
278
  message << if versions_with_platforms.any?
383
- "Source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}"
279
+ "The source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}"
384
280
  else
385
- "Source does not contain any versions of '#{requirement}'"
281
+ "The source does not contain any versions of '#{name}'"
386
282
  end
387
283
  else
388
- cache_message = begin
389
- " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
390
- rescue GemfileNotFound
391
- nil
392
- end
393
284
  message = "Could not find gem '#{requirement}' in any of the gem sources " \
394
285
  "listed in your Gemfile#{cache_message}."
395
286
  end
@@ -402,9 +293,81 @@ module Bundler
402
293
  version = vwp.first
403
294
  platform = vwp.last
404
295
  version_platform_str = String.new(version.to_s)
405
- version_platform_str << " #{platform}" unless platform.nil?
296
+ version_platform_str << " #{platform}" unless platform.nil? || platform == Gem::Platform::RUBY
297
+ version_platform_str
406
298
  end
407
299
  version_platform_strs.join(", ")
408
300
  end
301
+
302
+ def version_conflict_message(e)
303
+ e.message_with_trees(
304
+ :solver_name => "Bundler",
305
+ :possibility_type => "gem",
306
+ :reduce_trees => lambda do |trees|
307
+ # called first, because we want to reduce the amount of work required to find maximal empty sets
308
+ trees = trees.uniq {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
309
+
310
+ # bail out if tree size is too big for Array#combination to make any sense
311
+ return trees if trees.size > 15
312
+ maximal = 1.upto(trees.size).map do |size|
313
+ trees.map(&:last).flatten(1).combination(size).to_a
314
+ end.flatten(1).select do |deps|
315
+ Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
316
+ end.min_by(&:size)
317
+ trees.reject! {|t| !maximal.include?(t.last) } if maximal
318
+
319
+ trees = trees.sort_by {|t| t.flatten.map(&:to_s) }
320
+ trees.uniq! {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
321
+
322
+ trees.sort_by {|t| t.reverse.map(&:name) }
323
+ end,
324
+ :printable_requirement => lambda {|req| SharedHelpers.pretty_dependency(req) },
325
+ :additional_message_for_conflict => lambda do |o, name, conflict|
326
+ if name == "bundler"
327
+ o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
328
+ other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new Bundler::VERSION)
329
+ end
330
+
331
+ if name == "bundler" && other_bundler_required
332
+ o << "\n"
333
+ o << "This Gemfile requires a different version of Bundler.\n"
334
+ o << "Perhaps you need to update Bundler by running `gem install bundler`?\n"
335
+ end
336
+ if conflict.locked_requirement
337
+ o << "\n"
338
+ o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
339
+ o << %(the gems in your Gemfile, which may resolve the conflict.\n)
340
+ elsif !conflict.existing
341
+ o << "\n"
342
+
343
+ relevant_sources = if conflict.requirement.source
344
+ [conflict.requirement.source]
345
+ elsif conflict.requirement.all_sources
346
+ conflict.requirement.all_sources
347
+ elsif @lockfile_uses_separate_rubygems_sources
348
+ # every conflict should have an explicit group of sources when we
349
+ # enforce strict pinning
350
+ raise "no source set for #{conflict}"
351
+ else
352
+ []
353
+ end.compact.map(&:to_s).uniq.sort
354
+
355
+ o << "Could not find gem '#{SharedHelpers.pretty_dependency(conflict.requirement)}'"
356
+ if conflict.requirement_trees.first.size > 1
357
+ o << ", which is required by "
358
+ o << "gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}',"
359
+ end
360
+ o << " "
361
+
362
+ o << if relevant_sources.empty?
363
+ "in any of the sources.\n"
364
+ else
365
+ "in any of the relevant sources:\n #{relevant_sources * "\n "}\n"
366
+ end
367
+ end
368
+ end,
369
+ :version_for_spec => lambda {|spec| spec.version }
370
+ )
371
+ end
409
372
  end
410
373
  end