bundler 1.9.0 → 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 (328) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1157 -6
  3. data/README.md +33 -6
  4. data/bundler.gemspec +51 -18
  5. data/exe/bundle +31 -0
  6. data/{bin → exe}/bundle_ruby +10 -6
  7. data/exe/bundler +4 -0
  8. data/lib/bundler.rb +326 -207
  9. data/lib/bundler/build_metadata.rb +53 -0
  10. data/lib/bundler/capistrano.rb +9 -3
  11. data/lib/bundler/cli.rb +522 -141
  12. data/lib/bundler/cli/add.rb +35 -0
  13. data/lib/bundler/cli/binstubs.rb +22 -11
  14. data/lib/bundler/cli/cache.rb +7 -6
  15. data/lib/bundler/cli/check.rb +11 -8
  16. data/lib/bundler/cli/clean.rb +7 -8
  17. data/lib/bundler/cli/common.rb +53 -7
  18. data/lib/bundler/cli/config.rb +84 -49
  19. data/lib/bundler/cli/console.rb +13 -8
  20. data/lib/bundler/cli/doctor.rb +140 -0
  21. data/lib/bundler/cli/exec.rb +77 -16
  22. data/lib/bundler/cli/gem.rb +120 -52
  23. data/lib/bundler/cli/info.rb +50 -0
  24. data/lib/bundler/cli/init.rb +21 -7
  25. data/lib/bundler/cli/inject.rb +37 -10
  26. data/lib/bundler/cli/install.rb +139 -78
  27. data/lib/bundler/cli/issue.rb +40 -0
  28. data/lib/bundler/cli/list.rb +58 -0
  29. data/lib/bundler/cli/lock.rb +63 -0
  30. data/lib/bundler/cli/open.rb +9 -6
  31. data/lib/bundler/cli/outdated.rb +221 -35
  32. data/lib/bundler/cli/package.rb +11 -7
  33. data/lib/bundler/cli/platform.rb +7 -4
  34. data/lib/bundler/cli/plugin.rb +24 -0
  35. data/lib/bundler/cli/pristine.rb +47 -0
  36. data/lib/bundler/cli/remove.rb +18 -0
  37. data/lib/bundler/cli/show.rb +11 -10
  38. data/lib/bundler/cli/update.rb +47 -29
  39. data/lib/bundler/cli/viz.rb +12 -8
  40. data/lib/bundler/compact_index_client.rb +109 -0
  41. data/lib/bundler/compact_index_client/cache.rb +118 -0
  42. data/lib/bundler/compact_index_client/updater.rb +116 -0
  43. data/lib/bundler/compatibility_guard.rb +14 -0
  44. data/lib/bundler/constants.rb +3 -1
  45. data/lib/bundler/current_ruby.rb +47 -137
  46. data/lib/bundler/definition.rb +599 -230
  47. data/lib/bundler/dep_proxy.rb +15 -10
  48. data/lib/bundler/dependency.rb +54 -25
  49. data/lib/bundler/deployment.rb +12 -2
  50. data/lib/bundler/deprecate.rb +33 -4
  51. data/lib/bundler/dsl.rb +383 -99
  52. data/lib/bundler/endpoint_specification.rb +72 -7
  53. data/lib/bundler/env.rb +121 -41
  54. data/lib/bundler/environment_preserver.rb +59 -0
  55. data/lib/bundler/errors.rb +158 -0
  56. data/lib/bundler/feature_flag.rb +74 -0
  57. data/lib/bundler/fetcher.rb +171 -280
  58. data/lib/bundler/fetcher/base.rb +52 -0
  59. data/lib/bundler/fetcher/compact_index.rb +126 -0
  60. data/lib/bundler/fetcher/dependency.rb +82 -0
  61. data/lib/bundler/fetcher/downloader.rb +84 -0
  62. data/lib/bundler/fetcher/index.rb +52 -0
  63. data/lib/bundler/friendly_errors.rb +113 -58
  64. data/lib/bundler/gem_helper.rb +73 -46
  65. data/lib/bundler/gem_helpers.rb +85 -9
  66. data/lib/bundler/gem_remote_fetcher.rb +43 -0
  67. data/lib/bundler/gem_tasks.rb +6 -1
  68. data/lib/bundler/gem_version_promoter.rb +190 -0
  69. data/lib/bundler/gemdeps.rb +29 -0
  70. data/lib/bundler/graph.rb +32 -49
  71. data/lib/bundler/index.rb +79 -67
  72. data/lib/bundler/injector.rb +219 -30
  73. data/lib/bundler/inline.rb +74 -0
  74. data/lib/bundler/installer.rb +191 -206
  75. data/lib/bundler/installer/gem_installer.rb +85 -0
  76. data/lib/bundler/installer/parallel_installer.rb +233 -0
  77. data/lib/bundler/installer/standalone.rb +53 -0
  78. data/lib/bundler/lazy_specification.rb +53 -13
  79. data/lib/bundler/lockfile_generator.rb +95 -0
  80. data/lib/bundler/lockfile_parser.rb +157 -62
  81. data/lib/bundler/match_platform.rb +15 -4
  82. data/lib/bundler/mirror.rb +223 -0
  83. data/lib/bundler/plugin.rb +292 -0
  84. data/lib/bundler/plugin/api.rb +81 -0
  85. data/lib/bundler/plugin/api/source.rb +306 -0
  86. data/lib/bundler/plugin/dsl.rb +53 -0
  87. data/lib/bundler/plugin/events.rb +61 -0
  88. data/lib/bundler/plugin/index.rb +162 -0
  89. data/lib/bundler/plugin/installer.rb +96 -0
  90. data/lib/bundler/plugin/installer/git.rb +38 -0
  91. data/lib/bundler/plugin/installer/rubygems.rb +27 -0
  92. data/lib/bundler/plugin/source_list.rb +27 -0
  93. data/lib/bundler/process_lock.rb +24 -0
  94. data/lib/bundler/psyched_yaml.rb +17 -6
  95. data/lib/bundler/remote_specification.rb +68 -11
  96. data/lib/bundler/resolver.rb +263 -229
  97. data/lib/bundler/resolver/spec_group.rb +106 -0
  98. data/lib/bundler/retry.rb +25 -19
  99. data/lib/bundler/ruby_dsl.rb +9 -2
  100. data/lib/bundler/ruby_version.rb +101 -66
  101. data/lib/bundler/rubygems_ext.rb +77 -37
  102. data/lib/bundler/rubygems_gem_installer.rb +106 -0
  103. data/lib/bundler/rubygems_integration.rb +450 -163
  104. data/lib/bundler/runtime.rb +133 -103
  105. data/lib/bundler/settings.rb +344 -83
  106. data/lib/bundler/settings/validator.rb +102 -0
  107. data/lib/bundler/setup.rb +7 -3
  108. data/lib/bundler/shared_helpers.rb +284 -54
  109. data/lib/bundler/similarity_detector.rb +21 -21
  110. data/lib/bundler/source.rb +68 -15
  111. data/lib/bundler/source/gemspec.rb +18 -0
  112. data/lib/bundler/source/git.rb +90 -55
  113. data/lib/bundler/source/git/git_proxy.rb +135 -35
  114. data/lib/bundler/source/metadata.rb +62 -0
  115. data/lib/bundler/source/path.rb +84 -61
  116. data/lib/bundler/source/path/installer.rb +53 -17
  117. data/lib/bundler/source/rubygems.rb +282 -122
  118. data/lib/bundler/source/rubygems/remote.rb +69 -0
  119. data/lib/bundler/source_list.rb +107 -22
  120. data/lib/bundler/spec_set.rb +83 -45
  121. data/lib/bundler/ssl_certs/certificate_manager.rb +8 -7
  122. data/lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem +21 -0
  123. data/lib/bundler/ssl_certs/{DigiCertHighAssuranceEVRootCA.pem → rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem} +0 -0
  124. data/lib/bundler/ssl_certs/{AddTrustExternalCARoot-2048.pem → rubygems.org/AddTrustExternalCARoot.pem} +0 -0
  125. data/lib/bundler/stub_specification.rb +108 -0
  126. data/lib/bundler/templates/.document +1 -0
  127. data/lib/bundler/templates/Executable +19 -6
  128. data/lib/bundler/templates/Executable.bundler +105 -0
  129. data/lib/bundler/templates/Executable.standalone +6 -4
  130. data/lib/bundler/templates/Gemfile +4 -1
  131. data/lib/bundler/templates/gems.rb +8 -0
  132. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +68 -7
  133. data/lib/bundler/templates/newgem/Gemfile.tt +4 -2
  134. data/lib/bundler/templates/newgem/LICENSE.txt.tt +1 -1
  135. data/lib/bundler/templates/newgem/README.md.tt +19 -11
  136. data/lib/bundler/templates/newgem/Rakefile.tt +10 -6
  137. data/lib/bundler/templates/newgem/bin/console.tt +1 -1
  138. data/lib/bundler/templates/newgem/bin/setup.tt +2 -1
  139. data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +4 -4
  140. data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +3 -3
  141. data/lib/bundler/templates/newgem/gitignore.tt +5 -1
  142. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +7 -6
  143. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +4 -4
  144. data/lib/bundler/templates/newgem/newgem.gemspec.tt +31 -15
  145. data/lib/bundler/templates/newgem/rspec.tt +1 -0
  146. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +3 -5
  147. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +14 -2
  148. data/lib/bundler/templates/newgem/test/{test_newgem.rb.tt → newgem_test.rb.tt} +2 -2
  149. data/lib/bundler/templates/newgem/test/test_helper.rb.tt +4 -0
  150. data/lib/bundler/templates/newgem/travis.yml.tt +7 -0
  151. data/lib/bundler/ui.rb +5 -3
  152. data/lib/bundler/ui/rg_proxy.rb +5 -7
  153. data/lib/bundler/ui/shell.rb +69 -18
  154. data/lib/bundler/ui/silent.rb +26 -1
  155. data/lib/bundler/uri_credentials_filter.rb +37 -0
  156. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1638 -0
  157. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +12 -0
  158. data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +26 -0
  159. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +57 -0
  160. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +81 -0
  161. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +223 -0
  162. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +36 -0
  163. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +66 -0
  164. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +62 -0
  165. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +63 -0
  166. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +61 -0
  167. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +126 -0
  168. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +46 -0
  169. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +36 -0
  170. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +136 -0
  171. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +143 -0
  172. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +6 -0
  173. data/lib/bundler/vendor/{Molinillo-0.2.1 → molinillo}/lib/molinillo/modules/specification_provider.rb +11 -0
  174. data/lib/bundler/vendor/{Molinillo-0.2.1 → molinillo}/lib/molinillo/modules/ui.rb +6 -2
  175. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +837 -0
  176. data/lib/bundler/vendor/{Molinillo-0.2.1 → molinillo}/lib/molinillo/resolver.rb +6 -3
  177. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +58 -0
  178. data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/faster.rb +1 -0
  179. data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/persistent.rb +27 -24
  180. data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/persistent/ssl_reuse.rb +2 -1
  181. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor.rb +47 -22
  182. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions.rb +31 -29
  183. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/create_file.rb +3 -2
  184. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/create_link.rb +3 -2
  185. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/directory.rb +3 -3
  186. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/empty_directory.rb +16 -8
  187. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/file_manipulation.rb +66 -18
  188. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/inject_into_file.rb +18 -16
  189. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/base.rb +67 -44
  190. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/command.rb +13 -11
  191. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/core_ext/hash_with_indifferent_access.rb +21 -1
  192. data/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +12 -0
  193. data/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +129 -0
  194. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/error.rb +3 -3
  195. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/group.rb +14 -14
  196. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/invocation.rb +4 -5
  197. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/line_editor.rb +2 -2
  198. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/line_editor/basic.rb +2 -0
  199. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/line_editor/readline.rb +0 -0
  200. data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -0
  201. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/parser/argument.rb +4 -7
  202. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/parser/arguments.rb +16 -16
  203. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/parser/option.rb +42 -21
  204. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/parser/options.rb +13 -10
  205. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/rake_compat.rb +1 -1
  206. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/runner.rb +35 -33
  207. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/shell.rb +4 -4
  208. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/shell/basic.rb +49 -33
  209. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/shell/color.rb +2 -2
  210. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/shell/html.rb +5 -5
  211. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/util.rb +8 -7
  212. data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/version.rb +1 -1
  213. data/lib/bundler/vendored_fileutils.rb +9 -0
  214. data/lib/bundler/vendored_molinillo.rb +4 -5
  215. data/lib/bundler/vendored_persistent.rb +45 -4
  216. data/lib/bundler/vendored_thor.rb +8 -5
  217. data/lib/bundler/version.rb +23 -1
  218. data/lib/bundler/version_ranges.rb +76 -0
  219. data/lib/bundler/vlad.rb +8 -2
  220. data/lib/bundler/worker.rb +39 -6
  221. data/lib/bundler/yaml_serializer.rb +90 -0
  222. data/man/bundle-add.1 +58 -0
  223. data/man/bundle-add.1.txt +52 -0
  224. data/man/bundle-add.ronn +40 -0
  225. data/man/bundle-binstubs.1 +40 -0
  226. data/man/bundle-binstubs.1.txt +48 -0
  227. data/man/bundle-binstubs.ronn +43 -0
  228. data/man/bundle-check.1 +31 -0
  229. data/man/bundle-check.1.txt +33 -0
  230. data/man/bundle-check.ronn +26 -0
  231. data/man/bundle-clean.1 +24 -0
  232. data/man/bundle-clean.1.txt +26 -0
  233. data/man/bundle-clean.ronn +18 -0
  234. data/man/bundle-config.1 +497 -0
  235. data/man/bundle-config.1.txt +529 -0
  236. data/man/bundle-config.ronn +256 -31
  237. data/man/bundle-doctor.1 +44 -0
  238. data/man/bundle-doctor.1.txt +44 -0
  239. data/man/bundle-doctor.ronn +33 -0
  240. data/man/bundle-exec.1 +165 -0
  241. data/man/bundle-exec.1.txt +178 -0
  242. data/man/bundle-exec.ronn +19 -3
  243. data/man/bundle-gem.1 +80 -0
  244. data/man/bundle-gem.1.txt +91 -0
  245. data/man/bundle-gem.ronn +78 -0
  246. data/man/bundle-info.1 +20 -0
  247. data/man/bundle-info.1.txt +21 -0
  248. data/man/bundle-info.ronn +17 -0
  249. data/man/bundle-init.1 +25 -0
  250. data/man/bundle-init.1.txt +34 -0
  251. data/man/bundle-init.ronn +29 -0
  252. data/man/bundle-inject.1 +33 -0
  253. data/man/bundle-inject.1.txt +32 -0
  254. data/man/bundle-inject.ronn +22 -0
  255. data/man/bundle-install.1 +308 -0
  256. data/man/bundle-install.1.txt +396 -0
  257. data/man/bundle-install.ronn +64 -67
  258. data/man/bundle-list.1 +50 -0
  259. data/man/bundle-list.1.txt +43 -0
  260. data/man/bundle-list.ronn +33 -0
  261. data/man/bundle-lock.1 +84 -0
  262. data/man/bundle-lock.1.txt +93 -0
  263. data/man/bundle-lock.ronn +94 -0
  264. data/man/bundle-open.1 +32 -0
  265. data/man/bundle-open.1.txt +29 -0
  266. data/man/bundle-open.ronn +19 -0
  267. data/man/bundle-outdated.1 +155 -0
  268. data/man/bundle-outdated.1.txt +131 -0
  269. data/man/bundle-outdated.ronn +111 -0
  270. data/man/bundle-package.1 +55 -0
  271. data/man/bundle-package.1.txt +79 -0
  272. data/man/bundle-package.ronn +14 -8
  273. data/man/bundle-platform.1 +61 -0
  274. data/man/bundle-platform.1.txt +57 -0
  275. data/man/bundle-platform.ronn +1 -1
  276. data/man/bundle-pristine.1 +34 -0
  277. data/man/bundle-pristine.1.txt +44 -0
  278. data/man/bundle-pristine.ronn +34 -0
  279. data/man/bundle-remove.1 +31 -0
  280. data/man/bundle-remove.1.txt +34 -0
  281. data/man/bundle-remove.ronn +23 -0
  282. data/man/bundle-show.1 +23 -0
  283. data/man/bundle-show.1.txt +27 -0
  284. data/man/bundle-show.ronn +21 -0
  285. data/man/bundle-update.1 +394 -0
  286. data/man/bundle-update.1.txt +391 -0
  287. data/man/bundle-update.ronn +180 -18
  288. data/man/bundle-viz.1 +39 -0
  289. data/man/bundle-viz.1.txt +39 -0
  290. data/man/bundle-viz.ronn +30 -0
  291. data/man/bundle.1 +136 -0
  292. data/man/bundle.1.txt +116 -0
  293. data/man/bundle.ronn +46 -33
  294. data/man/gemfile.5 +689 -0
  295. data/man/gemfile.5.ronn +127 -79
  296. data/man/gemfile.5.txt +653 -0
  297. data/man/index.txt +25 -7
  298. metadata +242 -95
  299. data/.gitignore +0 -16
  300. data/.rspec +0 -3
  301. data/.travis.yml +0 -110
  302. data/CODE_OF_CONDUCT.md +0 -40
  303. data/CONTRIBUTING.md +0 -32
  304. data/DEVELOPMENT.md +0 -119
  305. data/ISSUES.md +0 -96
  306. data/Rakefile +0 -302
  307. data/UPGRADING.md +0 -103
  308. data/bin/bundle +0 -21
  309. data/bin/bundler +0 -21
  310. data/lib/bundler/anonymizable_uri.rb +0 -32
  311. data/lib/bundler/environment.rb +0 -42
  312. data/lib/bundler/gem_installer.rb +0 -9
  313. data/lib/bundler/gem_path_manipulation.rb +0 -8
  314. data/lib/bundler/ssl_certs/AddTrustExternalCARoot.pem +0 -32
  315. data/lib/bundler/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +0 -14
  316. data/lib/bundler/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +0 -28
  317. data/lib/bundler/ssl_certs/GeoTrustGlobalCA.pem +0 -20
  318. data/lib/bundler/templates/newgem/.travis.yml.tt +0 -3
  319. data/lib/bundler/templates/newgem/test/minitest_helper.rb.tt +0 -4
  320. data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo.rb +0 -5
  321. data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/dependency_graph.rb +0 -266
  322. data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/errors.rb +0 -69
  323. data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/gem_metadata.rb +0 -3
  324. data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/resolution.rb +0 -412
  325. data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/state.rb +0 -43
  326. data/lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/io_binary_read.rb +0 -10
  327. data/lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/ordered_hash.rb +0 -98
  328. data/lib/bundler/vendor/thor-0.19.1/lib/thor/parser.rb +0 -4
