rubygems-update 2.6.1 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (801) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +5899 -0
  3. data/CODE_OF_CONDUCT.md +76 -35
  4. data/CONTRIBUTING.md +231 -0
  5. data/MAINTAINERS.txt +8 -0
  6. data/Manifest.txt +428 -216
  7. data/POLICIES.md +135 -0
  8. data/README.md +112 -0
  9. data/UPGRADING.md +15 -0
  10. data/bundler/CHANGELOG.md +4719 -0
  11. data/bundler/LICENSE.md +22 -0
  12. data/bundler/README.md +58 -0
  13. data/bundler/UPGRADING.md +222 -0
  14. data/bundler/bundler.gemspec +46 -0
  15. data/bundler/exe/bundle +29 -0
  16. data/bundler/exe/bundler +4 -0
  17. data/bundler/lib/bundler/.document +1 -0
  18. data/bundler/lib/bundler/build_metadata.rb +45 -0
  19. data/bundler/lib/bundler/capistrano.rb +22 -0
  20. data/bundler/lib/bundler/checksum.rb +245 -0
  21. data/bundler/lib/bundler/ci_detector.rb +75 -0
  22. data/bundler/lib/bundler/cli/add.rb +47 -0
  23. data/bundler/lib/bundler/cli/binstubs.rb +57 -0
  24. data/bundler/lib/bundler/cli/cache.rb +43 -0
  25. data/bundler/lib/bundler/cli/check.rb +40 -0
  26. data/bundler/lib/bundler/cli/clean.rb +25 -0
  27. data/bundler/lib/bundler/cli/common.rb +138 -0
  28. data/bundler/lib/bundler/cli/config.rb +204 -0
  29. data/bundler/lib/bundler/cli/console.rb +44 -0
  30. data/bundler/lib/bundler/cli/doctor.rb +157 -0
  31. data/bundler/lib/bundler/cli/exec.rb +88 -0
  32. data/bundler/lib/bundler/cli/fund.rb +36 -0
  33. data/bundler/lib/bundler/cli/gem.rb +471 -0
  34. data/bundler/lib/bundler/cli/info.rb +83 -0
  35. data/bundler/lib/bundler/cli/init.rb +51 -0
  36. data/bundler/lib/bundler/cli/inject.rb +60 -0
  37. data/bundler/lib/bundler/cli/install.rb +190 -0
  38. data/bundler/lib/bundler/cli/issue.rb +41 -0
  39. data/bundler/lib/bundler/cli/list.rb +66 -0
  40. data/bundler/lib/bundler/cli/lock.rb +73 -0
  41. data/bundler/lib/bundler/cli/open.rb +29 -0
  42. data/bundler/lib/bundler/cli/outdated.rb +297 -0
  43. data/bundler/lib/bundler/cli/platform.rb +48 -0
  44. data/bundler/lib/bundler/cli/plugin.rb +34 -0
  45. data/bundler/lib/bundler/cli/pristine.rb +60 -0
  46. data/bundler/lib/bundler/cli/remove.rb +17 -0
  47. data/bundler/lib/bundler/cli/show.rb +75 -0
  48. data/bundler/lib/bundler/cli/update.rb +123 -0
  49. data/bundler/lib/bundler/cli/viz.rb +31 -0
  50. data/bundler/lib/bundler/cli.rb +846 -0
  51. data/bundler/lib/bundler/compact_index_client/cache.rb +121 -0
  52. data/bundler/lib/bundler/compact_index_client/cache_file.rb +153 -0
  53. data/bundler/lib/bundler/compact_index_client/gem_parser.rb +32 -0
  54. data/bundler/lib/bundler/compact_index_client/updater.rb +115 -0
  55. data/bundler/lib/bundler/compact_index_client.rb +126 -0
  56. data/bundler/lib/bundler/constants.rb +7 -0
  57. data/bundler/lib/bundler/current_ruby.rb +92 -0
  58. data/bundler/lib/bundler/definition.rb +1005 -0
  59. data/bundler/lib/bundler/dependency.rb +101 -0
  60. data/bundler/lib/bundler/deployment.rb +69 -0
  61. data/bundler/lib/bundler/deprecate.rb +44 -0
  62. data/bundler/lib/bundler/digest.rb +71 -0
  63. data/bundler/lib/bundler/dsl.rb +601 -0
  64. data/bundler/lib/bundler/endpoint_specification.rb +147 -0
  65. data/bundler/lib/bundler/env.rb +148 -0
  66. data/bundler/lib/bundler/environment_preserver.rb +86 -0
  67. data/bundler/lib/bundler/errors.rb +233 -0
  68. data/bundler/lib/bundler/feature_flag.rb +53 -0
  69. data/bundler/lib/bundler/fetcher/base.rb +52 -0
  70. data/bundler/lib/bundler/fetcher/compact_index.rb +129 -0
  71. data/bundler/lib/bundler/fetcher/dependency.rb +78 -0
  72. data/bundler/lib/bundler/fetcher/downloader.rb +91 -0
  73. data/bundler/lib/bundler/fetcher/gem_remote_fetcher.rb +16 -0
  74. data/bundler/lib/bundler/fetcher/index.rb +25 -0
  75. data/bundler/lib/bundler/fetcher.rb +324 -0
  76. data/bundler/lib/bundler/force_platform.rb +18 -0
  77. data/bundler/lib/bundler/friendly_errors.rb +126 -0
  78. data/bundler/lib/bundler/gem_helper.rb +237 -0
  79. data/bundler/lib/bundler/gem_helpers.rb +127 -0
  80. data/bundler/lib/bundler/gem_tasks.rb +7 -0
  81. data/bundler/lib/bundler/gem_version_promoter.rb +145 -0
  82. data/bundler/lib/bundler/graph.rb +152 -0
  83. data/bundler/lib/bundler/index.rb +205 -0
  84. data/bundler/lib/bundler/injector.rb +287 -0
  85. data/bundler/lib/bundler/inline.rb +73 -0
  86. data/bundler/lib/bundler/installer/gem_installer.rb +84 -0
  87. data/bundler/lib/bundler/installer/parallel_installer.rb +202 -0
  88. data/bundler/lib/bundler/installer/standalone.rb +116 -0
  89. data/bundler/lib/bundler/installer.rb +267 -0
  90. data/bundler/lib/bundler/lazy_specification.rb +170 -0
  91. data/bundler/lib/bundler/lockfile_generator.rb +104 -0
  92. data/bundler/lib/bundler/lockfile_parser.rb +289 -0
  93. data/bundler/lib/bundler/man/.document +1 -0
  94. data/bundler/lib/bundler/man/bundle-add.1 +59 -0
  95. data/bundler/lib/bundler/man/bundle-add.1.ronn +58 -0
  96. data/bundler/lib/bundler/man/bundle-binstubs.1 +30 -0
  97. data/bundler/lib/bundler/man/bundle-binstubs.1.ronn +41 -0
  98. data/bundler/lib/bundler/man/bundle-cache.1 +40 -0
  99. data/bundler/lib/bundler/man/bundle-cache.1.ronn +79 -0
  100. data/bundler/lib/bundler/man/bundle-check.1 +22 -0
  101. data/bundler/lib/bundler/man/bundle-check.1.ronn +26 -0
  102. data/bundler/lib/bundler/man/bundle-clean.1 +17 -0
  103. data/bundler/lib/bundler/man/bundle-clean.1.ronn +18 -0
  104. data/bundler/lib/bundler/man/bundle-config.1 +321 -0
  105. data/bundler/lib/bundler/man/bundle-config.1.ronn +411 -0
  106. data/bundler/lib/bundler/man/bundle-console.1 +35 -0
  107. data/bundler/lib/bundler/man/bundle-console.1.ronn +44 -0
  108. data/bundler/lib/bundler/man/bundle-doctor.1 +30 -0
  109. data/bundler/lib/bundler/man/bundle-doctor.1.ronn +33 -0
  110. data/bundler/lib/bundler/man/bundle-exec.1 +104 -0
  111. data/bundler/lib/bundler/man/bundle-exec.1.ronn +151 -0
  112. data/bundler/lib/bundler/man/bundle-gem.1 +69 -0
  113. data/bundler/lib/bundler/man/bundle-gem.1.ronn +117 -0
  114. data/bundler/lib/bundler/man/bundle-help.1 +9 -0
  115. data/bundler/lib/bundler/man/bundle-help.1.ronn +12 -0
  116. data/bundler/lib/bundler/man/bundle-info.1 +14 -0
  117. data/bundler/lib/bundler/man/bundle-info.1.ronn +17 -0
  118. data/bundler/lib/bundler/man/bundle-init.1 +20 -0
  119. data/bundler/lib/bundler/man/bundle-init.1.ronn +31 -0
  120. data/bundler/lib/bundler/man/bundle-inject.1 +23 -0
  121. data/bundler/lib/bundler/man/bundle-inject.1.ronn +24 -0
  122. data/bundler/lib/bundler/man/bundle-install.1 +215 -0
  123. data/bundler/lib/bundler/man/bundle-install.1.ronn +383 -0
  124. data/bundler/lib/bundler/man/bundle-list.1 +35 -0
  125. data/bundler/lib/bundler/man/bundle-list.1.ronn +33 -0
  126. data/bundler/lib/bundler/man/bundle-lock.1 +60 -0
  127. data/bundler/lib/bundler/man/bundle-lock.1.ronn +94 -0
  128. data/bundler/lib/bundler/man/bundle-open.1 +32 -0
  129. data/bundler/lib/bundler/man/bundle-open.1.ronn +27 -0
  130. data/bundler/lib/bundler/man/bundle-outdated.1 +100 -0
  131. data/bundler/lib/bundler/man/bundle-outdated.1.ronn +106 -0
  132. data/bundler/lib/bundler/man/bundle-platform.1 +49 -0
  133. data/bundler/lib/bundler/man/bundle-platform.1.ronn +49 -0
  134. data/bundler/lib/bundler/man/bundle-plugin.1 +55 -0
  135. data/bundler/lib/bundler/man/bundle-plugin.1.ronn +59 -0
  136. data/bundler/lib/bundler/man/bundle-pristine.1 +23 -0
  137. data/bundler/lib/bundler/man/bundle-pristine.1.ronn +34 -0
  138. data/bundler/lib/bundler/man/bundle-remove.1 +21 -0
  139. data/bundler/lib/bundler/man/bundle-remove.1.ronn +23 -0
  140. data/bundler/lib/bundler/man/bundle-show.1 +16 -0
  141. data/bundler/lib/bundler/man/bundle-show.1.ronn +21 -0
  142. data/bundler/lib/bundler/man/bundle-update.1 +275 -0
  143. data/bundler/lib/bundler/man/bundle-update.1.ronn +351 -0
  144. data/bundler/lib/bundler/man/bundle-version.1 +22 -0
  145. data/bundler/lib/bundler/man/bundle-version.1.ronn +24 -0
  146. data/bundler/lib/bundler/man/bundle-viz.1 +30 -0
  147. data/bundler/lib/bundler/man/bundle-viz.1.ronn +32 -0
  148. data/bundler/lib/bundler/man/bundle.1 +102 -0
  149. data/bundler/lib/bundler/man/bundle.1.ronn +116 -0
  150. data/bundler/lib/bundler/man/gemfile.5 +470 -0
  151. data/bundler/lib/bundler/man/gemfile.5.ronn +552 -0
  152. data/bundler/lib/bundler/man/index.txt +29 -0
  153. data/bundler/lib/bundler/match_metadata.rb +17 -0
  154. data/bundler/lib/bundler/match_platform.rb +23 -0
  155. data/bundler/lib/bundler/match_remote_metadata.rb +29 -0
  156. data/bundler/lib/bundler/mirror.rb +221 -0
  157. data/bundler/lib/bundler/plugin/api/source.rb +321 -0
  158. data/bundler/lib/bundler/plugin/api.rb +81 -0
  159. data/bundler/lib/bundler/plugin/dsl.rb +53 -0
  160. data/bundler/lib/bundler/plugin/events.rb +61 -0
  161. data/bundler/lib/bundler/plugin/index.rb +193 -0
  162. data/bundler/lib/bundler/plugin/installer/git.rb +34 -0
  163. data/bundler/lib/bundler/plugin/installer/rubygems.rb +19 -0
  164. data/bundler/lib/bundler/plugin/installer.rb +112 -0
  165. data/bundler/lib/bundler/plugin/source_list.rb +31 -0
  166. data/bundler/lib/bundler/plugin.rb +359 -0
  167. data/bundler/lib/bundler/process_lock.rb +24 -0
  168. data/bundler/lib/bundler/remote_specification.rb +117 -0
  169. data/bundler/lib/bundler/resolver/base.rb +107 -0
  170. data/bundler/lib/bundler/resolver/candidate.rb +94 -0
  171. data/bundler/lib/bundler/resolver/incompatibility.rb +15 -0
  172. data/bundler/lib/bundler/resolver/package.rb +77 -0
  173. data/bundler/lib/bundler/resolver/root.rb +25 -0
  174. data/bundler/lib/bundler/resolver/spec_group.rb +79 -0
  175. data/bundler/lib/bundler/resolver.rb +462 -0
  176. data/bundler/lib/bundler/retry.rb +66 -0
  177. data/bundler/lib/bundler/ruby_dsl.rb +53 -0
  178. data/bundler/lib/bundler/ruby_version.rb +131 -0
  179. data/bundler/lib/bundler/rubygems_ext.rb +328 -0
  180. data/bundler/lib/bundler/rubygems_gem_installer.rb +137 -0
  181. data/bundler/lib/bundler/rubygems_integration.rb +493 -0
  182. data/bundler/lib/bundler/runtime.rb +307 -0
  183. data/bundler/lib/bundler/safe_marshal.rb +31 -0
  184. data/bundler/lib/bundler/self_manager.rb +186 -0
  185. data/bundler/lib/bundler/settings/validator.rb +102 -0
  186. data/bundler/lib/bundler/settings.rb +588 -0
  187. data/bundler/lib/bundler/setup.rb +33 -0
  188. data/bundler/lib/bundler/shared_helpers.rb +380 -0
  189. data/bundler/lib/bundler/similarity_detector.rb +63 -0
  190. data/bundler/lib/bundler/source/gemspec.rb +18 -0
  191. data/bundler/lib/bundler/source/git/git_proxy.rb +455 -0
  192. data/bundler/lib/bundler/source/git.rb +380 -0
  193. data/bundler/lib/bundler/source/metadata.rb +62 -0
  194. data/bundler/lib/bundler/source/path/installer.rb +53 -0
  195. data/bundler/lib/bundler/source/path.rb +261 -0
  196. data/bundler/lib/bundler/source/rubygems/remote.rb +68 -0
  197. data/bundler/lib/bundler/source/rubygems.rb +516 -0
  198. data/bundler/lib/bundler/source/rubygems_aggregate.rb +68 -0
  199. data/bundler/lib/bundler/source.rb +116 -0
  200. data/bundler/lib/bundler/source_list.rb +227 -0
  201. data/bundler/lib/bundler/source_map.rb +71 -0
  202. data/bundler/lib/bundler/spec_set.rb +247 -0
  203. data/bundler/lib/bundler/stub_specification.rb +119 -0
  204. data/bundler/lib/bundler/templates/.document +1 -0
  205. data/bundler/lib/bundler/templates/Executable +27 -0
  206. data/bundler/lib/bundler/templates/Executable.bundler +109 -0
  207. data/bundler/lib/bundler/templates/Executable.standalone +14 -0
  208. data/bundler/lib/bundler/templates/Gemfile +5 -0
  209. data/bundler/lib/bundler/templates/newgem/CHANGELOG.md.tt +5 -0
  210. data/bundler/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +84 -0
  211. data/bundler/lib/bundler/templates/newgem/Cargo.toml.tt +7 -0
  212. data/bundler/lib/bundler/templates/newgem/Gemfile.tt +26 -0
  213. data/bundler/lib/bundler/templates/newgem/LICENSE.txt.tt +21 -0
  214. data/bundler/lib/bundler/templates/newgem/README.md.tt +45 -0
  215. data/bundler/lib/bundler/templates/newgem/Rakefile.tt +67 -0
  216. data/bundler/lib/bundler/templates/newgem/bin/console.tt +11 -0
  217. data/bundler/lib/bundler/templates/newgem/bin/setup.tt +8 -0
  218. data/bundler/lib/bundler/templates/newgem/circleci/config.yml.tt +25 -0
  219. data/bundler/lib/bundler/templates/newgem/exe/newgem.tt +3 -0
  220. data/bundler/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +15 -0
  221. data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt +10 -0
  222. data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +6 -0
  223. data/bundler/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +9 -0
  224. data/bundler/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +6 -0
  225. data/bundler/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +12 -0
  226. data/bundler/lib/bundler/templates/newgem/github/workflows/main.yml.tt +37 -0
  227. data/bundler/lib/bundler/templates/newgem/gitignore.tt +23 -0
  228. data/bundler/lib/bundler/templates/newgem/gitlab-ci.yml.tt +18 -0
  229. data/bundler/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +9 -0
  230. data/bundler/lib/bundler/templates/newgem/lib/newgem.rb.tt +15 -0
  231. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +51 -0
  232. data/bundler/lib/bundler/templates/newgem/rspec.tt +3 -0
  233. data/bundler/lib/bundler/templates/newgem/rubocop.yml.tt +13 -0
  234. data/bundler/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  235. data/bundler/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +11 -0
  236. data/bundler/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +15 -0
  237. data/bundler/lib/bundler/templates/newgem/standard.yml.tt +3 -0
  238. data/bundler/lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt +6 -0
  239. data/bundler/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +13 -0
  240. data/bundler/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt +15 -0
  241. data/bundler/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt +6 -0
  242. data/bundler/lib/bundler/ui/rg_proxy.rb +19 -0
  243. data/bundler/lib/bundler/ui/shell.rb +165 -0
  244. data/bundler/lib/bundler/ui/silent.rb +85 -0
  245. data/bundler/lib/bundler/ui.rb +9 -0
  246. data/bundler/lib/bundler/uri_credentials_filter.rb +43 -0
  247. data/bundler/lib/bundler/uri_normalizer.rb +23 -0
  248. data/bundler/lib/bundler/vendor/.document +1 -0
  249. data/bundler/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  250. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +174 -0
  251. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +3 -0
  252. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +56 -0
  253. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +175 -0
  254. data/bundler/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  255. data/bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb +2694 -0
  256. data/bundler/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  257. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +41 -0
  258. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +65 -0
  259. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +79 -0
  260. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1073 -0
  261. data/bundler/lib/bundler/vendor/pub_grub/LICENSE.txt +21 -0
  262. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
  263. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +189 -0
  264. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
  265. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb +150 -0
  266. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb +43 -0
  267. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
  268. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
  269. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb +19 -0
  270. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +60 -0
  271. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
  272. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
  273. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb +129 -0
  274. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +411 -0
  275. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +248 -0
  276. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb +178 -0
  277. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +31 -0
  278. data/bundler/lib/bundler/vendor/thor/LICENSE.md +20 -0
  279. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +105 -0
  280. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +61 -0
  281. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +108 -0
  282. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +143 -0
  283. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +373 -0
  284. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +130 -0
  285. data/bundler/lib/bundler/vendor/thor/lib/thor/actions.rb +340 -0
  286. data/bundler/lib/bundler/vendor/thor/lib/thor/base.rb +825 -0
  287. data/bundler/lib/bundler/vendor/thor/lib/thor/command.rb +151 -0
  288. data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +107 -0
  289. data/bundler/lib/bundler/vendor/thor/lib/thor/error.rb +106 -0
  290. data/bundler/lib/bundler/vendor/thor/lib/thor/group.rb +281 -0
  291. data/bundler/lib/bundler/vendor/thor/lib/thor/invocation.rb +178 -0
  292. data/bundler/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +37 -0
  293. data/bundler/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +88 -0
  294. data/bundler/lib/bundler/vendor/thor/lib/thor/line_editor.rb +17 -0
  295. data/bundler/lib/bundler/vendor/thor/lib/thor/nested_context.rb +29 -0
  296. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +89 -0
  297. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +195 -0
  298. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/option.rb +178 -0
  299. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/options.rb +293 -0
  300. data/bundler/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -0
  301. data/bundler/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +72 -0
  302. data/bundler/lib/bundler/vendor/thor/lib/thor/runner.rb +335 -0
  303. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +388 -0
  304. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/color.rb +115 -0
  305. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/column_printer.rb +29 -0
  306. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/html.rb +84 -0
  307. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/lcs_diff.rb +49 -0
  308. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb +134 -0
  309. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/terminal.rb +42 -0
  310. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/wrapped_printer.rb +38 -0
  311. data/bundler/lib/bundler/vendor/thor/lib/thor/shell.rb +81 -0
  312. data/bundler/lib/bundler/vendor/thor/lib/thor/util.rb +285 -0
  313. data/bundler/lib/bundler/vendor/thor/lib/thor/version.rb +3 -0
  314. data/bundler/lib/bundler/vendor/thor/lib/thor.rb +663 -0
  315. data/bundler/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  316. data/bundler/lib/bundler/vendor/tsort/lib/tsort.rb +455 -0
  317. data/bundler/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  318. data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +853 -0
  319. data/bundler/lib/bundler/vendor/uri/lib/uri/file.rb +100 -0
  320. data/bundler/lib/bundler/vendor/uri/lib/uri/ftp.rb +267 -0
  321. data/bundler/lib/bundler/vendor/uri/lib/uri/generic.rb +1588 -0
  322. data/bundler/lib/bundler/vendor/uri/lib/uri/http.rb +125 -0
  323. data/bundler/lib/bundler/vendor/uri/lib/uri/https.rb +23 -0
  324. data/bundler/lib/bundler/vendor/uri/lib/uri/ldap.rb +261 -0
  325. data/bundler/lib/bundler/vendor/uri/lib/uri/ldaps.rb +22 -0
  326. data/bundler/lib/bundler/vendor/uri/lib/uri/mailto.rb +293 -0
  327. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +539 -0
  328. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +183 -0
  329. data/bundler/lib/bundler/vendor/uri/lib/uri/version.rb +6 -0
  330. data/bundler/lib/bundler/vendor/uri/lib/uri/ws.rb +83 -0
  331. data/bundler/lib/bundler/vendor/uri/lib/uri/wss.rb +23 -0
  332. data/bundler/lib/bundler/vendor/uri/lib/uri.rb +104 -0
  333. data/bundler/lib/bundler/vendored_fileutils.rb +4 -0
  334. data/bundler/lib/bundler/vendored_net_http.rb +8 -0
  335. data/bundler/lib/bundler/vendored_persistent.rb +11 -0
  336. data/bundler/lib/bundler/vendored_pub_grub.rb +4 -0
  337. data/bundler/lib/bundler/vendored_thor.rb +8 -0
  338. data/bundler/lib/bundler/vendored_timeout.rb +8 -0
  339. data/bundler/lib/bundler/vendored_tsort.rb +4 -0
  340. data/bundler/lib/bundler/vendored_uri.rb +4 -0
  341. data/bundler/lib/bundler/version.rb +13 -0
  342. data/bundler/lib/bundler/vlad.rb +17 -0
  343. data/bundler/lib/bundler/worker.rb +117 -0
  344. data/bundler/lib/bundler/yaml_serializer.rb +93 -0
  345. data/bundler/lib/bundler.rb +665 -0
  346. data/{test/rubygems/bogussources.rb → exe/gem} +5 -2
  347. data/exe/update_rubygems +38 -0
  348. data/hide_lib_for_update/note.txt +0 -4
  349. data/lib/rubygems/available_set.rb +12 -12
  350. data/lib/rubygems/basic_specification.rb +75 -58
  351. data/lib/rubygems/bundler_version_finder.rb +77 -0
  352. data/lib/rubygems/ci_detector.rb +75 -0
  353. data/lib/rubygems/command.rb +144 -71
  354. data/lib/rubygems/command_manager.rb +64 -27
  355. data/lib/rubygems/commands/build_command.rb +88 -17
  356. data/lib/rubygems/commands/cert_command.rb +131 -83
  357. data/lib/rubygems/commands/check_command.rb +30 -27
  358. data/lib/rubygems/commands/cleanup_command.rb +57 -40
  359. data/lib/rubygems/commands/contents_command.rb +37 -39
  360. data/lib/rubygems/commands/dependency_command.rb +53 -65
  361. data/lib/rubygems/commands/environment_command.rb +32 -16
  362. data/lib/rubygems/commands/exec_command.rb +249 -0
  363. data/lib/rubygems/commands/fetch_command.rb +36 -19
  364. data/lib/rubygems/commands/generate_index_command.rb +40 -74
  365. data/lib/rubygems/commands/help_command.rb +22 -22
  366. data/lib/rubygems/commands/info_command.rb +38 -0
  367. data/lib/rubygems/commands/install_command.rb +67 -143
  368. data/lib/rubygems/commands/list_command.rb +10 -9
  369. data/lib/rubygems/commands/lock_command.rb +12 -14
  370. data/lib/rubygems/commands/mirror_command.rb +4 -4
  371. data/lib/rubygems/commands/open_command.rb +28 -26
  372. data/lib/rubygems/commands/outdated_command.rb +6 -6
  373. data/lib/rubygems/commands/owner_command.rb +51 -27
  374. data/lib/rubygems/commands/pristine_command.rb +99 -71
  375. data/lib/rubygems/commands/push_command.rb +53 -46
  376. data/lib/rubygems/commands/query_command.rb +21 -328
  377. data/lib/rubygems/commands/rdoc_command.rb +33 -33
  378. data/lib/rubygems/commands/search_command.rb +9 -9
  379. data/lib/rubygems/commands/server_command.rb +15 -76
  380. data/lib/rubygems/commands/setup_command.rb +370 -186
  381. data/lib/rubygems/commands/signin_command.rb +34 -0
  382. data/lib/rubygems/commands/signout_command.rb +32 -0
  383. data/lib/rubygems/commands/sources_command.rb +57 -41
  384. data/lib/rubygems/commands/specification_command.rb +38 -28
  385. data/lib/rubygems/commands/stale_command.rb +6 -5
  386. data/lib/rubygems/commands/uninstall_command.rb +96 -62
  387. data/lib/rubygems/commands/unpack_command.rb +44 -53
  388. data/lib/rubygems/commands/update_command.rb +155 -99
  389. data/lib/rubygems/commands/which_command.rb +14 -17
  390. data/lib/rubygems/commands/yank_command.rb +28 -32
  391. data/lib/rubygems/compatibility.rb +13 -32
  392. data/lib/rubygems/config_file.rb +214 -119
  393. data/lib/rubygems/core_ext/kernel_gem.rb +10 -16
  394. data/lib/rubygems/core_ext/kernel_require.rb +92 -90
  395. data/lib/rubygems/core_ext/kernel_warn.rb +49 -0
  396. data/lib/rubygems/core_ext/tcpsocket_init.rb +54 -0
  397. data/lib/rubygems/defaults.rb +184 -54
  398. data/lib/rubygems/dependency.rb +75 -62
  399. data/lib/rubygems/dependency_installer.rb +74 -230
  400. data/lib/rubygems/dependency_list.rb +32 -33
  401. data/lib/rubygems/deprecate.rb +113 -17
  402. data/lib/rubygems/doctor.rb +31 -31
  403. data/lib/rubygems/errors.rb +51 -13
  404. data/lib/rubygems/exceptions.rb +65 -35
  405. data/lib/rubygems/ext/build_error.rb +3 -1
  406. data/lib/rubygems/ext/builder.rb +103 -77
  407. data/lib/rubygems/ext/cargo_builder/link_flag_converter.rb +27 -0
  408. data/lib/rubygems/ext/cargo_builder.rb +360 -0
  409. data/lib/rubygems/ext/cmake_builder.rb +6 -7
  410. data/lib/rubygems/ext/configure_builder.rb +6 -9
  411. data/lib/rubygems/ext/ext_conf_builder.rb +40 -61
  412. data/lib/rubygems/ext/rake_builder.rb +18 -21
  413. data/lib/rubygems/ext.rb +8 -7
  414. data/lib/rubygems/gem_runner.rb +19 -21
  415. data/lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb +163 -0
  416. data/lib/rubygems/gemcutter_utilities/webauthn_listener.rb +105 -0
  417. data/lib/rubygems/gemcutter_utilities/webauthn_poller.rb +78 -0
  418. data/lib/rubygems/gemcutter_utilities.rb +246 -43
  419. data/lib/rubygems/install_default_message.rb +3 -3
  420. data/lib/rubygems/install_message.rb +3 -3
  421. data/lib/rubygems/install_update_options.rb +104 -98
  422. data/lib/rubygems/installer.rb +407 -225
  423. data/lib/rubygems/installer_uninstaller_utils.rb +27 -0
  424. data/lib/rubygems/local_remote_options.rb +29 -32
  425. data/lib/rubygems/name_tuple.rb +18 -23
  426. data/lib/rubygems/net/http.rb +3 -0
  427. data/lib/rubygems/net-http/LICENSE.txt +22 -0
  428. data/lib/rubygems/net-http/lib/net/http/backward.rb +40 -0
  429. data/lib/rubygems/net-http/lib/net/http/exceptions.rb +34 -0
  430. data/lib/rubygems/net-http/lib/net/http/generic_request.rb +414 -0
  431. data/lib/rubygems/net-http/lib/net/http/header.rb +981 -0
  432. data/lib/rubygems/net-http/lib/net/http/proxy_delta.rb +17 -0
  433. data/lib/rubygems/net-http/lib/net/http/request.rb +88 -0
  434. data/lib/rubygems/net-http/lib/net/http/requests.rb +425 -0
  435. data/lib/rubygems/net-http/lib/net/http/response.rb +738 -0
  436. data/lib/rubygems/net-http/lib/net/http/responses.rb +1174 -0
  437. data/lib/rubygems/net-http/lib/net/http/status.rb +84 -0
  438. data/lib/rubygems/net-http/lib/net/http.rb +2496 -0
  439. data/lib/rubygems/net-http/lib/net/https.rb +23 -0
  440. data/lib/rubygems/net-protocol/LICENSE.txt +22 -0
  441. data/lib/rubygems/net-protocol/lib/net/protocol.rb +544 -0
  442. data/lib/rubygems/openssl.rb +7 -0
  443. data/lib/rubygems/optparse/.document +1 -0
  444. data/lib/rubygems/optparse/COPYING +56 -0
  445. data/lib/rubygems/optparse/lib/optionparser.rb +2 -0
  446. data/lib/rubygems/optparse/lib/optparse/ac.rb +54 -0
  447. data/lib/rubygems/optparse/lib/optparse/date.rb +18 -0
  448. data/lib/rubygems/optparse/lib/optparse/kwargs.rb +22 -0
  449. data/lib/rubygems/optparse/lib/optparse/shellwords.rb +7 -0
  450. data/lib/rubygems/optparse/lib/optparse/time.rb +11 -0
  451. data/lib/rubygems/optparse/lib/optparse/uri.rb +7 -0
  452. data/lib/rubygems/optparse/lib/optparse/version.rb +71 -0
  453. data/lib/rubygems/optparse/lib/optparse.rb +2330 -0
  454. data/lib/rubygems/optparse.rb +3 -0
  455. data/lib/rubygems/package/digest_io.rb +5 -7
  456. data/lib/rubygems/package/file_source.rb +6 -8
  457. data/lib/rubygems/package/io_source.rb +6 -4
  458. data/lib/rubygems/package/old.rb +19 -28
  459. data/lib/rubygems/package/source.rb +1 -1
  460. data/lib/rubygems/package/tar_header.rb +114 -93
  461. data/lib/rubygems/package/tar_reader/entry.rb +116 -22
  462. data/lib/rubygems/package/tar_reader.rb +18 -40
  463. data/lib/rubygems/package/tar_writer.rb +42 -56
  464. data/lib/rubygems/package.rb +245 -145
  465. data/lib/rubygems/package_task.rb +8 -14
  466. data/lib/rubygems/path_support.rb +21 -16
  467. data/lib/rubygems/platform.rb +135 -74
  468. data/lib/rubygems/psych_tree.rb +3 -2
  469. data/lib/rubygems/query_utils.rb +349 -0
  470. data/lib/rubygems/rdoc.rb +4 -326
  471. data/lib/rubygems/remote_fetcher.rb +99 -181
  472. data/lib/rubygems/request/connection_pools.rb +31 -24
  473. data/lib/rubygems/request/http_pool.rb +6 -7
  474. data/lib/rubygems/request/https_pool.rb +2 -3
  475. data/lib/rubygems/request.rb +103 -53
  476. data/lib/rubygems/request_set/gem_dependency_api.rb +182 -190
  477. data/lib/rubygems/request_set/lockfile/parser.rb +42 -52
  478. data/lib/rubygems/request_set/lockfile/tokenizer.rb +34 -24
  479. data/lib/rubygems/request_set/lockfile.rb +32 -35
  480. data/lib/rubygems/request_set.rb +115 -71
  481. data/lib/rubygems/requirement.rb +77 -68
  482. data/lib/rubygems/resolv/LICENSE.txt +22 -0
  483. data/lib/rubygems/resolv/lib/resolv.rb +3387 -0
  484. data/lib/rubygems/resolver/activation_request.rb +34 -61
  485. data/lib/rubygems/resolver/api_set/gem_parser.rb +24 -0
  486. data/lib/rubygems/resolver/api_set.rb +40 -32
  487. data/lib/rubygems/resolver/api_specification.rb +37 -18
  488. data/lib/rubygems/resolver/best_set.rb +15 -17
  489. data/lib/rubygems/resolver/composed_set.rb +9 -11
  490. data/lib/rubygems/resolver/conflict.rb +19 -33
  491. data/lib/rubygems/resolver/current_set.rb +2 -4
  492. data/lib/rubygems/resolver/dependency_request.rb +8 -9
  493. data/lib/rubygems/resolver/git_set.rb +8 -10
  494. data/lib/rubygems/resolver/git_specification.rb +11 -13
  495. data/lib/rubygems/resolver/index_set.rb +13 -15
  496. data/lib/rubygems/resolver/index_specification.rb +42 -11
  497. data/lib/rubygems/resolver/installed_specification.rb +9 -11
  498. data/lib/rubygems/resolver/installer_set.rb +87 -45
  499. data/lib/rubygems/resolver/local_specification.rb +5 -7
  500. data/lib/rubygems/resolver/lock_set.rb +13 -15
  501. data/lib/rubygems/resolver/lock_specification.rb +13 -15
  502. data/lib/rubygems/resolver/molinillo/LICENSE +9 -0
  503. data/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb +57 -0
  504. data/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb +88 -0
  505. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb +36 -0
  506. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +66 -0
  507. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +62 -0
  508. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +63 -0
  509. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +61 -0
  510. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb +126 -0
  511. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb +46 -0
  512. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb +36 -0
  513. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb +164 -0
  514. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +110 -146
  515. data/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +83 -9
  516. data/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +2 -1
  517. data/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb +13 -1
  518. data/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb +3 -1
  519. data/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb +552 -172
  520. data/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb +3 -2
  521. data/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb +12 -6
  522. data/lib/rubygems/resolver/molinillo/lib/molinillo.rb +6 -5
  523. data/lib/rubygems/resolver/molinillo.rb +2 -1
  524. data/lib/rubygems/resolver/requirement_list.rb +2 -2
  525. data/lib/rubygems/resolver/set.rb +3 -5
  526. data/lib/rubygems/resolver/source_set.rb +6 -7
  527. data/lib/rubygems/resolver/spec_specification.rb +16 -4
  528. data/lib/rubygems/resolver/specification.rb +25 -10
  529. data/lib/rubygems/resolver/stats.rb +1 -0
  530. data/lib/rubygems/resolver/vendor_set.rb +6 -8
  531. data/lib/rubygems/resolver/vendor_specification.rb +6 -8
  532. data/lib/rubygems/resolver.rb +121 -72
  533. data/lib/rubygems/s3_uri_signer.rb +177 -0
  534. data/lib/rubygems/safe_marshal/elements.rb +138 -0
  535. data/lib/rubygems/safe_marshal/reader.rb +306 -0
  536. data/lib/rubygems/safe_marshal/visitors/stream_printer.rb +31 -0
  537. data/lib/rubygems/safe_marshal/visitors/to_ruby.rb +385 -0
  538. data/lib/rubygems/safe_marshal/visitors/visitor.rb +74 -0
  539. data/lib/rubygems/safe_marshal.rb +74 -0
  540. data/lib/rubygems/safe_yaml.rb +36 -0
  541. data/lib/rubygems/security/policies.rb +49 -51
  542. data/lib/rubygems/security/policy.rb +46 -53
  543. data/lib/rubygems/security/signer.rb +86 -29
  544. data/lib/rubygems/security/trust_dir.rb +22 -24
  545. data/lib/rubygems/security.rb +101 -82
  546. data/lib/rubygems/security_option.rb +43 -0
  547. data/lib/rubygems/shellwords.rb +3 -0
  548. data/lib/rubygems/source/git.rb +40 -42
  549. data/lib/rubygems/source/installed.rb +5 -9
  550. data/lib/rubygems/source/local.rb +30 -33
  551. data/lib/rubygems/source/lock.rb +10 -10
  552. data/lib/rubygems/source/specific_file.rb +7 -9
  553. data/lib/rubygems/source/vendor.rb +3 -7
  554. data/lib/rubygems/source.rb +78 -68
  555. data/lib/rubygems/source_list.rb +11 -15
  556. data/lib/rubygems/spec_fetcher.rb +71 -83
  557. data/lib/rubygems/specification.rb +833 -1115
  558. data/lib/rubygems/specification_policy.rb +538 -0
  559. data/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA.pem +21 -0
  560. data/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem +21 -0
  561. data/lib/rubygems/stub_specification.rb +55 -57
  562. data/lib/rubygems/text.rb +39 -27
  563. data/lib/rubygems/timeout/LICENSE.txt +22 -0
  564. data/lib/rubygems/timeout/lib/timeout.rb +199 -0
  565. data/lib/rubygems/timeout.rb +3 -0
  566. data/lib/rubygems/tsort/.document +1 -0
  567. data/lib/rubygems/tsort/LICENSE.txt +22 -0
  568. data/lib/rubygems/tsort/lib/tsort.rb +455 -0
  569. data/lib/rubygems/tsort.rb +3 -0
  570. data/lib/rubygems/uninstaller.rb +150 -87
  571. data/lib/rubygems/unknown_command_spell_checker.rb +21 -0
  572. data/lib/rubygems/update_suggestion.rb +56 -0
  573. data/lib/rubygems/uri.rb +126 -0
  574. data/lib/rubygems/uri_formatter.rb +4 -7
  575. data/lib/rubygems/user_interaction.rb +92 -146
  576. data/lib/rubygems/util/licenses.rb +712 -317
  577. data/lib/rubygems/util/list.rb +5 -2
  578. data/lib/rubygems/util.rb +58 -75
  579. data/lib/rubygems/validator.rb +26 -48
  580. data/lib/rubygems/version.rb +106 -56
  581. data/lib/rubygems/version_option.rb +22 -14
  582. data/lib/rubygems/yaml_serializer.rb +93 -0
  583. data/lib/rubygems.rb +427 -361
  584. data/rubygems-update.gemspec +38 -0
  585. data/setup.rb +13 -27
  586. metadata +500 -363
  587. data/.autotest +0 -71
  588. data/.document +0 -5
  589. data/.travis.yml +0 -46
  590. data/CONTRIBUTING.rdoc +0 -129
  591. data/CVE-2013-4287.txt +0 -35
  592. data/CVE-2013-4363.txt +0 -45
  593. data/CVE-2015-3900.txt +0 -40
  594. data/History.txt +0 -3105
  595. data/MAINTAINERS.md +0 -5
  596. data/POLICIES.rdoc +0 -61
  597. data/README.rdoc +0 -54
  598. data/Rakefile +0 -449
  599. data/UPGRADING.rdoc +0 -92
  600. data/appveyor.yml +0 -36
  601. data/bin/gem +0 -25
  602. data/bin/update_rubygems +0 -37
  603. data/lib/gauntlet_rubygems.rb +0 -51
  604. data/lib/rubygems/indexer.rb +0 -434
  605. data/lib/rubygems/installer_test_case.rb +0 -194
  606. data/lib/rubygems/mock_gem_ui.rb +0 -89
  607. data/lib/rubygems/package/tar_test_case.rb +0 -147
  608. data/lib/rubygems/psych_additions.rb +0 -10
  609. data/lib/rubygems/server.rb +0 -869
  610. data/lib/rubygems/source_local.rb +0 -6
  611. data/lib/rubygems/source_specific_file.rb +0 -5
  612. data/lib/rubygems/ssl_certs/AddTrustExternalCARoot-2048.pem +0 -25
  613. data/lib/rubygems/ssl_certs/AddTrustExternalCARoot.pem +0 -32
  614. data/lib/rubygems/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +0 -14
  615. data/lib/rubygems/ssl_certs/DigiCertHighAssuranceEVRootCA.pem +0 -23
  616. data/lib/rubygems/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +0 -28
  617. data/lib/rubygems/ssl_certs/GeoTrustGlobalCA.pem +0 -20
  618. data/lib/rubygems/syck_hack.rb +0 -77
  619. data/lib/rubygems/test_case.rb +0 -1496
  620. data/lib/rubygems/test_utilities.rb +0 -384
  621. data/lib/ubygems.rb +0 -11
  622. data/test/rubygems/alternate_cert.pem +0 -18
  623. data/test/rubygems/alternate_cert_32.pem +0 -18
  624. data/test/rubygems/alternate_key.pem +0 -27
  625. data/test/rubygems/bad_rake.rb +0 -2
  626. data/test/rubygems/ca_cert.pem +0 -68
  627. data/test/rubygems/child_cert.pem +0 -18
  628. data/test/rubygems/child_cert_32.pem +0 -18
  629. data/test/rubygems/child_key.pem +0 -27
  630. data/test/rubygems/client.pem +0 -49
  631. data/test/rubygems/data/gem-private_key.pem +0 -27
  632. data/test/rubygems/data/gem-public_cert.pem +0 -20
  633. data/test/rubygems/data/null-type.gemspec.rz +0 -0
  634. data/test/rubygems/encrypted_private_key.pem +0 -30
  635. data/test/rubygems/expired_cert.pem +0 -18
  636. data/test/rubygems/fake_certlib/openssl.rb +0 -8
  637. data/test/rubygems/fix_openssl_warnings.rb +0 -13
  638. data/test/rubygems/foo/discover.rb +0 -1
  639. data/test/rubygems/future_cert.pem +0 -18
  640. data/test/rubygems/future_cert_32.pem +0 -18
  641. data/test/rubygems/good_rake.rb +0 -2
  642. data/test/rubygems/grandchild_cert.pem +0 -18
  643. data/test/rubygems/grandchild_cert_32.pem +0 -18
  644. data/test/rubygems/grandchild_key.pem +0 -27
  645. data/test/rubygems/invalid_client.pem +0 -49
  646. data/test/rubygems/invalid_issuer_cert.pem +0 -18
  647. data/test/rubygems/invalid_issuer_cert_32.pem +0 -18
  648. data/test/rubygems/invalid_key.pem +0 -27
  649. data/test/rubygems/invalid_signer_cert.pem +0 -18
  650. data/test/rubygems/invalid_signer_cert_32.pem +0 -18
  651. data/test/rubygems/invalidchild_cert.pem +0 -18
  652. data/test/rubygems/invalidchild_cert_32.pem +0 -18
  653. data/test/rubygems/invalidchild_key.pem +0 -27
  654. data/test/rubygems/plugin/exception/rubygems_plugin.rb +0 -3
  655. data/test/rubygems/plugin/load/rubygems_plugin.rb +0 -4
  656. data/test/rubygems/plugin/standarderror/rubygems_plugin.rb +0 -3
  657. data/test/rubygems/private_key.pem +0 -27
  658. data/test/rubygems/public_cert.pem +0 -18
  659. data/test/rubygems/public_cert_32.pem +0 -18
  660. data/test/rubygems/public_key.pem +0 -9
  661. data/test/rubygems/rubygems/commands/crash_command.rb +0 -6
  662. data/test/rubygems/rubygems_plugin.rb +0 -22
  663. data/test/rubygems/sff/discover.rb +0 -1
  664. data/test/rubygems/simple_gem.rb +0 -67
  665. data/test/rubygems/specifications/bar-0.0.2.gemspec +0 -9
  666. data/test/rubygems/specifications/foo-0.0.1-x86-mswin32.gemspec +0 -0
  667. data/test/rubygems/ssl_cert.pem +0 -19
  668. data/test/rubygems/ssl_key.pem +0 -15
  669. data/test/rubygems/test_bundled_ca.rb +0 -59
  670. data/test/rubygems/test_config.rb +0 -24
  671. data/test/rubygems/test_deprecate.rb +0 -77
  672. data/test/rubygems/test_gem.rb +0 -1718
  673. data/test/rubygems/test_gem_available_set.rb +0 -130
  674. data/test/rubygems/test_gem_command.rb +0 -248
  675. data/test/rubygems/test_gem_command_manager.rb +0 -264
  676. data/test/rubygems/test_gem_commands_build_command.rb +0 -121
  677. data/test/rubygems/test_gem_commands_cert_command.rb +0 -671
  678. data/test/rubygems/test_gem_commands_check_command.rb +0 -69
  679. data/test/rubygems/test_gem_commands_cleanup_command.rb +0 -197
  680. data/test/rubygems/test_gem_commands_contents_command.rb +0 -240
  681. data/test/rubygems/test_gem_commands_dependency_command.rb +0 -230
  682. data/test/rubygems/test_gem_commands_environment_command.rb +0 -154
  683. data/test/rubygems/test_gem_commands_fetch_command.rb +0 -127
  684. data/test/rubygems/test_gem_commands_generate_index_command.rb +0 -51
  685. data/test/rubygems/test_gem_commands_help_command.rb +0 -75
  686. data/test/rubygems/test_gem_commands_install_command.rb +0 -1007
  687. data/test/rubygems/test_gem_commands_list_command.rb +0 -34
  688. data/test/rubygems/test_gem_commands_lock_command.rb +0 -69
  689. data/test/rubygems/test_gem_commands_mirror.rb +0 -20
  690. data/test/rubygems/test_gem_commands_open_command.rb +0 -70
  691. data/test/rubygems/test_gem_commands_outdated_command.rb +0 -33
  692. data/test/rubygems/test_gem_commands_owner_command.rb +0 -205
  693. data/test/rubygems/test_gem_commands_pristine_command.rb +0 -491
  694. data/test/rubygems/test_gem_commands_push_command.rb +0 -330
  695. data/test/rubygems/test_gem_commands_query_command.rb +0 -657
  696. data/test/rubygems/test_gem_commands_search_command.rb +0 -18
  697. data/test/rubygems/test_gem_commands_server_command.rb +0 -60
  698. data/test/rubygems/test_gem_commands_setup_command.rb +0 -136
  699. data/test/rubygems/test_gem_commands_sources_command.rb +0 -249
  700. data/test/rubygems/test_gem_commands_specification_command.rb +0 -251
  701. data/test/rubygems/test_gem_commands_stale_command.rb +0 -43
  702. data/test/rubygems/test_gem_commands_uninstall_command.rb +0 -283
  703. data/test/rubygems/test_gem_commands_unpack_command.rb +0 -209
  704. data/test/rubygems/test_gem_commands_update_command.rb +0 -514
  705. data/test/rubygems/test_gem_commands_which_command.rb +0 -87
  706. data/test/rubygems/test_gem_commands_yank_command.rb +0 -100
  707. data/test/rubygems/test_gem_config_file.rb +0 -491
  708. data/test/rubygems/test_gem_dependency.rb +0 -362
  709. data/test/rubygems/test_gem_dependency_installer.rb +0 -1235
  710. data/test/rubygems/test_gem_dependency_list.rb +0 -260
  711. data/test/rubygems/test_gem_dependency_resolution_error.rb +0 -29
  712. data/test/rubygems/test_gem_doctor.rb +0 -169
  713. data/test/rubygems/test_gem_ext_builder.rb +0 -341
  714. data/test/rubygems/test_gem_ext_cmake_builder.rb +0 -87
  715. data/test/rubygems/test_gem_ext_configure_builder.rb +0 -87
  716. data/test/rubygems/test_gem_ext_ext_conf_builder.rb +0 -211
  717. data/test/rubygems/test_gem_ext_rake_builder.rb +0 -65
  718. data/test/rubygems/test_gem_gem_runner.rb +0 -69
  719. data/test/rubygems/test_gem_gemcutter_utilities.rb +0 -235
  720. data/test/rubygems/test_gem_impossible_dependencies_error.rb +0 -62
  721. data/test/rubygems/test_gem_indexer.rb +0 -367
  722. data/test/rubygems/test_gem_install_update_options.rb +0 -197
  723. data/test/rubygems/test_gem_installer.rb +0 -1552
  724. data/test/rubygems/test_gem_local_remote_options.rb +0 -134
  725. data/test/rubygems/test_gem_name_tuple.rb +0 -45
  726. data/test/rubygems/test_gem_package.rb +0 -876
  727. data/test/rubygems/test_gem_package_old.rb +0 -90
  728. data/test/rubygems/test_gem_package_tar_header.rb +0 -147
  729. data/test/rubygems/test_gem_package_tar_reader.rb +0 -90
  730. data/test/rubygems/test_gem_package_tar_reader_entry.rb +0 -142
  731. data/test/rubygems/test_gem_package_tar_writer.rb +0 -264
  732. data/test/rubygems/test_gem_package_task.rb +0 -84
  733. data/test/rubygems/test_gem_path_support.rb +0 -121
  734. data/test/rubygems/test_gem_platform.rb +0 -308
  735. data/test/rubygems/test_gem_rdoc.rb +0 -270
  736. data/test/rubygems/test_gem_remote_fetcher.rb +0 -1051
  737. data/test/rubygems/test_gem_request.rb +0 -363
  738. data/test/rubygems/test_gem_request_connection_pools.rb +0 -130
  739. data/test/rubygems/test_gem_request_set.rb +0 -595
  740. data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +0 -831
  741. data/test/rubygems/test_gem_request_set_lockfile.rb +0 -470
  742. data/test/rubygems/test_gem_request_set_lockfile_parser.rb +0 -549
  743. data/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +0 -306
  744. data/test/rubygems/test_gem_requirement.rb +0 -387
  745. data/test/rubygems/test_gem_resolver.rb +0 -715
  746. data/test/rubygems/test_gem_resolver_activation_request.rb +0 -74
  747. data/test/rubygems/test_gem_resolver_api_set.rb +0 -209
  748. data/test/rubygems/test_gem_resolver_api_specification.rb +0 -145
  749. data/test/rubygems/test_gem_resolver_best_set.rb +0 -138
  750. data/test/rubygems/test_gem_resolver_composed_set.rb +0 -46
  751. data/test/rubygems/test_gem_resolver_conflict.rb +0 -88
  752. data/test/rubygems/test_gem_resolver_dependency_request.rb +0 -85
  753. data/test/rubygems/test_gem_resolver_git_set.rb +0 -190
  754. data/test/rubygems/test_gem_resolver_git_specification.rb +0 -114
  755. data/test/rubygems/test_gem_resolver_index_set.rb +0 -90
  756. data/test/rubygems/test_gem_resolver_index_specification.rb +0 -90
  757. data/test/rubygems/test_gem_resolver_installed_specification.rb +0 -50
  758. data/test/rubygems/test_gem_resolver_installer_set.rb +0 -258
  759. data/test/rubygems/test_gem_resolver_local_specification.rb +0 -46
  760. data/test/rubygems/test_gem_resolver_lock_set.rb +0 -64
  761. data/test/rubygems/test_gem_resolver_lock_specification.rb +0 -100
  762. data/test/rubygems/test_gem_resolver_requirement_list.rb +0 -21
  763. data/test/rubygems/test_gem_resolver_specification.rb +0 -65
  764. data/test/rubygems/test_gem_resolver_vendor_set.rb +0 -84
  765. data/test/rubygems/test_gem_resolver_vendor_specification.rb +0 -84
  766. data/test/rubygems/test_gem_security.rb +0 -307
  767. data/test/rubygems/test_gem_security_policy.rb +0 -541
  768. data/test/rubygems/test_gem_security_signer.rb +0 -209
  769. data/test/rubygems/test_gem_security_trust_dir.rb +0 -101
  770. data/test/rubygems/test_gem_server.rb +0 -409
  771. data/test/rubygems/test_gem_silent_ui.rb +0 -117
  772. data/test/rubygems/test_gem_source.rb +0 -242
  773. data/test/rubygems/test_gem_source_fetch_problem.rb +0 -20
  774. data/test/rubygems/test_gem_source_git.rb +0 -309
  775. data/test/rubygems/test_gem_source_installed.rb +0 -37
  776. data/test/rubygems/test_gem_source_list.rb +0 -118
  777. data/test/rubygems/test_gem_source_local.rb +0 -107
  778. data/test/rubygems/test_gem_source_lock.rb +0 -115
  779. data/test/rubygems/test_gem_source_specific_file.rb +0 -76
  780. data/test/rubygems/test_gem_source_vendor.rb +0 -32
  781. data/test/rubygems/test_gem_spec_fetcher.rb +0 -311
  782. data/test/rubygems/test_gem_specification.rb +0 -3519
  783. data/test/rubygems/test_gem_stream_ui.rb +0 -239
  784. data/test/rubygems/test_gem_stub_specification.rb +0 -217
  785. data/test/rubygems/test_gem_text.rb +0 -77
  786. data/test/rubygems/test_gem_uninstaller.rb +0 -485
  787. data/test/rubygems/test_gem_unsatisfiable_dependency_error.rb +0 -33
  788. data/test/rubygems/test_gem_uri_formatter.rb +0 -29
  789. data/test/rubygems/test_gem_util.rb +0 -40
  790. data/test/rubygems/test_gem_validator.rb +0 -46
  791. data/test/rubygems/test_gem_version.rb +0 -222
  792. data/test/rubygems/test_gem_version_option.rb +0 -152
  793. data/test/rubygems/test_kernel.rb +0 -86
  794. data/test/rubygems/test_require.rb +0 -322
  795. data/test/rubygems/wrong_key_cert.pem +0 -18
  796. data/test/rubygems/wrong_key_cert_32.pem +0 -18
  797. data/util/CL2notes +0 -56
  798. data/util/create_certs.rb +0 -157
  799. data/util/create_encrypted_key.rb +0 -17
  800. data/util/generate_spdx_license_list.rb +0 -51
  801. data/util/update_bundled_ca_certificates.rb +0 -118
