rubygems-update 2.6.1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +5899 -0
- data/CODE_OF_CONDUCT.md +76 -35
- data/CONTRIBUTING.md +231 -0
- data/MAINTAINERS.txt +8 -0
- data/Manifest.txt +428 -216
- data/POLICIES.md +135 -0
- data/README.md +112 -0
- data/UPGRADING.md +15 -0
- data/bundler/CHANGELOG.md +4719 -0
- data/bundler/LICENSE.md +22 -0
- data/bundler/README.md +58 -0
- data/bundler/UPGRADING.md +222 -0
- data/bundler/bundler.gemspec +46 -0
- data/bundler/exe/bundle +29 -0
- data/bundler/exe/bundler +4 -0
- data/bundler/lib/bundler/.document +1 -0
- data/bundler/lib/bundler/build_metadata.rb +45 -0
- data/bundler/lib/bundler/capistrano.rb +22 -0
- data/bundler/lib/bundler/checksum.rb +245 -0
- data/bundler/lib/bundler/ci_detector.rb +75 -0
- data/bundler/lib/bundler/cli/add.rb +47 -0
- data/bundler/lib/bundler/cli/binstubs.rb +57 -0
- data/bundler/lib/bundler/cli/cache.rb +43 -0
- data/bundler/lib/bundler/cli/check.rb +40 -0
- data/bundler/lib/bundler/cli/clean.rb +25 -0
- data/bundler/lib/bundler/cli/common.rb +138 -0
- data/bundler/lib/bundler/cli/config.rb +204 -0
- data/bundler/lib/bundler/cli/console.rb +44 -0
- data/bundler/lib/bundler/cli/doctor.rb +157 -0
- data/bundler/lib/bundler/cli/exec.rb +88 -0
- data/bundler/lib/bundler/cli/fund.rb +36 -0
- data/bundler/lib/bundler/cli/gem.rb +471 -0
- data/bundler/lib/bundler/cli/info.rb +83 -0
- data/bundler/lib/bundler/cli/init.rb +51 -0
- data/bundler/lib/bundler/cli/inject.rb +60 -0
- data/bundler/lib/bundler/cli/install.rb +190 -0
- data/bundler/lib/bundler/cli/issue.rb +41 -0
- data/bundler/lib/bundler/cli/list.rb +66 -0
- data/bundler/lib/bundler/cli/lock.rb +73 -0
- data/bundler/lib/bundler/cli/open.rb +29 -0
- data/bundler/lib/bundler/cli/outdated.rb +297 -0
- data/bundler/lib/bundler/cli/platform.rb +48 -0
- data/bundler/lib/bundler/cli/plugin.rb +34 -0
- data/bundler/lib/bundler/cli/pristine.rb +60 -0
- data/bundler/lib/bundler/cli/remove.rb +17 -0
- data/bundler/lib/bundler/cli/show.rb +75 -0
- data/bundler/lib/bundler/cli/update.rb +123 -0
- data/bundler/lib/bundler/cli/viz.rb +31 -0
- data/bundler/lib/bundler/cli.rb +846 -0
- data/bundler/lib/bundler/compact_index_client/cache.rb +121 -0
- data/bundler/lib/bundler/compact_index_client/cache_file.rb +153 -0
- data/bundler/lib/bundler/compact_index_client/gem_parser.rb +32 -0
- data/bundler/lib/bundler/compact_index_client/updater.rb +115 -0
- data/bundler/lib/bundler/compact_index_client.rb +126 -0
- data/bundler/lib/bundler/constants.rb +7 -0
- data/bundler/lib/bundler/current_ruby.rb +92 -0
- data/bundler/lib/bundler/definition.rb +1005 -0
- data/bundler/lib/bundler/dependency.rb +101 -0
- data/bundler/lib/bundler/deployment.rb +69 -0
- data/bundler/lib/bundler/deprecate.rb +44 -0
- data/bundler/lib/bundler/digest.rb +71 -0
- data/bundler/lib/bundler/dsl.rb +601 -0
- data/bundler/lib/bundler/endpoint_specification.rb +147 -0
- data/bundler/lib/bundler/env.rb +148 -0
- data/bundler/lib/bundler/environment_preserver.rb +86 -0
- data/bundler/lib/bundler/errors.rb +233 -0
- data/bundler/lib/bundler/feature_flag.rb +53 -0
- data/bundler/lib/bundler/fetcher/base.rb +52 -0
- data/bundler/lib/bundler/fetcher/compact_index.rb +129 -0
- data/bundler/lib/bundler/fetcher/dependency.rb +78 -0
- data/bundler/lib/bundler/fetcher/downloader.rb +91 -0
- data/bundler/lib/bundler/fetcher/gem_remote_fetcher.rb +16 -0
- data/bundler/lib/bundler/fetcher/index.rb +25 -0
- data/bundler/lib/bundler/fetcher.rb +324 -0
- data/bundler/lib/bundler/force_platform.rb +18 -0
- data/bundler/lib/bundler/friendly_errors.rb +126 -0
- data/bundler/lib/bundler/gem_helper.rb +237 -0
- data/bundler/lib/bundler/gem_helpers.rb +127 -0
- data/bundler/lib/bundler/gem_tasks.rb +7 -0
- data/bundler/lib/bundler/gem_version_promoter.rb +145 -0
- data/bundler/lib/bundler/graph.rb +152 -0
- data/bundler/lib/bundler/index.rb +205 -0
- data/bundler/lib/bundler/injector.rb +287 -0
- data/bundler/lib/bundler/inline.rb +73 -0
- data/bundler/lib/bundler/installer/gem_installer.rb +84 -0
- data/bundler/lib/bundler/installer/parallel_installer.rb +202 -0
- data/bundler/lib/bundler/installer/standalone.rb +116 -0
- data/bundler/lib/bundler/installer.rb +267 -0
- data/bundler/lib/bundler/lazy_specification.rb +170 -0
- data/bundler/lib/bundler/lockfile_generator.rb +104 -0
- data/bundler/lib/bundler/lockfile_parser.rb +289 -0
- data/bundler/lib/bundler/man/.document +1 -0
- data/bundler/lib/bundler/man/bundle-add.1 +59 -0
- data/bundler/lib/bundler/man/bundle-add.1.ronn +58 -0
- data/bundler/lib/bundler/man/bundle-binstubs.1 +30 -0
- data/bundler/lib/bundler/man/bundle-binstubs.1.ronn +41 -0
- data/bundler/lib/bundler/man/bundle-cache.1 +40 -0
- data/bundler/lib/bundler/man/bundle-cache.1.ronn +79 -0
- data/bundler/lib/bundler/man/bundle-check.1 +22 -0
- data/bundler/lib/bundler/man/bundle-check.1.ronn +26 -0
- data/bundler/lib/bundler/man/bundle-clean.1 +17 -0
- data/bundler/lib/bundler/man/bundle-clean.1.ronn +18 -0
- data/bundler/lib/bundler/man/bundle-config.1 +321 -0
- data/bundler/lib/bundler/man/bundle-config.1.ronn +411 -0
- data/bundler/lib/bundler/man/bundle-console.1 +35 -0
- data/bundler/lib/bundler/man/bundle-console.1.ronn +44 -0
- data/bundler/lib/bundler/man/bundle-doctor.1 +30 -0
- data/bundler/lib/bundler/man/bundle-doctor.1.ronn +33 -0
- data/bundler/lib/bundler/man/bundle-exec.1 +104 -0
- data/bundler/lib/bundler/man/bundle-exec.1.ronn +151 -0
- data/bundler/lib/bundler/man/bundle-gem.1 +69 -0
- data/bundler/lib/bundler/man/bundle-gem.1.ronn +117 -0
- data/bundler/lib/bundler/man/bundle-help.1 +9 -0
- data/bundler/lib/bundler/man/bundle-help.1.ronn +12 -0
- data/bundler/lib/bundler/man/bundle-info.1 +14 -0
- data/bundler/lib/bundler/man/bundle-info.1.ronn +17 -0
- data/bundler/lib/bundler/man/bundle-init.1 +20 -0
- data/bundler/lib/bundler/man/bundle-init.1.ronn +31 -0
- data/bundler/lib/bundler/man/bundle-inject.1 +23 -0
- data/bundler/lib/bundler/man/bundle-inject.1.ronn +24 -0
- data/bundler/lib/bundler/man/bundle-install.1 +215 -0
- data/bundler/lib/bundler/man/bundle-install.1.ronn +383 -0
- data/bundler/lib/bundler/man/bundle-list.1 +35 -0
- data/bundler/lib/bundler/man/bundle-list.1.ronn +33 -0
- data/bundler/lib/bundler/man/bundle-lock.1 +60 -0
- data/bundler/lib/bundler/man/bundle-lock.1.ronn +94 -0
- data/bundler/lib/bundler/man/bundle-open.1 +32 -0
- data/bundler/lib/bundler/man/bundle-open.1.ronn +27 -0
- data/bundler/lib/bundler/man/bundle-outdated.1 +100 -0
- data/bundler/lib/bundler/man/bundle-outdated.1.ronn +106 -0
- data/bundler/lib/bundler/man/bundle-platform.1 +49 -0
- data/bundler/lib/bundler/man/bundle-platform.1.ronn +49 -0
- data/bundler/lib/bundler/man/bundle-plugin.1 +55 -0
- data/bundler/lib/bundler/man/bundle-plugin.1.ronn +59 -0
- data/bundler/lib/bundler/man/bundle-pristine.1 +23 -0
- data/bundler/lib/bundler/man/bundle-pristine.1.ronn +34 -0
- data/bundler/lib/bundler/man/bundle-remove.1 +21 -0
- data/bundler/lib/bundler/man/bundle-remove.1.ronn +23 -0
- data/bundler/lib/bundler/man/bundle-show.1 +16 -0
- data/bundler/lib/bundler/man/bundle-show.1.ronn +21 -0
- data/bundler/lib/bundler/man/bundle-update.1 +275 -0
- data/bundler/lib/bundler/man/bundle-update.1.ronn +351 -0
- data/bundler/lib/bundler/man/bundle-version.1 +22 -0
- data/bundler/lib/bundler/man/bundle-version.1.ronn +24 -0
- data/bundler/lib/bundler/man/bundle-viz.1 +30 -0
- data/bundler/lib/bundler/man/bundle-viz.1.ronn +32 -0
- data/bundler/lib/bundler/man/bundle.1 +102 -0
- data/bundler/lib/bundler/man/bundle.1.ronn +116 -0
- data/bundler/lib/bundler/man/gemfile.5 +470 -0
- data/bundler/lib/bundler/man/gemfile.5.ronn +552 -0
- data/bundler/lib/bundler/man/index.txt +29 -0
- data/bundler/lib/bundler/match_metadata.rb +17 -0
- data/bundler/lib/bundler/match_platform.rb +23 -0
- data/bundler/lib/bundler/match_remote_metadata.rb +29 -0
- data/bundler/lib/bundler/mirror.rb +221 -0
- data/bundler/lib/bundler/plugin/api/source.rb +321 -0
- data/bundler/lib/bundler/plugin/api.rb +81 -0
- data/bundler/lib/bundler/plugin/dsl.rb +53 -0
- data/bundler/lib/bundler/plugin/events.rb +61 -0
- data/bundler/lib/bundler/plugin/index.rb +193 -0
- data/bundler/lib/bundler/plugin/installer/git.rb +34 -0
- data/bundler/lib/bundler/plugin/installer/rubygems.rb +19 -0
- data/bundler/lib/bundler/plugin/installer.rb +112 -0
- data/bundler/lib/bundler/plugin/source_list.rb +31 -0
- data/bundler/lib/bundler/plugin.rb +359 -0
- data/bundler/lib/bundler/process_lock.rb +24 -0
- data/bundler/lib/bundler/remote_specification.rb +117 -0
- data/bundler/lib/bundler/resolver/base.rb +107 -0
- data/bundler/lib/bundler/resolver/candidate.rb +94 -0
- data/bundler/lib/bundler/resolver/incompatibility.rb +15 -0
- data/bundler/lib/bundler/resolver/package.rb +77 -0
- data/bundler/lib/bundler/resolver/root.rb +25 -0
- data/bundler/lib/bundler/resolver/spec_group.rb +79 -0
- data/bundler/lib/bundler/resolver.rb +462 -0
- data/bundler/lib/bundler/retry.rb +66 -0
- data/bundler/lib/bundler/ruby_dsl.rb +53 -0
- data/bundler/lib/bundler/ruby_version.rb +131 -0
- data/bundler/lib/bundler/rubygems_ext.rb +328 -0
- data/bundler/lib/bundler/rubygems_gem_installer.rb +137 -0
- data/bundler/lib/bundler/rubygems_integration.rb +493 -0
- data/bundler/lib/bundler/runtime.rb +307 -0
- data/bundler/lib/bundler/safe_marshal.rb +31 -0
- data/bundler/lib/bundler/self_manager.rb +186 -0
- data/bundler/lib/bundler/settings/validator.rb +102 -0
- data/bundler/lib/bundler/settings.rb +588 -0
- data/bundler/lib/bundler/setup.rb +33 -0
- data/bundler/lib/bundler/shared_helpers.rb +380 -0
- data/bundler/lib/bundler/similarity_detector.rb +63 -0
- data/bundler/lib/bundler/source/gemspec.rb +18 -0
- data/bundler/lib/bundler/source/git/git_proxy.rb +455 -0
- data/bundler/lib/bundler/source/git.rb +380 -0
- data/bundler/lib/bundler/source/metadata.rb +62 -0
- data/bundler/lib/bundler/source/path/installer.rb +53 -0
- data/bundler/lib/bundler/source/path.rb +261 -0
- data/bundler/lib/bundler/source/rubygems/remote.rb +68 -0
- data/bundler/lib/bundler/source/rubygems.rb +516 -0
- data/bundler/lib/bundler/source/rubygems_aggregate.rb +68 -0
- data/bundler/lib/bundler/source.rb +116 -0
- data/bundler/lib/bundler/source_list.rb +227 -0
- data/bundler/lib/bundler/source_map.rb +71 -0
- data/bundler/lib/bundler/spec_set.rb +247 -0
- data/bundler/lib/bundler/stub_specification.rb +119 -0
- data/bundler/lib/bundler/templates/.document +1 -0
- data/bundler/lib/bundler/templates/Executable +27 -0
- data/bundler/lib/bundler/templates/Executable.bundler +109 -0
- data/bundler/lib/bundler/templates/Executable.standalone +14 -0
- data/bundler/lib/bundler/templates/Gemfile +5 -0
- data/bundler/lib/bundler/templates/newgem/CHANGELOG.md.tt +5 -0
- data/bundler/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +84 -0
- data/bundler/lib/bundler/templates/newgem/Cargo.toml.tt +7 -0
- data/bundler/lib/bundler/templates/newgem/Gemfile.tt +26 -0
- data/bundler/lib/bundler/templates/newgem/LICENSE.txt.tt +21 -0
- data/bundler/lib/bundler/templates/newgem/README.md.tt +45 -0
- data/bundler/lib/bundler/templates/newgem/Rakefile.tt +67 -0
- data/bundler/lib/bundler/templates/newgem/bin/console.tt +11 -0
- data/bundler/lib/bundler/templates/newgem/bin/setup.tt +8 -0
- data/bundler/lib/bundler/templates/newgem/circleci/config.yml.tt +25 -0
- data/bundler/lib/bundler/templates/newgem/exe/newgem.tt +3 -0
- data/bundler/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +15 -0
- data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt +10 -0
- data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +6 -0
- data/bundler/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +9 -0
- data/bundler/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +6 -0
- data/bundler/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +12 -0
- data/bundler/lib/bundler/templates/newgem/github/workflows/main.yml.tt +37 -0
- data/bundler/lib/bundler/templates/newgem/gitignore.tt +23 -0
- data/bundler/lib/bundler/templates/newgem/gitlab-ci.yml.tt +18 -0
- data/bundler/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +9 -0
- data/bundler/lib/bundler/templates/newgem/lib/newgem.rb.tt +15 -0
- data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +51 -0
- data/bundler/lib/bundler/templates/newgem/rspec.tt +3 -0
- data/bundler/lib/bundler/templates/newgem/rubocop.yml.tt +13 -0
- data/bundler/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
- data/bundler/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +11 -0
- data/bundler/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +15 -0
- data/bundler/lib/bundler/templates/newgem/standard.yml.tt +3 -0
- data/bundler/lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt +6 -0
- data/bundler/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +13 -0
- data/bundler/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt +15 -0
- data/bundler/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt +6 -0
- data/bundler/lib/bundler/ui/rg_proxy.rb +19 -0
- data/bundler/lib/bundler/ui/shell.rb +165 -0
- data/bundler/lib/bundler/ui/silent.rb +85 -0
- data/bundler/lib/bundler/ui.rb +9 -0
- data/bundler/lib/bundler/uri_credentials_filter.rb +43 -0
- data/bundler/lib/bundler/uri_normalizer.rb +23 -0
- data/bundler/lib/bundler/vendor/.document +1 -0
- data/bundler/lib/bundler/vendor/connection_pool/LICENSE +20 -0
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +174 -0
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +3 -0
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +56 -0
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +175 -0
- data/bundler/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
- data/bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb +2694 -0
- data/bundler/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +41 -0
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +65 -0
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +79 -0
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1073 -0
- data/bundler/lib/bundler/vendor/pub_grub/LICENSE.txt +21 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +189 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb +150 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb +43 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb +19 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +60 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb +129 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +411 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +248 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb +178 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +31 -0
- data/bundler/lib/bundler/vendor/thor/LICENSE.md +20 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +105 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +61 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +108 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +143 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +373 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +130 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions.rb +340 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/base.rb +825 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/command.rb +151 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +107 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/error.rb +106 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/group.rb +281 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/invocation.rb +178 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +37 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +88 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/line_editor.rb +17 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/nested_context.rb +29 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +89 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +195 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/option.rb +178 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/options.rb +293 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +72 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/runner.rb +335 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +388 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/color.rb +115 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/column_printer.rb +29 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/html.rb +84 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/lcs_diff.rb +49 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb +134 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/terminal.rb +42 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/wrapped_printer.rb +38 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell.rb +81 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/util.rb +285 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/version.rb +3 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor.rb +663 -0
- data/bundler/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
- data/bundler/lib/bundler/vendor/tsort/lib/tsort.rb +455 -0
- data/bundler/lib/bundler/vendor/uri/LICENSE.txt +22 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +853 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/file.rb +100 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/ftp.rb +267 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/generic.rb +1588 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/http.rb +125 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/https.rb +23 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/ldap.rb +261 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/ldaps.rb +22 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/mailto.rb +293 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +539 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +183 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/version.rb +6 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/ws.rb +83 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/wss.rb +23 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri.rb +104 -0
- data/bundler/lib/bundler/vendored_fileutils.rb +4 -0
- data/bundler/lib/bundler/vendored_net_http.rb +8 -0
- data/bundler/lib/bundler/vendored_persistent.rb +11 -0
- data/bundler/lib/bundler/vendored_pub_grub.rb +4 -0
- data/bundler/lib/bundler/vendored_thor.rb +8 -0
- data/bundler/lib/bundler/vendored_timeout.rb +8 -0
- data/bundler/lib/bundler/vendored_tsort.rb +4 -0
- data/bundler/lib/bundler/vendored_uri.rb +4 -0
- data/bundler/lib/bundler/version.rb +13 -0
- data/bundler/lib/bundler/vlad.rb +17 -0
- data/bundler/lib/bundler/worker.rb +117 -0
- data/bundler/lib/bundler/yaml_serializer.rb +93 -0
- data/bundler/lib/bundler.rb +665 -0
- data/{test/rubygems/bogussources.rb → exe/gem} +5 -2
- data/exe/update_rubygems +38 -0
- data/hide_lib_for_update/note.txt +0 -4
- data/lib/rubygems/available_set.rb +12 -12
- data/lib/rubygems/basic_specification.rb +75 -58
- data/lib/rubygems/bundler_version_finder.rb +77 -0
- data/lib/rubygems/ci_detector.rb +75 -0
- data/lib/rubygems/command.rb +144 -71
- data/lib/rubygems/command_manager.rb +64 -27
- data/lib/rubygems/commands/build_command.rb +88 -17
- data/lib/rubygems/commands/cert_command.rb +131 -83
- data/lib/rubygems/commands/check_command.rb +30 -27
- data/lib/rubygems/commands/cleanup_command.rb +57 -40
- data/lib/rubygems/commands/contents_command.rb +37 -39
- data/lib/rubygems/commands/dependency_command.rb +53 -65
- data/lib/rubygems/commands/environment_command.rb +32 -16
- data/lib/rubygems/commands/exec_command.rb +249 -0
- data/lib/rubygems/commands/fetch_command.rb +36 -19
- data/lib/rubygems/commands/generate_index_command.rb +40 -74
- data/lib/rubygems/commands/help_command.rb +22 -22
- data/lib/rubygems/commands/info_command.rb +38 -0
- data/lib/rubygems/commands/install_command.rb +67 -143
- data/lib/rubygems/commands/list_command.rb +10 -9
- data/lib/rubygems/commands/lock_command.rb +12 -14
- data/lib/rubygems/commands/mirror_command.rb +4 -4
- data/lib/rubygems/commands/open_command.rb +28 -26
- data/lib/rubygems/commands/outdated_command.rb +6 -6
- data/lib/rubygems/commands/owner_command.rb +51 -27
- data/lib/rubygems/commands/pristine_command.rb +99 -71
- data/lib/rubygems/commands/push_command.rb +53 -46
- data/lib/rubygems/commands/query_command.rb +21 -328
- data/lib/rubygems/commands/rdoc_command.rb +33 -33
- data/lib/rubygems/commands/search_command.rb +9 -9
- data/lib/rubygems/commands/server_command.rb +15 -76
- data/lib/rubygems/commands/setup_command.rb +370 -186
- data/lib/rubygems/commands/signin_command.rb +34 -0
- data/lib/rubygems/commands/signout_command.rb +32 -0
- data/lib/rubygems/commands/sources_command.rb +57 -41
- data/lib/rubygems/commands/specification_command.rb +38 -28
- data/lib/rubygems/commands/stale_command.rb +6 -5
- data/lib/rubygems/commands/uninstall_command.rb +96 -62
- data/lib/rubygems/commands/unpack_command.rb +44 -53
- data/lib/rubygems/commands/update_command.rb +155 -99
- data/lib/rubygems/commands/which_command.rb +14 -17
- data/lib/rubygems/commands/yank_command.rb +28 -32
- data/lib/rubygems/compatibility.rb +13 -32
- data/lib/rubygems/config_file.rb +214 -119
- data/lib/rubygems/core_ext/kernel_gem.rb +10 -16
- data/lib/rubygems/core_ext/kernel_require.rb +92 -90
- data/lib/rubygems/core_ext/kernel_warn.rb +49 -0
- data/lib/rubygems/core_ext/tcpsocket_init.rb +54 -0
- data/lib/rubygems/defaults.rb +184 -54
- data/lib/rubygems/dependency.rb +75 -62
- data/lib/rubygems/dependency_installer.rb +74 -230
- data/lib/rubygems/dependency_list.rb +32 -33
- data/lib/rubygems/deprecate.rb +113 -17
- data/lib/rubygems/doctor.rb +31 -31
- data/lib/rubygems/errors.rb +51 -13
- data/lib/rubygems/exceptions.rb +65 -35
- data/lib/rubygems/ext/build_error.rb +3 -1
- data/lib/rubygems/ext/builder.rb +103 -77
- data/lib/rubygems/ext/cargo_builder/link_flag_converter.rb +27 -0
- data/lib/rubygems/ext/cargo_builder.rb +360 -0
- data/lib/rubygems/ext/cmake_builder.rb +6 -7
- data/lib/rubygems/ext/configure_builder.rb +6 -9
- data/lib/rubygems/ext/ext_conf_builder.rb +40 -61
- data/lib/rubygems/ext/rake_builder.rb +18 -21
- data/lib/rubygems/ext.rb +8 -7
- data/lib/rubygems/gem_runner.rb +19 -21
- data/lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb +163 -0
- data/lib/rubygems/gemcutter_utilities/webauthn_listener.rb +105 -0
- data/lib/rubygems/gemcutter_utilities/webauthn_poller.rb +78 -0
- data/lib/rubygems/gemcutter_utilities.rb +246 -43
- data/lib/rubygems/install_default_message.rb +3 -3
- data/lib/rubygems/install_message.rb +3 -3
- data/lib/rubygems/install_update_options.rb +104 -98
- data/lib/rubygems/installer.rb +407 -225
- data/lib/rubygems/installer_uninstaller_utils.rb +27 -0
- data/lib/rubygems/local_remote_options.rb +29 -32
- data/lib/rubygems/name_tuple.rb +18 -23
- data/lib/rubygems/net/http.rb +3 -0
- data/lib/rubygems/net-http/LICENSE.txt +22 -0
- data/lib/rubygems/net-http/lib/net/http/backward.rb +40 -0
- data/lib/rubygems/net-http/lib/net/http/exceptions.rb +34 -0
- data/lib/rubygems/net-http/lib/net/http/generic_request.rb +414 -0
- data/lib/rubygems/net-http/lib/net/http/header.rb +981 -0
- data/lib/rubygems/net-http/lib/net/http/proxy_delta.rb +17 -0
- data/lib/rubygems/net-http/lib/net/http/request.rb +88 -0
- data/lib/rubygems/net-http/lib/net/http/requests.rb +425 -0
- data/lib/rubygems/net-http/lib/net/http/response.rb +738 -0
- data/lib/rubygems/net-http/lib/net/http/responses.rb +1174 -0
- data/lib/rubygems/net-http/lib/net/http/status.rb +84 -0
- data/lib/rubygems/net-http/lib/net/http.rb +2496 -0
- data/lib/rubygems/net-http/lib/net/https.rb +23 -0
- data/lib/rubygems/net-protocol/LICENSE.txt +22 -0
- data/lib/rubygems/net-protocol/lib/net/protocol.rb +544 -0
- data/lib/rubygems/openssl.rb +7 -0
- data/lib/rubygems/optparse/.document +1 -0
- data/lib/rubygems/optparse/COPYING +56 -0
- data/lib/rubygems/optparse/lib/optionparser.rb +2 -0
- data/lib/rubygems/optparse/lib/optparse/ac.rb +54 -0
- data/lib/rubygems/optparse/lib/optparse/date.rb +18 -0
- data/lib/rubygems/optparse/lib/optparse/kwargs.rb +22 -0
- data/lib/rubygems/optparse/lib/optparse/shellwords.rb +7 -0
- data/lib/rubygems/optparse/lib/optparse/time.rb +11 -0
- data/lib/rubygems/optparse/lib/optparse/uri.rb +7 -0
- data/lib/rubygems/optparse/lib/optparse/version.rb +71 -0
- data/lib/rubygems/optparse/lib/optparse.rb +2330 -0
- data/lib/rubygems/optparse.rb +3 -0
- data/lib/rubygems/package/digest_io.rb +5 -7
- data/lib/rubygems/package/file_source.rb +6 -8
- data/lib/rubygems/package/io_source.rb +6 -4
- data/lib/rubygems/package/old.rb +19 -28
- data/lib/rubygems/package/source.rb +1 -1
- data/lib/rubygems/package/tar_header.rb +114 -93
- data/lib/rubygems/package/tar_reader/entry.rb +116 -22
- data/lib/rubygems/package/tar_reader.rb +18 -40
- data/lib/rubygems/package/tar_writer.rb +42 -56
- data/lib/rubygems/package.rb +245 -145
- data/lib/rubygems/package_task.rb +8 -14
- data/lib/rubygems/path_support.rb +21 -16
- data/lib/rubygems/platform.rb +135 -74
- data/lib/rubygems/psych_tree.rb +3 -2
- data/lib/rubygems/query_utils.rb +349 -0
- data/lib/rubygems/rdoc.rb +4 -326
- data/lib/rubygems/remote_fetcher.rb +99 -181
- data/lib/rubygems/request/connection_pools.rb +31 -24
- data/lib/rubygems/request/http_pool.rb +6 -7
- data/lib/rubygems/request/https_pool.rb +2 -3
- data/lib/rubygems/request.rb +103 -53
- data/lib/rubygems/request_set/gem_dependency_api.rb +182 -190
- data/lib/rubygems/request_set/lockfile/parser.rb +42 -52
- data/lib/rubygems/request_set/lockfile/tokenizer.rb +34 -24
- data/lib/rubygems/request_set/lockfile.rb +32 -35
- data/lib/rubygems/request_set.rb +115 -71
- data/lib/rubygems/requirement.rb +77 -68
- data/lib/rubygems/resolv/LICENSE.txt +22 -0
- data/lib/rubygems/resolv/lib/resolv.rb +3387 -0
- data/lib/rubygems/resolver/activation_request.rb +34 -61
- data/lib/rubygems/resolver/api_set/gem_parser.rb +24 -0
- data/lib/rubygems/resolver/api_set.rb +40 -32
- data/lib/rubygems/resolver/api_specification.rb +37 -18
- data/lib/rubygems/resolver/best_set.rb +15 -17
- data/lib/rubygems/resolver/composed_set.rb +9 -11
- data/lib/rubygems/resolver/conflict.rb +19 -33
- data/lib/rubygems/resolver/current_set.rb +2 -4
- data/lib/rubygems/resolver/dependency_request.rb +8 -9
- data/lib/rubygems/resolver/git_set.rb +8 -10
- data/lib/rubygems/resolver/git_specification.rb +11 -13
- data/lib/rubygems/resolver/index_set.rb +13 -15
- data/lib/rubygems/resolver/index_specification.rb +42 -11
- data/lib/rubygems/resolver/installed_specification.rb +9 -11
- data/lib/rubygems/resolver/installer_set.rb +87 -45
- data/lib/rubygems/resolver/local_specification.rb +5 -7
- data/lib/rubygems/resolver/lock_set.rb +13 -15
- data/lib/rubygems/resolver/lock_specification.rb +13 -15
- data/lib/rubygems/resolver/molinillo/LICENSE +9 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb +57 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb +88 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb +36 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +66 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +62 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +63 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +61 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb +126 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb +46 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb +36 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb +164 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +110 -146
- data/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +83 -9
- data/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +2 -1
- data/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb +13 -1
- data/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb +3 -1
- data/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb +552 -172
- data/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb +3 -2
- data/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb +12 -6
- data/lib/rubygems/resolver/molinillo/lib/molinillo.rb +6 -5
- data/lib/rubygems/resolver/molinillo.rb +2 -1
- data/lib/rubygems/resolver/requirement_list.rb +2 -2
- data/lib/rubygems/resolver/set.rb +3 -5
- data/lib/rubygems/resolver/source_set.rb +6 -7
- data/lib/rubygems/resolver/spec_specification.rb +16 -4
- data/lib/rubygems/resolver/specification.rb +25 -10
- data/lib/rubygems/resolver/stats.rb +1 -0
- data/lib/rubygems/resolver/vendor_set.rb +6 -8
- data/lib/rubygems/resolver/vendor_specification.rb +6 -8
- data/lib/rubygems/resolver.rb +121 -72
- data/lib/rubygems/s3_uri_signer.rb +177 -0
- data/lib/rubygems/safe_marshal/elements.rb +138 -0
- data/lib/rubygems/safe_marshal/reader.rb +306 -0
- data/lib/rubygems/safe_marshal/visitors/stream_printer.rb +31 -0
- data/lib/rubygems/safe_marshal/visitors/to_ruby.rb +385 -0
- data/lib/rubygems/safe_marshal/visitors/visitor.rb +74 -0
- data/lib/rubygems/safe_marshal.rb +74 -0
- data/lib/rubygems/safe_yaml.rb +36 -0
- data/lib/rubygems/security/policies.rb +49 -51
- data/lib/rubygems/security/policy.rb +46 -53
- data/lib/rubygems/security/signer.rb +86 -29
- data/lib/rubygems/security/trust_dir.rb +22 -24
- data/lib/rubygems/security.rb +101 -82
- data/lib/rubygems/security_option.rb +43 -0
- data/lib/rubygems/shellwords.rb +3 -0
- data/lib/rubygems/source/git.rb +40 -42
- data/lib/rubygems/source/installed.rb +5 -9
- data/lib/rubygems/source/local.rb +30 -33
- data/lib/rubygems/source/lock.rb +10 -10
- data/lib/rubygems/source/specific_file.rb +7 -9
- data/lib/rubygems/source/vendor.rb +3 -7
- data/lib/rubygems/source.rb +78 -68
- data/lib/rubygems/source_list.rb +11 -15
- data/lib/rubygems/spec_fetcher.rb +71 -83
- data/lib/rubygems/specification.rb +833 -1115
- data/lib/rubygems/specification_policy.rb +538 -0
- data/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA.pem +21 -0
- data/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem +21 -0
- data/lib/rubygems/stub_specification.rb +55 -57
- data/lib/rubygems/text.rb +39 -27
- data/lib/rubygems/timeout/LICENSE.txt +22 -0
- data/lib/rubygems/timeout/lib/timeout.rb +199 -0
- data/lib/rubygems/timeout.rb +3 -0
- data/lib/rubygems/tsort/.document +1 -0
- data/lib/rubygems/tsort/LICENSE.txt +22 -0
- data/lib/rubygems/tsort/lib/tsort.rb +455 -0
- data/lib/rubygems/tsort.rb +3 -0
- data/lib/rubygems/uninstaller.rb +150 -87
- data/lib/rubygems/unknown_command_spell_checker.rb +21 -0
- data/lib/rubygems/update_suggestion.rb +56 -0
- data/lib/rubygems/uri.rb +126 -0
- data/lib/rubygems/uri_formatter.rb +4 -7
- data/lib/rubygems/user_interaction.rb +92 -146
- data/lib/rubygems/util/licenses.rb +712 -317
- data/lib/rubygems/util/list.rb +5 -2
- data/lib/rubygems/util.rb +58 -75
- data/lib/rubygems/validator.rb +26 -48
- data/lib/rubygems/version.rb +106 -56
- data/lib/rubygems/version_option.rb +22 -14
- data/lib/rubygems/yaml_serializer.rb +93 -0
- data/lib/rubygems.rb +427 -361
- data/rubygems-update.gemspec +38 -0
- data/setup.rb +13 -27
- metadata +500 -363
- data/.autotest +0 -71
- data/.document +0 -5
- data/.travis.yml +0 -46
- data/CONTRIBUTING.rdoc +0 -129
- data/CVE-2013-4287.txt +0 -35
- data/CVE-2013-4363.txt +0 -45
- data/CVE-2015-3900.txt +0 -40
- data/History.txt +0 -3105
- data/MAINTAINERS.md +0 -5
- data/POLICIES.rdoc +0 -61
- data/README.rdoc +0 -54
- data/Rakefile +0 -449
- data/UPGRADING.rdoc +0 -92
- data/appveyor.yml +0 -36
- data/bin/gem +0 -25
- data/bin/update_rubygems +0 -37
- data/lib/gauntlet_rubygems.rb +0 -51
- data/lib/rubygems/indexer.rb +0 -434
- data/lib/rubygems/installer_test_case.rb +0 -194
- data/lib/rubygems/mock_gem_ui.rb +0 -89
- data/lib/rubygems/package/tar_test_case.rb +0 -147
- data/lib/rubygems/psych_additions.rb +0 -10
- data/lib/rubygems/server.rb +0 -869
- data/lib/rubygems/source_local.rb +0 -6
- data/lib/rubygems/source_specific_file.rb +0 -5
- data/lib/rubygems/ssl_certs/AddTrustExternalCARoot-2048.pem +0 -25
- data/lib/rubygems/ssl_certs/AddTrustExternalCARoot.pem +0 -32
- data/lib/rubygems/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +0 -14
- data/lib/rubygems/ssl_certs/DigiCertHighAssuranceEVRootCA.pem +0 -23
- data/lib/rubygems/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +0 -28
- data/lib/rubygems/ssl_certs/GeoTrustGlobalCA.pem +0 -20
- data/lib/rubygems/syck_hack.rb +0 -77
- data/lib/rubygems/test_case.rb +0 -1496
- data/lib/rubygems/test_utilities.rb +0 -384
- data/lib/ubygems.rb +0 -11
- data/test/rubygems/alternate_cert.pem +0 -18
- data/test/rubygems/alternate_cert_32.pem +0 -18
- data/test/rubygems/alternate_key.pem +0 -27
- data/test/rubygems/bad_rake.rb +0 -2
- data/test/rubygems/ca_cert.pem +0 -68
- data/test/rubygems/child_cert.pem +0 -18
- data/test/rubygems/child_cert_32.pem +0 -18
- data/test/rubygems/child_key.pem +0 -27
- data/test/rubygems/client.pem +0 -49
- data/test/rubygems/data/gem-private_key.pem +0 -27
- data/test/rubygems/data/gem-public_cert.pem +0 -20
- data/test/rubygems/data/null-type.gemspec.rz +0 -0
- data/test/rubygems/encrypted_private_key.pem +0 -30
- data/test/rubygems/expired_cert.pem +0 -18
- data/test/rubygems/fake_certlib/openssl.rb +0 -8
- data/test/rubygems/fix_openssl_warnings.rb +0 -13
- data/test/rubygems/foo/discover.rb +0 -1
- data/test/rubygems/future_cert.pem +0 -18
- data/test/rubygems/future_cert_32.pem +0 -18
- data/test/rubygems/good_rake.rb +0 -2
- data/test/rubygems/grandchild_cert.pem +0 -18
- data/test/rubygems/grandchild_cert_32.pem +0 -18
- data/test/rubygems/grandchild_key.pem +0 -27
- data/test/rubygems/invalid_client.pem +0 -49
- data/test/rubygems/invalid_issuer_cert.pem +0 -18
- data/test/rubygems/invalid_issuer_cert_32.pem +0 -18
- data/test/rubygems/invalid_key.pem +0 -27
- data/test/rubygems/invalid_signer_cert.pem +0 -18
- data/test/rubygems/invalid_signer_cert_32.pem +0 -18
- data/test/rubygems/invalidchild_cert.pem +0 -18
- data/test/rubygems/invalidchild_cert_32.pem +0 -18
- data/test/rubygems/invalidchild_key.pem +0 -27
- data/test/rubygems/plugin/exception/rubygems_plugin.rb +0 -3
- data/test/rubygems/plugin/load/rubygems_plugin.rb +0 -4
- data/test/rubygems/plugin/standarderror/rubygems_plugin.rb +0 -3
- data/test/rubygems/private_key.pem +0 -27
- data/test/rubygems/public_cert.pem +0 -18
- data/test/rubygems/public_cert_32.pem +0 -18
- data/test/rubygems/public_key.pem +0 -9
- data/test/rubygems/rubygems/commands/crash_command.rb +0 -6
- data/test/rubygems/rubygems_plugin.rb +0 -22
- data/test/rubygems/sff/discover.rb +0 -1
- data/test/rubygems/simple_gem.rb +0 -67
- data/test/rubygems/specifications/bar-0.0.2.gemspec +0 -9
- data/test/rubygems/specifications/foo-0.0.1-x86-mswin32.gemspec +0 -0
- data/test/rubygems/ssl_cert.pem +0 -19
- data/test/rubygems/ssl_key.pem +0 -15
- data/test/rubygems/test_bundled_ca.rb +0 -59
- data/test/rubygems/test_config.rb +0 -24
- data/test/rubygems/test_deprecate.rb +0 -77
- data/test/rubygems/test_gem.rb +0 -1718
- data/test/rubygems/test_gem_available_set.rb +0 -130
- data/test/rubygems/test_gem_command.rb +0 -248
- data/test/rubygems/test_gem_command_manager.rb +0 -264
- data/test/rubygems/test_gem_commands_build_command.rb +0 -121
- data/test/rubygems/test_gem_commands_cert_command.rb +0 -671
- data/test/rubygems/test_gem_commands_check_command.rb +0 -69
- data/test/rubygems/test_gem_commands_cleanup_command.rb +0 -197
- data/test/rubygems/test_gem_commands_contents_command.rb +0 -240
- data/test/rubygems/test_gem_commands_dependency_command.rb +0 -230
- data/test/rubygems/test_gem_commands_environment_command.rb +0 -154
- data/test/rubygems/test_gem_commands_fetch_command.rb +0 -127
- data/test/rubygems/test_gem_commands_generate_index_command.rb +0 -51
- data/test/rubygems/test_gem_commands_help_command.rb +0 -75
- data/test/rubygems/test_gem_commands_install_command.rb +0 -1007
- data/test/rubygems/test_gem_commands_list_command.rb +0 -34
- data/test/rubygems/test_gem_commands_lock_command.rb +0 -69
- data/test/rubygems/test_gem_commands_mirror.rb +0 -20
- data/test/rubygems/test_gem_commands_open_command.rb +0 -70
- data/test/rubygems/test_gem_commands_outdated_command.rb +0 -33
- data/test/rubygems/test_gem_commands_owner_command.rb +0 -205
- data/test/rubygems/test_gem_commands_pristine_command.rb +0 -491
- data/test/rubygems/test_gem_commands_push_command.rb +0 -330
- data/test/rubygems/test_gem_commands_query_command.rb +0 -657
- data/test/rubygems/test_gem_commands_search_command.rb +0 -18
- data/test/rubygems/test_gem_commands_server_command.rb +0 -60
- data/test/rubygems/test_gem_commands_setup_command.rb +0 -136
- data/test/rubygems/test_gem_commands_sources_command.rb +0 -249
- data/test/rubygems/test_gem_commands_specification_command.rb +0 -251
- data/test/rubygems/test_gem_commands_stale_command.rb +0 -43
- data/test/rubygems/test_gem_commands_uninstall_command.rb +0 -283
- data/test/rubygems/test_gem_commands_unpack_command.rb +0 -209
- data/test/rubygems/test_gem_commands_update_command.rb +0 -514
- data/test/rubygems/test_gem_commands_which_command.rb +0 -87
- data/test/rubygems/test_gem_commands_yank_command.rb +0 -100
- data/test/rubygems/test_gem_config_file.rb +0 -491
- data/test/rubygems/test_gem_dependency.rb +0 -362
- data/test/rubygems/test_gem_dependency_installer.rb +0 -1235
- data/test/rubygems/test_gem_dependency_list.rb +0 -260
- data/test/rubygems/test_gem_dependency_resolution_error.rb +0 -29
- data/test/rubygems/test_gem_doctor.rb +0 -169
- data/test/rubygems/test_gem_ext_builder.rb +0 -341
- data/test/rubygems/test_gem_ext_cmake_builder.rb +0 -87
- data/test/rubygems/test_gem_ext_configure_builder.rb +0 -87
- data/test/rubygems/test_gem_ext_ext_conf_builder.rb +0 -211
- data/test/rubygems/test_gem_ext_rake_builder.rb +0 -65
- data/test/rubygems/test_gem_gem_runner.rb +0 -69
- data/test/rubygems/test_gem_gemcutter_utilities.rb +0 -235
- data/test/rubygems/test_gem_impossible_dependencies_error.rb +0 -62
- data/test/rubygems/test_gem_indexer.rb +0 -367
- data/test/rubygems/test_gem_install_update_options.rb +0 -197
- data/test/rubygems/test_gem_installer.rb +0 -1552
- data/test/rubygems/test_gem_local_remote_options.rb +0 -134
- data/test/rubygems/test_gem_name_tuple.rb +0 -45
- data/test/rubygems/test_gem_package.rb +0 -876
- data/test/rubygems/test_gem_package_old.rb +0 -90
- data/test/rubygems/test_gem_package_tar_header.rb +0 -147
- data/test/rubygems/test_gem_package_tar_reader.rb +0 -90
- data/test/rubygems/test_gem_package_tar_reader_entry.rb +0 -142
- data/test/rubygems/test_gem_package_tar_writer.rb +0 -264
- data/test/rubygems/test_gem_package_task.rb +0 -84
- data/test/rubygems/test_gem_path_support.rb +0 -121
- data/test/rubygems/test_gem_platform.rb +0 -308
- data/test/rubygems/test_gem_rdoc.rb +0 -270
- data/test/rubygems/test_gem_remote_fetcher.rb +0 -1051
- data/test/rubygems/test_gem_request.rb +0 -363
- data/test/rubygems/test_gem_request_connection_pools.rb +0 -130
- data/test/rubygems/test_gem_request_set.rb +0 -595
- data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +0 -831
- data/test/rubygems/test_gem_request_set_lockfile.rb +0 -470
- data/test/rubygems/test_gem_request_set_lockfile_parser.rb +0 -549
- data/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +0 -306
- data/test/rubygems/test_gem_requirement.rb +0 -387
- data/test/rubygems/test_gem_resolver.rb +0 -715
- data/test/rubygems/test_gem_resolver_activation_request.rb +0 -74
- data/test/rubygems/test_gem_resolver_api_set.rb +0 -209
- data/test/rubygems/test_gem_resolver_api_specification.rb +0 -145
- data/test/rubygems/test_gem_resolver_best_set.rb +0 -138
- data/test/rubygems/test_gem_resolver_composed_set.rb +0 -46
- data/test/rubygems/test_gem_resolver_conflict.rb +0 -88
- data/test/rubygems/test_gem_resolver_dependency_request.rb +0 -85
- data/test/rubygems/test_gem_resolver_git_set.rb +0 -190
- data/test/rubygems/test_gem_resolver_git_specification.rb +0 -114
- data/test/rubygems/test_gem_resolver_index_set.rb +0 -90
- data/test/rubygems/test_gem_resolver_index_specification.rb +0 -90
- data/test/rubygems/test_gem_resolver_installed_specification.rb +0 -50
- data/test/rubygems/test_gem_resolver_installer_set.rb +0 -258
- data/test/rubygems/test_gem_resolver_local_specification.rb +0 -46
- data/test/rubygems/test_gem_resolver_lock_set.rb +0 -64
- data/test/rubygems/test_gem_resolver_lock_specification.rb +0 -100
- data/test/rubygems/test_gem_resolver_requirement_list.rb +0 -21
- data/test/rubygems/test_gem_resolver_specification.rb +0 -65
- data/test/rubygems/test_gem_resolver_vendor_set.rb +0 -84
- data/test/rubygems/test_gem_resolver_vendor_specification.rb +0 -84
- data/test/rubygems/test_gem_security.rb +0 -307
- data/test/rubygems/test_gem_security_policy.rb +0 -541
- data/test/rubygems/test_gem_security_signer.rb +0 -209
- data/test/rubygems/test_gem_security_trust_dir.rb +0 -101
- data/test/rubygems/test_gem_server.rb +0 -409
- data/test/rubygems/test_gem_silent_ui.rb +0 -117
- data/test/rubygems/test_gem_source.rb +0 -242
- data/test/rubygems/test_gem_source_fetch_problem.rb +0 -20
- data/test/rubygems/test_gem_source_git.rb +0 -309
- data/test/rubygems/test_gem_source_installed.rb +0 -37
- data/test/rubygems/test_gem_source_list.rb +0 -118
- data/test/rubygems/test_gem_source_local.rb +0 -107
- data/test/rubygems/test_gem_source_lock.rb +0 -115
- data/test/rubygems/test_gem_source_specific_file.rb +0 -76
- data/test/rubygems/test_gem_source_vendor.rb +0 -32
- data/test/rubygems/test_gem_spec_fetcher.rb +0 -311
- data/test/rubygems/test_gem_specification.rb +0 -3519
- data/test/rubygems/test_gem_stream_ui.rb +0 -239
- data/test/rubygems/test_gem_stub_specification.rb +0 -217
- data/test/rubygems/test_gem_text.rb +0 -77
- data/test/rubygems/test_gem_uninstaller.rb +0 -485
- data/test/rubygems/test_gem_unsatisfiable_dependency_error.rb +0 -33
- data/test/rubygems/test_gem_uri_formatter.rb +0 -29
- data/test/rubygems/test_gem_util.rb +0 -40
- data/test/rubygems/test_gem_validator.rb +0 -46
- data/test/rubygems/test_gem_version.rb +0 -222
- data/test/rubygems/test_gem_version_option.rb +0 -152
- data/test/rubygems/test_kernel.rb +0 -86
- data/test/rubygems/test_require.rb +0 -322
- data/test/rubygems/wrong_key_cert.pem +0 -18
- data/test/rubygems/wrong_key_cert_32.pem +0 -18
- data/util/CL2notes +0 -56
- data/util/create_certs.rb +0 -157
- data/util/create_encrypted_key.rb +0 -17
- data/util/generate_spdx_license_list.rb +0 -51
- 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
|