@@ -0,0 +1,292 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/plugin/api"
4
+
5
+ module Bundler
6
+ module Plugin
7
+ autoload :DSL, "bundler/plugin/dsl"
8
+ autoload :Events, "bundler/plugin/events"
9
+ autoload :Index, "bundler/plugin/index"
10
+ autoload :Installer, "bundler/plugin/installer"
11
+ autoload :SourceList, "bundler/plugin/source_list"
12
+
13
+ class MalformattedPlugin < PluginError; end
14
+ class UndefinedCommandError < PluginError; end
15
+ class UnknownSourceError < PluginError; end
16
+
17
+ PLUGIN_FILE_NAME = "plugins.rb".freeze
18
+
19
+ module_function
20
+
21
+ def reset!
22
+ instance_variables.each {|i| remove_instance_variable(i) }
23
+
24
+ @sources = {}
25
+ @commands = {}
26
+ @hooks_by_event = Hash.new {|h, k| h[k] = [] }
27
+ @loaded_plugin_names = []
28
+ end
29
+
30
+ reset!
31
+
32
+ # Installs a new plugin by the given name
33
+ #
34
+ # @param [Array<String>] names the name of plugin to be installed
35
+ # @param [Hash] options various parameters as described in description.
36
+ # Refer to cli/plugin for available options
37
+ def install(names, options)
38
+ specs = Installer.new.install(names, options)
39
+
40
+ save_plugins names, specs
41
+ rescue PluginError => e
42
+ if specs
43
+ specs_to_delete = Hash[specs.select {|k, _v| names.include?(k) && !index.commands.values.include?(k) }]
44
+ specs_to_delete.values.each {|spec| Bundler.rm_rf(spec.full_gem_path) }
45
+ end
46
+
47
+ Bundler.ui.error "Failed to install plugin #{name}: #{e.message}\n #{e.backtrace.join("\n ")}"
48
+ end
49
+
50
+ # Evaluates the Gemfile with a limited DSL and installs the plugins
51
+ # specified by plugin method
52
+ #
53
+ # @param [Pathname] gemfile path
54
+ # @param [Proc] block that can be evaluated for (inline) Gemfile
55
+ def gemfile_install(gemfile = nil, &inline)
56
+ builder = DSL.new
57
+ if block_given?
58
+ builder.instance_eval(&inline)
59
+ else
60
+ builder.eval_gemfile(gemfile)
61
+ end
62
+ definition = builder.to_definition(nil, true)
63
+
64
+ return if definition.dependencies.empty?
65
+
66
+ plugins = definition.dependencies.map(&:name).reject {|p| index.installed? p }
67
+ installed_specs = Installer.new.install_definition(definition)
68
+
69
+ save_plugins plugins, installed_specs, builder.inferred_plugins
70
+ rescue RuntimeError => e
71
+ unless e.is_a?(GemfileError)
72
+ Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"
73
+ end
74
+ raise
75
+ end
76
+
77
+ # The index object used to store the details about the plugin
78
+ def index
79
+ @index ||= Index.new
80
+ end
81
+
82
+ # The directory root for all plugin related data
83
+ #
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")
86
+ def root
87
+ @root ||= if SharedHelpers.in_bundle?
88
+ local_root
89
+ else
90
+ global_root
91
+ end
92
+ end
93
+
94
+ def local_root
95
+ Bundler.app_config_path.join("plugin")
96
+ end
97
+
98
+ # The global directory root for all plugin related data
99
+ def global_root
100
+ Bundler.user_bundle_path("plugin")
101
+ end
102
+
103
+ # The cache directory for plugin stuffs
104
+ def cache
105
+ @cache ||= root.join("cache")
106
+ end
107
+
108
+ # To be called via the API to register to handle a command
109
+ def add_command(command, cls)
110
+ @commands[command] = cls
111
+ end
112
+
113
+ # Checks if any plugin handles the command
114
+ def command?(command)
115
+ !index.command_plugin(command).nil?
116
+ end
117
+
118
+ # To be called from Cli class to pass the command and argument to
119
+ # approriate plugin class
120
+ def exec_command(command, args)
121
+ raise UndefinedCommandError, "Command `#{command}` not found" unless command? command
122
+
123
+ load_plugin index.command_plugin(command) unless @commands.key? command
124
+
125
+ @commands[command].new.exec(command, args)
126
+ end
127
+
128
+ # To be called via the API to register to handle a source plugin
129
+ def add_source(source, cls)
130
+ @sources[source] = cls
131
+ end
132
+
133
+ # Checks if any plugin declares the source
134
+ def source?(name)
135
+ !index.source_plugin(name.to_s).nil?
136
+ end
137
+
138
+ # @return [Class] that handles the source. The calss includes API::Source
139
+ def source(name)
140
+ raise UnknownSourceError, "Source #{name} not found" unless source? name
141
+
142
+ load_plugin(index.source_plugin(name)) unless @sources.key? name
143
+
144
+ @sources[name]
145
+ end
146
+
147
+ # @param [Hash] The options that are present in the lock file
148
+ # @return [API::Source] the instance of the class that handles the source
149
+ # type passed in locked_opts
150
+ def source_from_lock(locked_opts)
151
+ src = source(locked_opts["type"])
152
+
153
+ src.new(locked_opts.merge("uri" => locked_opts["remote"]))
154
+ end
155
+
156
+ # To be called via the API to register a hooks and corresponding block that
157
+ # will be called to handle the hook
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
162
+ @hooks_by_event[event.to_s] << block
163
+ end
164
+
165
+ # Runs all the hooks that are registered for the passed event
166
+ #
167
+ # It passes the passed arguments and block to the block registered with
168
+ # the api.
169
+ #
170
+ # @param [String] event
171
+ def hook(event, *args, &arg_blk)
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
176
+
177
+ plugins = index.hook_plugins(event)
178
+ return unless plugins.any?
179
+
180
+ (plugins - @loaded_plugin_names).each {|name| load_plugin(name) }
181
+
182
+ @hooks_by_event[event].each {|blk| blk.call(*args, &arg_blk) }
183
+ end
184
+
185
+ # currently only intended for specs
186
+ #
187
+ # @return [String, nil] installed path
188
+ def installed?(plugin)
189
+ Index.new.installed?(plugin)
190
+ end
191
+
192
+ # Post installation processing and registering with index
193
+ #
194
+ # @param [Array<String>] plugins list to be installed
195
+ # @param [Hash] specs of plugins mapped to installation path (currently they
196
+ # contain all the installed specs, including plugins)
197
+ # @param [Array<String>] names of inferred source plugins that can be ignored
198
+ def save_plugins(plugins, specs, optional_plugins = [])
199
+ plugins.each do |name|
200
+ spec = specs[name]
201
+ validate_plugin! Pathname.new(spec.full_gem_path)
202
+ installed = register_plugin(name, spec, optional_plugins.include?(name))
203
+ Bundler.ui.info "Installed plugin #{name}" if installed
204
+ end
205
+ end
206
+
207
+ # Checks if the gem is good to be a plugin
208
+ #
209
+ # At present it only checks whether it contains plugins.rb file
210
+ #
211
+ # @param [Pathname] plugin_path the path plugin is installed at
212
+ # @raise [MalformattedPlugin] if plugins.rb file is not found
213
+ def validate_plugin!(plugin_path)
214
+ plugin_file = plugin_path.join(PLUGIN_FILE_NAME)
215
+ raise MalformattedPlugin, "#{PLUGIN_FILE_NAME} was not found in the plugin." unless plugin_file.file?
216
+ end
217
+
218
+ # Runs the plugins.rb file in an isolated namespace, records the plugin
219
+ # actions it registers for and then passes the data to index to be stored.
220
+ #
221
+ # @param [String] name the name of the plugin
222
+ # @param [Specification] spec of installed plugin
223
+ # @param [Boolean] optional_plugin, removed if there is conflict with any
224
+ # other plugin (used for default source plugins)
225
+ #
226
+ # @raise [MalformattedPlugin] if plugins.rb raises any error
227
+ def register_plugin(name, spec, optional_plugin = false)
228
+ commands = @commands
229
+ sources = @sources
230
+ hooks = @hooks_by_event
231
+
232
+ @commands = {}
233
+ @sources = {}
234
+ @hooks_by_event = Hash.new {|h, k| h[k] = [] }
235
+
236
+ load_paths = spec.load_paths
237
+ add_to_load_path(load_paths)
238
+ path = Pathname.new spec.full_gem_path
239
+
240
+ begin
241
+ load path.join(PLUGIN_FILE_NAME), true
242
+ rescue StandardError => e
243
+ raise MalformattedPlugin, "#{e.class}: #{e.message}"
244
+ end
245
+
246
+ if optional_plugin && @sources.keys.any? {|s| source? s }
247
+ Bundler.rm_rf(path)
248
+ false
249
+ else
250
+ index.register_plugin(name, path.to_s, load_paths, @commands.keys,
251
+ @sources.keys, @hooks_by_event.keys)
252
+ true
253
+ end
254
+ ensure
255
+ @commands = commands
256
+ @sources = sources
257
+ @hooks_by_event = hooks
258
+ end
259
+
260
+ # Executes the plugins.rb file
261
+ #
262
+ # @param [String] name of the plugin
263
+ def load_plugin(name)
264
+ # Need to ensure before this that plugin root where the rest of gems
265
+ # are installed to be on load path to support plugin deps. Currently not
266
+ # done to avoid conflicts
267
+ path = index.plugin_path(name)
268
+
269
+ add_to_load_path(index.load_paths(name))
270
+
271
+ load path.join(PLUGIN_FILE_NAME)
272
+
273
+ @loaded_plugin_names << name
274
+ rescue RuntimeError => e
275
+ Bundler.ui.error "Failed loading plugin #{name}: #{e.message}"
276
+ raise
277
+ end
278
+
279
+ def add_to_load_path(load_paths)
280
+ if insert_index = Bundler.rubygems.load_path_insert_index
281
+ $LOAD_PATH.insert(insert_index, *load_paths)
282
+ else
283
+ $LOAD_PATH.unshift(*load_paths)
284
+ end
285
+ end
286
+
287
+ class << self
288
+ private :load_plugin, :register_plugin, :save_plugins, :validate_plugin!,
289
+ :add_to_load_path
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ # This is the interfacing class represents the API that we intend to provide
5
+ # the plugins to use.
6
+ #
7
+ # For plugins to be independent of the Bundler internals they shall limit their
8
+ # interactions to methods of this class only. This will save them from breaking
9
+ # when some internal change.
10
+ #
11
+ # Currently we are delegating the methods defined in Bundler class to
12
+ # itself. So, this class acts as a buffer.
13
+ #
14
+ # If there is some change in the Bundler class that is incompatible to its
15
+ # previous behavior or if otherwise desired, we can reimplement(or implement)
16
+ # the method to preserve compatibility.
17
+ #
18
+ # To use this, either the class can inherit this class or use it directly.
19
+ # For example of both types of use, refer the file `spec/plugins/command.rb`
20
+ #
21
+ # To use it without inheriting, you will have to create an object of this
22
+ # to use the functions (except for declaration functions like command, source,
23
+ # and hooks).
24
+ module Plugin
25
+ class API
26
+ autoload :Source, "bundler/plugin/api/source"
27
+
28
+ # The plugins should declare that they handle a command through this helper.
29
+ #
30
+ # @param [String] command being handled by them
31
+ # @param [Class] (optional) class that handles the command. If not
32
+ # provided, the `self` class will be used.
33
+ def self.command(command, cls = self)
34
+ Plugin.add_command command, cls
35
+ end
36
+
37
+ # The plugins should declare that they provide a installation source
38
+ # through this helper.
39
+ #
40
+ # @param [String] the source type they provide
41
+ # @param [Class] (optional) class that handles the source. If not
42
+ # provided, the `self` class will be used.
43
+ def self.source(source, cls = self)
44
+ cls.send :include, Bundler::Plugin::API::Source
45
+ Plugin.add_source source, cls
46
+ end
47
+
48
+ def self.hook(event, &block)
49
+ Plugin.add_hook(event, &block)
50
+ end
51
+
52
+ # The cache dir to be used by the plugins for storage
53
+ #
54
+ # @return [Pathname] path of the cache dir
55
+ def cache_dir
56
+ Plugin.cache.join("plugins")
57
+ end
58
+
59
+ # A tmp dir to be used by plugins
60
+ # Accepts names that get concatenated as suffix
61
+ #
62
+ # @return [Pathname] object for the new directory created
63
+ def tmp(*names)
64
+ Bundler.tmp(["plugin", *names].join("-"))
65
+ end
66
+
67
+ def method_missing(name, *args, &blk)
68
+ return Bundler.send(name, *args, &blk) if Bundler.respond_to?(name)
69
+
70
+ return SharedHelpers.send(name, *args, &blk) if SharedHelpers.respond_to?(name)
71
+
72
+ super
73
+ end
74
+
75
+ def respond_to_missing?(name, include_private = false)
76
+ SharedHelpers.respond_to?(name, include_private) ||
77
+ Bundler.respond_to?(name, include_private) || super
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,306 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module Bundler
6
+ module Plugin
7
+ class API
8
+ # This class provides the base to build source plugins
9
+ # All the method here are required to build a source plugin (except
10
+ # `uri_hash`, `gem_install_dir`; they are helpers).
11
+ #
12
+ # Defaults for methods, where ever possible are provided which is
13
+ # expected to work. But, all source plugins have to override
14
+ # `fetch_gemspec_files` and `install`. Defaults are also not provided for
15
+ # `remote!`, `cache!` and `unlock!`.
16
+ #
17
+ # The defaults shall work for most situations but nevertheless they can
18
+ # be (preferably should be) overridden as per the plugins' needs safely
19
+ # (as long as they behave as expected).
20
+ # On overriding `initialize` you should call super first.
21
+ #
22
+ # If required plugin should override `hash`, `==` and `eql?` methods to be
23
+ # able to match objects representing same sources, but may be created in
24
+ # different situation (like form gemfile and lockfile). The default ones
25
+ # checks only for class and uri, but elaborate source plugins may need
26
+ # more comparisons (e.g. git checking on branch or tag).
27
+ #
28
+ # @!attribute [r] uri
29
+ # @return [String] the remote specified with `source` block in Gemfile
30
+ #
31
+ # @!attribute [r] options
32
+ # @return [String] options passed during initialization (either from
33
+ # lockfile or Gemfile)
34
+ #
35
+ # @!attribute [r] name
36
+ # @return [String] name that can be used to uniquely identify a source
37
+ #
38
+ # @!attribute [rw] dependency_names
39
+ # @return [Array<String>] Names of dependencies that the source should
40
+ # try to resolve. It is not necessary to use this list intenally. This
41
+ # is present to be compatible with `Definition` and is used by
42
+ # rubygems source.
43
+ module Source
44
+ attr_reader :uri, :options, :name
45
+ attr_accessor :dependency_names
46
+
47
+ def initialize(opts)
48
+ @options = opts
49
+ @dependency_names = []
50
+ @uri = opts["uri"]
51
+ @type = opts["type"]
52
+ @name = opts["name"] || "#{@type} at #{@uri}"
53
+ end
54
+
55
+ # This is used by the default `spec` method to constructs the
56
+ # Specification objects for the gems and versions that can be installed
57
+ # by this source plugin.
58
+ #
59
+ # Note: If the spec method is overridden, this function is not necessary
60
+ #
61
+ # @return [Array<String>] paths of the gemspec files for gems that can
62
+ # be installed
63
+ def fetch_gemspec_files
64
+ []
65
+ end
66
+
67
+ # Options to be saved in the lockfile so that the source plugin is able
68
+ # to check out same version of gem later.
69
+ #
70
+ # There options are passed when the source plugin is created from the
71
+ # lock file.
72
+ #
73
+ # @return [Hash]
74
+ def options_to_lock
75
+ {}
76
+ end
77
+
78
+ # Install the gem specified by the spec at appropriate path.
79
+ # `install_path` provides a sufficient default, if the source can only
80
+ # satisfy one gem, but is not binding.
81
+ #
82
+ # @return [String] post installation message (if any)
83
+ def install(spec, opts)
84
+ raise MalformattedPlugin, "Source plugins need to override the install method."
85
+ end
86
+
87
+ # It builds extensions, generates bins and installs them for the spec
88
+ # provided.
89
+ #
90
+ # It depends on `spec.loaded_from` to get full_gem_path. The source
91
+ # plugins should set that.
92
+ #
93
+ # It should be called in `install` after the plugin is done placing the
94
+ # gem at correct install location.
95
+ #
96
+ # It also runs Gem hooks `pre_install`, `post_build` and `post_install`
97
+ #
98
+ # Note: Do not override if you don't know what you are doing.
99
+ def post_install(spec, disable_exts = false)
100
+ opts = { :env_shebang => false, :disable_extensions => disable_exts }
101
+ installer = Bundler::Source::Path::Installer.new(spec, opts)
102
+ installer.post_install
103
+ end
104
+
105
+ # A default installation path to install a single gem. If the source
106
+ # servers multiple gems, it's not of much use and the source should one
107
+ # of its own.
108
+ def install_path
109
+ @install_path ||=
110
+ begin
111
+ base_name = File.basename(URI.parse(uri).normalize.path)
112
+
113
+ gem_install_dir.join("#{base_name}-#{uri_hash[0..11]}")
114
+ end
115
+ end
116
+
117
+ # Parses the gemspec files to find the specs for the gems that can be
118
+ # satisfied by the source.
119
+ #
120
+ # Few important points to keep in mind:
121
+ # - If the gems are not installed then it shall return specs for all
122
+ # the gems it can satisfy
123
+ # - If gem is installed (that is to be detected by the plugin itself)
124
+ # then it shall return at least the specs that are installed.
125
+ # - The `loaded_from` for each of the specs shall be correct (it is
126
+ # used to find the load path)
127
+ #
128
+ # @return [Bundler::Index] index containing the specs
129
+ def specs
130
+ files = fetch_gemspec_files
131
+
132
+ Bundler::Index.build do |index|
133
+ files.each do |file|
134
+ next unless spec = Bundler.load_gemspec(file)
135
+ Bundler.rubygems.set_installed_by_version(spec)
136
+
137
+ spec.source = self
138
+ Bundler.rubygems.validate(spec)
139
+
140
+ index << spec
141
+ end
142
+ end
143
+ end
144
+
145
+ # Set internal representation to fetch the gems/specs from remote.
146
+ #
147
+ # When this is called, the source should try to fetch the specs and
148
+ # install from remote path.
149
+ def remote!
150
+ end
151
+
152
+ # Set internal representation to fetch the gems/specs from app cache.
153
+ #
154
+ # When this is called, the source should try to fetch the specs and
155
+ # install from the path provided by `app_cache_path`.
156
+ def cached!
157
+ end
158
+
159
+ # This is called to update the spec and installation.
160
+ #
161
+ # If the source plugin is loaded from lockfile or otherwise, it shall
162
+ # refresh the cache/specs (e.g. git sources can make a fresh clone).
163
+ def unlock!
164
+ end
165
+
166
+ # Name of directory where plugin the is expected to cache the gems when
167
+ # #cache is called.
168
+ #
169
+ # Also this name is matched against the directories in cache for pruning
170
+ #
171
+ # This is used by `app_cache_path`
172
+ def app_cache_dirname
173
+ base_name = File.basename(URI.parse(uri).normalize.path)
174
+ "#{base_name}-#{uri_hash}"
175
+ end
176
+
177
+ # This method is called while caching to save copy of the gems that the
178
+ # source can resolve to path provided by `app_cache_app`so that they can
179
+ # be reinstalled from the cache without querying the remote (i.e. an
180
+ # alternative to remote)
181
+ #
182
+ # This is stored with the app and source plugins should try to provide
183
+ # specs and install only from this cache when `cached!` is called.
184
+ #
185
+ # This cache is different from the internal caching that can be done
186
+ # at sub paths of `cache_path` (from API). This can be though as caching
187
+ # by bundler.
188
+ def cache(spec, custom_path = nil)
189
+ new_cache_path = app_cache_path(custom_path)
190
+
191
+ FileUtils.rm_rf(new_cache_path)
192
+ FileUtils.cp_r(install_path, new_cache_path)
193
+ FileUtils.touch(app_cache_path.join(".bundlecache"))
194
+ end
195
+
196
+ # This shall check if two source object represent the same source.
197
+ #
198
+ # The comparison shall take place only on the attribute that can be
199
+ # inferred from the options passed from Gemfile and not on attibutes
200
+ # that are used to pin down the gem to specific version (e.g. Git
201
+ # sources should compare on branch and tag but not on commit hash)
202
+ #
203
+ # The sources objects are constructed from Gemfile as well as from
204
+ # lockfile. To converge the sources, it is necessary that they match.
205
+ #
206
+ # The same applies for `eql?` and `hash`
207
+ def ==(other)
208
+ other.is_a?(self.class) && uri == other.uri
209
+ end
210
+
211
+ # When overriding `eql?` please preserve the behaviour as mentioned in
212
+ # docstring for `==` method.
213
+ alias_method :eql?, :==
214
+
215
+ # When overriding `hash` please preserve the behaviour as mentioned in
216
+ # docstring for `==` method, i.e. two methods equal by above comparison
217
+ # should have same hash.
218
+ def hash
219
+ [self.class, uri].hash
220
+ end
221
+
222
+ # A helper method, not necessary if not used internally.
223
+ def installed?
224
+ File.directory?(install_path)
225
+ end
226
+
227
+ # The full path where the plugin should cache the gem so that it can be
228
+ # installed latter.
229
+ #
230
+ # Note: Do not override if you don't know what you are doing.
231
+ def app_cache_path(custom_path = nil)
232
+ @app_cache_path ||= Bundler.app_cache(custom_path).join(app_cache_dirname)
233
+ end
234
+
235
+ # Used by definition.
236
+ #
237
+ # Note: Do not override if you don't know what you are doing.
238
+ def unmet_deps
239
+ specs.unmet_dependency_names
240
+ end
241
+
242
+ # Note: Do not override if you don't know what you are doing.
243
+ def can_lock?(spec)
244
+ spec.source == self
245
+ end
246
+
247
+ # Generates the content to be entered into the lockfile.
248
+ # Saves type and remote and also calls to `options_to_lock`.
249
+ #
250
+ # Plugin should use `options_to_lock` to save information in lockfile
251
+ # and not override this.
252
+ #
253
+ # Note: Do not override if you don't know what you are doing.
254
+ def to_lock
255
+ out = String.new("#{LockfileParser::PLUGIN}\n")
256
+ out << " remote: #{@uri}\n"
257
+ out << " type: #{@type}\n"
258
+ options_to_lock.each do |opt, value|
259
+ out << " #{opt}: #{value}\n"
260
+ end
261
+ out << " specs:\n"
262
+ end
263
+
264
+ def to_s
265
+ "plugin source for #{options[:type]} with uri #{uri}"
266
+ end
267
+
268
+ # Note: Do not override if you don't know what you are doing.
269
+ def include?(other)
270
+ other == self
271
+ end
272
+
273
+ def uri_hash
274
+ SharedHelpers.digest(:SHA1).hexdigest(uri)
275
+ end
276
+
277
+ # Note: Do not override if you don't know what you are doing.
278
+ def gem_install_dir
279
+ Bundler.install_path
280
+ end
281
+
282
+ # It is used to obtain the full_gem_path.
283
+ #
284
+ # spec's loaded_from path is expanded against this to get full_gem_path
285
+ #
286
+ # Note: Do not override if you don't know what you are doing.
287
+ def root
288
+ Bundler.root
289
+ end
290
+
291
+ # @private
292
+ # Returns true
293
+ def bundler_plugin_api_source?
294
+ true
295
+ end
296
+
297
+ # @private
298
+ # This API on source might not be stable, and for now we expect plugins
299
+ # to download all specs in `#specs`, so we implement the method for
300
+ # compatibility purposes and leave it undocumented (and don't support)
301
+ # overriding it)
302
+ def double_check_for(*); end
303
+ end
304
+ end
305
+ end
306
+ end