@@ -0,0 +1,2694 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'rbconfig'
5
+ rescue LoadError
6
+ # for make rjit-headers
7
+ end
8
+
9
+ # Namespace for file utility methods for copying, moving, removing, etc.
10
+ #
11
+ # == What's Here
12
+ #
13
+ # First, what’s elsewhere. \Module \Bundler::FileUtils:
14
+ #
15
+ # - Inherits from {class Object}[https://docs.ruby-lang.org/en/master/Object.html].
16
+ # - Supplements {class File}[https://docs.ruby-lang.org/en/master/File.html]
17
+ # (but is not included or extended there).
18
+ #
19
+ # Here, module \Bundler::FileUtils provides methods that are useful for:
20
+ #
21
+ # - {Creating}[rdoc-ref:FileUtils@Creating].
22
+ # - {Deleting}[rdoc-ref:FileUtils@Deleting].
23
+ # - {Querying}[rdoc-ref:FileUtils@Querying].
24
+ # - {Setting}[rdoc-ref:FileUtils@Setting].
25
+ # - {Comparing}[rdoc-ref:FileUtils@Comparing].
26
+ # - {Copying}[rdoc-ref:FileUtils@Copying].
27
+ # - {Moving}[rdoc-ref:FileUtils@Moving].
28
+ # - {Options}[rdoc-ref:FileUtils@Options].
29
+ #
30
+ # === Creating
31
+ #
32
+ # - ::mkdir: Creates directories.
33
+ # - ::mkdir_p, ::makedirs, ::mkpath: Creates directories,
34
+ # also creating ancestor directories as needed.
35
+ # - ::link_entry: Creates a hard link.
36
+ # - ::ln, ::link: Creates hard links.
37
+ # - ::ln_s, ::symlink: Creates symbolic links.
38
+ # - ::ln_sf: Creates symbolic links, overwriting if necessary.
39
+ # - ::ln_sr: Creates symbolic links relative to targets
40
+ #
41
+ # === Deleting
42
+ #
43
+ # - ::remove_dir: Removes a directory and its descendants.
44
+ # - ::remove_entry: Removes an entry, including its descendants if it is a directory.
45
+ # - ::remove_entry_secure: Like ::remove_entry, but removes securely.
46
+ # - ::remove_file: Removes a file entry.
47
+ # - ::rm, ::remove: Removes entries.
48
+ # - ::rm_f, ::safe_unlink: Like ::rm, but removes forcibly.
49
+ # - ::rm_r: Removes entries and their descendants.
50
+ # - ::rm_rf, ::rmtree: Like ::rm_r, but removes forcibly.
51
+ # - ::rmdir: Removes directories.
52
+ #
53
+ # === Querying
54
+ #
55
+ # - ::pwd, ::getwd: Returns the path to the working directory.
56
+ # - ::uptodate?: Returns whether a given entry is newer than given other entries.
57
+ #
58
+ # === Setting
59
+ #
60
+ # - ::cd, ::chdir: Sets the working directory.
61
+ # - ::chmod: Sets permissions for an entry.
62
+ # - ::chmod_R: Sets permissions for an entry and its descendants.
63
+ # - ::chown: Sets the owner and group for entries.
64
+ # - ::chown_R: Sets the owner and group for entries and their descendants.
65
+ # - ::touch: Sets modification and access times for entries,
66
+ # creating if necessary.
67
+ #
68
+ # === Comparing
69
+ #
70
+ # - ::compare_file, ::cmp, ::identical?: Returns whether two entries are identical.
71
+ # - ::compare_stream: Returns whether two streams are identical.
72
+ #
73
+ # === Copying
74
+ #
75
+ # - ::copy_entry: Recursively copies an entry.
76
+ # - ::copy_file: Copies an entry.
77
+ # - ::copy_stream: Copies a stream.
78
+ # - ::cp, ::copy: Copies files.
79
+ # - ::cp_lr: Recursively creates hard links.
80
+ # - ::cp_r: Recursively copies files, retaining mode, owner, and group.
81
+ # - ::install: Recursively copies files, optionally setting mode,
82
+ # owner, and group.
83
+ #
84
+ # === Moving
85
+ #
86
+ # - ::mv, ::move: Moves entries.
87
+ #
88
+ # === Options
89
+ #
90
+ # - ::collect_method: Returns the names of methods that accept a given option.
91
+ # - ::commands: Returns the names of methods that accept options.
92
+ # - ::have_option?: Returns whether a given method accepts a given option.
93
+ # - ::options: Returns all option names.
94
+ # - ::options_of: Returns the names of the options for a given method.
95
+ #
96
+ # == Path Arguments
97
+ #
98
+ # Some methods in \Bundler::FileUtils accept _path_ arguments,
99
+ # which are interpreted as paths to filesystem entries:
100
+ #
101
+ # - If the argument is a string, that value is the path.
102
+ # - If the argument has method +:to_path+, it is converted via that method.
103
+ # - If the argument has method +:to_str+, it is converted via that method.
104
+ #
105
+ # == About the Examples
106
+ #
107
+ # Some examples here involve trees of file entries.
108
+ # For these, we sometimes display trees using the
109
+ # {tree command-line utility}[https://en.wikipedia.org/wiki/Tree_(command)],
110
+ # which is a recursive directory-listing utility that produces
111
+ # a depth-indented listing of files and directories.
112
+ #
113
+ # We use a helper method to launch the command and control the format:
114
+ #
115
+ # def tree(dirpath = '.')
116
+ # command = "tree --noreport --charset=ascii #{dirpath}"
117
+ # system(command)
118
+ # end
119
+ #
120
+ # To illustrate:
121
+ #
122
+ # tree('src0')
123
+ # # => src0
124
+ # # |-- sub0
125
+ # # | |-- src0.txt
126
+ # # | `-- src1.txt
127
+ # # `-- sub1
128
+ # # |-- src2.txt
129
+ # # `-- src3.txt
130
+ #
131
+ # == Avoiding the TOCTTOU Vulnerability
132
+ #
133
+ # For certain methods that recursively remove entries,
134
+ # there is a potential vulnerability called the
135
+ # {Time-of-check to time-of-use}[https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use],
136
+ # or TOCTTOU, vulnerability that can exist when:
137
+ #
138
+ # - An ancestor directory of the entry at the target path is world writable;
139
+ # such directories include <tt>/tmp</tt>.
140
+ # - The directory tree at the target path includes:
141
+ #
142
+ # - A world-writable descendant directory.
143
+ # - A symbolic link.
144
+ #
145
+ # To avoid that vulnerability, you can use this method to remove entries:
146
+ #
147
+ # - Bundler::FileUtils.remove_entry_secure: removes recursively
148
+ # if the target path points to a directory.
149
+ #
150
+ # Also available are these methods,
151
+ # each of which calls \Bundler::FileUtils.remove_entry_secure:
152
+ #
153
+ # - Bundler::FileUtils.rm_r with keyword argument <tt>secure: true</tt>.
154
+ # - Bundler::FileUtils.rm_rf with keyword argument <tt>secure: true</tt>.
155
+ #
156
+ # Finally, this method for moving entries calls \Bundler::FileUtils.remove_entry_secure
157
+ # if the source and destination are on different file systems
158
+ # (which means that the "move" is really a copy and remove):
159
+ #
160
+ # - Bundler::FileUtils.mv with keyword argument <tt>secure: true</tt>.
161
+ #
162
+ # \Method \Bundler::FileUtils.remove_entry_secure removes securely
163
+ # by applying a special pre-process:
164
+ #
165
+ # - If the target path points to a directory, this method uses methods
166
+ # {File#chown}[https://docs.ruby-lang.org/en/master/File.html#method-i-chown]
167
+ # and {File#chmod}[https://docs.ruby-lang.org/en/master/File.html#method-i-chmod]
168
+ # in removing directories.
169
+ # - The owner of the target directory should be either the current process
170
+ # or the super user (root).
171
+ #
172
+ # WARNING: You must ensure that *ALL* parent directories cannot be
173
+ # moved by other untrusted users. For example, parent directories
174
+ # should not be owned by untrusted users, and should not be world
175
+ # writable except when the sticky bit is set.
176
+ #
177
+ # For details of this security vulnerability, see Perl cases:
178
+ #
179
+ # - {CVE-2005-0448}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448].
180
+ # - {CVE-2004-0452}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452].
181
+ #
182
+ module Bundler::FileUtils
183
+ VERSION = "1.7.2"
184
+
185
+ def self.private_module_function(name) #:nodoc:
186
+ module_function name
187
+ private_class_method name
188
+ end
189
+
190
+ #
191
+ # Returns a string containing the path to the current directory:
192
+ #
193
+ # Bundler::FileUtils.pwd # => "/rdoc/fileutils"
194
+ #
195
+ # Related: Bundler::FileUtils.cd.
196
+ #
197
+ def pwd
198
+ Dir.pwd
199
+ end
200
+ module_function :pwd
201
+
202
+ alias getwd pwd
203
+ module_function :getwd
204
+
205
+ # Changes the working directory to the given +dir+, which
206
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments]:
207
+ #
208
+ # With no block given,
209
+ # changes the current directory to the directory at +dir+; returns zero:
210
+ #
211
+ # Bundler::FileUtils.pwd # => "/rdoc/fileutils"
212
+ # Bundler::FileUtils.cd('..')
213
+ # Bundler::FileUtils.pwd # => "/rdoc"
214
+ # Bundler::FileUtils.cd('fileutils')
215
+ #
216
+ # With a block given, changes the current directory to the directory
217
+ # at +dir+, calls the block with argument +dir+,
218
+ # and restores the original current directory; returns the block's value:
219
+ #
220
+ # Bundler::FileUtils.pwd # => "/rdoc/fileutils"
221
+ # Bundler::FileUtils.cd('..') { |arg| [arg, Bundler::FileUtils.pwd] } # => ["..", "/rdoc"]
222
+ # Bundler::FileUtils.pwd # => "/rdoc/fileutils"
223
+ #
224
+ # Keyword arguments:
225
+ #
226
+ # - <tt>verbose: true</tt> - prints an equivalent command:
227
+ #
228
+ # Bundler::FileUtils.cd('..')
229
+ # Bundler::FileUtils.cd('fileutils')
230
+ #
231
+ # Output:
232
+ #
233
+ # cd ..
234
+ # cd fileutils
235
+ #
236
+ # Related: Bundler::FileUtils.pwd.
237
+ #
238
+ def cd(dir, verbose: nil, &block) # :yield: dir
239
+ fu_output_message "cd #{dir}" if verbose
240
+ result = Dir.chdir(dir, &block)
241
+ fu_output_message 'cd -' if verbose and block
242
+ result
243
+ end
244
+ module_function :cd
245
+
246
+ alias chdir cd
247
+ module_function :chdir
248
+
249
+ #
250
+ # Returns +true+ if the file at path +new+
251
+ # is newer than all the files at paths in array +old_list+;
252
+ # +false+ otherwise.
253
+ #
254
+ # Argument +new+ and the elements of +old_list+
255
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments]:
256
+ #
257
+ # Bundler::FileUtils.uptodate?('Rakefile', ['Gemfile', 'README.md']) # => true
258
+ # Bundler::FileUtils.uptodate?('Gemfile', ['Rakefile', 'README.md']) # => false
259
+ #
260
+ # A non-existent file is considered to be infinitely old.
261
+ #
262
+ # Related: Bundler::FileUtils.touch.
263
+ #
264
+ def uptodate?(new, old_list)
265
+ return false unless File.exist?(new)
266
+ new_time = File.mtime(new)
267
+ old_list.each do |old|
268
+ if File.exist?(old)
269
+ return false unless new_time > File.mtime(old)
270
+ end
271
+ end
272
+ true
273
+ end
274
+ module_function :uptodate?
275
+
276
+ def remove_trailing_slash(dir) #:nodoc:
277
+ dir == '/' ? dir : dir.chomp(?/)
278
+ end
279
+ private_module_function :remove_trailing_slash
280
+
281
+ #
282
+ # Creates directories at the paths in the given +list+
283
+ # (a single path or an array of paths);
284
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise.
285
+ #
286
+ # Argument +list+ or its elements
287
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
288
+ #
289
+ # With no keyword arguments, creates a directory at each +path+ in +list+
290
+ # by calling: <tt>Dir.mkdir(path, mode)</tt>;
291
+ # see {Dir.mkdir}[https://docs.ruby-lang.org/en/master/Dir.html#method-c-mkdir]:
292
+ #
293
+ # Bundler::FileUtils.mkdir(%w[tmp0 tmp1]) # => ["tmp0", "tmp1"]
294
+ # Bundler::FileUtils.mkdir('tmp4') # => ["tmp4"]
295
+ #
296
+ # Keyword arguments:
297
+ #
298
+ # - <tt>mode: <i>mode</i></tt> - also calls <tt>File.chmod(mode, path)</tt>;
299
+ # see {File.chmod}[https://docs.ruby-lang.org/en/master/File.html#method-c-chmod].
300
+ # - <tt>noop: true</tt> - does not create directories.
301
+ # - <tt>verbose: true</tt> - prints an equivalent command:
302
+ #
303
+ # Bundler::FileUtils.mkdir(%w[tmp0 tmp1], verbose: true)
304
+ # Bundler::FileUtils.mkdir(%w[tmp2 tmp3], mode: 0700, verbose: true)
305
+ #
306
+ # Output:
307
+ #
308
+ # mkdir tmp0 tmp1
309
+ # mkdir -m 700 tmp2 tmp3
310
+ #
311
+ # Raises an exception if any path points to an existing
312
+ # file or directory, or if for any reason a directory cannot be created.
313
+ #
314
+ # Related: Bundler::FileUtils.mkdir_p.
315
+ #
316
+ def mkdir(list, mode: nil, noop: nil, verbose: nil)
317
+ list = fu_list(list)
318
+ fu_output_message "mkdir #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose
319
+ return if noop
320
+
321
+ list.each do |dir|
322
+ fu_mkdir dir, mode
323
+ end
324
+ end
325
+ module_function :mkdir
326
+
327
+ #
328
+ # Creates directories at the paths in the given +list+
329
+ # (a single path or an array of paths),
330
+ # also creating ancestor directories as needed;
331
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise.
332
+ #
333
+ # Argument +list+ or its elements
334
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
335
+ #
336
+ # With no keyword arguments, creates a directory at each +path+ in +list+,
337
+ # along with any needed ancestor directories,
338
+ # by calling: <tt>Dir.mkdir(path, mode)</tt>;
339
+ # see {Dir.mkdir}[https://docs.ruby-lang.org/en/master/Dir.html#method-c-mkdir]:
340
+ #
341
+ # Bundler::FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
342
+ # Bundler::FileUtils.mkdir_p('tmp4/tmp5') # => ["tmp4/tmp5"]
343
+ #
344
+ # Keyword arguments:
345
+ #
346
+ # - <tt>mode: <i>mode</i></tt> - also calls <tt>File.chmod(mode, path)</tt>;
347
+ # see {File.chmod}[https://docs.ruby-lang.org/en/master/File.html#method-c-chmod].
348
+ # - <tt>noop: true</tt> - does not create directories.
349
+ # - <tt>verbose: true</tt> - prints an equivalent command:
350
+ #
351
+ # Bundler::FileUtils.mkdir_p(%w[tmp0 tmp1], verbose: true)
352
+ # Bundler::FileUtils.mkdir_p(%w[tmp2 tmp3], mode: 0700, verbose: true)
353
+ #
354
+ # Output:
355
+ #
356
+ # mkdir -p tmp0 tmp1
357
+ # mkdir -p -m 700 tmp2 tmp3
358
+ #
359
+ # Raises an exception if for any reason a directory cannot be created.
360
+ #
361
+ # Bundler::FileUtils.mkpath and Bundler::FileUtils.makedirs are aliases for Bundler::FileUtils.mkdir_p.
362
+ #
363
+ # Related: Bundler::FileUtils.mkdir.
364
+ #
365
+ def mkdir_p(list, mode: nil, noop: nil, verbose: nil)
366
+ list = fu_list(list)
367
+ fu_output_message "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose
368
+ return *list if noop
369
+
370
+ list.each do |item|
371
+ path = remove_trailing_slash(item)
372
+
373
+ stack = []
374
+ until File.directory?(path) || File.dirname(path) == path
375
+ stack.push path
376
+ path = File.dirname(path)
377
+ end
378
+ stack.reverse_each do |dir|
379
+ begin
380
+ fu_mkdir dir, mode
381
+ rescue SystemCallError
382
+ raise unless File.directory?(dir)
383
+ end
384
+ end
385
+ end
386
+
387
+ return *list
388
+ end
389
+ module_function :mkdir_p
390
+
391
+ alias mkpath mkdir_p
392
+ alias makedirs mkdir_p
393
+ module_function :mkpath
394
+ module_function :makedirs
395
+
396
+ def fu_mkdir(path, mode) #:nodoc:
397
+ path = remove_trailing_slash(path)
398
+ if mode
399
+ Dir.mkdir path, mode
400
+ File.chmod mode, path
401
+ else
402
+ Dir.mkdir path
403
+ end
404
+ end
405
+ private_module_function :fu_mkdir
406
+
407
+ #
408
+ # Removes directories at the paths in the given +list+
409
+ # (a single path or an array of paths);
410
+ # returns +list+, if it is an array, <tt>[list]</tt> otherwise.
411
+ #
412
+ # Argument +list+ or its elements
413
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
414
+ #
415
+ # With no keyword arguments, removes the directory at each +path+ in +list+,
416
+ # by calling: <tt>Dir.rmdir(path)</tt>;
417
+ # see {Dir.rmdir}[https://docs.ruby-lang.org/en/master/Dir.html#method-c-rmdir]:
418
+ #
419
+ # Bundler::FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
420
+ # Bundler::FileUtils.rmdir('tmp4/tmp5') # => ["tmp4/tmp5"]
421
+ #
422
+ # Keyword arguments:
423
+ #
424
+ # - <tt>parents: true</tt> - removes successive ancestor directories
425
+ # if empty.
426
+ # - <tt>noop: true</tt> - does not remove directories.
427
+ # - <tt>verbose: true</tt> - prints an equivalent command:
428
+ #
429
+ # Bundler::FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3], parents: true, verbose: true)
430
+ # Bundler::FileUtils.rmdir('tmp4/tmp5', parents: true, verbose: true)
431
+ #
432
+ # Output:
433
+ #
434
+ # rmdir -p tmp0/tmp1 tmp2/tmp3
435
+ # rmdir -p tmp4/tmp5
436
+ #
437
+ # Raises an exception if a directory does not exist
438
+ # or if for any reason a directory cannot be removed.
439
+ #
440
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
441
+ #
442
+ def rmdir(list, parents: nil, noop: nil, verbose: nil)
443
+ list = fu_list(list)
444
+ fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if verbose
445
+ return if noop
446
+ list.each do |dir|
447
+ Dir.rmdir(dir = remove_trailing_slash(dir))
448
+ if parents
449
+ begin
450
+ until (parent = File.dirname(dir)) == '.' or parent == dir
451
+ dir = parent
452
+ Dir.rmdir(dir)
453
+ end
454
+ rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
455
+ end
456
+ end
457
+ end
458
+ end
459
+ module_function :rmdir
460
+
461
+ # Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link].
462
+ #
463
+ # Arguments +src+ (a single path or an array of paths)
464
+ # and +dest+ (a single path)
465
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
466
+ #
467
+ # When +src+ is the path to an existing file
468
+ # and +dest+ is the path to a non-existent file,
469
+ # creates a hard link at +dest+ pointing to +src+; returns zero:
470
+ #
471
+ # Dir.children('tmp0/') # => ["t.txt"]
472
+ # Dir.children('tmp1/') # => []
473
+ # Bundler::FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk') # => 0
474
+ # Dir.children('tmp1/') # => ["t.lnk"]
475
+ #
476
+ # When +src+ is the path to an existing file
477
+ # and +dest+ is the path to an existing directory,
478
+ # creates a hard link at <tt>dest/src</tt> pointing to +src+; returns zero:
479
+ #
480
+ # Dir.children('tmp2') # => ["t.dat"]
481
+ # Dir.children('tmp3') # => []
482
+ # Bundler::FileUtils.ln('tmp2/t.dat', 'tmp3') # => 0
483
+ # Dir.children('tmp3') # => ["t.dat"]
484
+ #
485
+ # When +src+ is an array of paths to existing files
486
+ # and +dest+ is the path to an existing directory,
487
+ # then for each path +target+ in +src+,
488
+ # creates a hard link at <tt>dest/target</tt> pointing to +target+;
489
+ # returns +src+:
490
+ #
491
+ # Dir.children('tmp4/') # => []
492
+ # Bundler::FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/') # => ["tmp0/t.txt", "tmp2/t.dat"]
493
+ # Dir.children('tmp4/') # => ["t.dat", "t.txt"]
494
+ #
495
+ # Keyword arguments:
496
+ #
497
+ # - <tt>force: true</tt> - overwrites +dest+ if it exists.
498
+ # - <tt>noop: true</tt> - does not create links.
499
+ # - <tt>verbose: true</tt> - prints an equivalent command:
500
+ #
501
+ # Bundler::FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk', verbose: true)
502
+ # Bundler::FileUtils.ln('tmp2/t.dat', 'tmp3', verbose: true)
503
+ # Bundler::FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/', verbose: true)
504
+ #
505
+ # Output:
506
+ #
507
+ # ln tmp0/t.txt tmp1/t.lnk
508
+ # ln tmp2/t.dat tmp3
509
+ # ln tmp0/t.txt tmp2/t.dat tmp4/
510
+ #
511
+ # Raises an exception if +dest+ is the path to an existing file
512
+ # and keyword argument +force+ is not +true+.
513
+ #
514
+ # Related: Bundler::FileUtils.link_entry (has different options).
515
+ #
516
+ def ln(src, dest, force: nil, noop: nil, verbose: nil)
517
+ fu_output_message "ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
518
+ return if noop
519
+ fu_each_src_dest0(src, dest) do |s,d|
520
+ remove_file d, true if force
521
+ File.link s, d
522
+ end
523
+ end
524
+ module_function :ln
525
+
526
+ alias link ln
527
+ module_function :link
528
+
529
+ # Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link].
530
+ #
531
+ # Arguments +src+ (a single path or an array of paths)
532
+ # and +dest+ (a single path)
533
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
534
+ #
535
+ # If +src+ is the path to a directory and +dest+ does not exist,
536
+ # creates links +dest+ and descendents pointing to +src+ and its descendents:
537
+ #
538
+ # tree('src0')
539
+ # # => src0
540
+ # # |-- sub0
541
+ # # | |-- src0.txt
542
+ # # | `-- src1.txt
543
+ # # `-- sub1
544
+ # # |-- src2.txt
545
+ # # `-- src3.txt
546
+ # File.exist?('dest0') # => false
547
+ # Bundler::FileUtils.cp_lr('src0', 'dest0')
548
+ # tree('dest0')
549
+ # # => dest0
550
+ # # |-- sub0
551
+ # # | |-- src0.txt
552
+ # # | `-- src1.txt
553
+ # # `-- sub1
554
+ # # |-- src2.txt
555
+ # # `-- src3.txt
556
+ #
557
+ # If +src+ and +dest+ are both paths to directories,
558
+ # creates links <tt>dest/src</tt> and descendents
559
+ # pointing to +src+ and its descendents:
560
+ #
561
+ # tree('src1')
562
+ # # => src1
563
+ # # |-- sub0
564
+ # # | |-- src0.txt
565
+ # # | `-- src1.txt
566
+ # # `-- sub1
567
+ # # |-- src2.txt
568
+ # # `-- src3.txt
569
+ # Bundler::FileUtils.mkdir('dest1')
570
+ # Bundler::FileUtils.cp_lr('src1', 'dest1')
571
+ # tree('dest1')
572
+ # # => dest1
573
+ # # `-- src1
574
+ # # |-- sub0
575
+ # # | |-- src0.txt
576
+ # # | `-- src1.txt
577
+ # # `-- sub1
578
+ # # |-- src2.txt
579
+ # # `-- src3.txt
580
+ #
581
+ # If +src+ is an array of paths to entries and +dest+ is the path to a directory,
582
+ # for each path +filepath+ in +src+, creates a link at <tt>dest/filepath</tt>
583
+ # pointing to that path:
584
+ #
585
+ # tree('src2')
586
+ # # => src2
587
+ # # |-- sub0
588
+ # # | |-- src0.txt
589
+ # # | `-- src1.txt
590
+ # # `-- sub1
591
+ # # |-- src2.txt
592
+ # # `-- src3.txt
593
+ # Bundler::FileUtils.mkdir('dest2')
594
+ # Bundler::FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2')
595
+ # tree('dest2')
596
+ # # => dest2
597
+ # # |-- sub0
598
+ # # | |-- src0.txt
599
+ # # | `-- src1.txt
600
+ # # `-- sub1
601
+ # # |-- src2.txt
602
+ # # `-- src3.txt
603
+ #
604
+ # Keyword arguments:
605
+ #
606
+ # - <tt>dereference_root: false</tt> - if +src+ is a symbolic link,
607
+ # does not dereference it.
608
+ # - <tt>noop: true</tt> - does not create links.
609
+ # - <tt>remove_destination: true</tt> - removes +dest+ before creating links.
610
+ # - <tt>verbose: true</tt> - prints an equivalent command:
611
+ #
612
+ # Bundler::FileUtils.cp_lr('src0', 'dest0', noop: true, verbose: true)
613
+ # Bundler::FileUtils.cp_lr('src1', 'dest1', noop: true, verbose: true)
614
+ # Bundler::FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2', noop: true, verbose: true)
615
+ #
616
+ # Output:
617
+ #
618
+ # cp -lr src0 dest0
619
+ # cp -lr src1 dest1
620
+ # cp -lr src2/sub0 src2/sub1 dest2
621
+ #
622
+ # Raises an exception if +dest+ is the path to an existing file or directory
623
+ # and keyword argument <tt>remove_destination: true</tt> is not given.
624
+ #
625
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
626
+ #
627
+ def cp_lr(src, dest, noop: nil, verbose: nil,
628
+ dereference_root: true, remove_destination: false)
629
+ fu_output_message "cp -lr#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose
630
+ return if noop
631
+ fu_each_src_dest(src, dest) do |s, d|
632
+ link_entry s, d, dereference_root, remove_destination
633
+ end
634
+ end
635
+ module_function :cp_lr
636
+
637
+ # Creates {symbolic links}[https://en.wikipedia.org/wiki/Symbolic_link].
638
+ #
639
+ # Arguments +src+ (a single path or an array of paths)
640
+ # and +dest+ (a single path)
641
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
642
+ #
643
+ # If +src+ is the path to an existing file:
644
+ #
645
+ # - When +dest+ is the path to a non-existent file,
646
+ # creates a symbolic link at +dest+ pointing to +src+:
647
+ #
648
+ # Bundler::FileUtils.touch('src0.txt')
649
+ # File.exist?('dest0.txt') # => false
650
+ # Bundler::FileUtils.ln_s('src0.txt', 'dest0.txt')
651
+ # File.symlink?('dest0.txt') # => true
652
+ #
653
+ # - When +dest+ is the path to an existing file,
654
+ # creates a symbolic link at +dest+ pointing to +src+
655
+ # if and only if keyword argument <tt>force: true</tt> is given
656
+ # (raises an exception otherwise):
657
+ #
658
+ # Bundler::FileUtils.touch('src1.txt')
659
+ # Bundler::FileUtils.touch('dest1.txt')
660
+ # Bundler::FileUtils.ln_s('src1.txt', 'dest1.txt', force: true)
661
+ # FileTest.symlink?('dest1.txt') # => true
662
+ #
663
+ # Bundler::FileUtils.ln_s('src1.txt', 'dest1.txt') # Raises Errno::EEXIST.
664
+ #
665
+ # If +dest+ is the path to a directory,
666
+ # creates a symbolic link at <tt>dest/src</tt> pointing to +src+:
667
+ #
668
+ # Bundler::FileUtils.touch('src2.txt')
669
+ # Bundler::FileUtils.mkdir('destdir2')
670
+ # Bundler::FileUtils.ln_s('src2.txt', 'destdir2')
671
+ # File.symlink?('destdir2/src2.txt') # => true
672
+ #
673
+ # If +src+ is an array of paths to existing files and +dest+ is a directory,
674
+ # for each child +child+ in +src+ creates a symbolic link <tt>dest/child</tt>
675
+ # pointing to +child+:
676
+ #
677
+ # Bundler::FileUtils.mkdir('srcdir3')
678
+ # Bundler::FileUtils.touch('srcdir3/src0.txt')
679
+ # Bundler::FileUtils.touch('srcdir3/src1.txt')
680
+ # Bundler::FileUtils.mkdir('destdir3')
681
+ # Bundler::FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3')
682
+ # File.symlink?('destdir3/src0.txt') # => true
683
+ # File.symlink?('destdir3/src1.txt') # => true
684
+ #
685
+ # Keyword arguments:
686
+ #
687
+ # - <tt>force: true</tt> - overwrites +dest+ if it exists.
688
+ # - <tt>relative: false</tt> - create links relative to +dest+.
689
+ # - <tt>noop: true</tt> - does not create links.
690
+ # - <tt>verbose: true</tt> - prints an equivalent command:
691
+ #
692
+ # Bundler::FileUtils.ln_s('src0.txt', 'dest0.txt', noop: true, verbose: true)
693
+ # Bundler::FileUtils.ln_s('src1.txt', 'destdir1', noop: true, verbose: true)
694
+ # Bundler::FileUtils.ln_s('src2.txt', 'dest2.txt', force: true, noop: true, verbose: true)
695
+ # Bundler::FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3', noop: true, verbose: true)
696
+ #
697
+ # Output:
698
+ #
699
+ # ln -s src0.txt dest0.txt
700
+ # ln -s src1.txt destdir1
701
+ # ln -sf src2.txt dest2.txt
702
+ # ln -s srcdir3/src0.txt srcdir3/src1.txt destdir3
703
+ #
704
+ # Related: Bundler::FileUtils.ln_sf.
705
+ #
706
+ def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
707
+ if relative
708
+ return ln_sr(src, dest, force: force, noop: noop, verbose: verbose)
709
+ end
710
+ fu_output_message "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose
711
+ return if noop
712
+ fu_each_src_dest0(src, dest) do |s,d|
713
+ remove_file d, true if force
714
+ File.symlink s, d
715
+ end
716
+ end
717
+ module_function :ln_s
718
+
719
+ alias symlink ln_s
720
+ module_function :symlink
721
+
722
+ # Like Bundler::FileUtils.ln_s, but always with keyword argument <tt>force: true</tt> given.
723
+ #
724
+ def ln_sf(src, dest, noop: nil, verbose: nil)
725
+ ln_s src, dest, force: true, noop: noop, verbose: verbose
726
+ end
727
+ module_function :ln_sf
728
+
729
+ # Like Bundler::FileUtils.ln_s, but create links relative to +dest+.
730
+ #
731
+ def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
732
+ options = "#{force ? 'f' : ''}#{target_directory ? '' : 'T'}"
733
+ dest = File.path(dest)
734
+ srcs = Array(src)
735
+ link = proc do |s, target_dir_p = true|
736
+ s = File.path(s)
737
+ if target_dir_p
738
+ d = File.join(destdirs = dest, File.basename(s))
739
+ else
740
+ destdirs = File.dirname(d = dest)
741
+ end
742
+ destdirs = fu_split_path(File.realpath(destdirs))
743
+ if fu_starting_path?(s)
744
+ srcdirs = fu_split_path((File.realdirpath(s) rescue File.expand_path(s)))
745
+ base = fu_relative_components_from(srcdirs, destdirs)
746
+ s = File.join(*base)
747
+ else
748
+ srcdirs = fu_clean_components(*fu_split_path(s))
749
+ base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs)
750
+ while srcdirs.first&. == ".." and base.last&.!=("..") and !fu_starting_path?(base.last)
751
+ srcdirs.shift
752
+ base.pop
753
+ end
754
+ s = File.join(*base, *srcdirs)
755
+ end
756
+ fu_output_message "ln -s#{options} #{s} #{d}" if verbose
757
+ next if noop
758
+ remove_file d, true if force
759
+ File.symlink s, d
760
+ end
761
+ case srcs.size
762
+ when 0
763
+ when 1
764
+ link[srcs[0], target_directory && File.directory?(dest)]
765
+ else
766
+ srcs.each(&link)
767
+ end
768
+ end
769
+ module_function :ln_sr
770
+
771
+ # Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link]; returns +nil+.
772
+ #
773
+ # Arguments +src+ and +dest+
774
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
775
+ #
776
+ # If +src+ is the path to a file and +dest+ does not exist,
777
+ # creates a hard link at +dest+ pointing to +src+:
778
+ #
779
+ # Bundler::FileUtils.touch('src0.txt')
780
+ # File.exist?('dest0.txt') # => false
781
+ # Bundler::FileUtils.link_entry('src0.txt', 'dest0.txt')
782
+ # File.file?('dest0.txt') # => true
783
+ #
784
+ # If +src+ is the path to a directory and +dest+ does not exist,
785
+ # recursively creates hard links at +dest+ pointing to paths in +src+:
786
+ #
787
+ # Bundler::FileUtils.mkdir_p(['src1/dir0', 'src1/dir1'])
788
+ # src_file_paths = [
789
+ # 'src1/dir0/t0.txt',
790
+ # 'src1/dir0/t1.txt',
791
+ # 'src1/dir1/t2.txt',
792
+ # 'src1/dir1/t3.txt',
793
+ # ]
794
+ # Bundler::FileUtils.touch(src_file_paths)
795
+ # File.directory?('dest1') # => true
796
+ # Bundler::FileUtils.link_entry('src1', 'dest1')
797
+ # File.file?('dest1/dir0/t0.txt') # => true
798
+ # File.file?('dest1/dir0/t1.txt') # => true
799
+ # File.file?('dest1/dir1/t2.txt') # => true
800
+ # File.file?('dest1/dir1/t3.txt') # => true
801
+ #
802
+ # Keyword arguments:
803
+ #
804
+ # - <tt>dereference_root: true</tt> - dereferences +src+ if it is a symbolic link.
805
+ # - <tt>remove_destination: true</tt> - removes +dest+ before creating links.
806
+ #
807
+ # Raises an exception if +dest+ is the path to an existing file or directory
808
+ # and keyword argument <tt>remove_destination: true</tt> is not given.
809
+ #
810
+ # Related: Bundler::FileUtils.ln (has different options).
811
+ #
812
+ def link_entry(src, dest, dereference_root = false, remove_destination = false)
813
+ Entry_.new(src, nil, dereference_root).traverse do |ent|
814
+ destent = Entry_.new(dest, ent.rel, false)
815
+ File.unlink destent.path if remove_destination && File.file?(destent.path)
816
+ ent.link destent.path
817
+ end
818
+ end
819
+ module_function :link_entry
820
+
821
+ # Copies files.
822
+ #
823
+ # Arguments +src+ (a single path or an array of paths)
824
+ # and +dest+ (a single path)
825
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
826
+ #
827
+ # If +src+ is the path to a file and +dest+ is not the path to a directory,
828
+ # copies +src+ to +dest+:
829
+ #
830
+ # Bundler::FileUtils.touch('src0.txt')
831
+ # File.exist?('dest0.txt') # => false
832
+ # Bundler::FileUtils.cp('src0.txt', 'dest0.txt')
833
+ # File.file?('dest0.txt') # => true
834
+ #
835
+ # If +src+ is the path to a file and +dest+ is the path to a directory,
836
+ # copies +src+ to <tt>dest/src</tt>:
837
+ #
838
+ # Bundler::FileUtils.touch('src1.txt')
839
+ # Bundler::FileUtils.mkdir('dest1')
840
+ # Bundler::FileUtils.cp('src1.txt', 'dest1')
841
+ # File.file?('dest1/src1.txt') # => true
842
+ #
843
+ # If +src+ is an array of paths to files and +dest+ is the path to a directory,
844
+ # copies from each +src+ to +dest+:
845
+ #
846
+ # src_file_paths = ['src2.txt', 'src2.dat']
847
+ # Bundler::FileUtils.touch(src_file_paths)
848
+ # Bundler::FileUtils.mkdir('dest2')
849
+ # Bundler::FileUtils.cp(src_file_paths, 'dest2')
850
+ # File.file?('dest2/src2.txt') # => true
851
+ # File.file?('dest2/src2.dat') # => true
852
+ #
853
+ # Keyword arguments:
854
+ #
855
+ # - <tt>preserve: true</tt> - preserves file times.
856
+ # - <tt>noop: true</tt> - does not copy files.
857
+ # - <tt>verbose: true</tt> - prints an equivalent command:
858
+ #
859
+ # Bundler::FileUtils.cp('src0.txt', 'dest0.txt', noop: true, verbose: true)
860
+ # Bundler::FileUtils.cp('src1.txt', 'dest1', noop: true, verbose: true)
861
+ # Bundler::FileUtils.cp(src_file_paths, 'dest2', noop: true, verbose: true)
862
+ #
863
+ # Output:
864
+ #
865
+ # cp src0.txt dest0.txt
866
+ # cp src1.txt dest1
867
+ # cp src2.txt src2.dat dest2
868
+ #
869
+ # Raises an exception if +src+ is a directory.
870
+ #
871
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
872
+ #
873
+ def cp(src, dest, preserve: nil, noop: nil, verbose: nil)
874
+ fu_output_message "cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if verbose
875
+ return if noop
876
+ fu_each_src_dest(src, dest) do |s, d|
877
+ copy_file s, d, preserve
878
+ end
879
+ end
880
+ module_function :cp
881
+
882
+ alias copy cp
883
+ module_function :copy
884
+
885
+ # Recursively copies files.
886
+ #
887
+ # Arguments +src+ (a single path or an array of paths)
888
+ # and +dest+ (a single path)
889
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
890
+ #
891
+ # The mode, owner, and group are retained in the copy;
892
+ # to change those, use Bundler::FileUtils.install instead.
893
+ #
894
+ # If +src+ is the path to a file and +dest+ is not the path to a directory,
895
+ # copies +src+ to +dest+:
896
+ #
897
+ # Bundler::FileUtils.touch('src0.txt')
898
+ # File.exist?('dest0.txt') # => false
899
+ # Bundler::FileUtils.cp_r('src0.txt', 'dest0.txt')
900
+ # File.file?('dest0.txt') # => true
901
+ #
902
+ # If +src+ is the path to a file and +dest+ is the path to a directory,
903
+ # copies +src+ to <tt>dest/src</tt>:
904
+ #
905
+ # Bundler::FileUtils.touch('src1.txt')
906
+ # Bundler::FileUtils.mkdir('dest1')
907
+ # Bundler::FileUtils.cp_r('src1.txt', 'dest1')
908
+ # File.file?('dest1/src1.txt') # => true
909
+ #
910
+ # If +src+ is the path to a directory and +dest+ does not exist,
911
+ # recursively copies +src+ to +dest+:
912
+ #
913
+ # tree('src2')
914
+ # # => src2
915
+ # # |-- dir0
916
+ # # | |-- src0.txt
917
+ # # | `-- src1.txt
918
+ # # `-- dir1
919
+ # # |-- src2.txt
920
+ # # `-- src3.txt
921
+ # Bundler::FileUtils.exist?('dest2') # => false
922
+ # Bundler::FileUtils.cp_r('src2', 'dest2')
923
+ # tree('dest2')
924
+ # # => dest2
925
+ # # |-- dir0
926
+ # # | |-- src0.txt
927
+ # # | `-- src1.txt
928
+ # # `-- dir1
929
+ # # |-- src2.txt
930
+ # # `-- src3.txt
931
+ #
932
+ # If +src+ and +dest+ are paths to directories,
933
+ # recursively copies +src+ to <tt>dest/src</tt>:
934
+ #
935
+ # tree('src3')
936
+ # # => src3
937
+ # # |-- dir0
938
+ # # | |-- src0.txt
939
+ # # | `-- src1.txt
940
+ # # `-- dir1
941
+ # # |-- src2.txt
942
+ # # `-- src3.txt
943
+ # Bundler::FileUtils.mkdir('dest3')
944
+ # Bundler::FileUtils.cp_r('src3', 'dest3')
945
+ # tree('dest3')
946
+ # # => dest3
947
+ # # `-- src3
948
+ # # |-- dir0
949
+ # # | |-- src0.txt
950
+ # # | `-- src1.txt
951
+ # # `-- dir1
952
+ # # |-- src2.txt
953
+ # # `-- src3.txt
954
+ #
955
+ # If +src+ is an array of paths and +dest+ is a directory,
956
+ # recursively copies from each path in +src+ to +dest+;
957
+ # the paths in +src+ may point to files and/or directories.
958
+ #
959
+ # Keyword arguments:
960
+ #
961
+ # - <tt>dereference_root: false</tt> - if +src+ is a symbolic link,
962
+ # does not dereference it.
963
+ # - <tt>noop: true</tt> - does not copy files.
964
+ # - <tt>preserve: true</tt> - preserves file times.
965
+ # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
966
+ # - <tt>verbose: true</tt> - prints an equivalent command:
967
+ #
968
+ # Bundler::FileUtils.cp_r('src0.txt', 'dest0.txt', noop: true, verbose: true)
969
+ # Bundler::FileUtils.cp_r('src1.txt', 'dest1', noop: true, verbose: true)
970
+ # Bundler::FileUtils.cp_r('src2', 'dest2', noop: true, verbose: true)
971
+ # Bundler::FileUtils.cp_r('src3', 'dest3', noop: true, verbose: true)
972
+ #
973
+ # Output:
974
+ #
975
+ # cp -r src0.txt dest0.txt
976
+ # cp -r src1.txt dest1
977
+ # cp -r src2 dest2
978
+ # cp -r src3 dest3
979
+ #
980
+ # Raises an exception of +src+ is the path to a directory
981
+ # and +dest+ is the path to a file.
982
+ #
983
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
984
+ #
985
+ def cp_r(src, dest, preserve: nil, noop: nil, verbose: nil,
986
+ dereference_root: true, remove_destination: nil)
987
+ fu_output_message "cp -r#{preserve ? 'p' : ''}#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose
988
+ return if noop
989
+ fu_each_src_dest(src, dest) do |s, d|
990
+ copy_entry s, d, preserve, dereference_root, remove_destination
991
+ end
992
+ end
993
+ module_function :cp_r
994
+
995
+ # Recursively copies files from +src+ to +dest+.
996
+ #
997
+ # Arguments +src+ and +dest+
998
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
999
+ #
1000
+ # If +src+ is the path to a file, copies +src+ to +dest+:
1001
+ #
1002
+ # Bundler::FileUtils.touch('src0.txt')
1003
+ # File.exist?('dest0.txt') # => false
1004
+ # Bundler::FileUtils.copy_entry('src0.txt', 'dest0.txt')
1005
+ # File.file?('dest0.txt') # => true
1006
+ #
1007
+ # If +src+ is a directory, recursively copies +src+ to +dest+:
1008
+ #
1009
+ # tree('src1')
1010
+ # # => src1
1011
+ # # |-- dir0
1012
+ # # | |-- src0.txt
1013
+ # # | `-- src1.txt
1014
+ # # `-- dir1
1015
+ # # |-- src2.txt
1016
+ # # `-- src3.txt
1017
+ # Bundler::FileUtils.copy_entry('src1', 'dest1')
1018
+ # tree('dest1')
1019
+ # # => dest1
1020
+ # # |-- dir0
1021
+ # # | |-- src0.txt
1022
+ # # | `-- src1.txt
1023
+ # # `-- dir1
1024
+ # # |-- src2.txt
1025
+ # # `-- src3.txt
1026
+ #
1027
+ # The recursive copying preserves file types for regular files,
1028
+ # directories, and symbolic links;
1029
+ # other file types (FIFO streams, device files, etc.) are not supported.
1030
+ #
1031
+ # Keyword arguments:
1032
+ #
1033
+ # - <tt>dereference_root: true</tt> - if +src+ is a symbolic link,
1034
+ # follows the link.
1035
+ # - <tt>preserve: true</tt> - preserves file times.
1036
+ # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
1037
+ #
1038
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
1039
+ #
1040
+ def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
1041
+ if dereference_root
1042
+ src = File.realpath(src)
1043
+ end
1044
+
1045
+ Entry_.new(src, nil, false).wrap_traverse(proc do |ent|
1046
+ destent = Entry_.new(dest, ent.rel, false)
1047
+ File.unlink destent.path if remove_destination && (File.file?(destent.path) || File.symlink?(destent.path))
1048
+ ent.copy destent.path
1049
+ end, proc do |ent|
1050
+ destent = Entry_.new(dest, ent.rel, false)
1051
+ ent.copy_metadata destent.path if preserve
1052
+ end)
1053
+ end
1054
+ module_function :copy_entry
1055
+
1056
+ # Copies file from +src+ to +dest+, which should not be directories.
1057
+ #
1058
+ # Arguments +src+ and +dest+
1059
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
1060
+ #
1061
+ # Examples:
1062
+ #
1063
+ # Bundler::FileUtils.touch('src0.txt')
1064
+ # Bundler::FileUtils.copy_file('src0.txt', 'dest0.txt')
1065
+ # File.file?('dest0.txt') # => true
1066
+ #
1067
+ # Keyword arguments:
1068
+ #
1069
+ # - <tt>dereference: false</tt> - if +src+ is a symbolic link,
1070
+ # does not follow the link.
1071
+ # - <tt>preserve: true</tt> - preserves file times.
1072
+ # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
1073
+ #
1074
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
1075
+ #
1076
+ def copy_file(src, dest, preserve = false, dereference = true)
1077
+ ent = Entry_.new(src, nil, dereference)
1078
+ ent.copy_file dest
1079
+ ent.copy_metadata dest if preserve
1080
+ end
1081
+ module_function :copy_file
1082
+
1083
+ # Copies \IO stream +src+ to \IO stream +dest+ via
1084
+ # {IO.copy_stream}[https://docs.ruby-lang.org/en/master/IO.html#method-c-copy_stream].
1085
+ #
1086
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
1087
+ #
1088
+ def copy_stream(src, dest)
1089
+ IO.copy_stream(src, dest)
1090
+ end
1091
+ module_function :copy_stream
1092
+
1093
+ # Moves entries.
1094
+ #
1095
+ # Arguments +src+ (a single path or an array of paths)
1096
+ # and +dest+ (a single path)
1097
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
1098
+ #
1099
+ # If +src+ and +dest+ are on different file systems,
1100
+ # first copies, then removes +src+.
1101
+ #
1102
+ # May cause a local vulnerability if not called with keyword argument
1103
+ # <tt>secure: true</tt>;
1104
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
1105
+ #
1106
+ # If +src+ is the path to a single file or directory and +dest+ does not exist,
1107
+ # moves +src+ to +dest+:
1108
+ #
1109
+ # tree('src0')
1110
+ # # => src0
1111
+ # # |-- src0.txt
1112
+ # # `-- src1.txt
1113
+ # File.exist?('dest0') # => false
1114
+ # Bundler::FileUtils.mv('src0', 'dest0')
1115
+ # File.exist?('src0') # => false
1116
+ # tree('dest0')
1117
+ # # => dest0
1118
+ # # |-- src0.txt
1119
+ # # `-- src1.txt
1120
+ #
1121
+ # If +src+ is an array of paths to files and directories
1122
+ # and +dest+ is the path to a directory,
1123
+ # copies from each path in the array to +dest+:
1124
+ #
1125
+ # File.file?('src1.txt') # => true
1126
+ # tree('src1')
1127
+ # # => src1
1128
+ # # |-- src.dat
1129
+ # # `-- src.txt
1130
+ # Dir.empty?('dest1') # => true
1131
+ # Bundler::FileUtils.mv(['src1.txt', 'src1'], 'dest1')
1132
+ # tree('dest1')
1133
+ # # => dest1
1134
+ # # |-- src1
1135
+ # # | |-- src.dat
1136
+ # # | `-- src.txt
1137
+ # # `-- src1.txt
1138
+ #
1139
+ # Keyword arguments:
1140
+ #
1141
+ # - <tt>force: true</tt> - if the move includes removing +src+
1142
+ # (that is, if +src+ and +dest+ are on different file systems),
1143
+ # ignores raised exceptions of StandardError and its descendants.
1144
+ # - <tt>noop: true</tt> - does not move files.
1145
+ # - <tt>secure: true</tt> - removes +src+ securely;
1146
+ # see details at Bundler::FileUtils.remove_entry_secure.
1147
+ # - <tt>verbose: true</tt> - prints an equivalent command:
1148
+ #
1149
+ # Bundler::FileUtils.mv('src0', 'dest0', noop: true, verbose: true)
1150
+ # Bundler::FileUtils.mv(['src1.txt', 'src1'], 'dest1', noop: true, verbose: true)
1151
+ #
1152
+ # Output:
1153
+ #
1154
+ # mv src0 dest0
1155
+ # mv src1.txt src1 dest1
1156
+ #
1157
+ def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
1158
+ fu_output_message "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
1159
+ return if noop
1160
+ fu_each_src_dest(src, dest) do |s, d|
1161
+ destent = Entry_.new(d, nil, true)
1162
+ begin
1163
+ if destent.exist?
1164
+ if destent.directory?
1165
+ raise Errno::EEXIST, d
1166
+ end
1167
+ end
1168
+ begin
1169
+ File.rename s, d
1170
+ rescue Errno::EXDEV,
1171
+ Errno::EPERM # move from unencrypted to encrypted dir (ext4)
1172
+ copy_entry s, d, true
1173
+ if secure
1174
+ remove_entry_secure s, force
1175
+ else
1176
+ remove_entry s, force
1177
+ end
1178
+ end
1179
+ rescue SystemCallError
1180
+ raise unless force
1181
+ end
1182
+ end
1183
+ end
1184
+ module_function :mv
1185
+
1186
+ alias move mv
1187
+ module_function :move
1188
+
1189
+ # Removes entries at the paths in the given +list+
1190
+ # (a single path or an array of paths)
1191
+ # returns +list+, if it is an array, <tt>[list]</tt> otherwise.
1192
+ #
1193
+ # Argument +list+ or its elements
1194
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
1195
+ #
1196
+ # With no keyword arguments, removes files at the paths given in +list+:
1197
+ #
1198
+ # Bundler::FileUtils.touch(['src0.txt', 'src0.dat'])
1199
+ # Bundler::FileUtils.rm(['src0.dat', 'src0.txt']) # => ["src0.dat", "src0.txt"]
1200
+ #
1201
+ # Keyword arguments:
1202
+ #
1203
+ # - <tt>force: true</tt> - ignores raised exceptions of StandardError
1204
+ # and its descendants.
1205
+ # - <tt>noop: true</tt> - does not remove files; returns +nil+.
1206
+ # - <tt>verbose: true</tt> - prints an equivalent command:
1207
+ #
1208
+ # Bundler::FileUtils.rm(['src0.dat', 'src0.txt'], noop: true, verbose: true)
1209
+ #
1210
+ # Output:
1211
+ #
1212
+ # rm src0.dat src0.txt
1213
+ #
1214
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
1215
+ #
1216
+ def rm(list, force: nil, noop: nil, verbose: nil)
1217
+ list = fu_list(list)
1218
+ fu_output_message "rm#{force ? ' -f' : ''} #{list.join ' '}" if verbose
1219
+ return if noop
1220
+
1221
+ list.each do |path|
1222
+ remove_file path, force
1223
+ end
1224
+ end
1225
+ module_function :rm
1226
+
1227
+ alias remove rm
1228
+ module_function :remove
1229
+
1230
+ # Equivalent to:
1231
+ #
1232
+ # Bundler::FileUtils.rm(list, force: true, **kwargs)
1233
+ #
1234
+ # Argument +list+ (a single path or an array of paths)
1235
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
1236
+ #
1237
+ # See Bundler::FileUtils.rm for keyword arguments.
1238
+ #
1239
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
1240
+ #
1241
+ def rm_f(list, noop: nil, verbose: nil)
1242
+ rm list, force: true, noop: noop, verbose: verbose
1243
+ end
1244
+ module_function :rm_f
1245
+
1246
+ alias safe_unlink rm_f
1247
+ module_function :safe_unlink
1248
+
1249
+ # Removes entries at the paths in the given +list+
1250
+ # (a single path or an array of paths);
1251
+ # returns +list+, if it is an array, <tt>[list]</tt> otherwise.
1252
+ #
1253
+ # Argument +list+ or its elements
1254
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
1255
+ #
1256
+ # May cause a local vulnerability if not called with keyword argument
1257
+ # <tt>secure: true</tt>;
1258
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
1259
+ #
1260
+ # For each file path, removes the file at that path:
1261
+ #
1262
+ # Bundler::FileUtils.touch(['src0.txt', 'src0.dat'])
1263
+ # Bundler::FileUtils.rm_r(['src0.dat', 'src0.txt'])
1264
+ # File.exist?('src0.txt') # => false
1265
+ # File.exist?('src0.dat') # => false
1266
+ #
1267
+ # For each directory path, recursively removes files and directories:
1268
+ #
1269
+ # tree('src1')
1270
+ # # => src1
1271
+ # # |-- dir0
1272
+ # # | |-- src0.txt
1273
+ # # | `-- src1.txt
1274
+ # # `-- dir1
1275
+ # # |-- src2.txt
1276
+ # # `-- src3.txt
1277
+ # Bundler::FileUtils.rm_r('src1')
1278
+ # File.exist?('src1') # => false
1279
+ #
1280
+ # Keyword arguments:
1281
+ #
1282
+ # - <tt>force: true</tt> - ignores raised exceptions of StandardError
1283
+ # and its descendants.
1284
+ # - <tt>noop: true</tt> - does not remove entries; returns +nil+.
1285
+ # - <tt>secure: true</tt> - removes +src+ securely;
1286
+ # see details at Bundler::FileUtils.remove_entry_secure.
1287
+ # - <tt>verbose: true</tt> - prints an equivalent command:
1288
+ #
1289
+ # Bundler::FileUtils.rm_r(['src0.dat', 'src0.txt'], noop: true, verbose: true)
1290
+ # Bundler::FileUtils.rm_r('src1', noop: true, verbose: true)
1291
+ #
1292
+ # Output:
1293
+ #
1294
+ # rm -r src0.dat src0.txt
1295
+ # rm -r src1
1296
+ #
1297
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
1298
+ #
1299
+ def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil)
1300
+ list = fu_list(list)
1301
+ fu_output_message "rm -r#{force ? 'f' : ''} #{list.join ' '}" if verbose
1302
+ return if noop
1303
+ list.each do |path|
1304
+ if secure
1305
+ remove_entry_secure path, force
1306
+ else
1307
+ remove_entry path, force
1308
+ end
1309
+ end
1310
+ end
1311
+ module_function :rm_r
1312
+
1313
+ # Equivalent to:
1314
+ #
1315
+ # Bundler::FileUtils.rm_r(list, force: true, **kwargs)
1316
+ #
1317
+ # Argument +list+ or its elements
1318
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
1319
+ #
1320
+ # May cause a local vulnerability if not called with keyword argument
1321
+ # <tt>secure: true</tt>;
1322
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
1323
+ #
1324
+ # See Bundler::FileUtils.rm_r for keyword arguments.
1325
+ #
1326
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
1327
+ #
1328
+ def rm_rf(list, noop: nil, verbose: nil, secure: nil)
1329
+ rm_r list, force: true, noop: noop, verbose: verbose, secure: secure
1330
+ end
1331
+ module_function :rm_rf
1332
+
1333
+ alias rmtree rm_rf
1334
+ module_function :rmtree
1335
+
1336
+ # Securely removes the entry given by +path+,
1337
+ # which should be the entry for a regular file, a symbolic link,
1338
+ # or a directory.
1339
+ #
1340
+ # Argument +path+
1341
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
1342
+ #
1343
+ # Avoids a local vulnerability that can exist in certain circumstances;
1344
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
1345
+ #
1346
+ # Optional argument +force+ specifies whether to ignore
1347
+ # raised exceptions of StandardError and its descendants.
1348
+ #
1349
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
1350
+ #
1351
+ def remove_entry_secure(path, force = false)
1352
+ unless fu_have_symlink?
1353
+ remove_entry path, force
1354
+ return
1355
+ end
1356
+ fullpath = File.expand_path(path)
1357
+ st = File.lstat(fullpath)
1358
+ unless st.directory?
1359
+ File.unlink fullpath
1360
+ return
1361
+ end
1362
+ # is a directory.
1363
+ parent_st = File.stat(File.dirname(fullpath))
1364
+ unless parent_st.world_writable?
1365
+ remove_entry path, force
1366
+ return
1367
+ end
1368
+ unless parent_st.sticky?
1369
+ raise ArgumentError, "parent directory is world writable, Bundler::FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})"
1370
+ end
1371
+
1372
+ # freeze tree root
1373
+ euid = Process.euid
1374
+ dot_file = fullpath + "/."
1375
+ begin
1376
+ File.open(dot_file) {|f|
1377
+ unless fu_stat_identical_entry?(st, f.stat)
1378
+ # symlink (TOC-to-TOU attack?)
1379
+ File.unlink fullpath
1380
+ return
1381
+ end
1382
+ f.chown euid, -1
1383
+ f.chmod 0700
1384
+ }
1385
+ rescue Errno::EISDIR # JRuby in non-native mode can't open files as dirs
1386
+ File.lstat(dot_file).tap {|fstat|
1387
+ unless fu_stat_identical_entry?(st, fstat)
1388
+ # symlink (TOC-to-TOU attack?)
1389
+ File.unlink fullpath
1390
+ return
1391
+ end
1392
+ File.chown euid, -1, dot_file
1393
+ File.chmod 0700, dot_file
1394
+ }
1395
+ end
1396
+
1397
+ unless fu_stat_identical_entry?(st, File.lstat(fullpath))
1398
+ # TOC-to-TOU attack?
1399
+ File.unlink fullpath
1400
+ return
1401
+ end
1402
+
1403
+ # ---- tree root is frozen ----
1404
+ root = Entry_.new(path)
1405
+ root.preorder_traverse do |ent|
1406
+ if ent.directory?
1407
+ ent.chown euid, -1
1408
+ ent.chmod 0700
1409
+ end
1410
+ end
1411
+ root.postorder_traverse do |ent|
1412
+ begin
1413
+ ent.remove
1414
+ rescue
1415
+ raise unless force
1416
+ end
1417
+ end
1418
+ rescue
1419
+ raise unless force
1420
+ end
1421
+ module_function :remove_entry_secure
1422
+
1423
+ def fu_have_symlink? #:nodoc:
1424
+ File.symlink nil, nil
1425
+ rescue NotImplementedError
1426
+ return false
1427
+ rescue TypeError
1428
+ return true
1429
+ end
1430
+ private_module_function :fu_have_symlink?
1431
+
1432
+ def fu_stat_identical_entry?(a, b) #:nodoc:
1433
+ a.dev == b.dev and a.ino == b.ino
1434
+ end
1435
+ private_module_function :fu_stat_identical_entry?
1436
+
1437
+ # Removes the entry given by +path+,
1438
+ # which should be the entry for a regular file, a symbolic link,
1439
+ # or a directory.
1440
+ #
1441
+ # Argument +path+
1442
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
1443
+ #
1444
+ # Optional argument +force+ specifies whether to ignore
1445
+ # raised exceptions of StandardError and its descendants.
1446
+ #
1447
+ # Related: Bundler::FileUtils.remove_entry_secure.
1448
+ #
1449
+ def remove_entry(path, force = false)
1450
+ Entry_.new(path).postorder_traverse do |ent|
1451
+ begin
1452
+ ent.remove
1453
+ rescue
1454
+ raise unless force
1455
+ end
1456
+ end
1457
+ rescue
1458
+ raise unless force
1459
+ end
1460
+ module_function :remove_entry
1461
+
1462
+ # Removes the file entry given by +path+,
1463
+ # which should be the entry for a regular file or a symbolic link.
1464
+ #
1465
+ # Argument +path+
1466
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
1467
+ #
1468
+ # Optional argument +force+ specifies whether to ignore
1469
+ # raised exceptions of StandardError and its descendants.
1470
+ #
1471
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
1472
+ #
1473
+ def remove_file(path, force = false)
1474
+ Entry_.new(path).remove_file
1475
+ rescue
1476
+ raise unless force
1477
+ end
1478
+ module_function :remove_file
1479
+
1480
+ # Recursively removes the directory entry given by +path+,
1481
+ # which should be the entry for a regular file, a symbolic link,
1482
+ # or a directory.
1483
+ #
1484
+ # Argument +path+
1485
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
1486
+ #
1487
+ # Optional argument +force+ specifies whether to ignore
1488
+ # raised exceptions of StandardError and its descendants.
1489
+ #
1490
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
1491
+ #
1492
+ def remove_dir(path, force = false)
1493
+ remove_entry path, force # FIXME?? check if it is a directory
1494
+ end
1495
+ module_function :remove_dir
1496
+
1497
+ # Returns +true+ if the contents of files +a+ and +b+ are identical,
1498
+ # +false+ otherwise.
1499
+ #
1500
+ # Arguments +a+ and +b+
1501
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
1502
+ #
1503
+ # Bundler::FileUtils.identical? and Bundler::FileUtils.cmp are aliases for Bundler::FileUtils.compare_file.
1504
+ #
1505
+ # Related: Bundler::FileUtils.compare_stream.
1506
+ #
1507
+ def compare_file(a, b)
1508
+ return false unless File.size(a) == File.size(b)
1509
+ File.open(a, 'rb') {|fa|
1510
+ File.open(b, 'rb') {|fb|
1511
+ return compare_stream(fa, fb)
1512
+ }
1513
+ }
1514
+ end
1515
+ module_function :compare_file
1516
+
1517
+ alias identical? compare_file
1518
+ alias cmp compare_file
1519
+ module_function :identical?
1520
+ module_function :cmp
1521
+
1522
+ # Returns +true+ if the contents of streams +a+ and +b+ are identical,
1523
+ # +false+ otherwise.
1524
+ #
1525
+ # Arguments +a+ and +b+
1526
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
1527
+ #
1528
+ # Related: Bundler::FileUtils.compare_file.
1529
+ #
1530
+ def compare_stream(a, b)
1531
+ bsize = fu_stream_blksize(a, b)
1532
+
1533
+ sa = String.new(capacity: bsize)
1534
+ sb = String.new(capacity: bsize)
1535
+
1536
+ begin
1537
+ a.read(bsize, sa)
1538
+ b.read(bsize, sb)
1539
+ return true if sa.empty? && sb.empty?
1540
+ end while sa == sb
1541
+ false
1542
+ end
1543
+ module_function :compare_stream
1544
+
1545
+ # Copies a file entry.
1546
+ # See {install(1)}[https://man7.org/linux/man-pages/man1/install.1.html].
1547
+ #
1548
+ # Arguments +src+ (a single path or an array of paths)
1549
+ # and +dest+ (a single path)
1550
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments];
1551
+ #
1552
+ # If the entry at +dest+ does not exist, copies from +src+ to +dest+:
1553
+ #
1554
+ # File.read('src0.txt') # => "aaa\n"
1555
+ # File.exist?('dest0.txt') # => false
1556
+ # Bundler::FileUtils.install('src0.txt', 'dest0.txt')
1557
+ # File.read('dest0.txt') # => "aaa\n"
1558
+ #
1559
+ # If +dest+ is a file entry, copies from +src+ to +dest+, overwriting:
1560
+ #
1561
+ # File.read('src1.txt') # => "aaa\n"
1562
+ # File.read('dest1.txt') # => "bbb\n"
1563
+ # Bundler::FileUtils.install('src1.txt', 'dest1.txt')
1564
+ # File.read('dest1.txt') # => "aaa\n"
1565
+ #
1566
+ # If +dest+ is a directory entry, copies from +src+ to <tt>dest/src</tt>,
1567
+ # overwriting if necessary:
1568
+ #
1569
+ # File.read('src2.txt') # => "aaa\n"
1570
+ # File.read('dest2/src2.txt') # => "bbb\n"
1571
+ # Bundler::FileUtils.install('src2.txt', 'dest2')
1572
+ # File.read('dest2/src2.txt') # => "aaa\n"
1573
+ #
1574
+ # If +src+ is an array of paths and +dest+ points to a directory,
1575
+ # copies each path +path+ in +src+ to <tt>dest/path</tt>:
1576
+ #
1577
+ # File.file?('src3.txt') # => true
1578
+ # File.file?('src3.dat') # => true
1579
+ # Bundler::FileUtils.mkdir('dest3')
1580
+ # Bundler::FileUtils.install(['src3.txt', 'src3.dat'], 'dest3')
1581
+ # File.file?('dest3/src3.txt') # => true
1582
+ # File.file?('dest3/src3.dat') # => true
1583
+ #
1584
+ # Keyword arguments:
1585
+ #
1586
+ # - <tt>group: <i>group</i></tt> - changes the group if not +nil+,
1587
+ # using {File.chown}[https://docs.ruby-lang.org/en/master/File.html#method-c-chown].
1588
+ # - <tt>mode: <i>permissions</i></tt> - changes the permissions.
1589
+ # using {File.chmod}[https://docs.ruby-lang.org/en/master/File.html#method-c-chmod].
1590
+ # - <tt>noop: true</tt> - does not copy entries; returns +nil+.
1591
+ # - <tt>owner: <i>owner</i></tt> - changes the owner if not +nil+,
1592
+ # using {File.chown}[https://docs.ruby-lang.org/en/master/File.html#method-c-chown].
1593
+ # - <tt>preserve: true</tt> - preserve timestamps
1594
+ # using {File.utime}[https://docs.ruby-lang.org/en/master/File.html#method-c-utime].
1595
+ # - <tt>verbose: true</tt> - prints an equivalent command:
1596
+ #
1597
+ # Bundler::FileUtils.install('src0.txt', 'dest0.txt', noop: true, verbose: true)
1598
+ # Bundler::FileUtils.install('src1.txt', 'dest1.txt', noop: true, verbose: true)
1599
+ # Bundler::FileUtils.install('src2.txt', 'dest2', noop: true, verbose: true)
1600
+ #
1601
+ # Output:
1602
+ #
1603
+ # install -c src0.txt dest0.txt
1604
+ # install -c src1.txt dest1.txt
1605
+ # install -c src2.txt dest2
1606
+ #
1607
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
1608
+ #
1609
+ def install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil,
1610
+ noop: nil, verbose: nil)
1611
+ if verbose
1612
+ msg = +"install -c"
1613
+ msg << ' -p' if preserve
1614
+ msg << ' -m ' << mode_to_s(mode) if mode
1615
+ msg << " -o #{owner}" if owner
1616
+ msg << " -g #{group}" if group
1617
+ msg << ' ' << [src,dest].flatten.join(' ')
1618
+ fu_output_message msg
1619
+ end
1620
+ return if noop
1621
+ uid = fu_get_uid(owner)
1622
+ gid = fu_get_gid(group)
1623
+ fu_each_src_dest(src, dest) do |s, d|
1624
+ st = File.stat(s)
1625
+ unless File.exist?(d) and compare_file(s, d)
1626
+ remove_file d, true
1627
+ if d.end_with?('/')
1628
+ mkdir_p d
1629
+ copy_file s, d + File.basename(s)
1630
+ else
1631
+ mkdir_p File.expand_path('..', d)
1632
+ copy_file s, d
1633
+ end
1634
+ File.utime st.atime, st.mtime, d if preserve
1635
+ File.chmod fu_mode(mode, st), d if mode
1636
+ File.chown uid, gid, d if uid or gid
1637
+ end
1638
+ end
1639
+ end
1640
+ module_function :install
1641
+
1642
+ def user_mask(target) #:nodoc:
1643
+ target.each_char.inject(0) do |mask, chr|
1644
+ case chr
1645
+ when "u"
1646
+ mask | 04700
1647
+ when "g"
1648
+ mask | 02070
1649
+ when "o"
1650
+ mask | 01007
1651
+ when "a"
1652
+ mask | 07777
1653
+ else
1654
+ raise ArgumentError, "invalid `who' symbol in file mode: #{chr}"
1655
+ end
1656
+ end
1657
+ end
1658
+ private_module_function :user_mask
1659
+
1660
+ def apply_mask(mode, user_mask, op, mode_mask) #:nodoc:
1661
+ case op
1662
+ when '='
1663
+ (mode & ~user_mask) | (user_mask & mode_mask)
1664
+ when '+'
1665
+ mode | (user_mask & mode_mask)
1666
+ when '-'
1667
+ mode & ~(user_mask & mode_mask)
1668
+ end
1669
+ end
1670
+ private_module_function :apply_mask
1671
+
1672
+ def symbolic_modes_to_i(mode_sym, path) #:nodoc:
1673
+ path = File.stat(path) unless File::Stat === path
1674
+ mode = path.mode
1675
+ mode_sym.split(/,/).inject(mode & 07777) do |current_mode, clause|
1676
+ target, *actions = clause.split(/([=+-])/)
1677
+ raise ArgumentError, "invalid file mode: #{mode_sym}" if actions.empty?
1678
+ target = 'a' if target.empty?
1679
+ user_mask = user_mask(target)
1680
+ actions.each_slice(2) do |op, perm|
1681
+ need_apply = op == '='
1682
+ mode_mask = (perm || '').each_char.inject(0) do |mask, chr|
1683
+ case chr
1684
+ when "r"
1685
+ mask | 0444
1686
+ when "w"
1687
+ mask | 0222
1688
+ when "x"
1689
+ mask | 0111
1690
+ when "X"
1691
+ if path.directory?
1692
+ mask | 0111
1693
+ else
1694
+ mask
1695
+ end
1696
+ when "s"
1697
+ mask | 06000
1698
+ when "t"
1699
+ mask | 01000
1700
+ when "u", "g", "o"
1701
+ if mask.nonzero?
1702
+ current_mode = apply_mask(current_mode, user_mask, op, mask)
1703
+ end
1704
+ need_apply = false
1705
+ copy_mask = user_mask(chr)
1706
+ (current_mode & copy_mask) / (copy_mask & 0111) * (user_mask & 0111)
1707
+ else
1708
+ raise ArgumentError, "invalid `perm' symbol in file mode: #{chr}"
1709
+ end
1710
+ end
1711
+
1712
+ if mode_mask.nonzero? || need_apply
1713
+ current_mode = apply_mask(current_mode, user_mask, op, mode_mask)
1714
+ end
1715
+ end
1716
+ current_mode
1717
+ end
1718
+ end
1719
+ private_module_function :symbolic_modes_to_i
1720
+
1721
+ def fu_mode(mode, path) #:nodoc:
1722
+ mode.is_a?(String) ? symbolic_modes_to_i(mode, path) : mode
1723
+ end
1724
+ private_module_function :fu_mode
1725
+
1726
+ def mode_to_s(mode) #:nodoc:
1727
+ mode.is_a?(String) ? mode : "%o" % mode
1728
+ end
1729
+ private_module_function :mode_to_s
1730
+
1731
+ # Changes permissions on the entries at the paths given in +list+
1732
+ # (a single path or an array of paths)
1733
+ # to the permissions given by +mode+;
1734
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise:
1735
+ #
1736
+ # - Modifies each entry that is a regular file using
1737
+ # {File.chmod}[https://docs.ruby-lang.org/en/master/File.html#method-c-chmod].
1738
+ # - Modifies each entry that is a symbolic link using
1739
+ # {File.lchmod}[https://docs.ruby-lang.org/en/master/File.html#method-c-lchmod].
1740
+ #
1741
+ # Argument +list+ or its elements
1742
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
1743
+ #
1744
+ # Argument +mode+ may be either an integer or a string:
1745
+ #
1746
+ # - \Integer +mode+: represents the permission bits to be set:
1747
+ #
1748
+ # Bundler::FileUtils.chmod(0755, 'src0.txt')
1749
+ # Bundler::FileUtils.chmod(0644, ['src0.txt', 'src0.dat'])
1750
+ #
1751
+ # - \String +mode+: represents the permissions to be set:
1752
+ #
1753
+ # The string is of the form <tt>[targets][[operator][perms[,perms]]</tt>, where:
1754
+ #
1755
+ # - +targets+ may be any combination of these letters:
1756
+ #
1757
+ # - <tt>'u'</tt>: permissions apply to the file's owner.
1758
+ # - <tt>'g'</tt>: permissions apply to users in the file's group.
1759
+ # - <tt>'o'</tt>: permissions apply to other users not in the file's group.
1760
+ # - <tt>'a'</tt> (the default): permissions apply to all users.
1761
+ #
1762
+ # - +operator+ may be one of these letters:
1763
+ #
1764
+ # - <tt>'+'</tt>: adds permissions.
1765
+ # - <tt>'-'</tt>: removes permissions.
1766
+ # - <tt>'='</tt>: sets (replaces) permissions.
1767
+ #
1768
+ # - +perms+ (may be repeated, with separating commas)
1769
+ # may be any combination of these letters:
1770
+ #
1771
+ # - <tt>'r'</tt>: Read.
1772
+ # - <tt>'w'</tt>: Write.
1773
+ # - <tt>'x'</tt>: Execute (search, for a directory).
1774
+ # - <tt>'X'</tt>: Search (for a directories only;
1775
+ # must be used with <tt>'+'</tt>)
1776
+ # - <tt>'s'</tt>: Uid or gid.
1777
+ # - <tt>'t'</tt>: Sticky bit.
1778
+ #
1779
+ # Examples:
1780
+ #
1781
+ # Bundler::FileUtils.chmod('u=wrx,go=rx', 'src1.txt')
1782
+ # Bundler::FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby')
1783
+ #
1784
+ # Keyword arguments:
1785
+ #
1786
+ # - <tt>noop: true</tt> - does not change permissions; returns +nil+.
1787
+ # - <tt>verbose: true</tt> - prints an equivalent command:
1788
+ #
1789
+ # Bundler::FileUtils.chmod(0755, 'src0.txt', noop: true, verbose: true)
1790
+ # Bundler::FileUtils.chmod(0644, ['src0.txt', 'src0.dat'], noop: true, verbose: true)
1791
+ # Bundler::FileUtils.chmod('u=wrx,go=rx', 'src1.txt', noop: true, verbose: true)
1792
+ # Bundler::FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby', noop: true, verbose: true)
1793
+ #
1794
+ # Output:
1795
+ #
1796
+ # chmod 755 src0.txt
1797
+ # chmod 644 src0.txt src0.dat
1798
+ # chmod u=wrx,go=rx src1.txt
1799
+ # chmod u=wrx,go=rx /usr/bin/ruby
1800
+ #
1801
+ # Related: Bundler::FileUtils.chmod_R.
1802
+ #
1803
+ def chmod(mode, list, noop: nil, verbose: nil)
1804
+ list = fu_list(list)
1805
+ fu_output_message sprintf('chmod %s %s', mode_to_s(mode), list.join(' ')) if verbose
1806
+ return if noop
1807
+ list.each do |path|
1808
+ Entry_.new(path).chmod(fu_mode(mode, path))
1809
+ end
1810
+ end
1811
+ module_function :chmod
1812
+
1813
+ # Like Bundler::FileUtils.chmod, but changes permissions recursively.
1814
+ #
1815
+ def chmod_R(mode, list, noop: nil, verbose: nil, force: nil)
1816
+ list = fu_list(list)
1817
+ fu_output_message sprintf('chmod -R%s %s %s',
1818
+ (force ? 'f' : ''),
1819
+ mode_to_s(mode), list.join(' ')) if verbose
1820
+ return if noop
1821
+ list.each do |root|
1822
+ Entry_.new(root).traverse do |ent|
1823
+ begin
1824
+ ent.chmod(fu_mode(mode, ent.path))
1825
+ rescue
1826
+ raise unless force
1827
+ end
1828
+ end
1829
+ end
1830
+ end
1831
+ module_function :chmod_R
1832
+
1833
+ # Changes the owner and group on the entries at the paths given in +list+
1834
+ # (a single path or an array of paths)
1835
+ # to the given +user+ and +group+;
1836
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise:
1837
+ #
1838
+ # - Modifies each entry that is a regular file using
1839
+ # {File.chown}[https://docs.ruby-lang.org/en/master/File.html#method-c-chown].
1840
+ # - Modifies each entry that is a symbolic link using
1841
+ # {File.lchown}[https://docs.ruby-lang.org/en/master/File.html#method-c-lchown].
1842
+ #
1843
+ # Argument +list+ or its elements
1844
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
1845
+ #
1846
+ # User and group:
1847
+ #
1848
+ # - Argument +user+ may be a user name or a user id;
1849
+ # if +nil+ or +-1+, the user is not changed.
1850
+ # - Argument +group+ may be a group name or a group id;
1851
+ # if +nil+ or +-1+, the group is not changed.
1852
+ # - The user must be a member of the group.
1853
+ #
1854
+ # Examples:
1855
+ #
1856
+ # # One path.
1857
+ # # User and group as string names.
1858
+ # File.stat('src0.txt').uid # => 1004
1859
+ # File.stat('src0.txt').gid # => 1004
1860
+ # Bundler::FileUtils.chown('user2', 'group1', 'src0.txt')
1861
+ # File.stat('src0.txt').uid # => 1006
1862
+ # File.stat('src0.txt').gid # => 1005
1863
+ #
1864
+ # # User and group as uid and gid.
1865
+ # Bundler::FileUtils.chown(1004, 1004, 'src0.txt')
1866
+ # File.stat('src0.txt').uid # => 1004
1867
+ # File.stat('src0.txt').gid # => 1004
1868
+ #
1869
+ # # Array of paths.
1870
+ # Bundler::FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'])
1871
+ #
1872
+ # # Directory (not recursive).
1873
+ # Bundler::FileUtils.chown('user2', 'group1', '.')
1874
+ #
1875
+ # Keyword arguments:
1876
+ #
1877
+ # - <tt>noop: true</tt> - does not change permissions; returns +nil+.
1878
+ # - <tt>verbose: true</tt> - prints an equivalent command:
1879
+ #
1880
+ # Bundler::FileUtils.chown('user2', 'group1', 'src0.txt', noop: true, verbose: true)
1881
+ # Bundler::FileUtils.chown(1004, 1004, 'src0.txt', noop: true, verbose: true)
1882
+ # Bundler::FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'], noop: true, verbose: true)
1883
+ # Bundler::FileUtils.chown('user2', 'group1', path, noop: true, verbose: true)
1884
+ # Bundler::FileUtils.chown('user2', 'group1', '.', noop: true, verbose: true)
1885
+ #
1886
+ # Output:
1887
+ #
1888
+ # chown user2:group1 src0.txt
1889
+ # chown 1004:1004 src0.txt
1890
+ # chown 1006:1005 src0.txt src0.dat
1891
+ # chown user2:group1 src0.txt
1892
+ # chown user2:group1 .
1893
+ #
1894
+ # Related: Bundler::FileUtils.chown_R.
1895
+ #
1896
+ def chown(user, group, list, noop: nil, verbose: nil)
1897
+ list = fu_list(list)
1898
+ fu_output_message sprintf('chown %s %s',
1899
+ (group ? "#{user}:#{group}" : user || ':'),
1900
+ list.join(' ')) if verbose
1901
+ return if noop
1902
+ uid = fu_get_uid(user)
1903
+ gid = fu_get_gid(group)
1904
+ list.each do |path|
1905
+ Entry_.new(path).chown uid, gid
1906
+ end
1907
+ end
1908
+ module_function :chown
1909
+
1910
+ # Like Bundler::FileUtils.chown, but changes owner and group recursively.
1911
+ #
1912
+ def chown_R(user, group, list, noop: nil, verbose: nil, force: nil)
1913
+ list = fu_list(list)
1914
+ fu_output_message sprintf('chown -R%s %s %s',
1915
+ (force ? 'f' : ''),
1916
+ (group ? "#{user}:#{group}" : user || ':'),
1917
+ list.join(' ')) if verbose
1918
+ return if noop
1919
+ uid = fu_get_uid(user)
1920
+ gid = fu_get_gid(group)
1921
+ list.each do |root|
1922
+ Entry_.new(root).traverse do |ent|
1923
+ begin
1924
+ ent.chown uid, gid
1925
+ rescue
1926
+ raise unless force
1927
+ end
1928
+ end
1929
+ end
1930
+ end
1931
+ module_function :chown_R
1932
+
1933
+ def fu_get_uid(user) #:nodoc:
1934
+ return nil unless user
1935
+ case user
1936
+ when Integer
1937
+ user
1938
+ when /\A\d+\z/
1939
+ user.to_i
1940
+ else
1941
+ require 'etc'
1942
+ Etc.getpwnam(user) ? Etc.getpwnam(user).uid : nil
1943
+ end
1944
+ end
1945
+ private_module_function :fu_get_uid
1946
+
1947
+ def fu_get_gid(group) #:nodoc:
1948
+ return nil unless group
1949
+ case group
1950
+ when Integer
1951
+ group
1952
+ when /\A\d+\z/
1953
+ group.to_i
1954
+ else
1955
+ require 'etc'
1956
+ Etc.getgrnam(group) ? Etc.getgrnam(group).gid : nil
1957
+ end
1958
+ end
1959
+ private_module_function :fu_get_gid
1960
+
1961
+ # Updates modification times (mtime) and access times (atime)
1962
+ # of the entries given by the paths in +list+
1963
+ # (a single path or an array of paths);
1964
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise.
1965
+ #
1966
+ # By default, creates an empty file for any path to a non-existent entry;
1967
+ # use keyword argument +nocreate+ to raise an exception instead.
1968
+ #
1969
+ # Argument +list+ or its elements
1970
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
1971
+ #
1972
+ # Examples:
1973
+ #
1974
+ # # Single path.
1975
+ # f = File.new('src0.txt') # Existing file.
1976
+ # f.atime # => 2022-06-10 11:11:21.200277 -0700
1977
+ # f.mtime # => 2022-06-10 11:11:21.200277 -0700
1978
+ # Bundler::FileUtils.touch('src0.txt')
1979
+ # f = File.new('src0.txt')
1980
+ # f.atime # => 2022-06-11 08:28:09.8185343 -0700
1981
+ # f.mtime # => 2022-06-11 08:28:09.8185343 -0700
1982
+ #
1983
+ # # Array of paths.
1984
+ # Bundler::FileUtils.touch(['src0.txt', 'src0.dat'])
1985
+ #
1986
+ # Keyword arguments:
1987
+ #
1988
+ # - <tt>mtime: <i>time</i></tt> - sets the entry's mtime to the given time,
1989
+ # instead of the current time.
1990
+ # - <tt>nocreate: true</tt> - raises an exception if the entry does not exist.
1991
+ # - <tt>noop: true</tt> - does not touch entries; returns +nil+.
1992
+ # - <tt>verbose: true</tt> - prints an equivalent command:
1993
+ #
1994
+ # Bundler::FileUtils.touch('src0.txt', noop: true, verbose: true)
1995
+ # Bundler::FileUtils.touch(['src0.txt', 'src0.dat'], noop: true, verbose: true)
1996
+ # Bundler::FileUtils.touch(path, noop: true, verbose: true)
1997
+ #
1998
+ # Output:
1999
+ #
2000
+ # touch src0.txt
2001
+ # touch src0.txt src0.dat
2002
+ # touch src0.txt
2003
+ #
2004
+ # Related: Bundler::FileUtils.uptodate?.
2005
+ #
2006
+ def touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil)
2007
+ list = fu_list(list)
2008
+ t = mtime
2009
+ if verbose
2010
+ fu_output_message "touch #{nocreate ? '-c ' : ''}#{t ? t.strftime('-t %Y%m%d%H%M.%S ') : ''}#{list.join ' '}"
2011
+ end
2012
+ return if noop
2013
+ list.each do |path|
2014
+ created = nocreate
2015
+ begin
2016
+ File.utime(t, t, path)
2017
+ rescue Errno::ENOENT
2018
+ raise if created
2019
+ File.open(path, 'a') {
2020
+ ;
2021
+ }
2022
+ created = true
2023
+ retry if t
2024
+ end
2025
+ end
2026
+ end
2027
+ module_function :touch
2028
+
2029
+ private
2030
+
2031
+ module StreamUtils_
2032
+ private
2033
+
2034
+ case (defined?(::RbConfig) ? ::RbConfig::CONFIG['host_os'] : ::RUBY_PLATFORM)
2035
+ when /mswin|mingw/
2036
+ def fu_windows?; true end
2037
+ else
2038
+ def fu_windows?; false end
2039
+ end
2040
+
2041
+ def fu_copy_stream0(src, dest, blksize = nil) #:nodoc:
2042
+ IO.copy_stream(src, dest)
2043
+ end
2044
+
2045
+ def fu_stream_blksize(*streams)
2046
+ streams.each do |s|
2047
+ next unless s.respond_to?(:stat)
2048
+ size = fu_blksize(s.stat)
2049
+ return size if size
2050
+ end
2051
+ fu_default_blksize()
2052
+ end
2053
+
2054
+ def fu_blksize(st)
2055
+ s = st.blksize
2056
+ return nil unless s
2057
+ return nil if s == 0
2058
+ s
2059
+ end
2060
+
2061
+ def fu_default_blksize
2062
+ 1024
2063
+ end
2064
+ end
2065
+
2066
+ include StreamUtils_
2067
+ extend StreamUtils_
2068
+
2069
+ class Entry_ #:nodoc: internal use only
2070
+ include StreamUtils_
2071
+
2072
+ def initialize(a, b = nil, deref = false)
2073
+ @prefix = @rel = @path = nil
2074
+ if b
2075
+ @prefix = a
2076
+ @rel = b
2077
+ else
2078
+ @path = a
2079
+ end
2080
+ @deref = deref
2081
+ @stat = nil
2082
+ @lstat = nil
2083
+ end
2084
+
2085
+ def inspect
2086
+ "\#<#{self.class} #{path()}>"
2087
+ end
2088
+
2089
+ def path
2090
+ if @path
2091
+ File.path(@path)
2092
+ else
2093
+ join(@prefix, @rel)
2094
+ end
2095
+ end
2096
+
2097
+ def prefix
2098
+ @prefix || @path
2099
+ end
2100
+
2101
+ def rel
2102
+ @rel
2103
+ end
2104
+
2105
+ def dereference?
2106
+ @deref
2107
+ end
2108
+
2109
+ def exist?
2110
+ begin
2111
+ lstat
2112
+ true
2113
+ rescue Errno::ENOENT
2114
+ false
2115
+ end
2116
+ end
2117
+
2118
+ def file?
2119
+ s = lstat!
2120
+ s and s.file?
2121
+ end
2122
+
2123
+ def directory?
2124
+ s = lstat!
2125
+ s and s.directory?
2126
+ end
2127
+
2128
+ def symlink?
2129
+ s = lstat!
2130
+ s and s.symlink?
2131
+ end
2132
+
2133
+ def chardev?
2134
+ s = lstat!
2135
+ s and s.chardev?
2136
+ end
2137
+
2138
+ def blockdev?
2139
+ s = lstat!
2140
+ s and s.blockdev?
2141
+ end
2142
+
2143
+ def socket?
2144
+ s = lstat!
2145
+ s and s.socket?
2146
+ end
2147
+
2148
+ def pipe?
2149
+ s = lstat!
2150
+ s and s.pipe?
2151
+ end
2152
+
2153
+ S_IF_DOOR = 0xD000
2154
+
2155
+ def door?
2156
+ s = lstat!
2157
+ s and (s.mode & 0xF000 == S_IF_DOOR)
2158
+ end
2159
+
2160
+ def entries
2161
+ opts = {}
2162
+ opts[:encoding] = fu_windows? ? ::Encoding::UTF_8 : path.encoding
2163
+
2164
+ files = Dir.children(path, **opts)
2165
+
2166
+ untaint = RUBY_VERSION < '2.7'
2167
+ files.map {|n| Entry_.new(prefix(), join(rel(), untaint ? n.untaint : n)) }
2168
+ end
2169
+
2170
+ def stat
2171
+ return @stat if @stat
2172
+ if lstat() and lstat().symlink?
2173
+ @stat = File.stat(path())
2174
+ else
2175
+ @stat = lstat()
2176
+ end
2177
+ @stat
2178
+ end
2179
+
2180
+ def stat!
2181
+ return @stat if @stat
2182
+ if lstat! and lstat!.symlink?
2183
+ @stat = File.stat(path())
2184
+ else
2185
+ @stat = lstat!
2186
+ end
2187
+ @stat
2188
+ rescue SystemCallError
2189
+ nil
2190
+ end
2191
+
2192
+ def lstat
2193
+ if dereference?
2194
+ @lstat ||= File.stat(path())
2195
+ else
2196
+ @lstat ||= File.lstat(path())
2197
+ end
2198
+ end
2199
+
2200
+ def lstat!
2201
+ lstat()
2202
+ rescue SystemCallError
2203
+ nil
2204
+ end
2205
+
2206
+ def chmod(mode)
2207
+ if symlink?
2208
+ File.lchmod mode, path() if have_lchmod?
2209
+ else
2210
+ File.chmod mode, path()
2211
+ end
2212
+ rescue Errno::EOPNOTSUPP
2213
+ end
2214
+
2215
+ def chown(uid, gid)
2216
+ if symlink?
2217
+ File.lchown uid, gid, path() if have_lchown?
2218
+ else
2219
+ File.chown uid, gid, path()
2220
+ end
2221
+ end
2222
+
2223
+ def link(dest)
2224
+ case
2225
+ when directory?
2226
+ if !File.exist?(dest) and descendant_directory?(dest, path)
2227
+ raise ArgumentError, "cannot link directory %s to itself %s" % [path, dest]
2228
+ end
2229
+ begin
2230
+ Dir.mkdir dest
2231
+ rescue
2232
+ raise unless File.directory?(dest)
2233
+ end
2234
+ else
2235
+ File.link path(), dest
2236
+ end
2237
+ end
2238
+
2239
+ def copy(dest)
2240
+ lstat
2241
+ case
2242
+ when file?
2243
+ copy_file dest
2244
+ when directory?
2245
+ if !File.exist?(dest) and descendant_directory?(dest, path)
2246
+ raise ArgumentError, "cannot copy directory %s to itself %s" % [path, dest]
2247
+ end
2248
+ begin
2249
+ Dir.mkdir dest
2250
+ rescue
2251
+ raise unless File.directory?(dest)
2252
+ end
2253
+ when symlink?
2254
+ File.symlink File.readlink(path()), dest
2255
+ when chardev?, blockdev?
2256
+ raise "cannot handle device file"
2257
+ when socket?
2258
+ begin
2259
+ require 'socket'
2260
+ rescue LoadError
2261
+ raise "cannot handle socket"
2262
+ else
2263
+ raise "cannot handle socket" unless defined?(UNIXServer)
2264
+ end
2265
+ UNIXServer.new(dest).close
2266
+ File.chmod lstat().mode, dest
2267
+ when pipe?
2268
+ raise "cannot handle FIFO" unless File.respond_to?(:mkfifo)
2269
+ File.mkfifo dest, lstat().mode
2270
+ when door?
2271
+ raise "cannot handle door: #{path()}"
2272
+ else
2273
+ raise "unknown file type: #{path()}"
2274
+ end
2275
+ end
2276
+
2277
+ def copy_file(dest)
2278
+ File.open(path()) do |s|
2279
+ File.open(dest, 'wb', s.stat.mode) do |f|
2280
+ IO.copy_stream(s, f)
2281
+ end
2282
+ end
2283
+ end
2284
+
2285
+ def copy_metadata(path)
2286
+ st = lstat()
2287
+ if !st.symlink?
2288
+ File.utime st.atime, st.mtime, path
2289
+ end
2290
+ mode = st.mode
2291
+ begin
2292
+ if st.symlink?
2293
+ begin
2294
+ File.lchown st.uid, st.gid, path
2295
+ rescue NotImplementedError
2296
+ end
2297
+ else
2298
+ File.chown st.uid, st.gid, path
2299
+ end
2300
+ rescue Errno::EPERM, Errno::EACCES
2301
+ # clear setuid/setgid
2302
+ mode &= 01777
2303
+ end
2304
+ if st.symlink?
2305
+ begin
2306
+ File.lchmod mode, path
2307
+ rescue NotImplementedError, Errno::EOPNOTSUPP
2308
+ end
2309
+ else
2310
+ File.chmod mode, path
2311
+ end
2312
+ end
2313
+
2314
+ def remove
2315
+ if directory?
2316
+ remove_dir1
2317
+ else
2318
+ remove_file
2319
+ end
2320
+ end
2321
+
2322
+ def remove_dir1
2323
+ platform_support {
2324
+ Dir.rmdir path().chomp(?/)
2325
+ }
2326
+ end
2327
+
2328
+ def remove_file
2329
+ platform_support {
2330
+ File.unlink path
2331
+ }
2332
+ end
2333
+
2334
+ def platform_support
2335
+ return yield unless fu_windows?
2336
+ first_time_p = true
2337
+ begin
2338
+ yield
2339
+ rescue Errno::ENOENT
2340
+ raise
2341
+ rescue => err
2342
+ if first_time_p
2343
+ first_time_p = false
2344
+ begin
2345
+ File.chmod 0700, path() # Windows does not have symlink
2346
+ retry
2347
+ rescue SystemCallError
2348
+ end
2349
+ end
2350
+ raise err
2351
+ end
2352
+ end
2353
+
2354
+ def preorder_traverse
2355
+ stack = [self]
2356
+ while ent = stack.pop
2357
+ yield ent
2358
+ stack.concat ent.entries.reverse if ent.directory?
2359
+ end
2360
+ end
2361
+
2362
+ alias traverse preorder_traverse
2363
+
2364
+ def postorder_traverse
2365
+ if directory?
2366
+ begin
2367
+ children = entries()
2368
+ rescue Errno::EACCES
2369
+ # Failed to get the list of children.
2370
+ # Assuming there is no children, try to process the parent directory.
2371
+ yield self
2372
+ return
2373
+ end
2374
+
2375
+ children.each do |ent|
2376
+ ent.postorder_traverse do |e|
2377
+ yield e
2378
+ end
2379
+ end
2380
+ end
2381
+ yield self
2382
+ end
2383
+
2384
+ def wrap_traverse(pre, post)
2385
+ pre.call self
2386
+ if directory?
2387
+ entries.each do |ent|
2388
+ ent.wrap_traverse pre, post
2389
+ end
2390
+ end
2391
+ post.call self
2392
+ end
2393
+
2394
+ private
2395
+
2396
+ @@fileutils_rb_have_lchmod = nil
2397
+
2398
+ def have_lchmod?
2399
+ # This is not MT-safe, but it does not matter.
2400
+ if @@fileutils_rb_have_lchmod == nil
2401
+ @@fileutils_rb_have_lchmod = check_have_lchmod?
2402
+ end
2403
+ @@fileutils_rb_have_lchmod
2404
+ end
2405
+
2406
+ def check_have_lchmod?
2407
+ return false unless File.respond_to?(:lchmod)
2408
+ File.lchmod 0
2409
+ return true
2410
+ rescue NotImplementedError
2411
+ return false
2412
+ end
2413
+
2414
+ @@fileutils_rb_have_lchown = nil
2415
+
2416
+ def have_lchown?
2417
+ # This is not MT-safe, but it does not matter.
2418
+ if @@fileutils_rb_have_lchown == nil
2419
+ @@fileutils_rb_have_lchown = check_have_lchown?
2420
+ end
2421
+ @@fileutils_rb_have_lchown
2422
+ end
2423
+
2424
+ def check_have_lchown?
2425
+ return false unless File.respond_to?(:lchown)
2426
+ File.lchown nil, nil
2427
+ return true
2428
+ rescue NotImplementedError
2429
+ return false
2430
+ end
2431
+
2432
+ def join(dir, base)
2433
+ return File.path(dir) if not base or base == '.'
2434
+ return File.path(base) if not dir or dir == '.'
2435
+ begin
2436
+ File.join(dir, base)
2437
+ rescue EncodingError
2438
+ if fu_windows?
2439
+ File.join(dir.encode(::Encoding::UTF_8), base.encode(::Encoding::UTF_8))
2440
+ else
2441
+ raise
2442
+ end
2443
+ end
2444
+ end
2445
+
2446
+ if File::ALT_SEPARATOR
2447
+ DIRECTORY_TERM = "(?=[/#{Regexp.quote(File::ALT_SEPARATOR)}]|\\z)"
2448
+ else
2449
+ DIRECTORY_TERM = "(?=/|\\z)"
2450
+ end
2451
+
2452
+ def descendant_directory?(descendant, ascendant)
2453
+ if File::FNM_SYSCASE.nonzero?
2454
+ File.expand_path(File.dirname(descendant)).casecmp(File.expand_path(ascendant)) == 0
2455
+ else
2456
+ File.expand_path(File.dirname(descendant)) == File.expand_path(ascendant)
2457
+ end
2458
+ end
2459
+ end # class Entry_
2460
+
2461
+ def fu_list(arg) #:nodoc:
2462
+ [arg].flatten.map {|path| File.path(path) }
2463
+ end
2464
+ private_module_function :fu_list
2465
+
2466
+ def fu_each_src_dest(src, dest) #:nodoc:
2467
+ fu_each_src_dest0(src, dest) do |s, d|
2468
+ raise ArgumentError, "same file: #{s} and #{d}" if fu_same?(s, d)
2469
+ yield s, d
2470
+ end
2471
+ end
2472
+ private_module_function :fu_each_src_dest
2473
+
2474
+ def fu_each_src_dest0(src, dest, target_directory = true) #:nodoc:
2475
+ if tmp = Array.try_convert(src)
2476
+ tmp.each do |s|
2477
+ s = File.path(s)
2478
+ yield s, (target_directory ? File.join(dest, File.basename(s)) : dest)
2479
+ end
2480
+ else
2481
+ src = File.path(src)
2482
+ if target_directory and File.directory?(dest)
2483
+ yield src, File.join(dest, File.basename(src))
2484
+ else
2485
+ yield src, File.path(dest)
2486
+ end
2487
+ end
2488
+ end
2489
+ private_module_function :fu_each_src_dest0
2490
+
2491
+ def fu_same?(a, b) #:nodoc:
2492
+ File.identical?(a, b)
2493
+ end
2494
+ private_module_function :fu_same?
2495
+
2496
+ def fu_output_message(msg) #:nodoc:
2497
+ output = @fileutils_output if defined?(@fileutils_output)
2498
+ output ||= $stdout
2499
+ if defined?(@fileutils_label)
2500
+ msg = @fileutils_label + msg
2501
+ end
2502
+ output.puts msg
2503
+ end
2504
+ private_module_function :fu_output_message
2505
+
2506
+ def fu_split_path(path)
2507
+ path = File.path(path)
2508
+ list = []
2509
+ until (parent, base = File.split(path); parent == path or parent == ".")
2510
+ list << base
2511
+ path = parent
2512
+ end
2513
+ list << path
2514
+ list.reverse!
2515
+ end
2516
+ private_module_function :fu_split_path
2517
+
2518
+ def fu_relative_components_from(target, base) #:nodoc:
2519
+ i = 0
2520
+ while target[i]&.== base[i]
2521
+ i += 1
2522
+ end
2523
+ Array.new(base.size-i, '..').concat(target[i..-1])
2524
+ end
2525
+ private_module_function :fu_relative_components_from
2526
+
2527
+ def fu_clean_components(*comp)
2528
+ comp.shift while comp.first == "."
2529
+ return comp if comp.empty?
2530
+ clean = [comp.shift]
2531
+ path = File.join(*clean, "") # ending with File::SEPARATOR
2532
+ while c = comp.shift
2533
+ if c == ".." and clean.last != ".." and !(fu_have_symlink? && File.symlink?(path))
2534
+ clean.pop
2535
+ path.chomp!(%r((?<=\A|/)[^/]+/\z), "")
2536
+ else
2537
+ clean << c
2538
+ path << c << "/"
2539
+ end
2540
+ end
2541
+ clean
2542
+ end
2543
+ private_module_function :fu_clean_components
2544
+
2545
+ if fu_windows?
2546
+ def fu_starting_path?(path)
2547
+ path&.start_with?(%r(\w:|/))
2548
+ end
2549
+ else
2550
+ def fu_starting_path?(path)
2551
+ path&.start_with?("/")
2552
+ end
2553
+ end
2554
+ private_module_function :fu_starting_path?
2555
+
2556
+ # This hash table holds command options.
2557
+ OPT_TABLE = {} #:nodoc: internal use only
2558
+ (private_instance_methods & methods(false)).inject(OPT_TABLE) {|tbl, name|
2559
+ (tbl[name.to_s] = instance_method(name).parameters).map! {|t, n| n if t == :key}.compact!
2560
+ tbl
2561
+ }
2562
+
2563
+ public
2564
+
2565
+ # Returns an array of the string names of \Bundler::FileUtils methods
2566
+ # that accept one or more keyword arguments:
2567
+ #
2568
+ # Bundler::FileUtils.commands.sort.take(3) # => ["cd", "chdir", "chmod"]
2569
+ #
2570
+ def self.commands
2571
+ OPT_TABLE.keys
2572
+ end
2573
+
2574
+ # Returns an array of the string keyword names:
2575
+ #
2576
+ # Bundler::FileUtils.options.take(3) # => ["noop", "verbose", "force"]
2577
+ #
2578
+ def self.options
2579
+ OPT_TABLE.values.flatten.uniq.map {|sym| sym.to_s }
2580
+ end
2581
+
2582
+ # Returns +true+ if method +mid+ accepts the given option +opt+, +false+ otherwise;
2583
+ # the arguments may be strings or symbols:
2584
+ #
2585
+ # Bundler::FileUtils.have_option?(:chmod, :noop) # => true
2586
+ # Bundler::FileUtils.have_option?('chmod', 'secure') # => false
2587
+ #
2588
+ def self.have_option?(mid, opt)
2589
+ li = OPT_TABLE[mid.to_s] or raise ArgumentError, "no such method: #{mid}"
2590
+ li.include?(opt)
2591
+ end
2592
+
2593
+ # Returns an array of the string keyword name for method +mid+;
2594
+ # the argument may be a string or a symbol:
2595
+ #
2596
+ # Bundler::FileUtils.options_of(:rm) # => ["force", "noop", "verbose"]
2597
+ # Bundler::FileUtils.options_of('mv') # => ["force", "noop", "verbose", "secure"]
2598
+ #
2599
+ def self.options_of(mid)
2600
+ OPT_TABLE[mid.to_s].map {|sym| sym.to_s }
2601
+ end
2602
+
2603
+ # Returns an array of the string method names of the methods
2604
+ # that accept the given keyword option +opt+;
2605
+ # the argument must be a symbol:
2606
+ #
2607
+ # Bundler::FileUtils.collect_method(:preserve) # => ["cp", "copy", "cp_r", "install"]
2608
+ #
2609
+ def self.collect_method(opt)
2610
+ OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) }
2611
+ end
2612
+
2613
+ private
2614
+
2615
+ LOW_METHODS = singleton_methods(false) - collect_method(:noop).map(&:intern) # :nodoc:
2616
+ module LowMethods # :nodoc: internal use only
2617
+ private
2618
+ def _do_nothing(*)end
2619
+ ::Bundler::FileUtils::LOW_METHODS.map {|name| alias_method name, :_do_nothing}
2620
+ end
2621
+
2622
+ METHODS = singleton_methods() - [:private_module_function, # :nodoc:
2623
+ :commands, :options, :have_option?, :options_of, :collect_method]
2624
+
2625
+ #
2626
+ # This module has all methods of Bundler::FileUtils module, but it outputs messages
2627
+ # before acting. This equates to passing the <tt>:verbose</tt> flag to
2628
+ # methods in Bundler::FileUtils.
2629
+ #
2630
+ module Verbose
2631
+ include Bundler::FileUtils
2632
+ names = ::Bundler::FileUtils.collect_method(:verbose)
2633
+ names.each do |name|
2634
+ module_eval(<<-EOS, __FILE__, __LINE__ + 1)
2635
+ def #{name}(*args, **options)
2636
+ super(*args, **options, verbose: true)
2637
+ end
2638
+ EOS
2639
+ end
2640
+ private(*names)
2641
+ extend self
2642
+ class << self
2643
+ public(*::Bundler::FileUtils::METHODS)
2644
+ end
2645
+ end
2646
+
2647
+ #
2648
+ # This module has all methods of Bundler::FileUtils module, but never changes
2649
+ # files/directories. This equates to passing the <tt>:noop</tt> flag
2650
+ # to methods in Bundler::FileUtils.
2651
+ #
2652
+ module NoWrite
2653
+ include Bundler::FileUtils
2654
+ include LowMethods
2655
+ names = ::Bundler::FileUtils.collect_method(:noop)
2656
+ names.each do |name|
2657
+ module_eval(<<-EOS, __FILE__, __LINE__ + 1)
2658
+ def #{name}(*args, **options)
2659
+ super(*args, **options, noop: true)
2660
+ end
2661
+ EOS
2662
+ end
2663
+ private(*names)
2664
+ extend self
2665
+ class << self
2666
+ public(*::Bundler::FileUtils::METHODS)
2667
+ end
2668
+ end
2669
+
2670
+ #
2671
+ # This module has all methods of Bundler::FileUtils module, but never changes
2672
+ # files/directories, with printing message before acting.
2673
+ # This equates to passing the <tt>:noop</tt> and <tt>:verbose</tt> flag
2674
+ # to methods in Bundler::FileUtils.
2675
+ #
2676
+ module DryRun
2677
+ include Bundler::FileUtils
2678
+ include LowMethods
2679
+ names = ::Bundler::FileUtils.collect_method(:noop)
2680
+ names.each do |name|
2681
+ module_eval(<<-EOS, __FILE__, __LINE__ + 1)
2682
+ def #{name}(*args, **options)
2683
+ super(*args, **options, noop: true, verbose: true)
2684
+ end
2685
+ EOS
2686
+ end
2687
+ private(*names)
2688
+ extend self
2689
+ class << self
2690
+ public(*::Bundler::FileUtils::METHODS)
2691
+ end
2692
+ end
2693
+
2694
+ end