bundler 2.0.2

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 (303) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3111 -0
  3. data/LICENSE.md +23 -0
  4. data/README.md +63 -0
  5. data/bundler.gemspec +65 -0
  6. data/exe/bundle +31 -0
  7. data/exe/bundle_ruby +60 -0
  8. data/exe/bundler +4 -0
  9. data/lib/bundler.rb +567 -0
  10. data/lib/bundler/build_metadata.rb +53 -0
  11. data/lib/bundler/capistrano.rb +22 -0
  12. data/lib/bundler/cli.rb +792 -0
  13. data/lib/bundler/cli/add.rb +35 -0
  14. data/lib/bundler/cli/binstubs.rb +49 -0
  15. data/lib/bundler/cli/cache.rb +36 -0
  16. data/lib/bundler/cli/check.rb +38 -0
  17. data/lib/bundler/cli/clean.rb +25 -0
  18. data/lib/bundler/cli/common.rb +102 -0
  19. data/lib/bundler/cli/config.rb +119 -0
  20. data/lib/bundler/cli/console.rb +43 -0
  21. data/lib/bundler/cli/doctor.rb +140 -0
  22. data/lib/bundler/cli/exec.rb +105 -0
  23. data/lib/bundler/cli/gem.rb +252 -0
  24. data/lib/bundler/cli/info.rb +50 -0
  25. data/lib/bundler/cli/init.rb +47 -0
  26. data/lib/bundler/cli/inject.rb +60 -0
  27. data/lib/bundler/cli/install.rb +218 -0
  28. data/lib/bundler/cli/issue.rb +40 -0
  29. data/lib/bundler/cli/list.rb +58 -0
  30. data/lib/bundler/cli/lock.rb +63 -0
  31. data/lib/bundler/cli/open.rb +26 -0
  32. data/lib/bundler/cli/outdated.rb +266 -0
  33. data/lib/bundler/cli/package.rb +49 -0
  34. data/lib/bundler/cli/platform.rb +46 -0
  35. data/lib/bundler/cli/plugin.rb +24 -0
  36. data/lib/bundler/cli/pristine.rb +47 -0
  37. data/lib/bundler/cli/remove.rb +18 -0
  38. data/lib/bundler/cli/show.rb +75 -0
  39. data/lib/bundler/cli/update.rb +91 -0
  40. data/lib/bundler/cli/viz.rb +31 -0
  41. data/lib/bundler/compact_index_client.rb +109 -0
  42. data/lib/bundler/compact_index_client/cache.rb +118 -0
  43. data/lib/bundler/compact_index_client/updater.rb +116 -0
  44. data/lib/bundler/compatibility_guard.rb +13 -0
  45. data/lib/bundler/constants.rb +7 -0
  46. data/lib/bundler/current_ruby.rb +94 -0
  47. data/lib/bundler/definition.rb +995 -0
  48. data/lib/bundler/dep_proxy.rb +48 -0
  49. data/lib/bundler/dependency.rb +139 -0
  50. data/lib/bundler/deployment.rb +69 -0
  51. data/lib/bundler/deprecate.rb +44 -0
  52. data/lib/bundler/dsl.rb +615 -0
  53. data/lib/bundler/endpoint_specification.rb +141 -0
  54. data/lib/bundler/env.rb +149 -0
  55. data/lib/bundler/environment_preserver.rb +59 -0
  56. data/lib/bundler/errors.rb +158 -0
  57. data/lib/bundler/feature_flag.rb +75 -0
  58. data/lib/bundler/fetcher.rb +312 -0
  59. data/lib/bundler/fetcher/base.rb +52 -0
  60. data/lib/bundler/fetcher/compact_index.rb +126 -0
  61. data/lib/bundler/fetcher/dependency.rb +82 -0
  62. data/lib/bundler/fetcher/downloader.rb +84 -0
  63. data/lib/bundler/fetcher/index.rb +52 -0
  64. data/lib/bundler/friendly_errors.rb +131 -0
  65. data/lib/bundler/gem_helper.rb +217 -0
  66. data/lib/bundler/gem_helpers.rb +101 -0
  67. data/lib/bundler/gem_remote_fetcher.rb +43 -0
  68. data/lib/bundler/gem_tasks.rb +7 -0
  69. data/lib/bundler/gem_version_promoter.rb +190 -0
  70. data/lib/bundler/gemdeps.rb +29 -0
  71. data/lib/bundler/graph.rb +152 -0
  72. data/lib/bundler/index.rb +213 -0
  73. data/lib/bundler/injector.rb +253 -0
  74. data/lib/bundler/inline.rb +74 -0
  75. data/lib/bundler/installer.rb +318 -0
  76. data/lib/bundler/installer/gem_installer.rb +85 -0
  77. data/lib/bundler/installer/parallel_installer.rb +229 -0
  78. data/lib/bundler/installer/standalone.rb +53 -0
  79. data/lib/bundler/lazy_specification.rb +123 -0
  80. data/lib/bundler/lockfile_generator.rb +95 -0
  81. data/lib/bundler/lockfile_parser.rb +256 -0
  82. data/lib/bundler/match_platform.rb +24 -0
  83. data/lib/bundler/mirror.rb +223 -0
  84. data/lib/bundler/plugin.rb +294 -0
  85. data/lib/bundler/plugin/api.rb +81 -0
  86. data/lib/bundler/plugin/api/source.rb +306 -0
  87. data/lib/bundler/plugin/dsl.rb +53 -0
  88. data/lib/bundler/plugin/events.rb +61 -0
  89. data/lib/bundler/plugin/index.rb +165 -0
  90. data/lib/bundler/plugin/installer.rb +96 -0
  91. data/lib/bundler/plugin/installer/git.rb +38 -0
  92. data/lib/bundler/plugin/installer/rubygems.rb +27 -0
  93. data/lib/bundler/plugin/source_list.rb +27 -0
  94. data/lib/bundler/process_lock.rb +24 -0
  95. data/lib/bundler/psyched_yaml.rb +37 -0
  96. data/lib/bundler/remote_specification.rb +114 -0
  97. data/lib/bundler/resolver.rb +373 -0
  98. data/lib/bundler/resolver/spec_group.rb +106 -0
  99. data/lib/bundler/retry.rb +66 -0
  100. data/lib/bundler/ruby_dsl.rb +18 -0
  101. data/lib/bundler/ruby_version.rb +152 -0
  102. data/lib/bundler/rubygems_ext.rb +209 -0
  103. data/lib/bundler/rubygems_gem_installer.rb +99 -0
  104. data/lib/bundler/rubygems_integration.rb +915 -0
  105. data/lib/bundler/runtime.rb +322 -0
  106. data/lib/bundler/settings.rb +464 -0
  107. data/lib/bundler/settings/validator.rb +102 -0
  108. data/lib/bundler/setup.rb +28 -0
  109. data/lib/bundler/shared_helpers.rb +386 -0
  110. data/lib/bundler/similarity_detector.rb +63 -0
  111. data/lib/bundler/source.rb +94 -0
  112. data/lib/bundler/source/gemspec.rb +18 -0
  113. data/lib/bundler/source/git.rb +329 -0
  114. data/lib/bundler/source/git/git_proxy.rb +262 -0
  115. data/lib/bundler/source/metadata.rb +62 -0
  116. data/lib/bundler/source/path.rb +249 -0
  117. data/lib/bundler/source/path/installer.rb +74 -0
  118. data/lib/bundler/source/rubygems.rb +539 -0
  119. data/lib/bundler/source/rubygems/remote.rb +69 -0
  120. data/lib/bundler/source_list.rb +186 -0
  121. data/lib/bundler/spec_set.rb +208 -0
  122. data/lib/bundler/ssl_certs/.document +1 -0
  123. data/lib/bundler/ssl_certs/certificate_manager.rb +66 -0
  124. data/lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem +21 -0
  125. data/lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +23 -0
  126. data/lib/bundler/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +25 -0
  127. data/lib/bundler/stub_specification.rb +108 -0
  128. data/lib/bundler/templates/.document +1 -0
  129. data/lib/bundler/templates/Executable +29 -0
  130. data/lib/bundler/templates/Executable.bundler +105 -0
  131. data/lib/bundler/templates/Executable.standalone +14 -0
  132. data/lib/bundler/templates/Gemfile +7 -0
  133. data/lib/bundler/templates/gems.rb +8 -0
  134. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +74 -0
  135. data/lib/bundler/templates/newgem/Gemfile.tt +4 -0
  136. data/lib/bundler/templates/newgem/LICENSE.txt.tt +21 -0
  137. data/lib/bundler/templates/newgem/README.md.tt +47 -0
  138. data/lib/bundler/templates/newgem/Rakefile.tt +29 -0
  139. data/lib/bundler/templates/newgem/bin/console.tt +14 -0
  140. data/lib/bundler/templates/newgem/bin/setup.tt +8 -0
  141. data/lib/bundler/templates/newgem/exe/newgem.tt +3 -0
  142. data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +3 -0
  143. data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +9 -0
  144. data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +6 -0
  145. data/lib/bundler/templates/newgem/gitignore.tt +20 -0
  146. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +13 -0
  147. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +7 -0
  148. data/lib/bundler/templates/newgem/newgem.gemspec.tt +50 -0
  149. data/lib/bundler/templates/newgem/rspec.tt +3 -0
  150. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +9 -0
  151. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +14 -0
  152. data/lib/bundler/templates/newgem/test/newgem_test.rb.tt +11 -0
  153. data/lib/bundler/templates/newgem/test/test_helper.rb.tt +8 -0
  154. data/lib/bundler/templates/newgem/travis.yml.tt +7 -0
  155. data/lib/bundler/ui.rb +9 -0
  156. data/lib/bundler/ui/rg_proxy.rb +19 -0
  157. data/lib/bundler/ui/shell.rb +146 -0
  158. data/lib/bundler/ui/silent.rb +69 -0
  159. data/lib/bundler/uri_credentials_filter.rb +37 -0
  160. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1741 -0
  161. data/lib/bundler/vendor/fileutils/lib/fileutils/version.rb +5 -0
  162. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +12 -0
  163. data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +26 -0
  164. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +57 -0
  165. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +81 -0
  166. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +223 -0
  167. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +36 -0
  168. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +66 -0
  169. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +62 -0
  170. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +63 -0
  171. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +61 -0
  172. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +126 -0
  173. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +46 -0
  174. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +36 -0
  175. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +136 -0
  176. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +143 -0
  177. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +6 -0
  178. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +101 -0
  179. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +67 -0
  180. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +837 -0
  181. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +46 -0
  182. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +58 -0
  183. data/lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb +27 -0
  184. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1233 -0
  185. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb +129 -0
  186. data/lib/bundler/vendor/thor/lib/thor.rb +509 -0
  187. data/lib/bundler/vendor/thor/lib/thor/actions.rb +331 -0
  188. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +104 -0
  189. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +60 -0
  190. data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +118 -0
  191. data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +143 -0
  192. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +373 -0
  193. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +109 -0
  194. data/lib/bundler/vendor/thor/lib/thor/base.rb +678 -0
  195. data/lib/bundler/vendor/thor/lib/thor/command.rb +135 -0
  196. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +97 -0
  197. data/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +12 -0
  198. data/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +129 -0
  199. data/lib/bundler/vendor/thor/lib/thor/error.rb +114 -0
  200. data/lib/bundler/vendor/thor/lib/thor/group.rb +281 -0
  201. data/lib/bundler/vendor/thor/lib/thor/invocation.rb +177 -0
  202. data/lib/bundler/vendor/thor/lib/thor/line_editor.rb +17 -0
  203. data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +37 -0
  204. data/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +88 -0
  205. data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -0
  206. data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +70 -0
  207. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +175 -0
  208. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +146 -0
  209. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +226 -0
  210. data/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +71 -0
  211. data/lib/bundler/vendor/thor/lib/thor/runner.rb +324 -0
  212. data/lib/bundler/vendor/thor/lib/thor/shell.rb +81 -0
  213. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +482 -0
  214. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +149 -0
  215. data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +126 -0
  216. data/lib/bundler/vendor/thor/lib/thor/util.rb +268 -0
  217. data/lib/bundler/vendor/thor/lib/thor/version.rb +3 -0
  218. data/lib/bundler/vendored_fileutils.rb +9 -0
  219. data/lib/bundler/vendored_molinillo.rb +4 -0
  220. data/lib/bundler/vendored_persistent.rb +52 -0
  221. data/lib/bundler/vendored_thor.rb +8 -0
  222. data/lib/bundler/version.rb +28 -0
  223. data/lib/bundler/version_ranges.rb +76 -0
  224. data/lib/bundler/vlad.rb +17 -0
  225. data/lib/bundler/worker.rb +106 -0
  226. data/lib/bundler/yaml_serializer.rb +90 -0
  227. data/man/bundle-add.1 +58 -0
  228. data/man/bundle-add.1.txt +52 -0
  229. data/man/bundle-add.ronn +40 -0
  230. data/man/bundle-binstubs.1 +40 -0
  231. data/man/bundle-binstubs.1.txt +48 -0
  232. data/man/bundle-binstubs.ronn +43 -0
  233. data/man/bundle-check.1 +31 -0
  234. data/man/bundle-check.1.txt +33 -0
  235. data/man/bundle-check.ronn +26 -0
  236. data/man/bundle-clean.1 +24 -0
  237. data/man/bundle-clean.1.txt +26 -0
  238. data/man/bundle-clean.ronn +18 -0
  239. data/man/bundle-config.1 +497 -0
  240. data/man/bundle-config.1.txt +529 -0
  241. data/man/bundle-config.ronn +397 -0
  242. data/man/bundle-doctor.1 +44 -0
  243. data/man/bundle-doctor.1.txt +44 -0
  244. data/man/bundle-doctor.ronn +33 -0
  245. data/man/bundle-exec.1 +165 -0
  246. data/man/bundle-exec.1.txt +178 -0
  247. data/man/bundle-exec.ronn +152 -0
  248. data/man/bundle-gem.1 +80 -0
  249. data/man/bundle-gem.1.txt +91 -0
  250. data/man/bundle-gem.ronn +78 -0
  251. data/man/bundle-info.1 +20 -0
  252. data/man/bundle-info.1.txt +21 -0
  253. data/man/bundle-info.ronn +17 -0
  254. data/man/bundle-init.1 +25 -0
  255. data/man/bundle-init.1.txt +34 -0
  256. data/man/bundle-init.ronn +29 -0
  257. data/man/bundle-inject.1 +33 -0
  258. data/man/bundle-inject.1.txt +32 -0
  259. data/man/bundle-inject.ronn +22 -0
  260. data/man/bundle-install.1 +308 -0
  261. data/man/bundle-install.1.txt +396 -0
  262. data/man/bundle-install.ronn +378 -0
  263. data/man/bundle-list.1 +50 -0
  264. data/man/bundle-list.1.txt +43 -0
  265. data/man/bundle-list.ronn +33 -0
  266. data/man/bundle-lock.1 +84 -0
  267. data/man/bundle-lock.1.txt +93 -0
  268. data/man/bundle-lock.ronn +94 -0
  269. data/man/bundle-open.1 +32 -0
  270. data/man/bundle-open.1.txt +29 -0
  271. data/man/bundle-open.ronn +19 -0
  272. data/man/bundle-outdated.1 +155 -0
  273. data/man/bundle-outdated.1.txt +131 -0
  274. data/man/bundle-outdated.ronn +111 -0
  275. data/man/bundle-package.1 +55 -0
  276. data/man/bundle-package.1.txt +79 -0
  277. data/man/bundle-package.ronn +72 -0
  278. data/man/bundle-platform.1 +61 -0
  279. data/man/bundle-platform.1.txt +57 -0
  280. data/man/bundle-platform.ronn +42 -0
  281. data/man/bundle-pristine.1 +34 -0
  282. data/man/bundle-pristine.1.txt +44 -0
  283. data/man/bundle-pristine.ronn +34 -0
  284. data/man/bundle-remove.1 +31 -0
  285. data/man/bundle-remove.1.txt +34 -0
  286. data/man/bundle-remove.ronn +23 -0
  287. data/man/bundle-show.1 +23 -0
  288. data/man/bundle-show.1.txt +27 -0
  289. data/man/bundle-show.ronn +21 -0
  290. data/man/bundle-update.1 +394 -0
  291. data/man/bundle-update.1.txt +391 -0
  292. data/man/bundle-update.ronn +350 -0
  293. data/man/bundle-viz.1 +39 -0
  294. data/man/bundle-viz.1.txt +39 -0
  295. data/man/bundle-viz.ronn +30 -0
  296. data/man/bundle.1 +136 -0
  297. data/man/bundle.1.txt +116 -0
  298. data/man/bundle.ronn +111 -0
  299. data/man/gemfile.5 +689 -0
  300. data/man/gemfile.5.ronn +521 -0
  301. data/man/gemfile.5.txt +653 -0
  302. data/man/index.txt +25 -0
  303. metadata +463 -0
@@ -0,0 +1,213 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+
5
+ module Bundler
6
+ class Index
7
+ include Enumerable
8
+
9
+ def self.build
10
+ i = new
11
+ yield i
12
+ i
13
+ end
14
+
15
+ attr_reader :specs, :all_specs, :sources
16
+ protected :specs, :all_specs
17
+
18
+ RUBY = "ruby".freeze
19
+ NULL = "\0".freeze
20
+
21
+ def initialize
22
+ @sources = []
23
+ @cache = {}
24
+ @specs = Hash.new {|h, k| h[k] = {} }
25
+ @all_specs = Hash.new {|h, k| h[k] = EMPTY_SEARCH }
26
+ end
27
+
28
+ def initialize_copy(o)
29
+ @sources = o.sources.dup
30
+ @cache = {}
31
+ @specs = Hash.new {|h, k| h[k] = {} }
32
+ @all_specs = Hash.new {|h, k| h[k] = EMPTY_SEARCH }
33
+
34
+ o.specs.each do |name, hash|
35
+ @specs[name] = hash.dup
36
+ end
37
+ o.all_specs.each do |name, array|
38
+ @all_specs[name] = array.dup
39
+ end
40
+ end
41
+
42
+ def inspect
43
+ "#<#{self.class}:0x#{object_id} sources=#{sources.map(&:inspect)} specs.size=#{specs.size}>"
44
+ end
45
+
46
+ def empty?
47
+ each { return false }
48
+ true
49
+ end
50
+
51
+ def search_all(name)
52
+ all_matches = local_search(name) + @all_specs[name]
53
+ @sources.each do |source|
54
+ all_matches.concat(source.search_all(name))
55
+ end
56
+ all_matches
57
+ end
58
+
59
+ # Search this index's specs, and any source indexes that this index knows
60
+ # about, returning all of the results.
61
+ def search(query, base = nil)
62
+ sort_specs(unsorted_search(query, base))
63
+ end
64
+
65
+ def unsorted_search(query, base)
66
+ results = local_search(query, base)
67
+
68
+ seen = results.map(&:full_name).to_set unless @sources.empty?
69
+
70
+ @sources.each do |source|
71
+ source.unsorted_search(query, base).each do |spec|
72
+ results << spec if seen.add?(spec.full_name)
73
+ end
74
+ end
75
+
76
+ results
77
+ end
78
+ protected :unsorted_search
79
+
80
+ def self.sort_specs(specs)
81
+ specs.sort_by do |s|
82
+ platform_string = s.platform.to_s
83
+ [s.version, platform_string == RUBY ? NULL : platform_string]
84
+ end
85
+ end
86
+
87
+ def sort_specs(specs)
88
+ self.class.sort_specs(specs)
89
+ end
90
+
91
+ def local_search(query, base = nil)
92
+ case query
93
+ when Gem::Specification, RemoteSpecification, LazySpecification, EndpointSpecification then search_by_spec(query)
94
+ when String then specs_by_name(query)
95
+ when Gem::Dependency then search_by_dependency(query, base)
96
+ when DepProxy then search_by_dependency(query.dep, base)
97
+ else
98
+ raise "You can't search for a #{query.inspect}."
99
+ end
100
+ end
101
+
102
+ alias_method :[], :search
103
+
104
+ def <<(spec)
105
+ @specs[spec.name][spec.full_name] = spec
106
+ spec
107
+ end
108
+
109
+ def each(&blk)
110
+ return enum_for(:each) unless blk
111
+ specs.values.each do |spec_sets|
112
+ spec_sets.values.each(&blk)
113
+ end
114
+ sources.each {|s| s.each(&blk) }
115
+ self
116
+ end
117
+
118
+ def spec_names
119
+ names = specs.keys + sources.map(&:spec_names)
120
+ names.uniq!
121
+ names
122
+ end
123
+
124
+ # returns a list of the dependencies
125
+ def unmet_dependency_names
126
+ dependency_names.select do |name|
127
+ name != "bundler" && search(name).empty?
128
+ end
129
+ end
130
+
131
+ def dependency_names
132
+ names = []
133
+ each do |spec|
134
+ spec.dependencies.each do |dep|
135
+ next if dep.type == :development
136
+ names << dep.name
137
+ end
138
+ end
139
+ names.uniq
140
+ end
141
+
142
+ def use(other, override_dupes = false)
143
+ return unless other
144
+ other.each do |s|
145
+ if (dupes = search_by_spec(s)) && !dupes.empty?
146
+ # safe to << since it's a new array when it has contents
147
+ @all_specs[s.name] = dupes << s
148
+ next unless override_dupes
149
+ end
150
+ self << s
151
+ end
152
+ self
153
+ end
154
+
155
+ def size
156
+ @sources.inject(@specs.size) do |size, source|
157
+ size += source.size
158
+ end
159
+ end
160
+
161
+ # Whether all the specs in self are in other
162
+ # TODO: rename to #include?
163
+ def ==(other)
164
+ all? do |spec|
165
+ other_spec = other[spec].first
166
+ other_spec && dependencies_eql?(spec, other_spec) && spec.source == other_spec.source
167
+ end
168
+ end
169
+
170
+ def dependencies_eql?(spec, other_spec)
171
+ deps = spec.dependencies.select {|d| d.type != :development }
172
+ other_deps = other_spec.dependencies.select {|d| d.type != :development }
173
+ Set.new(deps) == Set.new(other_deps)
174
+ end
175
+
176
+ def add_source(index)
177
+ raise ArgumentError, "Source must be an index, not #{index.class}" unless index.is_a?(Index)
178
+ @sources << index
179
+ @sources.uniq! # need to use uniq! here instead of checking for the item before adding
180
+ end
181
+
182
+ private
183
+
184
+ def specs_by_name(name)
185
+ @specs[name].values
186
+ end
187
+
188
+ def search_by_dependency(dependency, base = nil)
189
+ @cache[base || false] ||= {}
190
+ @cache[base || false][dependency] ||= begin
191
+ specs = specs_by_name(dependency.name)
192
+ specs += base if base
193
+ found = specs.select do |spec|
194
+ next true if spec.source.is_a?(Source::Gemspec)
195
+ if base # allow all platforms when searching from a lockfile
196
+ dependency.matches_spec?(spec)
197
+ else
198
+ dependency.matches_spec?(spec) && Gem::Platform.match(spec.platform)
199
+ end
200
+ end
201
+
202
+ found
203
+ end
204
+ end
205
+
206
+ EMPTY_SEARCH = [].freeze
207
+
208
+ def search_by_spec(spec)
209
+ spec = @specs[spec.name][spec.full_name]
210
+ spec ? [spec] : EMPTY_SEARCH
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,253 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class Injector
5
+ INJECTED_GEMS = "injected gems".freeze
6
+
7
+ def self.inject(new_deps, options = {})
8
+ injector = new(new_deps, options)
9
+ injector.inject(Bundler.default_gemfile, Bundler.default_lockfile)
10
+ end
11
+
12
+ def self.remove(gems, options = {})
13
+ injector = new(gems, options)
14
+ injector.remove(Bundler.default_gemfile, Bundler.default_lockfile)
15
+ end
16
+
17
+ def initialize(deps, options = {})
18
+ @deps = deps
19
+ @options = options
20
+ end
21
+
22
+ # @param [Pathname] gemfile_path The Gemfile in which to inject the new dependency.
23
+ # @param [Pathname] lockfile_path The lockfile in which to inject the new dependency.
24
+ # @return [Array]
25
+ def inject(gemfile_path, lockfile_path)
26
+ if Bundler.frozen_bundle?
27
+ # ensure the lock and Gemfile are synced
28
+ Bundler.definition.ensure_equivalent_gemfile_and_lockfile(true)
29
+ end
30
+
31
+ # temporarily unfreeze
32
+ Bundler.settings.temporary(:deployment => false, :frozen => false) do
33
+ # evaluate the Gemfile we have now
34
+ builder = Dsl.new
35
+ builder.eval_gemfile(gemfile_path)
36
+
37
+ # don't inject any gems that are already in the Gemfile
38
+ @deps -= builder.dependencies
39
+
40
+ # add new deps to the end of the in-memory Gemfile
41
+ # Set conservative versioning to false because
42
+ # we want to let the resolver resolve the version first
43
+ builder.eval_gemfile(INJECTED_GEMS, build_gem_lines(false)) if @deps.any?
44
+
45
+ # resolve to see if the new deps broke anything
46
+ @definition = builder.to_definition(lockfile_path, {})
47
+ @definition.resolve_remotely!
48
+
49
+ # since nothing broke, we can add those gems to the gemfile
50
+ append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @deps.any?
51
+
52
+ # since we resolved successfully, write out the lockfile
53
+ @definition.lock(Bundler.default_lockfile)
54
+
55
+ # invalidate the cached Bundler.definition
56
+ Bundler.reset_paths!
57
+
58
+ # return an array of the deps that we added
59
+ @deps
60
+ end
61
+ end
62
+
63
+ # @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
64
+ # @param [Pathname] lockfile_path The lockfile from which to remove dependencies.
65
+ # @return [Array]
66
+ def remove(gemfile_path, lockfile_path)
67
+ # remove gems from each gemfiles we have
68
+ Bundler.definition.gemfiles.each do |path|
69
+ deps = remove_deps(path)
70
+
71
+ show_warning("No gems were removed from the gemfile.") if deps.empty?
72
+
73
+ deps.each {|dep| Bundler.ui.confirm "#{SharedHelpers.pretty_dependency(dep, false)} was removed." }
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def conservative_version(spec)
80
+ version = spec.version
81
+ return ">= 0" if version.nil?
82
+ segments = version.segments
83
+ seg_end_index = version >= Gem::Version.new("1.0") ? 1 : 2
84
+
85
+ prerelease_suffix = version.to_s.gsub(version.release.to_s, "") if version.prerelease?
86
+ "#{version_prefix}#{segments[0..seg_end_index].join(".")}#{prerelease_suffix}"
87
+ end
88
+
89
+ def version_prefix
90
+ if @options[:strict]
91
+ "= "
92
+ elsif @options[:optimistic]
93
+ ">= "
94
+ else
95
+ "~> "
96
+ end
97
+ end
98
+
99
+ def build_gem_lines(conservative_versioning)
100
+ @deps.map do |d|
101
+ name = d.name.dump
102
+
103
+ requirement = if conservative_versioning
104
+ ", \"#{conservative_version(@definition.specs[d.name][0])}\""
105
+ else
106
+ ", #{d.requirement.as_list.map(&:dump).join(", ")}"
107
+ end
108
+
109
+ if d.groups != Array(:default)
110
+ group = d.groups.size == 1 ? ", :group => #{d.groups.first.inspect}" : ", :groups => #{d.groups.inspect}"
111
+ end
112
+
113
+ source = ", :source => \"#{d.source}\"" unless d.source.nil?
114
+
115
+ %(gem #{name}#{requirement}#{group}#{source})
116
+ end.join("\n")
117
+ end
118
+
119
+ def append_to(gemfile_path, new_gem_lines)
120
+ gemfile_path.open("a") do |f|
121
+ f.puts
122
+ f.puts new_gem_lines
123
+ end
124
+ end
125
+
126
+ # evaluates a gemfile to remove the specified gem
127
+ # from it.
128
+ def remove_deps(gemfile_path)
129
+ initial_gemfile = IO.readlines(gemfile_path)
130
+
131
+ Bundler.ui.info "Removing gems from #{gemfile_path}"
132
+
133
+ # evaluate the Gemfile we have
134
+ builder = Dsl.new
135
+ builder.eval_gemfile(gemfile_path)
136
+
137
+ removed_deps = remove_gems_from_dependencies(builder, @deps, gemfile_path)
138
+
139
+ # abort the operation if no gems were removed
140
+ # no need to operate on gemfile further
141
+ return [] if removed_deps.empty?
142
+
143
+ cleaned_gemfile = remove_gems_from_gemfile(@deps, gemfile_path)
144
+
145
+ SharedHelpers.write_to_gemfile(gemfile_path, cleaned_gemfile)
146
+
147
+ # check for errors
148
+ # including extra gems being removed
149
+ # or some gems not being removed
150
+ # and return the actual removed deps
151
+ cross_check_for_errors(gemfile_path, builder.dependencies, removed_deps, initial_gemfile)
152
+ end
153
+
154
+ # @param [Dsl] builder Dsl object of current Gemfile.
155
+ # @param [Array] gems Array of names of gems to be removed.
156
+ # @param [Pathname] gemfile_path Path of the Gemfile.
157
+ # @return [Array] Array of removed dependencies.
158
+ def remove_gems_from_dependencies(builder, gems, gemfile_path)
159
+ removed_deps = []
160
+
161
+ gems.each do |gem_name|
162
+ deleted_dep = builder.dependencies.find {|d| d.name == gem_name }
163
+
164
+ if deleted_dep.nil?
165
+ raise GemfileError, "`#{gem_name}` is not specified in #{gemfile_path} so it could not be removed."
166
+ end
167
+
168
+ builder.dependencies.delete(deleted_dep)
169
+
170
+ removed_deps << deleted_dep
171
+ end
172
+
173
+ removed_deps
174
+ end
175
+
176
+ # @param [Array] gems Array of names of gems to be removed.
177
+ # @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
178
+ def remove_gems_from_gemfile(gems, gemfile_path)
179
+ patterns = /gem\s+(['"])#{Regexp.union(gems)}\1|gem\s*\((['"])#{Regexp.union(gems)}\2\)/
180
+
181
+ # remove lines which match the regex
182
+ new_gemfile = IO.readlines(gemfile_path).reject {|line| line.match(patterns) }
183
+
184
+ # remove lone \n and append them with other strings
185
+ new_gemfile.each_with_index do |_line, index|
186
+ if new_gemfile[index + 1] == "\n"
187
+ new_gemfile[index] += new_gemfile[index + 1]
188
+ new_gemfile.delete_at(index + 1)
189
+ end
190
+ end
191
+
192
+ %w[group source env install_if].each {|block| remove_nested_blocks(new_gemfile, block) }
193
+
194
+ new_gemfile.join.chomp
195
+ end
196
+
197
+ # @param [Array] gemfile Array of gemfile contents.
198
+ # @param [String] block_name Name of block name to look for.
199
+ def remove_nested_blocks(gemfile, block_name)
200
+ nested_blocks = 0
201
+
202
+ # count number of nested blocks
203
+ gemfile.each_with_index {|line, index| nested_blocks += 1 if !gemfile[index + 1].nil? && gemfile[index + 1].include?(block_name) && line.include?(block_name) }
204
+
205
+ while nested_blocks >= 0
206
+ nested_blocks -= 1
207
+
208
+ gemfile.each_with_index do |line, index|
209
+ next unless !line.nil? && line.strip.start_with?(block_name)
210
+ if gemfile[index + 1] =~ /^\s*end\s*$/
211
+ gemfile[index] = nil
212
+ gemfile[index + 1] = nil
213
+ end
214
+ end
215
+
216
+ gemfile.compact!
217
+ end
218
+ end
219
+
220
+ # @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
221
+ # @param [Array] original_deps Array of original dependencies.
222
+ # @param [Array] removed_deps Array of removed dependencies.
223
+ # @param [Array] initial_gemfile Contents of original Gemfile before any operation.
224
+ def cross_check_for_errors(gemfile_path, original_deps, removed_deps, initial_gemfile)
225
+ # evaluate the new gemfile to look for any failure cases
226
+ builder = Dsl.new
227
+ builder.eval_gemfile(gemfile_path)
228
+
229
+ # record gems which were removed but not requested
230
+ extra_removed_gems = original_deps - builder.dependencies
231
+
232
+ # if some extra gems were removed then raise error
233
+ # and revert Gemfile to original
234
+ unless extra_removed_gems.empty?
235
+ SharedHelpers.write_to_gemfile(gemfile_path, initial_gemfile.join)
236
+
237
+ raise InvalidOption, "Gems could not be removed. #{extra_removed_gems.join(", ")} would also have been removed. Bundler cannot continue."
238
+ end
239
+
240
+ # record gems which could not be removed due to some reasons
241
+ errored_deps = builder.dependencies.select {|d| d.gemfile == gemfile_path } & removed_deps.select {|d| d.gemfile == gemfile_path }
242
+
243
+ show_warning "#{errored_deps.map(&:name).join(", ")} could not be removed." unless errored_deps.empty?
244
+
245
+ # return actual removed dependencies
246
+ removed_deps - errored_deps
247
+ end
248
+
249
+ def show_warning(message)
250
+ Bundler.ui.info Bundler.ui.add_color(message, :yellow)
251
+ end
252
+ end
253
+ end