rubygems-update 3.0.3 → 3.4.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5633 -0
- data/CODE_OF_CONDUCT.md +62 -24
- data/CONTRIBUTING.md +111 -21
- data/MAINTAINERS.txt +1 -6
- data/Manifest.txt +216 -101
- data/POLICIES.md +70 -27
- data/README.md +40 -19
- data/UPGRADING.md +5 -81
- data/bin/gem +2 -16
- data/bin/update_rubygems +5 -5
- data/bundler/CHANGELOG.md +2698 -1256
- data/bundler/LICENSE.md +18 -19
- data/bundler/README.md +10 -14
- data/bundler/UPGRADING.md +222 -0
- data/bundler/bundler.gemspec +13 -33
- data/bundler/exe/bundle +26 -11
- data/bundler/exe/bundler +1 -1
- data/bundler/lib/bundler/.document +1 -0
- data/bundler/lib/bundler/build_metadata.rb +5 -13
- data/bundler/lib/bundler/capistrano.rb +4 -4
- data/bundler/lib/bundler/cli/add.rb +28 -16
- data/bundler/lib/bundler/cli/binstubs.rb +11 -3
- data/bundler/lib/bundler/cli/cache.rb +24 -17
- data/bundler/lib/bundler/cli/check.rb +5 -3
- data/bundler/lib/bundler/cli/clean.rb +1 -1
- data/bundler/lib/bundler/cli/common.rb +41 -13
- data/bundler/lib/bundler/cli/config.rb +170 -86
- data/bundler/lib/bundler/cli/console.rb +3 -3
- data/bundler/lib/bundler/cli/doctor.rb +27 -10
- data/bundler/lib/bundler/cli/exec.rb +8 -25
- data/bundler/lib/bundler/cli/fund.rb +36 -0
- data/bundler/lib/bundler/cli/gem.rb +261 -48
- data/bundler/lib/bundler/cli/info.rb +52 -8
- data/bundler/lib/bundler/cli/init.rb +7 -3
- data/bundler/lib/bundler/cli/inject.rb +1 -1
- data/bundler/lib/bundler/cli/install.rb +38 -66
- data/bundler/lib/bundler/cli/issue.rb +8 -7
- data/bundler/lib/bundler/cli/list.rb +19 -11
- data/bundler/lib/bundler/cli/lock.rb +11 -4
- data/bundler/lib/bundler/cli/open.rb +14 -9
- data/bundler/lib/bundler/cli/outdated.rb +152 -121
- data/bundler/lib/bundler/cli/platform.rb +2 -2
- data/bundler/lib/bundler/cli/plugin.rb +19 -2
- data/bundler/lib/bundler/cli/pristine.rb +6 -1
- data/bundler/lib/bundler/cli/remove.rb +1 -2
- data/bundler/lib/bundler/cli/show.rb +3 -3
- data/bundler/lib/bundler/cli/update.rb +49 -18
- data/bundler/lib/bundler/cli/viz.rb +1 -1
- data/bundler/lib/bundler/cli.rb +269 -165
- data/bundler/lib/bundler/compact_index_client/cache.rb +7 -24
- data/bundler/lib/bundler/compact_index_client/gem_parser.rb +28 -0
- data/bundler/lib/bundler/compact_index_client/updater.rb +58 -57
- data/bundler/lib/bundler/compact_index_client.rb +28 -18
- data/bundler/lib/bundler/constants.rb +1 -1
- data/bundler/lib/bundler/current_ruby.rb +26 -11
- data/bundler/lib/bundler/definition.rb +371 -441
- data/bundler/lib/bundler/dependency.rb +29 -71
- data/bundler/lib/bundler/deployment.rb +1 -1
- data/bundler/lib/bundler/digest.rb +71 -0
- data/bundler/lib/bundler/dsl.rb +84 -116
- data/bundler/lib/bundler/endpoint_specification.rb +16 -14
- data/bundler/lib/bundler/env.rb +10 -15
- data/bundler/lib/bundler/environment_preserver.rb +32 -5
- data/bundler/lib/bundler/errors.rb +31 -14
- data/bundler/lib/bundler/feature_flag.rb +13 -33
- data/bundler/lib/bundler/fetcher/base.rb +7 -9
- data/bundler/lib/bundler/fetcher/compact_index.rb +46 -39
- data/bundler/lib/bundler/fetcher/dependency.rb +3 -7
- data/bundler/lib/bundler/fetcher/downloader.rb +15 -12
- data/bundler/lib/bundler/fetcher/index.rb +4 -30
- data/bundler/lib/bundler/fetcher.rb +40 -42
- data/bundler/lib/bundler/force_platform.rb +18 -0
- data/bundler/lib/bundler/friendly_errors.rb +49 -54
- data/bundler/lib/bundler/gem_helper.rb +79 -43
- data/bundler/lib/bundler/gem_helpers.rb +44 -28
- data/bundler/lib/bundler/gem_tasks.rb +1 -1
- data/bundler/lib/bundler/gem_version_promoter.rb +54 -99
- data/bundler/lib/bundler/graph.rb +5 -5
- data/bundler/lib/bundler/index.rb +16 -54
- data/bundler/lib/bundler/injector.rb +51 -17
- data/bundler/lib/bundler/inline.rb +28 -29
- data/bundler/lib/bundler/installer/gem_installer.rb +22 -23
- data/bundler/lib/bundler/installer/parallel_installer.rb +38 -51
- data/bundler/lib/bundler/installer/standalone.rb +62 -12
- data/bundler/lib/bundler/installer.rb +46 -97
- data/bundler/lib/bundler/lazy_specification.rb +88 -52
- data/bundler/lib/bundler/lockfile_generator.rb +4 -4
- data/bundler/lib/bundler/lockfile_parser.rb +40 -72
- data/bundler/{man → lib/bundler/man}/bundle-add.1 +29 -5
- data/bundler/{man/bundle-add.ronn → lib/bundler/man/bundle-add.1.ronn} +22 -4
- data/bundler/{man → lib/bundler/man}/bundle-binstubs.1 +6 -4
- data/bundler/{man/bundle-binstubs.ronn → lib/bundler/man/bundle-binstubs.1.ronn} +3 -5
- data/bundler/lib/bundler/man/bundle-cache.1 +61 -0
- data/bundler/{man/bundle-package.ronn → lib/bundler/man/bundle-cache.1.ronn} +22 -15
- data/bundler/{man → lib/bundler/man}/bundle-check.1 +1 -1
- data/bundler/{man → lib/bundler/man}/bundle-clean.1 +2 -2
- data/bundler/{man/bundle-clean.ronn → lib/bundler/man/bundle-clean.1.ronn} +1 -1
- data/bundler/{man → lib/bundler/man}/bundle-config.1 +78 -60
- data/bundler/{man/bundle-config.ronn → lib/bundler/man/bundle-config.1.ronn} +96 -85
- data/bundler/lib/bundler/man/bundle-console.1 +53 -0
- data/bundler/lib/bundler/man/bundle-console.1.ronn +44 -0
- data/bundler/{man → lib/bundler/man}/bundle-doctor.1 +1 -1
- data/bundler/{man → lib/bundler/man}/bundle-exec.1 +6 -6
- data/bundler/{man/bundle-exec.ronn → lib/bundler/man/bundle-exec.1.ronn} +6 -6
- data/bundler/lib/bundler/man/bundle-gem.1 +105 -0
- data/bundler/lib/bundler/man/bundle-gem.1.ronn +117 -0
- data/bundler/lib/bundler/man/bundle-help.1 +13 -0
- data/bundler/lib/bundler/man/bundle-help.1.ronn +12 -0
- data/bundler/{man → lib/bundler/man}/bundle-info.1 +1 -1
- data/bundler/{man → lib/bundler/man}/bundle-init.1 +6 -2
- data/bundler/{man/bundle-init.ronn → lib/bundler/man/bundle-init.1.ronn} +3 -1
- data/bundler/{man → lib/bundler/man}/bundle-inject.1 +5 -2
- data/bundler/{man/bundle-inject.ronn → lib/bundler/man/bundle-inject.1.ronn} +3 -1
- data/bundler/{man → lib/bundler/man}/bundle-install.1 +42 -37
- data/bundler/{man/bundle-install.ronn → lib/bundler/man/bundle-install.1.ronn} +42 -38
- data/bundler/{man → lib/bundler/man}/bundle-list.1 +7 -7
- data/bundler/{man/bundle-list.ronn → lib/bundler/man/bundle-list.1.ronn} +6 -6
- data/bundler/{man → lib/bundler/man}/bundle-lock.1 +1 -1
- data/bundler/{man → lib/bundler/man}/bundle-open.1 +22 -2
- data/bundler/{man/bundle-open.ronn → lib/bundler/man/bundle-open.1.ronn} +9 -1
- data/bundler/{man → lib/bundler/man}/bundle-outdated.1 +3 -10
- data/bundler/{man/bundle-outdated.ronn → lib/bundler/man/bundle-outdated.1.ronn} +1 -10
- data/bundler/{man → lib/bundler/man}/bundle-platform.1 +16 -6
- data/bundler/{man/bundle-platform.ronn → lib/bundler/man/bundle-platform.1.ronn} +14 -7
- data/bundler/lib/bundler/man/bundle-plugin.1 +81 -0
- data/bundler/lib/bundler/man/bundle-plugin.1.ronn +59 -0
- data/bundler/{man → lib/bundler/man}/bundle-pristine.1 +1 -1
- data/bundler/{man → lib/bundler/man}/bundle-remove.1 +1 -1
- data/bundler/{man → lib/bundler/man}/bundle-show.1 +1 -1
- data/bundler/{man → lib/bundler/man}/bundle-update.1 +8 -8
- data/bundler/{man/bundle-update.ronn → lib/bundler/man/bundle-update.1.ronn} +8 -7
- data/bundler/lib/bundler/man/bundle-version.1 +35 -0
- data/bundler/lib/bundler/man/bundle-version.1.ronn +24 -0
- data/bundler/{man → lib/bundler/man}/bundle-viz.1 +4 -1
- data/bundler/{man/bundle-viz.ronn → lib/bundler/man/bundle-viz.1.ronn} +2 -0
- data/bundler/{man → lib/bundler/man}/bundle.1 +17 -12
- data/bundler/{man/bundle.ronn → lib/bundler/man/bundle.1.ronn} +14 -9
- data/bundler/lib/bundler/man/gemfile.5 +723 -0
- data/bundler/{man → lib/bundler/man}/gemfile.5.ronn +112 -95
- data/bundler/lib/bundler/man/index.txt +29 -0
- data/bundler/lib/bundler/match_metadata.rb +13 -0
- data/bundler/lib/bundler/match_platform.rb +1 -2
- data/bundler/lib/bundler/match_remote_metadata.rb +29 -0
- data/bundler/lib/bundler/mirror.rb +10 -12
- data/bundler/lib/bundler/plugin/api/source.rb +29 -15
- data/bundler/lib/bundler/plugin/api.rb +1 -1
- data/bundler/lib/bundler/plugin/dsl.rb +1 -1
- data/bundler/lib/bundler/plugin/index.rb +31 -8
- data/bundler/lib/bundler/plugin/installer/git.rb +0 -4
- data/bundler/lib/bundler/plugin/installer/rubygems.rb +1 -9
- data/bundler/lib/bundler/plugin/installer.rb +40 -24
- data/bundler/lib/bundler/plugin/source_list.rb +5 -1
- data/bundler/lib/bundler/plugin.rb +103 -43
- data/bundler/lib/bundler/process_lock.rb +1 -1
- data/bundler/lib/bundler/remote_specification.rb +12 -9
- 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 +72 -0
- data/bundler/lib/bundler/resolver/root.rb +25 -0
- data/bundler/lib/bundler/resolver/spec_group.rb +49 -73
- data/bundler/lib/bundler/resolver.rb +341 -301
- data/bundler/lib/bundler/retry.rb +4 -4
- data/bundler/lib/bundler/ruby_dsl.rb +1 -1
- data/bundler/lib/bundler/ruby_version.rb +10 -38
- data/bundler/lib/bundler/rubygems_ext.rb +237 -92
- data/bundler/lib/bundler/rubygems_gem_installer.rb +87 -21
- data/bundler/lib/bundler/rubygems_integration.rb +179 -515
- data/bundler/lib/bundler/runtime.rb +25 -40
- data/bundler/lib/bundler/self_manager.rb +168 -0
- data/bundler/lib/bundler/settings.rb +163 -119
- data/bundler/lib/bundler/setup.rb +14 -12
- data/bundler/lib/bundler/shared_helpers.rb +62 -103
- data/bundler/lib/bundler/similarity_detector.rb +3 -3
- data/bundler/lib/bundler/source/git/git_proxy.rb +274 -128
- data/bundler/lib/bundler/source/git.rb +86 -62
- data/bundler/lib/bundler/source/metadata.rb +9 -9
- data/bundler/lib/bundler/source/path/installer.rb +11 -32
- data/bundler/lib/bundler/source/path.rb +29 -18
- data/bundler/lib/bundler/source/rubygems/remote.rb +3 -4
- data/bundler/lib/bundler/source/rubygems.rb +176 -206
- data/bundler/lib/bundler/source/rubygems_aggregate.rb +68 -0
- data/bundler/lib/bundler/source.rb +30 -10
- data/bundler/lib/bundler/source_list.rb +112 -67
- data/bundler/lib/bundler/source_map.rb +71 -0
- data/bundler/lib/bundler/spec_set.rb +96 -72
- data/bundler/lib/bundler/stub_specification.rb +45 -37
- data/bundler/lib/bundler/templates/Executable +3 -5
- data/bundler/lib/bundler/templates/Executable.bundler +22 -18
- data/bundler/lib/bundler/templates/Executable.standalone +4 -4
- data/bundler/lib/bundler/templates/Gemfile +0 -2
- data/bundler/lib/bundler/templates/newgem/CHANGELOG.md.tt +5 -0
- data/bundler/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +57 -47
- data/bundler/lib/bundler/templates/newgem/Cargo.toml.tt +7 -0
- data/bundler/lib/bundler/templates/newgem/Gemfile.tt +22 -2
- data/bundler/lib/bundler/templates/newgem/README.md.tt +13 -15
- data/bundler/lib/bundler/templates/newgem/Rakefile.tt +43 -5
- data/bundler/lib/bundler/templates/newgem/bin/console.tt +1 -4
- data/bundler/lib/bundler/templates/newgem/circleci/config.yml.tt +25 -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 +1 -1
- 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 +3 -0
- data/bundler/lib/bundler/templates/newgem/gitlab-ci.yml.tt +18 -0
- data/bundler/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +2 -0
- data/bundler/lib/bundler/templates/newgem/lib/newgem.rb.tt +4 -2
- data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +36 -41
- 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 +2 -0
- data/bundler/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +2 -1
- 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/{newgem_test.rb.tt → minitest/test_newgem.rb.tt} +3 -1
- 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 +1 -1
- data/bundler/lib/bundler/ui/shell.rb +39 -20
- data/bundler/lib/bundler/ui/silent.rb +21 -5
- data/bundler/lib/bundler/ui.rb +3 -3
- data/bundler/lib/bundler/uri_credentials_filter.rb +10 -4
- 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 +128 -0
- data/bundler/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
- data/bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb +1493 -425
- 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 +40 -0
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +53 -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 +302 -462
- 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 +243 -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 +1 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +3 -2
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +7 -17
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +25 -14
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +20 -10
- data/bundler/lib/bundler/vendor/thor/lib/thor/actions.rb +34 -15
- data/bundler/lib/bundler/vendor/thor/lib/thor/base.rb +63 -43
- data/bundler/lib/bundler/vendor/thor/lib/thor/command.rb +21 -14
- data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/error.rb +83 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/group.rb +3 -3
- data/bundler/lib/bundler/vendor/thor/lib/thor/invocation.rb +1 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +1 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +6 -6
- data/bundler/lib/bundler/vendor/thor/lib/thor/line_editor.rb +2 -2
- data/bundler/lib/bundler/vendor/thor/lib/thor/nested_context.rb +29 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +7 -3
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/option.rb +20 -7
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser/options.rb +40 -6
- data/bundler/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -4
- data/bundler/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +1 -0
- data/bundler/lib/bundler/vendor/thor/lib/thor/runner.rb +15 -14
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +88 -13
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/color.rb +10 -2
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell/html.rb +3 -3
- data/bundler/lib/bundler/vendor/thor/lib/thor/shell.rb +5 -5
- data/bundler/lib/bundler/vendor/thor/lib/thor/util.rb +18 -2
- data/bundler/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
- data/bundler/lib/bundler/vendor/thor/lib/thor.rb +16 -9
- data/bundler/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
- data/bundler/lib/bundler/vendor/tsort/lib/tsort.rb +452 -0
- data/bundler/lib/bundler/vendor/uri/LICENSE.txt +22 -0
- data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +729 -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 +1587 -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 +119 -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 +1 -6
- data/bundler/lib/bundler/vendored_persistent.rb +2 -39
- data/bundler/lib/bundler/{vendored_molinillo.rb → vendored_pub_grub.rb} +1 -1
- data/bundler/lib/bundler/vendored_thor.rb +2 -2
- data/bundler/lib/bundler/vendored_tsort.rb +4 -0
- data/bundler/lib/bundler/vendored_uri.rb +4 -0
- data/bundler/lib/bundler/version.rb +5 -20
- data/bundler/lib/bundler/vlad.rb +2 -2
- data/bundler/lib/bundler/worker.rb +26 -15
- data/bundler/lib/bundler/yaml_serializer.rb +3 -4
- data/bundler/lib/bundler.rb +290 -187
- data/hide_lib_for_update/note.txt +0 -4
- data/lib/rubygems/available_set.rb +7 -8
- data/lib/rubygems/basic_specification.rb +44 -31
- data/lib/rubygems/bundler_version_finder.rb +29 -51
- data/lib/rubygems/command.rb +114 -52
- data/lib/rubygems/command_manager.rb +38 -18
- data/lib/rubygems/commands/build_command.rb +77 -26
- data/lib/rubygems/commands/cert_command.rb +78 -76
- data/lib/rubygems/commands/check_command.rb +20 -22
- data/lib/rubygems/commands/cleanup_command.rb +36 -32
- data/lib/rubygems/commands/contents_command.rb +16 -18
- data/lib/rubygems/commands/dependency_command.rb +39 -50
- data/lib/rubygems/commands/environment_command.rb +11 -13
- data/lib/rubygems/commands/exec_command.rb +248 -0
- data/lib/rubygems/commands/fetch_command.rb +33 -16
- data/lib/rubygems/commands/generate_index_command.rb +18 -17
- data/lib/rubygems/commands/help_command.rb +10 -10
- data/lib/rubygems/commands/info_command.rb +11 -6
- data/lib/rubygems/commands/install_command.rb +45 -79
- data/lib/rubygems/commands/list_command.rb +9 -8
- data/lib/rubygems/commands/lock_command.rb +7 -9
- data/lib/rubygems/commands/mirror_command.rb +3 -4
- data/lib/rubygems/commands/open_command.rb +11 -14
- data/lib/rubygems/commands/outdated_command.rb +5 -6
- data/lib/rubygems/commands/owner_command.rb +33 -24
- data/lib/rubygems/commands/pristine_command.rb +70 -51
- data/lib/rubygems/commands/push_command.rb +26 -63
- data/lib/rubygems/commands/query_command.rb +21 -337
- data/lib/rubygems/commands/rdoc_command.rb +26 -26
- data/lib/rubygems/commands/search_command.rb +8 -8
- data/lib/rubygems/commands/server_command.rb +16 -77
- data/lib/rubygems/commands/setup_command.rb +282 -241
- data/lib/rubygems/commands/signin_command.rb +9 -10
- data/lib/rubygems/commands/signout_command.rb +7 -9
- data/lib/rubygems/commands/sources_command.rb +42 -26
- data/lib/rubygems/commands/specification_command.rb +25 -20
- data/lib/rubygems/commands/stale_command.rb +3 -3
- data/lib/rubygems/commands/uninstall_command.rb +61 -49
- data/lib/rubygems/commands/unpack_command.rb +15 -44
- data/lib/rubygems/commands/update_command.rb +133 -81
- data/lib/rubygems/commands/which_command.rb +8 -11
- data/lib/rubygems/commands/yank_command.rb +22 -19
- data/lib/rubygems/compatibility.rb +7 -5
- data/lib/rubygems/config_file.rb +101 -47
- data/lib/rubygems/core_ext/kernel_gem.rb +8 -12
- data/lib/rubygems/core_ext/kernel_require.rb +115 -84
- data/lib/rubygems/core_ext/kernel_warn.rb +35 -30
- data/lib/rubygems/core_ext/tcpsocket_init.rb +52 -0
- data/lib/rubygems/defaults.rb +132 -56
- data/lib/rubygems/dependency.rb +44 -27
- data/lib/rubygems/dependency_installer.rb +49 -205
- data/lib/rubygems/dependency_list.rb +24 -25
- data/lib/rubygems/deprecate.rb +106 -12
- data/lib/rubygems/doctor.rb +22 -22
- data/lib/rubygems/errors.rb +8 -14
- data/lib/rubygems/exceptions.rb +45 -33
- data/lib/rubygems/ext/build_error.rb +2 -0
- data/lib/rubygems/ext/builder.rb +86 -93
- 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 +5 -8
- data/lib/rubygems/ext/ext_conf_builder.rb +44 -65
- data/lib/rubygems/ext/rake_builder.rb +7 -10
- data/lib/rubygems/ext.rb +7 -6
- data/lib/rubygems/gem_runner.rb +15 -26
- data/lib/rubygems/gemcutter_utilities.rb +221 -54
- data/lib/rubygems/indexer.rb +38 -53
- data/lib/rubygems/install_default_message.rb +2 -2
- data/lib/rubygems/install_message.rb +2 -2
- data/lib/rubygems/install_update_options.rb +73 -64
- data/lib/rubygems/installer.rb +231 -174
- data/lib/rubygems/installer_uninstaller_utils.rb +29 -0
- data/lib/rubygems/local_remote_options.rb +22 -24
- data/lib/rubygems/mock_gem_ui.rb +2 -5
- data/lib/rubygems/name_tuple.rb +10 -14
- 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 +2308 -0
- data/lib/rubygems/optparse.rb +3 -0
- data/lib/rubygems/package/digest_io.rb +0 -2
- data/lib/rubygems/package/file_source.rb +2 -4
- data/lib/rubygems/package/io_source.rb +4 -2
- data/lib/rubygems/package/old.rb +9 -11
- data/lib/rubygems/package/tar_header.rb +73 -66
- data/lib/rubygems/package/tar_reader/entry.rb +89 -11
- data/lib/rubygems/package/tar_reader.rb +1 -26
- data/lib/rubygems/package/tar_writer.rb +12 -22
- data/lib/rubygems/package.rb +142 -125
- data/lib/rubygems/package_task.rb +5 -11
- data/lib/rubygems/path_support.rb +3 -8
- data/lib/rubygems/platform.rb +113 -73
- data/lib/rubygems/psych_tree.rb +1 -1
- data/lib/rubygems/query_utils.rb +351 -0
- data/lib/rubygems/rdoc.rb +4 -16
- data/lib/rubygems/remote_fetcher.rb +64 -136
- data/lib/rubygems/request/connection_pools.rb +7 -11
- data/lib/rubygems/request/http_pool.rb +2 -3
- data/lib/rubygems/request.rb +31 -32
- data/lib/rubygems/request_set/gem_dependency_api.rb +134 -136
- data/lib/rubygems/request_set/lockfile/parser.rb +28 -28
- data/lib/rubygems/request_set/lockfile/tokenizer.rb +5 -5
- data/lib/rubygems/request_set/lockfile.rb +21 -20
- data/lib/rubygems/request_set.rb +32 -45
- data/lib/rubygems/requirement.rb +43 -65
- data/lib/rubygems/resolver/activation_request.rb +29 -53
- data/lib/rubygems/resolver/api_set/gem_parser.rb +20 -0
- data/lib/rubygems/resolver/api_set.rb +33 -26
- data/lib/rubygems/resolver/api_specification.rb +30 -16
- data/lib/rubygems/resolver/best_set.rb +9 -11
- data/lib/rubygems/resolver/composed_set.rb +3 -5
- data/lib/rubygems/resolver/conflict.rb +12 -19
- data/lib/rubygems/resolver/current_set.rb +0 -2
- data/lib/rubygems/resolver/dependency_request.rb +3 -5
- data/lib/rubygems/resolver/git_set.rb +2 -4
- data/lib/rubygems/resolver/git_specification.rb +6 -8
- data/lib/rubygems/resolver/index_set.rb +4 -6
- data/lib/rubygems/resolver/index_specification.rb +38 -7
- data/lib/rubygems/resolver/installed_specification.rb +4 -6
- data/lib/rubygems/resolver/installer_set.rb +69 -27
- data/lib/rubygems/resolver/local_specification.rb +2 -4
- data/lib/rubygems/resolver/lock_set.rb +7 -9
- data/lib/rubygems/resolver/lock_specification.rb +6 -8
- data/lib/rubygems/resolver/molinillo/LICENSE +9 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb +7 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb +8 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb +1 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +2 -1
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +2 -1
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +2 -1
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +2 -1
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb +7 -6
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb +2 -1
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb +4 -3
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb +51 -12
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +42 -9
- data/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +82 -8
- 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 +510 -165
- data/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb +3 -2
- data/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb +8 -4
- data/lib/rubygems/resolver/molinillo/lib/molinillo.rb +6 -5
- data/lib/rubygems/resolver/molinillo.rb +1 -1
- data/lib/rubygems/resolver/requirement_list.rb +0 -1
- data/lib/rubygems/resolver/set.rb +0 -3
- data/lib/rubygems/resolver/source_set.rb +0 -2
- data/lib/rubygems/resolver/spec_specification.rb +14 -2
- data/lib/rubygems/resolver/specification.rb +14 -3
- data/lib/rubygems/resolver/stats.rb +1 -1
- data/lib/rubygems/resolver/vendor_set.rb +1 -3
- data/lib/rubygems/resolver/vendor_specification.rb +3 -5
- data/lib/rubygems/resolver.rb +58 -54
- data/lib/rubygems/s3_uri_signer.rb +175 -0
- data/lib/rubygems/safe_yaml.rb +14 -16
- data/lib/rubygems/security/policies.rb +47 -47
- data/lib/rubygems/security/policy.rb +25 -29
- data/lib/rubygems/security/signer.rb +16 -18
- data/lib/rubygems/security/trust_dir.rb +5 -6
- data/lib/rubygems/security.rb +90 -69
- data/lib/rubygems/security_option.rb +7 -8
- data/lib/rubygems/source/git.rb +31 -31
- data/lib/rubygems/source/installed.rb +1 -3
- data/lib/rubygems/source/local.rb +4 -6
- data/lib/rubygems/source/lock.rb +0 -2
- data/lib/rubygems/source/specific_file.rb +1 -3
- data/lib/rubygems/source/vendor.rb +0 -2
- data/lib/rubygems/source.rb +50 -38
- data/lib/rubygems/source_list.rb +9 -13
- data/lib/rubygems/spec_fetcher.rb +52 -64
- data/lib/rubygems/specification.rb +444 -465
- data/lib/rubygems/specification_policy.rb +185 -87
- data/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem +21 -0
- data/lib/rubygems/stub_specification.rb +28 -32
- data/lib/rubygems/text.rb +22 -22
- data/lib/rubygems/tsort/.document +1 -0
- data/lib/rubygems/tsort/LICENSE.txt +22 -0
- data/lib/rubygems/tsort/lib/tsort.rb +452 -0
- data/lib/rubygems/tsort.rb +3 -0
- data/lib/rubygems/uninstaller.rb +110 -57
- data/lib/rubygems/unknown_command_spell_checker.rb +21 -0
- data/lib/rubygems/update_suggestion.rb +69 -0
- data/lib/rubygems/uri.rb +126 -0
- data/lib/rubygems/uri_formatter.rb +2 -4
- data/lib/rubygems/user_interaction.rb +46 -49
- data/lib/rubygems/util/licenses.rb +511 -404
- data/lib/rubygems/util.rb +40 -56
- data/lib/rubygems/validator.rb +15 -37
- data/lib/rubygems/version.rb +50 -31
- data/lib/rubygems/version_option.rb +11 -5
- data/lib/rubygems/webauthn_listener/response.rb +161 -0
- data/lib/rubygems/webauthn_listener.rb +92 -0
- data/lib/rubygems.rb +307 -334
- data/rubygems-update.gemspec +6 -13
- data/setup.rb +11 -22
- data/test/rubygems/alternate_cert.pem +14 -14
- data/test/rubygems/alternate_cert_32.pem +15 -15
- data/test/rubygems/alternate_key.pem +25 -25
- data/test/rubygems/bundler_test_gem.rb +419 -0
- data/test/rubygems/ca_cert.pem +74 -65
- data/test/rubygems/child_cert.pem +15 -16
- data/test/rubygems/child_cert_32.pem +15 -16
- data/test/rubygems/child_key.pem +25 -25
- data/test/rubygems/client.pem +103 -45
- data/test/rubygems/data/excon-0.7.7.gemspec.rz +0 -0
- data/test/rubygems/data/null-required-ruby-version.gemspec.rz +0 -0
- data/test/rubygems/data/null-required-rubygems-version.gemspec.rz +0 -0
- data/test/rubygems/data/pry-0.4.7.gemspec.rz +0 -0
- data/test/rubygems/encrypted_private_key.pem +26 -26
- data/test/rubygems/expired_cert.pem +15 -15
- data/test/rubygems/future_cert.pem +15 -15
- data/test/rubygems/future_cert_32.pem +15 -15
- data/test/rubygems/grandchild_cert.pem +15 -16
- data/test/rubygems/grandchild_cert_32.pem +15 -16
- data/test/rubygems/grandchild_key.pem +25 -25
- data/{lib/rubygems/test_case.rb → test/rubygems/helper.rb} +518 -507
- data/{lib → test}/rubygems/installer_test_case.rb +115 -53
- data/test/rubygems/invalid_issuer_cert.pem +16 -16
- data/test/rubygems/invalid_issuer_cert_32.pem +16 -16
- data/test/rubygems/invalid_key.pem +25 -25
- data/test/rubygems/invalid_signer_cert.pem +15 -15
- data/test/rubygems/invalid_signer_cert_32.pem +15 -15
- data/test/rubygems/invalidchild_cert.pem +15 -16
- data/test/rubygems/invalidchild_cert_32.pem +15 -16
- data/test/rubygems/invalidchild_key.pem +25 -25
- data/{lib → test}/rubygems/package/tar_test_case.rb +51 -18
- data/test/rubygems/packages/Bluebie-legs-0.6.2.gem +0 -0
- data/test/rubygems/packages/ascii_binder-0.1.10.1.gem +0 -0
- data/test/rubygems/packages/ill-formatted-platform-1.0.0.10.gem +0 -0
- data/test/rubygems/plugin/exception/rubygems_plugin.rb +1 -1
- data/test/rubygems/plugin/standarderror/rubygems_plugin.rb +1 -1
- data/test/rubygems/private_ec_key.pem +9 -0
- data/test/rubygems/private_key.pem +25 -25
- data/test/rubygems/public_cert.pem +16 -16
- data/test/rubygems/public_cert_32.pem +15 -15
- data/test/rubygems/public_key.pem +7 -7
- data/test/rubygems/rubygems/commands/crash_command.rb +0 -2
- data/test/rubygems/rubygems_plugin.rb +2 -4
- data/test/rubygems/simple_gem.rb +1 -1
- data/test/rubygems/specifications/bar-0.0.2.gemspec +0 -2
- data/test/rubygems/specifications/rubyforge-0.0.1.gemspec +12 -0
- data/test/rubygems/ssl_cert.pem +78 -17
- data/test/rubygems/ssl_key.pem +25 -13
- data/test/rubygems/test_bundled_ca.rb +44 -47
- data/test/rubygems/test_config.rb +6 -8
- data/test/rubygems/test_deprecate.rb +91 -11
- data/test/rubygems/test_exit.rb +17 -0
- data/test/rubygems/test_gem.rb +701 -878
- data/test/rubygems/test_gem_available_set.rb +24 -25
- data/test/rubygems/test_gem_bundler_version_finder.rb +42 -42
- data/test/rubygems/test_gem_command.rb +186 -39
- data/test/rubygems/test_gem_command_manager.rb +166 -36
- data/test/rubygems/test_gem_commands_build_command.rb +436 -52
- data/test/rubygems/test_gem_commands_cert_command.rb +193 -124
- data/test/rubygems/test_gem_commands_check_command.rb +9 -11
- data/test/rubygems/test_gem_commands_cleanup_command.rb +87 -62
- data/test/rubygems/test_gem_commands_contents_command.rb +73 -42
- data/test/rubygems/test_gem_commands_dependency_command.rb +39 -41
- data/test/rubygems/test_gem_commands_environment_command.rb +60 -48
- data/test/rubygems/test_gem_commands_exec_command.rb +851 -0
- data/test/rubygems/test_gem_commands_fetch_command.rb +163 -32
- data/test/rubygems/test_gem_commands_generate_index_command.rb +39 -9
- data/test/rubygems/test_gem_commands_help_command.rb +34 -19
- data/test/rubygems/test_gem_commands_info_command.rb +34 -9
- data/test/rubygems/test_gem_commands_install_command.rb +601 -174
- data/test/rubygems/test_gem_commands_list_command.rb +5 -7
- data/test/rubygems/test_gem_commands_lock_command.rb +11 -13
- data/test/rubygems/test_gem_commands_mirror.rb +3 -4
- data/test/rubygems/test_gem_commands_open_command.rb +16 -19
- data/test/rubygems/test_gem_commands_outdated_command.rb +24 -7
- data/test/rubygems/test_gem_commands_owner_command.rb +250 -49
- data/test/rubygems/test_gem_commands_pristine_command.rb +270 -89
- data/test/rubygems/test_gem_commands_push_command.rb +251 -69
- data/test/rubygems/test_gem_commands_query_command.rb +114 -89
- data/test/rubygems/test_gem_commands_search_command.rb +2 -4
- data/test/rubygems/test_gem_commands_server_command.rb +6 -46
- data/test/rubygems/test_gem_commands_setup_command.rb +334 -157
- data/test/rubygems/test_gem_commands_signin_command.rb +187 -27
- data/test/rubygems/test_gem_commands_signout_command.rb +3 -10
- data/test/rubygems/test_gem_commands_sources_command.rb +266 -33
- data/test/rubygems/test_gem_commands_specification_command.rb +81 -55
- data/test/rubygems/test_gem_commands_stale_command.rb +4 -6
- data/test/rubygems/test_gem_commands_uninstall_command.rb +251 -99
- data/test/rubygems/test_gem_commands_unpack_command.rb +32 -34
- data/test/rubygems/test_gem_commands_update_command.rb +412 -102
- data/test/rubygems/test_gem_commands_which_command.rb +12 -14
- data/test/rubygems/test_gem_commands_yank_command.rb +191 -26
- data/test/rubygems/test_gem_config_file.rb +120 -96
- data/test/rubygems/test_gem_dependency.rb +94 -86
- data/test/rubygems/test_gem_dependency_installer.rb +305 -388
- data/test/rubygems/test_gem_dependency_list.rb +66 -61
- data/test/rubygems/test_gem_dependency_resolution_error.rb +5 -7
- data/test/rubygems/test_gem_doctor.rb +73 -47
- data/test/rubygems/test_gem_ext_builder.rb +116 -108
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/.gitignore +1 -0
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec +8 -0
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock +233 -0
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml +10 -0
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/src/lib.rs +27 -0
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb +1 -0
- data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/.gitignore +1 -0
- data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +247 -0
- data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +10 -0
- data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec +8 -0
- data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs +51 -0
- data/test/rubygems/test_gem_ext_cargo_builder.rb +167 -0
- data/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb +33 -0
- data/test/rubygems/test_gem_ext_cargo_builder_unit.rb +60 -0
- data/test/rubygems/test_gem_ext_cmake_builder.rb +32 -37
- data/test/rubygems/test_gem_ext_configure_builder.rb +23 -31
- data/test/rubygems/test_gem_ext_ext_conf_builder.rb +75 -79
- data/test/rubygems/test_gem_ext_rake_builder.rb +49 -30
- data/test/rubygems/test_gem_gem_runner.rb +58 -8
- data/test/rubygems/test_gem_gemcutter_utilities.rb +159 -76
- data/test/rubygems/test_gem_impossible_dependencies_error.rb +4 -6
- data/test/rubygems/test_gem_indexer.rb +120 -105
- data/test/rubygems/test_gem_install_update_options.rb +57 -33
- data/test/rubygems/test_gem_installer.rb +1230 -644
- data/test/rubygems/test_gem_local_remote_options.rb +11 -13
- data/test/rubygems/test_gem_name_tuple.rb +4 -6
- data/test/rubygems/test_gem_package.rb +390 -285
- data/test/rubygems/test_gem_package_old.rb +57 -56
- data/test/rubygems/test_gem_package_tar_header.rb +108 -50
- data/test/rubygems/test_gem_package_tar_reader.rb +54 -9
- data/test/rubygems/test_gem_package_tar_reader_entry.rb +168 -24
- data/test/rubygems/test_gem_package_tar_writer.rb +107 -101
- data/test/rubygems/test_gem_package_task.rb +58 -25
- data/test/rubygems/test_gem_path_support.rb +29 -29
- data/test/rubygems/test_gem_platform.rb +388 -199
- data/test/rubygems/test_gem_rdoc.rb +20 -155
- data/test/rubygems/test_gem_remote_fetcher.rb +475 -304
- data/test/rubygems/test_gem_request.rb +128 -85
- data/test/rubygems/test_gem_request_connection_pools.rb +32 -32
- data/test/rubygems/test_gem_request_set.rb +186 -110
- data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +283 -264
- data/test/rubygems/test_gem_request_set_lockfile.rb +93 -94
- data/test/rubygems/test_gem_request_set_lockfile_parser.rb +69 -70
- data/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +136 -136
- data/test/rubygems/test_gem_requirement.rb +140 -55
- data/test/rubygems/test_gem_resolver.rb +224 -115
- data/test/rubygems/test_gem_resolver_activation_request.rb +9 -40
- data/test/rubygems/test_gem_resolver_api_set.rb +79 -78
- data/test/rubygems/test_gem_resolver_api_specification.rb +47 -49
- data/test/rubygems/test_gem_resolver_best_set.rb +43 -22
- data/test/rubygems/test_gem_resolver_composed_set.rb +1 -3
- data/test/rubygems/test_gem_resolver_conflict.rb +12 -18
- data/test/rubygems/test_gem_resolver_dependency_request.rb +15 -17
- data/test/rubygems/test_gem_resolver_git_set.rb +22 -24
- data/test/rubygems/test_gem_resolver_git_specification.rb +22 -22
- data/test/rubygems/test_gem_resolver_index_set.rb +14 -16
- data/test/rubygems/test_gem_resolver_index_specification.rb +21 -18
- data/test/rubygems/test_gem_resolver_installed_specification.rb +5 -8
- data/test/rubygems/test_gem_resolver_installer_set.rb +106 -44
- data/test/rubygems/test_gem_resolver_local_specification.rb +7 -9
- data/test/rubygems/test_gem_resolver_lock_set.rb +15 -17
- data/test/rubygems/test_gem_resolver_lock_specification.rb +17 -19
- data/test/rubygems/test_gem_resolver_requirement_list.rb +1 -3
- data/test/rubygems/test_gem_resolver_specification.rb +8 -10
- data/test/rubygems/test_gem_resolver_vendor_set.rb +9 -11
- data/test/rubygems/test_gem_resolver_vendor_specification.rb +10 -12
- data/test/rubygems/test_gem_security.rb +109 -79
- data/test/rubygems/test_gem_security_policy.rb +102 -107
- data/test/rubygems/test_gem_security_signer.rb +51 -52
- data/test/rubygems/test_gem_security_trust_dir.rb +14 -16
- data/test/rubygems/test_gem_silent_ui.rb +47 -42
- data/test/rubygems/test_gem_source.rb +66 -51
- data/test/rubygems/test_gem_source_fetch_problem.rb +17 -8
- data/test/rubygems/test_gem_source_git.rb +78 -77
- data/test/rubygems/test_gem_source_installed.rb +16 -18
- data/test/rubygems/test_gem_source_list.rb +5 -5
- data/test/rubygems/test_gem_source_local.rb +15 -16
- data/test/rubygems/test_gem_source_lock.rb +31 -33
- data/test/rubygems/test_gem_source_specific_file.rb +18 -19
- data/test/rubygems/test_gem_source_subpath_problem.rb +49 -0
- data/test/rubygems/test_gem_source_vendor.rb +13 -15
- data/test/rubygems/test_gem_spec_fetcher.rb +74 -67
- data/test/rubygems/test_gem_specification.rb +1070 -1073
- data/test/rubygems/test_gem_stream_ui.rb +25 -23
- data/test/rubygems/test_gem_stub_specification.rb +39 -56
- data/test/rubygems/test_gem_text.rb +8 -3
- data/test/rubygems/test_gem_uninstaller.rb +269 -100
- data/test/rubygems/test_gem_unsatisfiable_dependency_error.rb +3 -5
- data/test/rubygems/test_gem_update_suggestion.rb +208 -0
- data/test/rubygems/test_gem_uri.rb +39 -0
- data/test/rubygems/test_gem_uri_formatter.rb +14 -16
- data/test/rubygems/test_gem_util.rb +46 -34
- data/test/rubygems/test_gem_validator.rb +12 -15
- data/test/rubygems/test_gem_version.rb +50 -35
- data/test/rubygems/test_gem_version_option.rb +16 -18
- data/test/rubygems/test_kernel.rb +61 -61
- data/test/rubygems/test_project_sanity.rb +49 -0
- data/test/rubygems/test_remote_fetch_error.rb +8 -9
- data/test/rubygems/test_require.rb +415 -121
- data/test/rubygems/test_rubygems.rb +74 -0
- data/test/rubygems/test_webauthn_listener.rb +120 -0
- data/test/rubygems/test_webauthn_listener_response.rb +93 -0
- data/{lib/rubygems/test_utilities.rb → test/rubygems/utilities.rb} +115 -51
- data/test/rubygems/wrong_key_cert.pem +15 -15
- data/test/rubygems/wrong_key_cert_32.pem +15 -15
- data/test/test_changelog_generator.rb +17 -0
- metadata +225 -244
- data/.rubocop.yml +0 -66
- data/.travis.yml +0 -38
- data/History.txt +0 -3965
- data/Rakefile +0 -372
- data/appveyor.yml +0 -43
- data/bundler/CODE_OF_CONDUCT.md +0 -42
- data/bundler/CONTRIBUTING.md +0 -17
- data/bundler/exe/bundle_ruby +0 -60
- data/bundler/lib/bundler/cli/package.rb +0 -49
- data/bundler/lib/bundler/compatibility_guard.rb +0 -14
- data/bundler/lib/bundler/dep_proxy.rb +0 -48
- data/bundler/lib/bundler/gem_remote_fetcher.rb +0 -43
- data/bundler/lib/bundler/gemdeps.rb +0 -29
- data/bundler/lib/bundler/psyched_yaml.rb +0 -37
- data/bundler/lib/bundler/ssl_certs/certificate_manager.rb +0 -66
- data/bundler/lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +0 -23
- data/bundler/lib/bundler/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +0 -25
- data/bundler/lib/bundler/templates/gems.rb +0 -8
- data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +0 -3
- data/bundler/lib/bundler/templates/newgem/test/test_helper.rb.tt +0 -4
- data/bundler/lib/bundler/templates/newgem/travis.yml.tt +0 -7
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +0 -26
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +0 -81
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +0 -36
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +0 -66
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +0 -62
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +0 -63
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +0 -61
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +0 -126
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +0 -46
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +0 -36
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +0 -136
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +0 -223
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +0 -143
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +0 -6
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +0 -101
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +0 -67
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +0 -837
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +0 -46
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +0 -58
- data/bundler/lib/bundler/vendor/molinillo/lib/molinillo.rb +0 -12
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb +0 -27
- data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb +0 -129
- data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +0 -12
- data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +0 -129
- data/bundler/lib/bundler/version_ranges.rb +0 -76
- data/bundler/man/bundle-gem.1 +0 -80
- data/bundler/man/bundle-gem.ronn +0 -78
- data/bundler/man/bundle-package.1 +0 -55
- data/lib/rubygems/psych_additions.rb +0 -10
- data/lib/rubygems/server.rb +0 -878
- data/lib/rubygems/source_local.rb +0 -7
- data/lib/rubygems/source_specific_file.rb +0 -6
- data/lib/rubygems/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem +0 -21
- data/lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +0 -23
- data/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +0 -25
- data/lib/rubygems/syck_hack.rb +0 -77
- data/lib/ubygems.rb +0 -14
- data/test/rubygems/bogussources.rb +0 -9
- data/test/rubygems/data/null-type.gemspec.rz +0 -0
- data/test/rubygems/test_gem_server.rb +0 -607
- data/util/CL2notes +0 -55
- data/util/ci +0 -77
- data/util/create_certs.rb +0 -171
- data/util/create_encrypted_key.rb +0 -16
- data/util/generate_spdx_license_list.rb +0 -61
- data/util/patch_with_prs.rb +0 -77
- data/util/rubocop +0 -8
- data/util/update_bundled_ca_certificates.rb +0 -139
- data/util/update_changelog.rb +0 -67
- /data/bundler/lib/bundler/{ssl_certs → man}/.document +0 -0
- /data/bundler/{man/bundle-check.ronn → lib/bundler/man/bundle-check.1.ronn} +0 -0
- /data/bundler/{man/bundle-doctor.ronn → lib/bundler/man/bundle-doctor.1.ronn} +0 -0
- /data/bundler/{man/bundle-info.ronn → lib/bundler/man/bundle-info.1.ronn} +0 -0
- /data/bundler/{man/bundle-lock.ronn → lib/bundler/man/bundle-lock.1.ronn} +0 -0
- /data/bundler/{man/bundle-pristine.ronn → lib/bundler/man/bundle-pristine.1.ronn} +0 -0
- /data/bundler/{man/bundle-remove.ronn → lib/bundler/man/bundle-remove.1.ronn} +0 -0
- /data/bundler/{man/bundle-show.ronn → lib/bundler/man/bundle-show.1.ronn} +0 -0
- /data/{bundler/lib/bundler/ssl_certs/index.rubygems.org → lib/rubygems/ssl_certs/rubygems.org}/GlobalSignRootCA.pem +0 -0
@@ -1,91 +1,186 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rbconfig'
|
5
|
+
rescue LoadError
|
6
|
+
# for make mjit-headers
|
7
|
+
end
|
8
|
+
|
9
|
+
# Namespace for file utility methods for copying, moving, removing, etc.
|
2
10
|
#
|
3
|
-
#
|
11
|
+
# == What's Here
|
4
12
|
#
|
5
|
-
#
|
13
|
+
# First, what’s elsewhere. \Module \Bundler::FileUtils:
|
6
14
|
#
|
7
|
-
#
|
8
|
-
#
|
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).
|
9
18
|
#
|
10
|
-
#
|
19
|
+
# Here, module \Bundler::FileUtils provides methods that are useful for:
|
11
20
|
#
|
12
|
-
#
|
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].
|
13
29
|
#
|
14
|
-
# ===
|
30
|
+
# === Creating
|
15
31
|
#
|
16
|
-
#
|
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
|
17
40
|
#
|
18
|
-
#
|
19
|
-
# Bundler::FileUtils.cd(dir, options) {|dir| block }
|
20
|
-
# Bundler::FileUtils.pwd()
|
21
|
-
# Bundler::FileUtils.mkdir(dir, options)
|
22
|
-
# Bundler::FileUtils.mkdir(list, options)
|
23
|
-
# Bundler::FileUtils.mkdir_p(dir, options)
|
24
|
-
# Bundler::FileUtils.mkdir_p(list, options)
|
25
|
-
# Bundler::FileUtils.rmdir(dir, options)
|
26
|
-
# Bundler::FileUtils.rmdir(list, options)
|
27
|
-
# Bundler::FileUtils.ln(target, link, options)
|
28
|
-
# Bundler::FileUtils.ln(targets, dir, options)
|
29
|
-
# Bundler::FileUtils.ln_s(target, link, options)
|
30
|
-
# Bundler::FileUtils.ln_s(targets, dir, options)
|
31
|
-
# Bundler::FileUtils.ln_sf(target, link, options)
|
32
|
-
# Bundler::FileUtils.cp(src, dest, options)
|
33
|
-
# Bundler::FileUtils.cp(list, dir, options)
|
34
|
-
# Bundler::FileUtils.cp_r(src, dest, options)
|
35
|
-
# Bundler::FileUtils.cp_r(list, dir, options)
|
36
|
-
# Bundler::FileUtils.mv(src, dest, options)
|
37
|
-
# Bundler::FileUtils.mv(list, dir, options)
|
38
|
-
# Bundler::FileUtils.rm(list, options)
|
39
|
-
# Bundler::FileUtils.rm_r(list, options)
|
40
|
-
# Bundler::FileUtils.rm_rf(list, options)
|
41
|
-
# Bundler::FileUtils.install(src, dest, options)
|
42
|
-
# Bundler::FileUtils.chmod(mode, list, options)
|
43
|
-
# Bundler::FileUtils.chmod_R(mode, list, options)
|
44
|
-
# Bundler::FileUtils.chown(user, group, list, options)
|
45
|
-
# Bundler::FileUtils.chown_R(user, group, list, options)
|
46
|
-
# Bundler::FileUtils.touch(list, options)
|
41
|
+
# === Deleting
|
47
42
|
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
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
52
|
#
|
53
|
-
#
|
54
|
-
# either one file or a list of files in that argument. See the method
|
55
|
-
# documentation for examples.
|
53
|
+
# === Querying
|
56
54
|
#
|
57
|
-
#
|
55
|
+
# - ::pwd, ::getwd: Returns the path to the working directory.
|
56
|
+
# - ::uptodate?: Returns whether a given entry is newer than given other entries.
|
58
57
|
#
|
59
|
-
#
|
60
|
-
# Bundler::FileUtils.copy_file(src, dest, preserve = false, dereference = true)
|
61
|
-
# Bundler::FileUtils.copy_stream(srcstream, deststream)
|
62
|
-
# Bundler::FileUtils.remove_entry(path, force = false)
|
63
|
-
# Bundler::FileUtils.remove_entry_secure(path, force = false)
|
64
|
-
# Bundler::FileUtils.remove_file(path, force = false)
|
65
|
-
# Bundler::FileUtils.compare_file(path_a, path_b)
|
66
|
-
# Bundler::FileUtils.compare_stream(stream_a, stream_b)
|
67
|
-
# Bundler::FileUtils.uptodate?(file, cmp_list)
|
58
|
+
# === Setting
|
68
59
|
#
|
69
|
-
#
|
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.
|
70
67
|
#
|
71
|
-
#
|
72
|
-
# before acting. This equates to passing the <tt>:verbose</tt> flag to methods
|
73
|
-
# in Bundler::FileUtils.
|
68
|
+
# === Comparing
|
74
69
|
#
|
75
|
-
#
|
70
|
+
# - ::compare_file, ::cmp, ::identical?: Returns whether two entries are identical.
|
71
|
+
# - ::compare_stream: Returns whether two streams are identical.
|
76
72
|
#
|
77
|
-
#
|
78
|
-
# files/directories. This equates to passing the <tt>:noop</tt> flag to methods
|
79
|
-
# in Bundler::FileUtils.
|
73
|
+
# === Copying
|
80
74
|
#
|
81
|
-
#
|
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.
|
82
83
|
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
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].
|
86
181
|
#
|
87
|
-
|
88
182
|
module Bundler::FileUtils
|
183
|
+
VERSION = "1.7.0"
|
89
184
|
|
90
185
|
def self.private_module_function(name) #:nodoc:
|
91
186
|
module_function name
|
@@ -93,7 +188,13 @@ module Bundler::FileUtils
|
|
93
188
|
end
|
94
189
|
|
95
190
|
#
|
96
|
-
# Returns the
|
191
|
+
# Returns a string containing the path to the current directory:
|
192
|
+
#
|
193
|
+
# Bundler::FileUtils.pwd # => "/rdoc/fileutils"
|
194
|
+
#
|
195
|
+
# Bundler::FileUtils.getwd is an alias for Bundler::FileUtils.pwd.
|
196
|
+
#
|
197
|
+
# Related: Bundler::FileUtils.cd.
|
97
198
|
#
|
98
199
|
def pwd
|
99
200
|
Dir.pwd
|
@@ -103,22 +204,46 @@ module Bundler::FileUtils
|
|
103
204
|
alias getwd pwd
|
104
205
|
module_function :getwd
|
105
206
|
|
207
|
+
# Changes the working directory to the given +dir+, which
|
208
|
+
# should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments]:
|
209
|
+
#
|
210
|
+
# With no block given,
|
211
|
+
# changes the current directory to the directory at +dir+; returns zero:
|
212
|
+
#
|
213
|
+
# Bundler::FileUtils.pwd # => "/rdoc/fileutils"
|
214
|
+
# Bundler::FileUtils.cd('..')
|
215
|
+
# Bundler::FileUtils.pwd # => "/rdoc"
|
216
|
+
# Bundler::FileUtils.cd('fileutils')
|
217
|
+
#
|
218
|
+
# With a block given, changes the current directory to the directory
|
219
|
+
# at +dir+, calls the block with argument +dir+,
|
220
|
+
# and restores the original current directory; returns the block's value:
|
106
221
|
#
|
107
|
-
#
|
222
|
+
# Bundler::FileUtils.pwd # => "/rdoc/fileutils"
|
223
|
+
# Bundler::FileUtils.cd('..') { |arg| [arg, Bundler::FileUtils.pwd] } # => ["..", "/rdoc"]
|
224
|
+
# Bundler::FileUtils.pwd # => "/rdoc/fileutils"
|
108
225
|
#
|
109
|
-
#
|
110
|
-
# working directory after the block execution finished.
|
226
|
+
# Keyword arguments:
|
111
227
|
#
|
112
|
-
#
|
228
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
113
229
|
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
230
|
+
# Bundler::FileUtils.cd('..')
|
231
|
+
# Bundler::FileUtils.cd('fileutils')
|
232
|
+
#
|
233
|
+
# Output:
|
234
|
+
#
|
235
|
+
# cd ..
|
236
|
+
# cd fileutils
|
237
|
+
#
|
238
|
+
# Bundler::FileUtils.chdir is an alias for Bundler::FileUtils.cd.
|
239
|
+
#
|
240
|
+
# Related: Bundler::FileUtils.pwd.
|
117
241
|
#
|
118
242
|
def cd(dir, verbose: nil, &block) # :yield: dir
|
119
243
|
fu_output_message "cd #{dir}" if verbose
|
120
|
-
Dir.chdir(dir, &block)
|
244
|
+
result = Dir.chdir(dir, &block)
|
121
245
|
fu_output_message 'cd -' if verbose and block
|
246
|
+
result
|
122
247
|
end
|
123
248
|
module_function :cd
|
124
249
|
|
@@ -126,11 +251,19 @@ module Bundler::FileUtils
|
|
126
251
|
module_function :chdir
|
127
252
|
|
128
253
|
#
|
129
|
-
# Returns true if
|
130
|
-
#
|
254
|
+
# Returns +true+ if the file at path +new+
|
255
|
+
# is newer than all the files at paths in array +old_list+;
|
256
|
+
# +false+ otherwise.
|
257
|
+
#
|
258
|
+
# Argument +new+ and the elements of +old_list+
|
259
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments]:
|
131
260
|
#
|
132
|
-
# Bundler::FileUtils.uptodate?('
|
133
|
-
#
|
261
|
+
# Bundler::FileUtils.uptodate?('Rakefile', ['Gemfile', 'README.md']) # => true
|
262
|
+
# Bundler::FileUtils.uptodate?('Gemfile', ['Rakefile', 'README.md']) # => false
|
263
|
+
#
|
264
|
+
# A non-existent file is considered to be infinitely old.
|
265
|
+
#
|
266
|
+
# Related: Bundler::FileUtils.touch.
|
134
267
|
#
|
135
268
|
def uptodate?(new, old_list)
|
136
269
|
return false unless File.exist?(new)
|
@@ -150,12 +283,39 @@ module Bundler::FileUtils
|
|
150
283
|
private_module_function :remove_trailing_slash
|
151
284
|
|
152
285
|
#
|
153
|
-
# Creates
|
286
|
+
# Creates directories at the paths in the given +list+
|
287
|
+
# (a single path or an array of paths);
|
288
|
+
# returns +list+ if it is an array, <tt>[list]</tt> otherwise.
|
289
|
+
#
|
290
|
+
# Argument +list+ or its elements
|
291
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
292
|
+
#
|
293
|
+
# With no keyword arguments, creates a directory at each +path+ in +list+
|
294
|
+
# by calling: <tt>Dir.mkdir(path, mode)</tt>;
|
295
|
+
# see {Dir.mkdir}[https://docs.ruby-lang.org/en/master/Dir.html#method-c-mkdir]:
|
296
|
+
#
|
297
|
+
# Bundler::FileUtils.mkdir(%w[tmp0 tmp1]) # => ["tmp0", "tmp1"]
|
298
|
+
# Bundler::FileUtils.mkdir('tmp4') # => ["tmp4"]
|
299
|
+
#
|
300
|
+
# Keyword arguments:
|
301
|
+
#
|
302
|
+
# - <tt>mode: <i>mode</i></tt> - also calls <tt>File.chmod(mode, path)</tt>;
|
303
|
+
# see {File.chmod}[https://docs.ruby-lang.org/en/master/File.html#method-c-chmod].
|
304
|
+
# - <tt>noop: true</tt> - does not create directories.
|
305
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
306
|
+
#
|
307
|
+
# Bundler::FileUtils.mkdir(%w[tmp0 tmp1], verbose: true)
|
308
|
+
# Bundler::FileUtils.mkdir(%w[tmp2 tmp3], mode: 0700, verbose: true)
|
309
|
+
#
|
310
|
+
# Output:
|
311
|
+
#
|
312
|
+
# mkdir tmp0 tmp1
|
313
|
+
# mkdir -m 700 tmp2 tmp3
|
314
|
+
#
|
315
|
+
# Raises an exception if any path points to an existing
|
316
|
+
# file or directory, or if for any reason a directory cannot be created.
|
154
317
|
#
|
155
|
-
#
|
156
|
-
# Bundler::FileUtils.mkdir %w( tmp data )
|
157
|
-
# Bundler::FileUtils.mkdir 'notexist', :noop => true # Does not really create.
|
158
|
-
# Bundler::FileUtils.mkdir 'tmp', :mode => 0700
|
318
|
+
# Related: Bundler::FileUtils.mkdir_p.
|
159
319
|
#
|
160
320
|
def mkdir(list, mode: nil, noop: nil, verbose: nil)
|
161
321
|
list = fu_list(list)
|
@@ -169,40 +329,56 @@ module Bundler::FileUtils
|
|
169
329
|
module_function :mkdir
|
170
330
|
|
171
331
|
#
|
172
|
-
# Creates
|
173
|
-
#
|
332
|
+
# Creates directories at the paths in the given +list+
|
333
|
+
# (a single path or an array of paths),
|
334
|
+
# also creating ancestor directories as needed;
|
335
|
+
# returns +list+ if it is an array, <tt>[list]</tt> otherwise.
|
174
336
|
#
|
175
|
-
#
|
337
|
+
# Argument +list+ or its elements
|
338
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
176
339
|
#
|
177
|
-
#
|
340
|
+
# With no keyword arguments, creates a directory at each +path+ in +list+,
|
341
|
+
# along with any needed ancestor directories,
|
342
|
+
# by calling: <tt>Dir.mkdir(path, mode)</tt>;
|
343
|
+
# see {Dir.mkdir}[https://docs.ruby-lang.org/en/master/Dir.html#method-c-mkdir]:
|
178
344
|
#
|
179
|
-
#
|
180
|
-
#
|
181
|
-
# * /usr/local/lib
|
182
|
-
# * /usr/local/lib/ruby
|
345
|
+
# Bundler::FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
|
346
|
+
# Bundler::FileUtils.mkdir_p('tmp4/tmp5') # => ["tmp4/tmp5"]
|
183
347
|
#
|
184
|
-
#
|
348
|
+
# Keyword arguments:
|
349
|
+
#
|
350
|
+
# - <tt>mode: <i>mode</i></tt> - also calls <tt>File.chmod(mode, path)</tt>;
|
351
|
+
# see {File.chmod}[https://docs.ruby-lang.org/en/master/File.html#method-c-chmod].
|
352
|
+
# - <tt>noop: true</tt> - does not create directories.
|
353
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
354
|
+
#
|
355
|
+
# Bundler::FileUtils.mkdir_p(%w[tmp0 tmp1], verbose: true)
|
356
|
+
# Bundler::FileUtils.mkdir_p(%w[tmp2 tmp3], mode: 0700, verbose: true)
|
357
|
+
#
|
358
|
+
# Output:
|
359
|
+
#
|
360
|
+
# mkdir -p tmp0 tmp1
|
361
|
+
# mkdir -p -m 700 tmp2 tmp3
|
362
|
+
#
|
363
|
+
# Raises an exception if for any reason a directory cannot be created.
|
364
|
+
#
|
365
|
+
# Bundler::FileUtils.mkpath and Bundler::FileUtils.makedirs are aliases for Bundler::FileUtils.mkdir_p.
|
366
|
+
#
|
367
|
+
# Related: Bundler::FileUtils.mkdir.
|
185
368
|
#
|
186
369
|
def mkdir_p(list, mode: nil, noop: nil, verbose: nil)
|
187
370
|
list = fu_list(list)
|
188
371
|
fu_output_message "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose
|
189
372
|
return *list if noop
|
190
373
|
|
191
|
-
list.
|
192
|
-
|
193
|
-
begin
|
194
|
-
fu_mkdir path, mode
|
195
|
-
next
|
196
|
-
rescue SystemCallError
|
197
|
-
next if File.directory?(path)
|
198
|
-
end
|
374
|
+
list.each do |item|
|
375
|
+
path = remove_trailing_slash(item)
|
199
376
|
|
200
377
|
stack = []
|
201
|
-
until path
|
378
|
+
until File.directory?(path) || File.dirname(path) == path
|
202
379
|
stack.push path
|
203
380
|
path = File.dirname(path)
|
204
381
|
end
|
205
|
-
stack.pop # root directory should exist
|
206
382
|
stack.reverse_each do |dir|
|
207
383
|
begin
|
208
384
|
fu_mkdir dir, mode
|
@@ -233,52 +409,115 @@ module Bundler::FileUtils
|
|
233
409
|
private_module_function :fu_mkdir
|
234
410
|
|
235
411
|
#
|
236
|
-
# Removes
|
412
|
+
# Removes directories at the paths in the given +list+
|
413
|
+
# (a single path or an array of paths);
|
414
|
+
# returns +list+, if it is an array, <tt>[list]</tt> otherwise.
|
237
415
|
#
|
238
|
-
#
|
239
|
-
#
|
240
|
-
#
|
241
|
-
#
|
416
|
+
# Argument +list+ or its elements
|
417
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
418
|
+
#
|
419
|
+
# With no keyword arguments, removes the directory at each +path+ in +list+,
|
420
|
+
# by calling: <tt>Dir.rmdir(path)</tt>;
|
421
|
+
# see {Dir.rmdir}[https://docs.ruby-lang.org/en/master/Dir.html#method-c-rmdir]:
|
422
|
+
#
|
423
|
+
# Bundler::FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
|
424
|
+
# Bundler::FileUtils.rmdir('tmp4/tmp5') # => ["tmp4/tmp5"]
|
425
|
+
#
|
426
|
+
# Keyword arguments:
|
427
|
+
#
|
428
|
+
# - <tt>parents: true</tt> - removes successive ancestor directories
|
429
|
+
# if empty.
|
430
|
+
# - <tt>noop: true</tt> - does not remove directories.
|
431
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
432
|
+
#
|
433
|
+
# Bundler::FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3], parents: true, verbose: true)
|
434
|
+
# Bundler::FileUtils.rmdir('tmp4/tmp5', parents: true, verbose: true)
|
435
|
+
#
|
436
|
+
# Output:
|
437
|
+
#
|
438
|
+
# rmdir -p tmp0/tmp1 tmp2/tmp3
|
439
|
+
# rmdir -p tmp4/tmp5
|
440
|
+
#
|
441
|
+
# Raises an exception if a directory does not exist
|
442
|
+
# or if for any reason a directory cannot be removed.
|
443
|
+
#
|
444
|
+
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
|
242
445
|
#
|
243
446
|
def rmdir(list, parents: nil, noop: nil, verbose: nil)
|
244
447
|
list = fu_list(list)
|
245
448
|
fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if verbose
|
246
449
|
return if noop
|
247
450
|
list.each do |dir|
|
248
|
-
|
249
|
-
|
250
|
-
|
451
|
+
Dir.rmdir(dir = remove_trailing_slash(dir))
|
452
|
+
if parents
|
453
|
+
begin
|
251
454
|
until (parent = File.dirname(dir)) == '.' or parent == dir
|
252
455
|
dir = parent
|
253
456
|
Dir.rmdir(dir)
|
254
457
|
end
|
458
|
+
rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
|
255
459
|
end
|
256
|
-
rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
|
257
460
|
end
|
258
461
|
end
|
259
462
|
end
|
260
463
|
module_function :rmdir
|
261
464
|
|
465
|
+
# Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link].
|
466
|
+
#
|
467
|
+
# Arguments +src+ (a single path or an array of paths)
|
468
|
+
# and +dest+ (a single path)
|
469
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
470
|
+
#
|
471
|
+
# When +src+ is the path to an existing file
|
472
|
+
# and +dest+ is the path to a non-existent file,
|
473
|
+
# creates a hard link at +dest+ pointing to +src+; returns zero:
|
474
|
+
#
|
475
|
+
# Dir.children('tmp0/') # => ["t.txt"]
|
476
|
+
# Dir.children('tmp1/') # => []
|
477
|
+
# Bundler::FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk') # => 0
|
478
|
+
# Dir.children('tmp1/') # => ["t.lnk"]
|
479
|
+
#
|
480
|
+
# When +src+ is the path to an existing file
|
481
|
+
# and +dest+ is the path to an existing directory,
|
482
|
+
# creates a hard link at <tt>dest/src</tt> pointing to +src+; returns zero:
|
483
|
+
#
|
484
|
+
# Dir.children('tmp2') # => ["t.dat"]
|
485
|
+
# Dir.children('tmp3') # => []
|
486
|
+
# Bundler::FileUtils.ln('tmp2/t.dat', 'tmp3') # => 0
|
487
|
+
# Dir.children('tmp3') # => ["t.dat"]
|
488
|
+
#
|
489
|
+
# When +src+ is an array of paths to existing files
|
490
|
+
# and +dest+ is the path to an existing directory,
|
491
|
+
# then for each path +target+ in +src+,
|
492
|
+
# creates a hard link at <tt>dest/target</tt> pointing to +target+;
|
493
|
+
# returns +src+:
|
494
|
+
#
|
495
|
+
# Dir.children('tmp4/') # => []
|
496
|
+
# Bundler::FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/') # => ["tmp0/t.txt", "tmp2/t.dat"]
|
497
|
+
# Dir.children('tmp4/') # => ["t.dat", "t.txt"]
|
498
|
+
#
|
499
|
+
# Keyword arguments:
|
500
|
+
#
|
501
|
+
# - <tt>force: true</tt> - overwrites +dest+ if it exists.
|
502
|
+
# - <tt>noop: true</tt> - does not create links.
|
503
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
504
|
+
#
|
505
|
+
# Bundler::FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk', verbose: true)
|
506
|
+
# Bundler::FileUtils.ln('tmp2/t.dat', 'tmp3', verbose: true)
|
507
|
+
# Bundler::FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/', verbose: true)
|
262
508
|
#
|
263
|
-
#
|
264
|
-
# Bundler::FileUtils.ln(target, link, force: nil, noop: nil, verbose: nil)
|
265
|
-
# Bundler::FileUtils.ln(target, dir, force: nil, noop: nil, verbose: nil)
|
266
|
-
# Bundler::FileUtils.ln(targets, dir, force: nil, noop: nil, verbose: nil)
|
509
|
+
# Output:
|
267
510
|
#
|
268
|
-
#
|
269
|
-
#
|
270
|
-
#
|
511
|
+
# ln tmp0/t.txt tmp1/t.lnk
|
512
|
+
# ln tmp2/t.dat tmp3
|
513
|
+
# ln tmp0/t.txt tmp2/t.dat tmp4/
|
271
514
|
#
|
272
|
-
#
|
273
|
-
#
|
515
|
+
# Raises an exception if +dest+ is the path to an existing file
|
516
|
+
# and keyword argument +force+ is not +true+.
|
274
517
|
#
|
275
|
-
#
|
276
|
-
# In the third form, creates several hard links in the directory +dir+,
|
277
|
-
# pointing to each item in +targets+.
|
278
|
-
# If +dir+ is not a directory, raises Errno::ENOTDIR.
|
518
|
+
# Bundler::FileUtils#link is an alias for Bundler::FileUtils#ln.
|
279
519
|
#
|
280
|
-
#
|
281
|
-
# Bundler::FileUtils.ln %w(cp mv mkdir), '/bin' # Now /sbin/cp and /bin/cp are linked.
|
520
|
+
# Related: Bundler::FileUtils.link_entry (has different options).
|
282
521
|
#
|
283
522
|
def ln(src, dest, force: nil, noop: nil, verbose: nil)
|
284
523
|
fu_output_message "ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
|
@@ -293,27 +532,189 @@ module Bundler::FileUtils
|
|
293
532
|
alias link ln
|
294
533
|
module_function :link
|
295
534
|
|
535
|
+
# Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link].
|
536
|
+
#
|
537
|
+
# Arguments +src+ (a single path or an array of paths)
|
538
|
+
# and +dest+ (a single path)
|
539
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
540
|
+
#
|
541
|
+
# If +src+ is the path to a directory and +dest+ does not exist,
|
542
|
+
# creates links +dest+ and descendents pointing to +src+ and its descendents:
|
543
|
+
#
|
544
|
+
# tree('src0')
|
545
|
+
# # => src0
|
546
|
+
# # |-- sub0
|
547
|
+
# # | |-- src0.txt
|
548
|
+
# # | `-- src1.txt
|
549
|
+
# # `-- sub1
|
550
|
+
# # |-- src2.txt
|
551
|
+
# # `-- src3.txt
|
552
|
+
# File.exist?('dest0') # => false
|
553
|
+
# Bundler::FileUtils.cp_lr('src0', 'dest0')
|
554
|
+
# tree('dest0')
|
555
|
+
# # => dest0
|
556
|
+
# # |-- sub0
|
557
|
+
# # | |-- src0.txt
|
558
|
+
# # | `-- src1.txt
|
559
|
+
# # `-- sub1
|
560
|
+
# # |-- src2.txt
|
561
|
+
# # `-- src3.txt
|
562
|
+
#
|
563
|
+
# If +src+ and +dest+ are both paths to directories,
|
564
|
+
# creates links <tt>dest/src</tt> and descendents
|
565
|
+
# pointing to +src+ and its descendents:
|
566
|
+
#
|
567
|
+
# tree('src1')
|
568
|
+
# # => src1
|
569
|
+
# # |-- sub0
|
570
|
+
# # | |-- src0.txt
|
571
|
+
# # | `-- src1.txt
|
572
|
+
# # `-- sub1
|
573
|
+
# # |-- src2.txt
|
574
|
+
# # `-- src3.txt
|
575
|
+
# Bundler::FileUtils.mkdir('dest1')
|
576
|
+
# Bundler::FileUtils.cp_lr('src1', 'dest1')
|
577
|
+
# tree('dest1')
|
578
|
+
# # => dest1
|
579
|
+
# # `-- src1
|
580
|
+
# # |-- sub0
|
581
|
+
# # | |-- src0.txt
|
582
|
+
# # | `-- src1.txt
|
583
|
+
# # `-- sub1
|
584
|
+
# # |-- src2.txt
|
585
|
+
# # `-- src3.txt
|
586
|
+
#
|
587
|
+
# If +src+ is an array of paths to entries and +dest+ is the path to a directory,
|
588
|
+
# for each path +filepath+ in +src+, creates a link at <tt>dest/filepath</tt>
|
589
|
+
# pointing to that path:
|
590
|
+
#
|
591
|
+
# tree('src2')
|
592
|
+
# # => src2
|
593
|
+
# # |-- sub0
|
594
|
+
# # | |-- src0.txt
|
595
|
+
# # | `-- src1.txt
|
596
|
+
# # `-- sub1
|
597
|
+
# # |-- src2.txt
|
598
|
+
# # `-- src3.txt
|
599
|
+
# Bundler::FileUtils.mkdir('dest2')
|
600
|
+
# Bundler::FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2')
|
601
|
+
# tree('dest2')
|
602
|
+
# # => dest2
|
603
|
+
# # |-- sub0
|
604
|
+
# # | |-- src0.txt
|
605
|
+
# # | `-- src1.txt
|
606
|
+
# # `-- sub1
|
607
|
+
# # |-- src2.txt
|
608
|
+
# # `-- src3.txt
|
609
|
+
#
|
610
|
+
# Keyword arguments:
|
611
|
+
#
|
612
|
+
# - <tt>dereference_root: false</tt> - if +src+ is a symbolic link,
|
613
|
+
# does not dereference it.
|
614
|
+
# - <tt>noop: true</tt> - does not create links.
|
615
|
+
# - <tt>remove_destination: true</tt> - removes +dest+ before creating links.
|
616
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
617
|
+
#
|
618
|
+
# Bundler::FileUtils.cp_lr('src0', 'dest0', noop: true, verbose: true)
|
619
|
+
# Bundler::FileUtils.cp_lr('src1', 'dest1', noop: true, verbose: true)
|
620
|
+
# Bundler::FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2', noop: true, verbose: true)
|
621
|
+
#
|
622
|
+
# Output:
|
623
|
+
#
|
624
|
+
# cp -lr src0 dest0
|
625
|
+
# cp -lr src1 dest1
|
626
|
+
# cp -lr src2/sub0 src2/sub1 dest2
|
627
|
+
#
|
628
|
+
# Raises an exception if +dest+ is the path to an existing file or directory
|
629
|
+
# and keyword argument <tt>remove_destination: true</tt> is not given.
|
630
|
+
#
|
631
|
+
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
|
632
|
+
#
|
633
|
+
def cp_lr(src, dest, noop: nil, verbose: nil,
|
634
|
+
dereference_root: true, remove_destination: false)
|
635
|
+
fu_output_message "cp -lr#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose
|
636
|
+
return if noop
|
637
|
+
fu_each_src_dest(src, dest) do |s, d|
|
638
|
+
link_entry s, d, dereference_root, remove_destination
|
639
|
+
end
|
640
|
+
end
|
641
|
+
module_function :cp_lr
|
642
|
+
|
643
|
+
# Creates {symbolic links}[https://en.wikipedia.org/wiki/Symbolic_link].
|
644
|
+
#
|
645
|
+
# Arguments +src+ (a single path or an array of paths)
|
646
|
+
# and +dest+ (a single path)
|
647
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
648
|
+
#
|
649
|
+
# If +src+ is the path to an existing file:
|
650
|
+
#
|
651
|
+
# - When +dest+ is the path to a non-existent file,
|
652
|
+
# creates a symbolic link at +dest+ pointing to +src+:
|
653
|
+
#
|
654
|
+
# Bundler::FileUtils.touch('src0.txt')
|
655
|
+
# File.exist?('dest0.txt') # => false
|
656
|
+
# Bundler::FileUtils.ln_s('src0.txt', 'dest0.txt')
|
657
|
+
# File.symlink?('dest0.txt') # => true
|
658
|
+
#
|
659
|
+
# - When +dest+ is the path to an existing file,
|
660
|
+
# creates a symbolic link at +dest+ pointing to +src+
|
661
|
+
# if and only if keyword argument <tt>force: true</tt> is given
|
662
|
+
# (raises an exception otherwise):
|
663
|
+
#
|
664
|
+
# Bundler::FileUtils.touch('src1.txt')
|
665
|
+
# Bundler::FileUtils.touch('dest1.txt')
|
666
|
+
# Bundler::FileUtils.ln_s('src1.txt', 'dest1.txt', force: true)
|
667
|
+
# FileTest.symlink?('dest1.txt') # => true
|
296
668
|
#
|
297
|
-
#
|
298
|
-
# Bundler::FileUtils.ln_s(target, link, force: nil, noop: nil, verbose: nil)
|
299
|
-
# Bundler::FileUtils.ln_s(target, dir, force: nil, noop: nil, verbose: nil)
|
300
|
-
# Bundler::FileUtils.ln_s(targets, dir, force: nil, noop: nil, verbose: nil)
|
669
|
+
# Bundler::FileUtils.ln_s('src1.txt', 'dest1.txt') # Raises Errno::EEXIST.
|
301
670
|
#
|
302
|
-
#
|
303
|
-
#
|
304
|
-
# But if the :force option is set, overwrites +link+.
|
671
|
+
# If +dest+ is the path to a directory,
|
672
|
+
# creates a symbolic link at <tt>dest/src</tt> pointing to +src+:
|
305
673
|
#
|
306
|
-
# Bundler::FileUtils.
|
307
|
-
# Bundler::FileUtils.
|
674
|
+
# Bundler::FileUtils.touch('src2.txt')
|
675
|
+
# Bundler::FileUtils.mkdir('destdir2')
|
676
|
+
# Bundler::FileUtils.ln_s('src2.txt', 'destdir2')
|
677
|
+
# File.symlink?('destdir2/src2.txt') # => true
|
308
678
|
#
|
309
|
-
#
|
310
|
-
#
|
311
|
-
# pointing to
|
312
|
-
# If +dir+ is not a directory, raises Errno::ENOTDIR.
|
679
|
+
# If +src+ is an array of paths to existing files and +dest+ is a directory,
|
680
|
+
# for each child +child+ in +src+ creates a symbolic link <tt>dest/child</tt>
|
681
|
+
# pointing to +child+:
|
313
682
|
#
|
314
|
-
# Bundler::FileUtils.
|
683
|
+
# Bundler::FileUtils.mkdir('srcdir3')
|
684
|
+
# Bundler::FileUtils.touch('srcdir3/src0.txt')
|
685
|
+
# Bundler::FileUtils.touch('srcdir3/src1.txt')
|
686
|
+
# Bundler::FileUtils.mkdir('destdir3')
|
687
|
+
# Bundler::FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3')
|
688
|
+
# File.symlink?('destdir3/src0.txt') # => true
|
689
|
+
# File.symlink?('destdir3/src1.txt') # => true
|
315
690
|
#
|
316
|
-
|
691
|
+
# Keyword arguments:
|
692
|
+
#
|
693
|
+
# - <tt>force: true</tt> - overwrites +dest+ if it exists.
|
694
|
+
# - <tt>relative: false</tt> - create links relative to +dest+.
|
695
|
+
# - <tt>noop: true</tt> - does not create links.
|
696
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
697
|
+
#
|
698
|
+
# Bundler::FileUtils.ln_s('src0.txt', 'dest0.txt', noop: true, verbose: true)
|
699
|
+
# Bundler::FileUtils.ln_s('src1.txt', 'destdir1', noop: true, verbose: true)
|
700
|
+
# Bundler::FileUtils.ln_s('src2.txt', 'dest2.txt', force: true, noop: true, verbose: true)
|
701
|
+
# Bundler::FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3', noop: true, verbose: true)
|
702
|
+
#
|
703
|
+
# Output:
|
704
|
+
#
|
705
|
+
# ln -s src0.txt dest0.txt
|
706
|
+
# ln -s src1.txt destdir1
|
707
|
+
# ln -sf src2.txt dest2.txt
|
708
|
+
# ln -s srcdir3/src0.txt srcdir3/src1.txt destdir3
|
709
|
+
#
|
710
|
+
# Bundler::FileUtils.symlink is an alias for Bundler::FileUtils.ln_s.
|
711
|
+
#
|
712
|
+
# Related: Bundler::FileUtils.ln_sf.
|
713
|
+
#
|
714
|
+
def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
|
715
|
+
if relative
|
716
|
+
return ln_sr(src, dest, force: force, noop: noop, verbose: verbose)
|
717
|
+
end
|
317
718
|
fu_output_message "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose
|
318
719
|
return if noop
|
319
720
|
fu_each_src_dest0(src, dest) do |s,d|
|
@@ -326,29 +727,158 @@ module Bundler::FileUtils
|
|
326
727
|
alias symlink ln_s
|
327
728
|
module_function :symlink
|
328
729
|
|
329
|
-
#
|
330
|
-
# :call-seq:
|
331
|
-
# Bundler::FileUtils.ln_sf(*args)
|
332
|
-
#
|
333
|
-
# Same as
|
334
|
-
#
|
335
|
-
# Bundler::FileUtils.ln_s(*args, force: true)
|
730
|
+
# Like Bundler::FileUtils.ln_s, but always with keyword argument <tt>force: true</tt> given.
|
336
731
|
#
|
337
732
|
def ln_sf(src, dest, noop: nil, verbose: nil)
|
338
733
|
ln_s src, dest, force: true, noop: noop, verbose: verbose
|
339
734
|
end
|
340
735
|
module_function :ln_sf
|
341
736
|
|
737
|
+
# Like Bundler::FileUtils.ln_s, but create links relative to +dest+.
|
342
738
|
#
|
343
|
-
|
344
|
-
|
739
|
+
def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
|
740
|
+
options = "#{force ? 'f' : ''}#{target_directory ? '' : 'T'}"
|
741
|
+
dest = File.path(dest)
|
742
|
+
srcs = Array(src)
|
743
|
+
link = proc do |s, target_dir_p = true|
|
744
|
+
s = File.path(s)
|
745
|
+
if target_dir_p
|
746
|
+
d = File.join(destdirs = dest, File.basename(s))
|
747
|
+
else
|
748
|
+
destdirs = File.dirname(d = dest)
|
749
|
+
end
|
750
|
+
destdirs = fu_split_path(File.realpath(destdirs))
|
751
|
+
if fu_starting_path?(s)
|
752
|
+
srcdirs = fu_split_path((File.realdirpath(s) rescue File.expand_path(s)))
|
753
|
+
base = fu_relative_components_from(srcdirs, destdirs)
|
754
|
+
s = File.join(*base)
|
755
|
+
else
|
756
|
+
srcdirs = fu_clean_components(*fu_split_path(s))
|
757
|
+
base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs)
|
758
|
+
while srcdirs.first&. == ".." and base.last&.!=("..") and !fu_starting_path?(base.last)
|
759
|
+
srcdirs.shift
|
760
|
+
base.pop
|
761
|
+
end
|
762
|
+
s = File.join(*base, *srcdirs)
|
763
|
+
end
|
764
|
+
fu_output_message "ln -s#{options} #{s} #{d}" if verbose
|
765
|
+
next if noop
|
766
|
+
remove_file d, true if force
|
767
|
+
File.symlink s, d
|
768
|
+
end
|
769
|
+
case srcs.size
|
770
|
+
when 0
|
771
|
+
when 1
|
772
|
+
link[srcs[0], target_directory && File.directory?(dest)]
|
773
|
+
else
|
774
|
+
srcs.each(&link)
|
775
|
+
end
|
776
|
+
end
|
777
|
+
module_function :ln_sr
|
778
|
+
|
779
|
+
# Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link]; returns +nil+.
|
780
|
+
#
|
781
|
+
# Arguments +src+ and +dest+
|
782
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
783
|
+
#
|
784
|
+
# If +src+ is the path to a file and +dest+ does not exist,
|
785
|
+
# creates a hard link at +dest+ pointing to +src+:
|
786
|
+
#
|
787
|
+
# Bundler::FileUtils.touch('src0.txt')
|
788
|
+
# File.exist?('dest0.txt') # => false
|
789
|
+
# Bundler::FileUtils.link_entry('src0.txt', 'dest0.txt')
|
790
|
+
# File.file?('dest0.txt') # => true
|
345
791
|
#
|
346
|
-
# If +src+ is
|
792
|
+
# If +src+ is the path to a directory and +dest+ does not exist,
|
793
|
+
# recursively creates hard links at +dest+ pointing to paths in +src+:
|
347
794
|
#
|
348
|
-
# Bundler::FileUtils.
|
349
|
-
#
|
350
|
-
#
|
351
|
-
#
|
795
|
+
# Bundler::FileUtils.mkdir_p(['src1/dir0', 'src1/dir1'])
|
796
|
+
# src_file_paths = [
|
797
|
+
# 'src1/dir0/t0.txt',
|
798
|
+
# 'src1/dir0/t1.txt',
|
799
|
+
# 'src1/dir1/t2.txt',
|
800
|
+
# 'src1/dir1/t3.txt',
|
801
|
+
# ]
|
802
|
+
# Bundler::FileUtils.touch(src_file_paths)
|
803
|
+
# File.directory?('dest1') # => true
|
804
|
+
# Bundler::FileUtils.link_entry('src1', 'dest1')
|
805
|
+
# File.file?('dest1/dir0/t0.txt') # => true
|
806
|
+
# File.file?('dest1/dir0/t1.txt') # => true
|
807
|
+
# File.file?('dest1/dir1/t2.txt') # => true
|
808
|
+
# File.file?('dest1/dir1/t3.txt') # => true
|
809
|
+
#
|
810
|
+
# Keyword arguments:
|
811
|
+
#
|
812
|
+
# - <tt>dereference_root: true</tt> - dereferences +src+ if it is a symbolic link.
|
813
|
+
# - <tt>remove_destination: true</tt> - removes +dest+ before creating links.
|
814
|
+
#
|
815
|
+
# Raises an exception if +dest+ is the path to an existing file or directory
|
816
|
+
# and keyword argument <tt>remove_destination: true</tt> is not given.
|
817
|
+
#
|
818
|
+
# Related: Bundler::FileUtils.ln (has different options).
|
819
|
+
#
|
820
|
+
def link_entry(src, dest, dereference_root = false, remove_destination = false)
|
821
|
+
Entry_.new(src, nil, dereference_root).traverse do |ent|
|
822
|
+
destent = Entry_.new(dest, ent.rel, false)
|
823
|
+
File.unlink destent.path if remove_destination && File.file?(destent.path)
|
824
|
+
ent.link destent.path
|
825
|
+
end
|
826
|
+
end
|
827
|
+
module_function :link_entry
|
828
|
+
|
829
|
+
# Copies files.
|
830
|
+
#
|
831
|
+
# Arguments +src+ (a single path or an array of paths)
|
832
|
+
# and +dest+ (a single path)
|
833
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
834
|
+
#
|
835
|
+
# If +src+ is the path to a file and +dest+ is not the path to a directory,
|
836
|
+
# copies +src+ to +dest+:
|
837
|
+
#
|
838
|
+
# Bundler::FileUtils.touch('src0.txt')
|
839
|
+
# File.exist?('dest0.txt') # => false
|
840
|
+
# Bundler::FileUtils.cp('src0.txt', 'dest0.txt')
|
841
|
+
# File.file?('dest0.txt') # => true
|
842
|
+
#
|
843
|
+
# If +src+ is the path to a file and +dest+ is the path to a directory,
|
844
|
+
# copies +src+ to <tt>dest/src</tt>:
|
845
|
+
#
|
846
|
+
# Bundler::FileUtils.touch('src1.txt')
|
847
|
+
# Bundler::FileUtils.mkdir('dest1')
|
848
|
+
# Bundler::FileUtils.cp('src1.txt', 'dest1')
|
849
|
+
# File.file?('dest1/src1.txt') # => true
|
850
|
+
#
|
851
|
+
# If +src+ is an array of paths to files and +dest+ is the path to a directory,
|
852
|
+
# copies from each +src+ to +dest+:
|
853
|
+
#
|
854
|
+
# src_file_paths = ['src2.txt', 'src2.dat']
|
855
|
+
# Bundler::FileUtils.touch(src_file_paths)
|
856
|
+
# Bundler::FileUtils.mkdir('dest2')
|
857
|
+
# Bundler::FileUtils.cp(src_file_paths, 'dest2')
|
858
|
+
# File.file?('dest2/src2.txt') # => true
|
859
|
+
# File.file?('dest2/src2.dat') # => true
|
860
|
+
#
|
861
|
+
# Keyword arguments:
|
862
|
+
#
|
863
|
+
# - <tt>preserve: true</tt> - preserves file times.
|
864
|
+
# - <tt>noop: true</tt> - does not copy files.
|
865
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
866
|
+
#
|
867
|
+
# Bundler::FileUtils.cp('src0.txt', 'dest0.txt', noop: true, verbose: true)
|
868
|
+
# Bundler::FileUtils.cp('src1.txt', 'dest1', noop: true, verbose: true)
|
869
|
+
# Bundler::FileUtils.cp(src_file_paths, 'dest2', noop: true, verbose: true)
|
870
|
+
#
|
871
|
+
# Output:
|
872
|
+
#
|
873
|
+
# cp src0.txt dest0.txt
|
874
|
+
# cp src1.txt dest1
|
875
|
+
# cp src2.txt src2.dat dest2
|
876
|
+
#
|
877
|
+
# Raises an exception if +src+ is a directory.
|
878
|
+
#
|
879
|
+
# Bundler::FileUtils.copy is an alias for Bundler::FileUtils.cp.
|
880
|
+
#
|
881
|
+
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
|
352
882
|
#
|
353
883
|
def cp(src, dest, preserve: nil, noop: nil, verbose: nil)
|
354
884
|
fu_output_message "cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if verbose
|
@@ -362,26 +892,105 @@ module Bundler::FileUtils
|
|
362
892
|
alias copy cp
|
363
893
|
module_function :copy
|
364
894
|
|
365
|
-
#
|
366
|
-
#
|
367
|
-
#
|
368
|
-
# +
|
369
|
-
#
|
370
|
-
#
|
371
|
-
#
|
372
|
-
#
|
373
|
-
#
|
374
|
-
#
|
375
|
-
#
|
376
|
-
#
|
377
|
-
# Bundler::FileUtils.
|
378
|
-
#
|
379
|
-
#
|
380
|
-
# #
|
381
|
-
#
|
382
|
-
#
|
383
|
-
#
|
384
|
-
#
|
895
|
+
# Recursively copies files.
|
896
|
+
#
|
897
|
+
# Arguments +src+ (a single path or an array of paths)
|
898
|
+
# and +dest+ (a single path)
|
899
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
900
|
+
#
|
901
|
+
# The mode, owner, and group are retained in the copy;
|
902
|
+
# to change those, use Bundler::FileUtils.install instead.
|
903
|
+
#
|
904
|
+
# If +src+ is the path to a file and +dest+ is not the path to a directory,
|
905
|
+
# copies +src+ to +dest+:
|
906
|
+
#
|
907
|
+
# Bundler::FileUtils.touch('src0.txt')
|
908
|
+
# File.exist?('dest0.txt') # => false
|
909
|
+
# Bundler::FileUtils.cp_r('src0.txt', 'dest0.txt')
|
910
|
+
# File.file?('dest0.txt') # => true
|
911
|
+
#
|
912
|
+
# If +src+ is the path to a file and +dest+ is the path to a directory,
|
913
|
+
# copies +src+ to <tt>dest/src</tt>:
|
914
|
+
#
|
915
|
+
# Bundler::FileUtils.touch('src1.txt')
|
916
|
+
# Bundler::FileUtils.mkdir('dest1')
|
917
|
+
# Bundler::FileUtils.cp_r('src1.txt', 'dest1')
|
918
|
+
# File.file?('dest1/src1.txt') # => true
|
919
|
+
#
|
920
|
+
# If +src+ is the path to a directory and +dest+ does not exist,
|
921
|
+
# recursively copies +src+ to +dest+:
|
922
|
+
#
|
923
|
+
# tree('src2')
|
924
|
+
# # => src2
|
925
|
+
# # |-- dir0
|
926
|
+
# # | |-- src0.txt
|
927
|
+
# # | `-- src1.txt
|
928
|
+
# # `-- dir1
|
929
|
+
# # |-- src2.txt
|
930
|
+
# # `-- src3.txt
|
931
|
+
# Bundler::FileUtils.exist?('dest2') # => false
|
932
|
+
# Bundler::FileUtils.cp_r('src2', 'dest2')
|
933
|
+
# tree('dest2')
|
934
|
+
# # => dest2
|
935
|
+
# # |-- dir0
|
936
|
+
# # | |-- src0.txt
|
937
|
+
# # | `-- src1.txt
|
938
|
+
# # `-- dir1
|
939
|
+
# # |-- src2.txt
|
940
|
+
# # `-- src3.txt
|
941
|
+
#
|
942
|
+
# If +src+ and +dest+ are paths to directories,
|
943
|
+
# recursively copies +src+ to <tt>dest/src</tt>:
|
944
|
+
#
|
945
|
+
# tree('src3')
|
946
|
+
# # => src3
|
947
|
+
# # |-- dir0
|
948
|
+
# # | |-- src0.txt
|
949
|
+
# # | `-- src1.txt
|
950
|
+
# # `-- dir1
|
951
|
+
# # |-- src2.txt
|
952
|
+
# # `-- src3.txt
|
953
|
+
# Bundler::FileUtils.mkdir('dest3')
|
954
|
+
# Bundler::FileUtils.cp_r('src3', 'dest3')
|
955
|
+
# tree('dest3')
|
956
|
+
# # => dest3
|
957
|
+
# # `-- src3
|
958
|
+
# # |-- dir0
|
959
|
+
# # | |-- src0.txt
|
960
|
+
# # | `-- src1.txt
|
961
|
+
# # `-- dir1
|
962
|
+
# # |-- src2.txt
|
963
|
+
# # `-- src3.txt
|
964
|
+
#
|
965
|
+
# If +src+ is an array of paths and +dest+ is a directory,
|
966
|
+
# recursively copies from each path in +src+ to +dest+;
|
967
|
+
# the paths in +src+ may point to files and/or directories.
|
968
|
+
#
|
969
|
+
# Keyword arguments:
|
970
|
+
#
|
971
|
+
# - <tt>dereference_root: false</tt> - if +src+ is a symbolic link,
|
972
|
+
# does not dereference it.
|
973
|
+
# - <tt>noop: true</tt> - does not copy files.
|
974
|
+
# - <tt>preserve: true</tt> - preserves file times.
|
975
|
+
# - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
|
976
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
977
|
+
#
|
978
|
+
# Bundler::FileUtils.cp_r('src0.txt', 'dest0.txt', noop: true, verbose: true)
|
979
|
+
# Bundler::FileUtils.cp_r('src1.txt', 'dest1', noop: true, verbose: true)
|
980
|
+
# Bundler::FileUtils.cp_r('src2', 'dest2', noop: true, verbose: true)
|
981
|
+
# Bundler::FileUtils.cp_r('src3', 'dest3', noop: true, verbose: true)
|
982
|
+
#
|
983
|
+
# Output:
|
984
|
+
#
|
985
|
+
# cp -r src0.txt dest0.txt
|
986
|
+
# cp -r src1.txt dest1
|
987
|
+
# cp -r src2 dest2
|
988
|
+
# cp -r src3 dest3
|
989
|
+
#
|
990
|
+
# Raises an exception of +src+ is the path to a directory
|
991
|
+
# and +dest+ is the path to a file.
|
992
|
+
#
|
993
|
+
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
|
385
994
|
#
|
386
995
|
def cp_r(src, dest, preserve: nil, noop: nil, verbose: nil,
|
387
996
|
dereference_root: true, remove_destination: nil)
|
@@ -393,26 +1002,59 @@ module Bundler::FileUtils
|
|
393
1002
|
end
|
394
1003
|
module_function :cp_r
|
395
1004
|
|
1005
|
+
# Recursively copies files from +src+ to +dest+.
|
1006
|
+
#
|
1007
|
+
# Arguments +src+ and +dest+
|
1008
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
396
1009
|
#
|
397
|
-
#
|
398
|
-
# If +src+ is a directory, this method copies its contents recursively.
|
399
|
-
# This method preserves file types, c.f. symlink, directory...
|
400
|
-
# (FIFO, device files and etc. are not supported yet)
|
1010
|
+
# If +src+ is the path to a file, copies +src+ to +dest+:
|
401
1011
|
#
|
402
|
-
#
|
403
|
-
#
|
1012
|
+
# Bundler::FileUtils.touch('src0.txt')
|
1013
|
+
# File.exist?('dest0.txt') # => false
|
1014
|
+
# Bundler::FileUtils.copy_entry('src0.txt', 'dest0.txt')
|
1015
|
+
# File.file?('dest0.txt') # => true
|
404
1016
|
#
|
405
|
-
# If +
|
406
|
-
# modified time. Permissions are copied regardless +preserve+.
|
1017
|
+
# If +src+ is a directory, recursively copies +src+ to +dest+:
|
407
1018
|
#
|
408
|
-
#
|
1019
|
+
# tree('src1')
|
1020
|
+
# # => src1
|
1021
|
+
# # |-- dir0
|
1022
|
+
# # | |-- src0.txt
|
1023
|
+
# # | `-- src1.txt
|
1024
|
+
# # `-- dir1
|
1025
|
+
# # |-- src2.txt
|
1026
|
+
# # `-- src3.txt
|
1027
|
+
# Bundler::FileUtils.copy_entry('src1', 'dest1')
|
1028
|
+
# tree('dest1')
|
1029
|
+
# # => dest1
|
1030
|
+
# # |-- dir0
|
1031
|
+
# # | |-- src0.txt
|
1032
|
+
# # | `-- src1.txt
|
1033
|
+
# # `-- dir1
|
1034
|
+
# # |-- src2.txt
|
1035
|
+
# # `-- src3.txt
|
409
1036
|
#
|
410
|
-
#
|
1037
|
+
# The recursive copying preserves file types for regular files,
|
1038
|
+
# directories, and symbolic links;
|
1039
|
+
# other file types (FIFO streams, device files, etc.) are not supported.
|
1040
|
+
#
|
1041
|
+
# Keyword arguments:
|
1042
|
+
#
|
1043
|
+
# - <tt>dereference_root: true</tt> - if +src+ is a symbolic link,
|
1044
|
+
# follows the link.
|
1045
|
+
# - <tt>preserve: true</tt> - preserves file times.
|
1046
|
+
# - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
|
1047
|
+
#
|
1048
|
+
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
|
411
1049
|
#
|
412
1050
|
def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
|
413
|
-
|
1051
|
+
if dereference_root
|
1052
|
+
src = File.realpath(src)
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
Entry_.new(src, nil, false).wrap_traverse(proc do |ent|
|
414
1056
|
destent = Entry_.new(dest, ent.rel, false)
|
415
|
-
File.unlink destent.path if remove_destination && File.file?(destent.path)
|
1057
|
+
File.unlink destent.path if remove_destination && (File.file?(destent.path) || File.symlink?(destent.path))
|
416
1058
|
ent.copy destent.path
|
417
1059
|
end, proc do |ent|
|
418
1060
|
destent = Entry_.new(dest, ent.rel, false)
|
@@ -421,9 +1063,25 @@ module Bundler::FileUtils
|
|
421
1063
|
end
|
422
1064
|
module_function :copy_entry
|
423
1065
|
|
1066
|
+
# Copies file from +src+ to +dest+, which should not be directories.
|
1067
|
+
#
|
1068
|
+
# Arguments +src+ and +dest+
|
1069
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
1070
|
+
#
|
1071
|
+
# Examples:
|
1072
|
+
#
|
1073
|
+
# Bundler::FileUtils.touch('src0.txt')
|
1074
|
+
# Bundler::FileUtils.copy_file('src0.txt', 'dest0.txt')
|
1075
|
+
# File.file?('dest0.txt') # => true
|
1076
|
+
#
|
1077
|
+
# Keyword arguments:
|
424
1078
|
#
|
425
|
-
#
|
426
|
-
#
|
1079
|
+
# - <tt>dereference: false</tt> - if +src+ is a symbolic link,
|
1080
|
+
# does not follow the link.
|
1081
|
+
# - <tt>preserve: true</tt> - preserves file times.
|
1082
|
+
# - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
|
1083
|
+
#
|
1084
|
+
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
|
427
1085
|
#
|
428
1086
|
def copy_file(src, dest, preserve = false, dereference = true)
|
429
1087
|
ent = Entry_.new(src, nil, dereference)
|
@@ -432,25 +1090,81 @@ module Bundler::FileUtils
|
|
432
1090
|
end
|
433
1091
|
module_function :copy_file
|
434
1092
|
|
1093
|
+
# Copies \IO stream +src+ to \IO stream +dest+ via
|
1094
|
+
# {IO.copy_stream}[https://docs.ruby-lang.org/en/master/IO.html#method-c-copy_stream].
|
435
1095
|
#
|
436
|
-
#
|
437
|
-
# +src+ must respond to #read(n) and
|
438
|
-
# +dest+ must respond to #write(str).
|
1096
|
+
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
|
439
1097
|
#
|
440
1098
|
def copy_stream(src, dest)
|
441
1099
|
IO.copy_stream(src, dest)
|
442
1100
|
end
|
443
1101
|
module_function :copy_stream
|
444
1102
|
|
445
|
-
#
|
446
|
-
#
|
447
|
-
#
|
448
|
-
#
|
449
|
-
#
|
450
|
-
#
|
451
|
-
#
|
452
|
-
#
|
453
|
-
#
|
1103
|
+
# Moves entries.
|
1104
|
+
#
|
1105
|
+
# Arguments +src+ (a single path or an array of paths)
|
1106
|
+
# and +dest+ (a single path)
|
1107
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
1108
|
+
#
|
1109
|
+
# If +src+ and +dest+ are on different file systems,
|
1110
|
+
# first copies, then removes +src+.
|
1111
|
+
#
|
1112
|
+
# May cause a local vulnerability if not called with keyword argument
|
1113
|
+
# <tt>secure: true</tt>;
|
1114
|
+
# see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
|
1115
|
+
#
|
1116
|
+
# If +src+ is the path to a single file or directory and +dest+ does not exist,
|
1117
|
+
# moves +src+ to +dest+:
|
1118
|
+
#
|
1119
|
+
# tree('src0')
|
1120
|
+
# # => src0
|
1121
|
+
# # |-- src0.txt
|
1122
|
+
# # `-- src1.txt
|
1123
|
+
# File.exist?('dest0') # => false
|
1124
|
+
# Bundler::FileUtils.mv('src0', 'dest0')
|
1125
|
+
# File.exist?('src0') # => false
|
1126
|
+
# tree('dest0')
|
1127
|
+
# # => dest0
|
1128
|
+
# # |-- src0.txt
|
1129
|
+
# # `-- src1.txt
|
1130
|
+
#
|
1131
|
+
# If +src+ is an array of paths to files and directories
|
1132
|
+
# and +dest+ is the path to a directory,
|
1133
|
+
# copies from each path in the array to +dest+:
|
1134
|
+
#
|
1135
|
+
# File.file?('src1.txt') # => true
|
1136
|
+
# tree('src1')
|
1137
|
+
# # => src1
|
1138
|
+
# # |-- src.dat
|
1139
|
+
# # `-- src.txt
|
1140
|
+
# Dir.empty?('dest1') # => true
|
1141
|
+
# Bundler::FileUtils.mv(['src1.txt', 'src1'], 'dest1')
|
1142
|
+
# tree('dest1')
|
1143
|
+
# # => dest1
|
1144
|
+
# # |-- src1
|
1145
|
+
# # | |-- src.dat
|
1146
|
+
# # | `-- src.txt
|
1147
|
+
# # `-- src1.txt
|
1148
|
+
#
|
1149
|
+
# Keyword arguments:
|
1150
|
+
#
|
1151
|
+
# - <tt>force: true</tt> - if the move includes removing +src+
|
1152
|
+
# (that is, if +src+ and +dest+ are on different file systems),
|
1153
|
+
# ignores raised exceptions of StandardError and its descendants.
|
1154
|
+
# - <tt>noop: true</tt> - does not move files.
|
1155
|
+
# - <tt>secure: true</tt> - removes +src+ securely;
|
1156
|
+
# see details at Bundler::FileUtils.remove_entry_secure.
|
1157
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
1158
|
+
#
|
1159
|
+
# Bundler::FileUtils.mv('src0', 'dest0', noop: true, verbose: true)
|
1160
|
+
# Bundler::FileUtils.mv(['src1.txt', 'src1'], 'dest1', noop: true, verbose: true)
|
1161
|
+
#
|
1162
|
+
# Output:
|
1163
|
+
#
|
1164
|
+
# mv src0 dest0
|
1165
|
+
# mv src1.txt src1 dest1
|
1166
|
+
#
|
1167
|
+
# Bundler::FileUtils.move is an alias for Bundler::FileUtils.mv.
|
454
1168
|
#
|
455
1169
|
def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
|
456
1170
|
fu_output_message "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
|
@@ -461,13 +1175,12 @@ module Bundler::FileUtils
|
|
461
1175
|
if destent.exist?
|
462
1176
|
if destent.directory?
|
463
1177
|
raise Errno::EEXIST, d
|
464
|
-
else
|
465
|
-
destent.remove_file if rename_cannot_overwrite_file?
|
466
1178
|
end
|
467
1179
|
end
|
468
1180
|
begin
|
469
1181
|
File.rename s, d
|
470
|
-
rescue Errno::EXDEV
|
1182
|
+
rescue Errno::EXDEV,
|
1183
|
+
Errno::EPERM # move from unencrypted to encrypted dir (ext4)
|
471
1184
|
copy_entry s, d, true
|
472
1185
|
if secure
|
473
1186
|
remove_entry_secure s, force
|
@@ -485,18 +1198,34 @@ module Bundler::FileUtils
|
|
485
1198
|
alias move mv
|
486
1199
|
module_function :move
|
487
1200
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
1201
|
+
# Removes entries at the paths in the given +list+
|
1202
|
+
# (a single path or an array of paths)
|
1203
|
+
# returns +list+, if it is an array, <tt>[list]</tt> otherwise.
|
1204
|
+
#
|
1205
|
+
# Argument +list+ or its elements
|
1206
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
1207
|
+
#
|
1208
|
+
# With no keyword arguments, removes files at the paths given in +list+:
|
1209
|
+
#
|
1210
|
+
# Bundler::FileUtils.touch(['src0.txt', 'src0.dat'])
|
1211
|
+
# Bundler::FileUtils.rm(['src0.dat', 'src0.txt']) # => ["src0.dat", "src0.txt"]
|
1212
|
+
#
|
1213
|
+
# Keyword arguments:
|
493
1214
|
#
|
494
|
-
#
|
495
|
-
#
|
1215
|
+
# - <tt>force: true</tt> - ignores raised exceptions of StandardError
|
1216
|
+
# and its descendants.
|
1217
|
+
# - <tt>noop: true</tt> - does not remove files; returns +nil+.
|
1218
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
496
1219
|
#
|
497
|
-
#
|
498
|
-
#
|
499
|
-
#
|
1220
|
+
# Bundler::FileUtils.rm(['src0.dat', 'src0.txt'], noop: true, verbose: true)
|
1221
|
+
#
|
1222
|
+
# Output:
|
1223
|
+
#
|
1224
|
+
# rm src0.dat src0.txt
|
1225
|
+
#
|
1226
|
+
# Bundler::FileUtils.remove is an alias for Bundler::FileUtils.rm.
|
1227
|
+
#
|
1228
|
+
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
|
500
1229
|
#
|
501
1230
|
def rm(list, force: nil, noop: nil, verbose: nil)
|
502
1231
|
list = fu_list(list)
|
@@ -512,10 +1241,18 @@ module Bundler::FileUtils
|
|
512
1241
|
alias remove rm
|
513
1242
|
module_function :remove
|
514
1243
|
|
1244
|
+
# Equivalent to:
|
1245
|
+
#
|
1246
|
+
# Bundler::FileUtils.rm(list, force: true, **kwargs)
|
515
1247
|
#
|
516
|
-
#
|
1248
|
+
# Argument +list+ (a single path or an array of paths)
|
1249
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
517
1250
|
#
|
518
|
-
#
|
1251
|
+
# See Bundler::FileUtils.rm for keyword arguments.
|
1252
|
+
#
|
1253
|
+
# Bundler::FileUtils.safe_unlink is an alias for Bundler::FileUtils.rm_f.
|
1254
|
+
#
|
1255
|
+
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
|
519
1256
|
#
|
520
1257
|
def rm_f(list, noop: nil, verbose: nil)
|
521
1258
|
rm list, force: true, noop: noop, verbose: verbose
|
@@ -525,24 +1262,55 @@ module Bundler::FileUtils
|
|
525
1262
|
alias safe_unlink rm_f
|
526
1263
|
module_function :safe_unlink
|
527
1264
|
|
1265
|
+
# Removes entries at the paths in the given +list+
|
1266
|
+
# (a single path or an array of paths);
|
1267
|
+
# returns +list+, if it is an array, <tt>[list]</tt> otherwise.
|
1268
|
+
#
|
1269
|
+
# Argument +list+ or its elements
|
1270
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
1271
|
+
#
|
1272
|
+
# May cause a local vulnerability if not called with keyword argument
|
1273
|
+
# <tt>secure: true</tt>;
|
1274
|
+
# see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
|
1275
|
+
#
|
1276
|
+
# For each file path, removes the file at that path:
|
1277
|
+
#
|
1278
|
+
# Bundler::FileUtils.touch(['src0.txt', 'src0.dat'])
|
1279
|
+
# Bundler::FileUtils.rm_r(['src0.dat', 'src0.txt'])
|
1280
|
+
# File.exist?('src0.txt') # => false
|
1281
|
+
# File.exist?('src0.dat') # => false
|
1282
|
+
#
|
1283
|
+
# For each directory path, recursively removes files and directories:
|
1284
|
+
#
|
1285
|
+
# tree('src1')
|
1286
|
+
# # => src1
|
1287
|
+
# # |-- dir0
|
1288
|
+
# # | |-- src0.txt
|
1289
|
+
# # | `-- src1.txt
|
1290
|
+
# # `-- dir1
|
1291
|
+
# # |-- src2.txt
|
1292
|
+
# # `-- src3.txt
|
1293
|
+
# Bundler::FileUtils.rm_r('src1')
|
1294
|
+
# File.exist?('src1') # => false
|
1295
|
+
#
|
1296
|
+
# Keyword arguments:
|
1297
|
+
#
|
1298
|
+
# - <tt>force: true</tt> - ignores raised exceptions of StandardError
|
1299
|
+
# and its descendants.
|
1300
|
+
# - <tt>noop: true</tt> - does not remove entries; returns +nil+.
|
1301
|
+
# - <tt>secure: true</tt> - removes +src+ securely;
|
1302
|
+
# see details at Bundler::FileUtils.remove_entry_secure.
|
1303
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
528
1304
|
#
|
529
|
-
#
|
530
|
-
#
|
531
|
-
# StandardError when :force option is set.
|
1305
|
+
# Bundler::FileUtils.rm_r(['src0.dat', 'src0.txt'], noop: true, verbose: true)
|
1306
|
+
# Bundler::FileUtils.rm_r('src1', noop: true, verbose: true)
|
532
1307
|
#
|
533
|
-
#
|
534
|
-
# Bundler::FileUtils.rm_r 'some_dir', :force => true
|
1308
|
+
# Output:
|
535
1309
|
#
|
536
|
-
#
|
537
|
-
#
|
538
|
-
# writable (including /tmp, whose permission is 1777), and the current
|
539
|
-
# process has strong privilege such as Unix super user (root), and the
|
540
|
-
# system has symbolic link. For secure removing, read the documentation
|
541
|
-
# of #remove_entry_secure carefully, and set :secure option to true.
|
542
|
-
# Default is :secure=>false.
|
1310
|
+
# rm -r src0.dat src0.txt
|
1311
|
+
# rm -r src1
|
543
1312
|
#
|
544
|
-
#
|
545
|
-
# See also #remove_entry_secure.
|
1313
|
+
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
|
546
1314
|
#
|
547
1315
|
def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil)
|
548
1316
|
list = fu_list(list)
|
@@ -558,13 +1326,22 @@ module Bundler::FileUtils
|
|
558
1326
|
end
|
559
1327
|
module_function :rm_r
|
560
1328
|
|
1329
|
+
# Equivalent to:
|
561
1330
|
#
|
562
|
-
#
|
1331
|
+
# Bundler::FileUtils.rm_r(list, force: true, **kwargs)
|
563
1332
|
#
|
564
|
-
#
|
1333
|
+
# Argument +list+ or its elements
|
1334
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
565
1335
|
#
|
566
|
-
#
|
567
|
-
#
|
1336
|
+
# May cause a local vulnerability if not called with keyword argument
|
1337
|
+
# <tt>secure: true</tt>;
|
1338
|
+
# see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
|
1339
|
+
#
|
1340
|
+
# See Bundler::FileUtils.rm_r for keyword arguments.
|
1341
|
+
#
|
1342
|
+
# Bundler::FileUtils.rmtree is an alias for Bundler::FileUtils.rm_rf.
|
1343
|
+
#
|
1344
|
+
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
|
568
1345
|
#
|
569
1346
|
def rm_rf(list, noop: nil, verbose: nil, secure: nil)
|
570
1347
|
rm_r list, force: true, noop: noop, verbose: verbose, secure: secure
|
@@ -574,37 +1351,20 @@ module Bundler::FileUtils
|
|
574
1351
|
alias rmtree rm_rf
|
575
1352
|
module_function :rmtree
|
576
1353
|
|
1354
|
+
# Securely removes the entry given by +path+,
|
1355
|
+
# which should be the entry for a regular file, a symbolic link,
|
1356
|
+
# or a directory.
|
577
1357
|
#
|
578
|
-
#
|
579
|
-
#
|
580
|
-
# remove it recursively. This method is required to avoid TOCTTOU
|
581
|
-
# (time-of-check-to-time-of-use) local security vulnerability of #rm_r.
|
582
|
-
# #rm_r causes security hole when:
|
583
|
-
#
|
584
|
-
# * Parent directory is world writable (including /tmp).
|
585
|
-
# * Removing directory tree includes world writable directory.
|
586
|
-
# * The system has symbolic link.
|
587
|
-
#
|
588
|
-
# To avoid this security hole, this method applies special preprocess.
|
589
|
-
# If +path+ is a directory, this method chown(2) and chmod(2) all
|
590
|
-
# removing directories. This requires the current process is the
|
591
|
-
# owner of the removing whole directory tree, or is the super user (root).
|
592
|
-
#
|
593
|
-
# WARNING: You must ensure that *ALL* parent directories cannot be
|
594
|
-
# moved by other untrusted users. For example, parent directories
|
595
|
-
# should not be owned by untrusted users, and should not be world
|
596
|
-
# writable except when the sticky bit set.
|
1358
|
+
# Argument +path+
|
1359
|
+
# should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
|
597
1360
|
#
|
598
|
-
#
|
599
|
-
#
|
600
|
-
# work.
|
1361
|
+
# Avoids a local vulnerability that can exist in certain circumstances;
|
1362
|
+
# see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
|
601
1363
|
#
|
602
|
-
#
|
1364
|
+
# Optional argument +force+ specifies whether to ignore
|
1365
|
+
# raised exceptions of StandardError and its descendants.
|
603
1366
|
#
|
604
|
-
#
|
605
|
-
# * http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452
|
606
|
-
#
|
607
|
-
# For fileutils.rb, this vulnerability is reported in [ruby-dev:26100].
|
1367
|
+
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
|
608
1368
|
#
|
609
1369
|
def remove_entry_secure(path, force = false)
|
610
1370
|
unless fu_have_symlink?
|
@@ -626,22 +1386,38 @@ module Bundler::FileUtils
|
|
626
1386
|
unless parent_st.sticky?
|
627
1387
|
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})"
|
628
1388
|
end
|
1389
|
+
|
629
1390
|
# freeze tree root
|
630
1391
|
euid = Process.euid
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
1392
|
+
dot_file = fullpath + "/."
|
1393
|
+
begin
|
1394
|
+
File.open(dot_file) {|f|
|
1395
|
+
unless fu_stat_identical_entry?(st, f.stat)
|
1396
|
+
# symlink (TOC-to-TOU attack?)
|
1397
|
+
File.unlink fullpath
|
1398
|
+
return
|
1399
|
+
end
|
1400
|
+
f.chown euid, -1
|
1401
|
+
f.chmod 0700
|
1402
|
+
}
|
1403
|
+
rescue Errno::EISDIR # JRuby in non-native mode can't open files as dirs
|
1404
|
+
File.lstat(dot_file).tap {|fstat|
|
1405
|
+
unless fu_stat_identical_entry?(st, fstat)
|
1406
|
+
# symlink (TOC-to-TOU attack?)
|
1407
|
+
File.unlink fullpath
|
1408
|
+
return
|
1409
|
+
end
|
1410
|
+
File.chown euid, -1, dot_file
|
1411
|
+
File.chmod 0700, dot_file
|
1412
|
+
}
|
1413
|
+
end
|
1414
|
+
|
1415
|
+
unless fu_stat_identical_entry?(st, File.lstat(fullpath))
|
1416
|
+
# TOC-to-TOU attack?
|
1417
|
+
File.unlink fullpath
|
1418
|
+
return
|
1419
|
+
end
|
1420
|
+
|
645
1421
|
# ---- tree root is frozen ----
|
646
1422
|
root = Entry_.new(path)
|
647
1423
|
root.preorder_traverse do |ent|
|
@@ -676,12 +1452,17 @@ module Bundler::FileUtils
|
|
676
1452
|
end
|
677
1453
|
private_module_function :fu_stat_identical_entry?
|
678
1454
|
|
1455
|
+
# Removes the entry given by +path+,
|
1456
|
+
# which should be the entry for a regular file, a symbolic link,
|
1457
|
+
# or a directory.
|
1458
|
+
#
|
1459
|
+
# Argument +path+
|
1460
|
+
# should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
|
679
1461
|
#
|
680
|
-
#
|
681
|
-
#
|
682
|
-
# If +path+ is a directory, remove it recursively.
|
1462
|
+
# Optional argument +force+ specifies whether to ignore
|
1463
|
+
# raised exceptions of StandardError and its descendants.
|
683
1464
|
#
|
684
|
-
#
|
1465
|
+
# Related: Bundler::FileUtils.remove_entry_secure.
|
685
1466
|
#
|
686
1467
|
def remove_entry(path, force = false)
|
687
1468
|
Entry_.new(path).postorder_traverse do |ent|
|
@@ -696,9 +1477,16 @@ module Bundler::FileUtils
|
|
696
1477
|
end
|
697
1478
|
module_function :remove_entry
|
698
1479
|
|
1480
|
+
# Removes the file entry given by +path+,
|
1481
|
+
# which should be the entry for a regular file or a symbolic link.
|
1482
|
+
#
|
1483
|
+
# Argument +path+
|
1484
|
+
# should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
|
699
1485
|
#
|
700
|
-
#
|
701
|
-
#
|
1486
|
+
# Optional argument +force+ specifies whether to ignore
|
1487
|
+
# raised exceptions of StandardError and its descendants.
|
1488
|
+
#
|
1489
|
+
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
|
702
1490
|
#
|
703
1491
|
def remove_file(path, force = false)
|
704
1492
|
Entry_.new(path).remove_file
|
@@ -707,20 +1495,32 @@ module Bundler::FileUtils
|
|
707
1495
|
end
|
708
1496
|
module_function :remove_file
|
709
1497
|
|
1498
|
+
# Recursively removes the directory entry given by +path+,
|
1499
|
+
# which should be the entry for a regular file, a symbolic link,
|
1500
|
+
# or a directory.
|
1501
|
+
#
|
1502
|
+
# Argument +path+
|
1503
|
+
# should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
|
1504
|
+
#
|
1505
|
+
# Optional argument +force+ specifies whether to ignore
|
1506
|
+
# raised exceptions of StandardError and its descendants.
|
710
1507
|
#
|
711
|
-
#
|
712
|
-
# This method ignores StandardError if +force+ is true.
|
1508
|
+
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
|
713
1509
|
#
|
714
1510
|
def remove_dir(path, force = false)
|
715
1511
|
remove_entry path, force # FIXME?? check if it is a directory
|
716
1512
|
end
|
717
1513
|
module_function :remove_dir
|
718
1514
|
|
1515
|
+
# Returns +true+ if the contents of files +a+ and +b+ are identical,
|
1516
|
+
# +false+ otherwise.
|
719
1517
|
#
|
720
|
-
#
|
1518
|
+
# Arguments +a+ and +b+
|
1519
|
+
# should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
|
721
1520
|
#
|
722
|
-
#
|
723
|
-
#
|
1521
|
+
# Bundler::FileUtils.identical? and Bundler::FileUtils.cmp are aliases for Bundler::FileUtils.compare_file.
|
1522
|
+
#
|
1523
|
+
# Related: Bundler::FileUtils.compare_stream.
|
724
1524
|
#
|
725
1525
|
def compare_file(a, b)
|
726
1526
|
return false unless File.size(a) == File.size(b)
|
@@ -737,13 +1537,20 @@ module Bundler::FileUtils
|
|
737
1537
|
module_function :identical?
|
738
1538
|
module_function :cmp
|
739
1539
|
|
1540
|
+
# Returns +true+ if the contents of streams +a+ and +b+ are identical,
|
1541
|
+
# +false+ otherwise.
|
1542
|
+
#
|
1543
|
+
# Arguments +a+ and +b+
|
1544
|
+
# should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
|
740
1545
|
#
|
741
|
-
#
|
1546
|
+
# Related: Bundler::FileUtils.compare_file.
|
742
1547
|
#
|
743
1548
|
def compare_stream(a, b)
|
744
1549
|
bsize = fu_stream_blksize(a, b)
|
1550
|
+
|
745
1551
|
sa = String.new(capacity: bsize)
|
746
1552
|
sb = String.new(capacity: bsize)
|
1553
|
+
|
747
1554
|
begin
|
748
1555
|
a.read(bsize, sa)
|
749
1556
|
b.read(bsize, sb)
|
@@ -753,13 +1560,69 @@ module Bundler::FileUtils
|
|
753
1560
|
end
|
754
1561
|
module_function :compare_stream
|
755
1562
|
|
1563
|
+
# Copies a file entry.
|
1564
|
+
# See {install(1)}[https://man7.org/linux/man-pages/man1/install.1.html].
|
1565
|
+
#
|
1566
|
+
# Arguments +src+ (a single path or an array of paths)
|
1567
|
+
# and +dest+ (a single path)
|
1568
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments];
|
1569
|
+
#
|
1570
|
+
# If the entry at +dest+ does not exist, copies from +src+ to +dest+:
|
1571
|
+
#
|
1572
|
+
# File.read('src0.txt') # => "aaa\n"
|
1573
|
+
# File.exist?('dest0.txt') # => false
|
1574
|
+
# Bundler::FileUtils.install('src0.txt', 'dest0.txt')
|
1575
|
+
# File.read('dest0.txt') # => "aaa\n"
|
1576
|
+
#
|
1577
|
+
# If +dest+ is a file entry, copies from +src+ to +dest+, overwriting:
|
1578
|
+
#
|
1579
|
+
# File.read('src1.txt') # => "aaa\n"
|
1580
|
+
# File.read('dest1.txt') # => "bbb\n"
|
1581
|
+
# Bundler::FileUtils.install('src1.txt', 'dest1.txt')
|
1582
|
+
# File.read('dest1.txt') # => "aaa\n"
|
1583
|
+
#
|
1584
|
+
# If +dest+ is a directory entry, copies from +src+ to <tt>dest/src</tt>,
|
1585
|
+
# overwriting if necessary:
|
1586
|
+
#
|
1587
|
+
# File.read('src2.txt') # => "aaa\n"
|
1588
|
+
# File.read('dest2/src2.txt') # => "bbb\n"
|
1589
|
+
# Bundler::FileUtils.install('src2.txt', 'dest2')
|
1590
|
+
# File.read('dest2/src2.txt') # => "aaa\n"
|
1591
|
+
#
|
1592
|
+
# If +src+ is an array of paths and +dest+ points to a directory,
|
1593
|
+
# copies each path +path+ in +src+ to <tt>dest/path</tt>:
|
1594
|
+
#
|
1595
|
+
# File.file?('src3.txt') # => true
|
1596
|
+
# File.file?('src3.dat') # => true
|
1597
|
+
# Bundler::FileUtils.mkdir('dest3')
|
1598
|
+
# Bundler::FileUtils.install(['src3.txt', 'src3.dat'], 'dest3')
|
1599
|
+
# File.file?('dest3/src3.txt') # => true
|
1600
|
+
# File.file?('dest3/src3.dat') # => true
|
1601
|
+
#
|
1602
|
+
# Keyword arguments:
|
1603
|
+
#
|
1604
|
+
# - <tt>group: <i>group</i></tt> - changes the group if not +nil+,
|
1605
|
+
# using {File.chown}[https://docs.ruby-lang.org/en/master/File.html#method-c-chown].
|
1606
|
+
# - <tt>mode: <i>permissions</i></tt> - changes the permissions.
|
1607
|
+
# using {File.chmod}[https://docs.ruby-lang.org/en/master/File.html#method-c-chmod].
|
1608
|
+
# - <tt>noop: true</tt> - does not copy entries; returns +nil+.
|
1609
|
+
# - <tt>owner: <i>owner</i></tt> - changes the owner if not +nil+,
|
1610
|
+
# using {File.chown}[https://docs.ruby-lang.org/en/master/File.html#method-c-chown].
|
1611
|
+
# - <tt>preserve: true</tt> - preserve timestamps
|
1612
|
+
# using {File.utime}[https://docs.ruby-lang.org/en/master/File.html#method-c-utime].
|
1613
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
756
1614
|
#
|
757
|
-
#
|
758
|
-
#
|
759
|
-
#
|
1615
|
+
# Bundler::FileUtils.install('src0.txt', 'dest0.txt', noop: true, verbose: true)
|
1616
|
+
# Bundler::FileUtils.install('src1.txt', 'dest1.txt', noop: true, verbose: true)
|
1617
|
+
# Bundler::FileUtils.install('src2.txt', 'dest2', noop: true, verbose: true)
|
760
1618
|
#
|
761
|
-
#
|
762
|
-
#
|
1619
|
+
# Output:
|
1620
|
+
#
|
1621
|
+
# install -c src0.txt dest0.txt
|
1622
|
+
# install -c src1.txt dest1.txt
|
1623
|
+
# install -c src2.txt dest2
|
1624
|
+
#
|
1625
|
+
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
|
763
1626
|
#
|
764
1627
|
def install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil,
|
765
1628
|
noop: nil, verbose: nil)
|
@@ -819,11 +1682,8 @@ module Bundler::FileUtils
|
|
819
1682
|
private_module_function :apply_mask
|
820
1683
|
|
821
1684
|
def symbolic_modes_to_i(mode_sym, path) #:nodoc:
|
822
|
-
|
823
|
-
|
824
|
-
else
|
825
|
-
File.stat(path).mode
|
826
|
-
end
|
1685
|
+
path = File.stat(path) unless File::Stat === path
|
1686
|
+
mode = path.mode
|
827
1687
|
mode_sym.split(/,/).inject(mode & 07777) do |current_mode, clause|
|
828
1688
|
target, *actions = clause.split(/([=+-])/)
|
829
1689
|
raise ArgumentError, "invalid file mode: #{mode_sym}" if actions.empty?
|
@@ -840,7 +1700,7 @@ module Bundler::FileUtils
|
|
840
1700
|
when "x"
|
841
1701
|
mask | 0111
|
842
1702
|
when "X"
|
843
|
-
if
|
1703
|
+
if path.directory?
|
844
1704
|
mask | 0111
|
845
1705
|
else
|
846
1706
|
mask
|
@@ -880,37 +1740,78 @@ module Bundler::FileUtils
|
|
880
1740
|
end
|
881
1741
|
private_module_function :mode_to_s
|
882
1742
|
|
1743
|
+
# Changes permissions on the entries at the paths given in +list+
|
1744
|
+
# (a single path or an array of paths)
|
1745
|
+
# to the permissions given by +mode+;
|
1746
|
+
# returns +list+ if it is an array, <tt>[list]</tt> otherwise:
|
1747
|
+
#
|
1748
|
+
# - Modifies each entry that is a regular file using
|
1749
|
+
# {File.chmod}[https://docs.ruby-lang.org/en/master/File.html#method-c-chmod].
|
1750
|
+
# - Modifies each entry that is a symbolic link using
|
1751
|
+
# {File.lchmod}[https://docs.ruby-lang.org/en/master/File.html#method-c-lchmod].
|
1752
|
+
#
|
1753
|
+
# Argument +list+ or its elements
|
1754
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
1755
|
+
#
|
1756
|
+
# Argument +mode+ may be either an integer or a string:
|
1757
|
+
#
|
1758
|
+
# - \Integer +mode+: represents the permission bits to be set:
|
1759
|
+
#
|
1760
|
+
# Bundler::FileUtils.chmod(0755, 'src0.txt')
|
1761
|
+
# Bundler::FileUtils.chmod(0644, ['src0.txt', 'src0.dat'])
|
1762
|
+
#
|
1763
|
+
# - \String +mode+: represents the permissions to be set:
|
1764
|
+
#
|
1765
|
+
# The string is of the form <tt>[targets][[operator][perms[,perms]]</tt>, where:
|
1766
|
+
#
|
1767
|
+
# - +targets+ may be any combination of these letters:
|
1768
|
+
#
|
1769
|
+
# - <tt>'u'</tt>: permissions apply to the file's owner.
|
1770
|
+
# - <tt>'g'</tt>: permissions apply to users in the file's group.
|
1771
|
+
# - <tt>'o'</tt>: permissions apply to other users not in the file's group.
|
1772
|
+
# - <tt>'a'</tt> (the default): permissions apply to all users.
|
1773
|
+
#
|
1774
|
+
# - +operator+ may be one of these letters:
|
1775
|
+
#
|
1776
|
+
# - <tt>'+'</tt>: adds permissions.
|
1777
|
+
# - <tt>'-'</tt>: removes permissions.
|
1778
|
+
# - <tt>'='</tt>: sets (replaces) permissions.
|
1779
|
+
#
|
1780
|
+
# - +perms+ (may be repeated, with separating commas)
|
1781
|
+
# may be any combination of these letters:
|
1782
|
+
#
|
1783
|
+
# - <tt>'r'</tt>: Read.
|
1784
|
+
# - <tt>'w'</tt>: Write.
|
1785
|
+
# - <tt>'x'</tt>: Execute (search, for a directory).
|
1786
|
+
# - <tt>'X'</tt>: Search (for a directories only;
|
1787
|
+
# must be used with <tt>'+'</tt>)
|
1788
|
+
# - <tt>'s'</tt>: Uid or gid.
|
1789
|
+
# - <tt>'t'</tt>: Sticky bit.
|
1790
|
+
#
|
1791
|
+
# Examples:
|
1792
|
+
#
|
1793
|
+
# Bundler::FileUtils.chmod('u=wrx,go=rx', 'src1.txt')
|
1794
|
+
# Bundler::FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby')
|
1795
|
+
#
|
1796
|
+
# Keyword arguments:
|
1797
|
+
#
|
1798
|
+
# - <tt>noop: true</tt> - does not change permissions; returns +nil+.
|
1799
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
1800
|
+
#
|
1801
|
+
# Bundler::FileUtils.chmod(0755, 'src0.txt', noop: true, verbose: true)
|
1802
|
+
# Bundler::FileUtils.chmod(0644, ['src0.txt', 'src0.dat'], noop: true, verbose: true)
|
1803
|
+
# Bundler::FileUtils.chmod('u=wrx,go=rx', 'src1.txt', noop: true, verbose: true)
|
1804
|
+
# Bundler::FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby', noop: true, verbose: true)
|
1805
|
+
#
|
1806
|
+
# Output:
|
1807
|
+
#
|
1808
|
+
# chmod 755 src0.txt
|
1809
|
+
# chmod 644 src0.txt src0.dat
|
1810
|
+
# chmod u=wrx,go=rx src1.txt
|
1811
|
+
# chmod u=wrx,go=rx /usr/bin/ruby
|
1812
|
+
#
|
1813
|
+
# Related: Bundler::FileUtils.chmod_R.
|
883
1814
|
#
|
884
|
-
# Changes permission bits on the named files (in +list+) to the bit pattern
|
885
|
-
# represented by +mode+.
|
886
|
-
#
|
887
|
-
# +mode+ is the symbolic and absolute mode can be used.
|
888
|
-
#
|
889
|
-
# Absolute mode is
|
890
|
-
# Bundler::FileUtils.chmod 0755, 'somecommand'
|
891
|
-
# Bundler::FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb)
|
892
|
-
# Bundler::FileUtils.chmod 0755, '/usr/bin/ruby', :verbose => true
|
893
|
-
#
|
894
|
-
# Symbolic mode is
|
895
|
-
# Bundler::FileUtils.chmod "u=wrx,go=rx", 'somecommand'
|
896
|
-
# Bundler::FileUtils.chmod "u=wr,go=rr", %w(my.rb your.rb his.rb her.rb)
|
897
|
-
# Bundler::FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', :verbose => true
|
898
|
-
#
|
899
|
-
# "a" :: is user, group, other mask.
|
900
|
-
# "u" :: is user's mask.
|
901
|
-
# "g" :: is group's mask.
|
902
|
-
# "o" :: is other's mask.
|
903
|
-
# "w" :: is write permission.
|
904
|
-
# "r" :: is read permission.
|
905
|
-
# "x" :: is execute permission.
|
906
|
-
# "X" ::
|
907
|
-
# is execute permission for directories only, must be used in conjunction with "+"
|
908
|
-
# "s" :: is uid, gid.
|
909
|
-
# "t" :: is sticky bit.
|
910
|
-
# "+" :: is added to a class given the specified mode.
|
911
|
-
# "-" :: Is removed from a given class given mode.
|
912
|
-
# "=" :: Is the exact nature of the class will be given a specified mode.
|
913
|
-
|
914
1815
|
def chmod(mode, list, noop: nil, verbose: nil)
|
915
1816
|
list = fu_list(list)
|
916
1817
|
fu_output_message sprintf('chmod %s %s', mode_to_s(mode), list.join(' ')) if verbose
|
@@ -921,12 +1822,7 @@ module Bundler::FileUtils
|
|
921
1822
|
end
|
922
1823
|
module_function :chmod
|
923
1824
|
|
924
|
-
#
|
925
|
-
# Changes permission bits on the named files (in +list+)
|
926
|
-
# to the bit pattern represented by +mode+.
|
927
|
-
#
|
928
|
-
# Bundler::FileUtils.chmod_R 0700, "/tmp/app.#{$$}"
|
929
|
-
# Bundler::FileUtils.chmod_R "u=wrx", "/tmp/app.#{$$}"
|
1825
|
+
# Like Bundler::FileUtils.chmod, but changes permissions recursively.
|
930
1826
|
#
|
931
1827
|
def chmod_R(mode, list, noop: nil, verbose: nil, force: nil)
|
932
1828
|
list = fu_list(list)
|
@@ -946,15 +1842,68 @@ module Bundler::FileUtils
|
|
946
1842
|
end
|
947
1843
|
module_function :chmod_R
|
948
1844
|
|
1845
|
+
# Changes the owner and group on the entries at the paths given in +list+
|
1846
|
+
# (a single path or an array of paths)
|
1847
|
+
# to the given +user+ and +group+;
|
1848
|
+
# returns +list+ if it is an array, <tt>[list]</tt> otherwise:
|
1849
|
+
#
|
1850
|
+
# - Modifies each entry that is a regular file using
|
1851
|
+
# {File.chown}[https://docs.ruby-lang.org/en/master/File.html#method-c-chown].
|
1852
|
+
# - Modifies each entry that is a symbolic link using
|
1853
|
+
# {File.lchown}[https://docs.ruby-lang.org/en/master/File.html#method-c-lchown].
|
1854
|
+
#
|
1855
|
+
# Argument +list+ or its elements
|
1856
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
1857
|
+
#
|
1858
|
+
# User and group:
|
1859
|
+
#
|
1860
|
+
# - Argument +user+ may be a user name or a user id;
|
1861
|
+
# if +nil+ or +-1+, the user is not changed.
|
1862
|
+
# - Argument +group+ may be a group name or a group id;
|
1863
|
+
# if +nil+ or +-1+, the group is not changed.
|
1864
|
+
# - The user must be a member of the group.
|
1865
|
+
#
|
1866
|
+
# Examples:
|
1867
|
+
#
|
1868
|
+
# # One path.
|
1869
|
+
# # User and group as string names.
|
1870
|
+
# File.stat('src0.txt').uid # => 1004
|
1871
|
+
# File.stat('src0.txt').gid # => 1004
|
1872
|
+
# Bundler::FileUtils.chown('user2', 'group1', 'src0.txt')
|
1873
|
+
# File.stat('src0.txt').uid # => 1006
|
1874
|
+
# File.stat('src0.txt').gid # => 1005
|
949
1875
|
#
|
950
|
-
#
|
951
|
-
#
|
952
|
-
#
|
953
|
-
#
|
954
|
-
# the attribute.
|
1876
|
+
# # User and group as uid and gid.
|
1877
|
+
# Bundler::FileUtils.chown(1004, 1004, 'src0.txt')
|
1878
|
+
# File.stat('src0.txt').uid # => 1004
|
1879
|
+
# File.stat('src0.txt').gid # => 1004
|
955
1880
|
#
|
956
|
-
#
|
957
|
-
# Bundler::FileUtils.chown
|
1881
|
+
# # Array of paths.
|
1882
|
+
# Bundler::FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'])
|
1883
|
+
#
|
1884
|
+
# # Directory (not recursive).
|
1885
|
+
# Bundler::FileUtils.chown('user2', 'group1', '.')
|
1886
|
+
#
|
1887
|
+
# Keyword arguments:
|
1888
|
+
#
|
1889
|
+
# - <tt>noop: true</tt> - does not change permissions; returns +nil+.
|
1890
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
1891
|
+
#
|
1892
|
+
# Bundler::FileUtils.chown('user2', 'group1', 'src0.txt', noop: true, verbose: true)
|
1893
|
+
# Bundler::FileUtils.chown(1004, 1004, 'src0.txt', noop: true, verbose: true)
|
1894
|
+
# Bundler::FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'], noop: true, verbose: true)
|
1895
|
+
# Bundler::FileUtils.chown('user2', 'group1', path, noop: true, verbose: true)
|
1896
|
+
# Bundler::FileUtils.chown('user2', 'group1', '.', noop: true, verbose: true)
|
1897
|
+
#
|
1898
|
+
# Output:
|
1899
|
+
#
|
1900
|
+
# chown user2:group1 src0.txt
|
1901
|
+
# chown 1004:1004 src0.txt
|
1902
|
+
# chown 1006:1005 src0.txt src0.dat
|
1903
|
+
# chown user2:group1 src0.txt
|
1904
|
+
# chown user2:group1 .
|
1905
|
+
#
|
1906
|
+
# Related: Bundler::FileUtils.chown_R.
|
958
1907
|
#
|
959
1908
|
def chown(user, group, list, noop: nil, verbose: nil)
|
960
1909
|
list = fu_list(list)
|
@@ -970,15 +1919,7 @@ module Bundler::FileUtils
|
|
970
1919
|
end
|
971
1920
|
module_function :chown
|
972
1921
|
|
973
|
-
#
|
974
|
-
# Changes owner and group on the named files (in +list+)
|
975
|
-
# to the user +user+ and the group +group+ recursively.
|
976
|
-
# +user+ and +group+ may be an ID (Integer/String) or
|
977
|
-
# a name (String). If +user+ or +group+ is nil, this
|
978
|
-
# method does not change the attribute.
|
979
|
-
#
|
980
|
-
# Bundler::FileUtils.chown_R 'www', 'www', '/var/www/htdocs'
|
981
|
-
# Bundler::FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', :verbose => true
|
1922
|
+
# Like Bundler::FileUtils.chown, but changes owner and group recursively.
|
982
1923
|
#
|
983
1924
|
def chown_R(user, group, list, noop: nil, verbose: nil, force: nil)
|
984
1925
|
list = fu_list(list)
|
@@ -1001,11 +1942,6 @@ module Bundler::FileUtils
|
|
1001
1942
|
end
|
1002
1943
|
module_function :chown_R
|
1003
1944
|
|
1004
|
-
begin
|
1005
|
-
require 'etc'
|
1006
|
-
rescue LoadError # rescue LoadError for miniruby
|
1007
|
-
end
|
1008
|
-
|
1009
1945
|
def fu_get_uid(user) #:nodoc:
|
1010
1946
|
return nil unless user
|
1011
1947
|
case user
|
@@ -1014,6 +1950,7 @@ module Bundler::FileUtils
|
|
1014
1950
|
when /\A\d+\z/
|
1015
1951
|
user.to_i
|
1016
1952
|
else
|
1953
|
+
require 'etc'
|
1017
1954
|
Etc.getpwnam(user) ? Etc.getpwnam(user).uid : nil
|
1018
1955
|
end
|
1019
1956
|
end
|
@@ -1027,17 +1964,56 @@ module Bundler::FileUtils
|
|
1027
1964
|
when /\A\d+\z/
|
1028
1965
|
group.to_i
|
1029
1966
|
else
|
1967
|
+
require 'etc'
|
1030
1968
|
Etc.getgrnam(group) ? Etc.getgrnam(group).gid : nil
|
1031
1969
|
end
|
1032
1970
|
end
|
1033
1971
|
private_module_function :fu_get_gid
|
1034
1972
|
|
1973
|
+
# Updates modification times (mtime) and access times (atime)
|
1974
|
+
# of the entries given by the paths in +list+
|
1975
|
+
# (a single path or an array of paths);
|
1976
|
+
# returns +list+ if it is an array, <tt>[list]</tt> otherwise.
|
1977
|
+
#
|
1978
|
+
# By default, creates an empty file for any path to a non-existent entry;
|
1979
|
+
# use keyword argument +nocreate+ to raise an exception instead.
|
1980
|
+
#
|
1981
|
+
# Argument +list+ or its elements
|
1982
|
+
# should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
|
1983
|
+
#
|
1984
|
+
# Examples:
|
1985
|
+
#
|
1986
|
+
# # Single path.
|
1987
|
+
# f = File.new('src0.txt') # Existing file.
|
1988
|
+
# f.atime # => 2022-06-10 11:11:21.200277 -0700
|
1989
|
+
# f.mtime # => 2022-06-10 11:11:21.200277 -0700
|
1990
|
+
# Bundler::FileUtils.touch('src0.txt')
|
1991
|
+
# f = File.new('src0.txt')
|
1992
|
+
# f.atime # => 2022-06-11 08:28:09.8185343 -0700
|
1993
|
+
# f.mtime # => 2022-06-11 08:28:09.8185343 -0700
|
1994
|
+
#
|
1995
|
+
# # Array of paths.
|
1996
|
+
# Bundler::FileUtils.touch(['src0.txt', 'src0.dat'])
|
1035
1997
|
#
|
1036
|
-
#
|
1037
|
-
# +list+. Files are created if they don't exist.
|
1998
|
+
# Keyword arguments:
|
1038
1999
|
#
|
1039
|
-
#
|
1040
|
-
#
|
2000
|
+
# - <tt>mtime: <i>time</i></tt> - sets the entry's mtime to the given time,
|
2001
|
+
# instead of the current time.
|
2002
|
+
# - <tt>nocreate: true</tt> - raises an exception if the entry does not exist.
|
2003
|
+
# - <tt>noop: true</tt> - does not touch entries; returns +nil+.
|
2004
|
+
# - <tt>verbose: true</tt> - prints an equivalent command:
|
2005
|
+
#
|
2006
|
+
# Bundler::FileUtils.touch('src0.txt', noop: true, verbose: true)
|
2007
|
+
# Bundler::FileUtils.touch(['src0.txt', 'src0.dat'], noop: true, verbose: true)
|
2008
|
+
# Bundler::FileUtils.touch(path, noop: true, verbose: true)
|
2009
|
+
#
|
2010
|
+
# Output:
|
2011
|
+
#
|
2012
|
+
# touch src0.txt
|
2013
|
+
# touch src0.txt src0.dat
|
2014
|
+
# touch src0.txt
|
2015
|
+
#
|
2016
|
+
# Related: Bundler::FileUtils.uptodate?.
|
1041
2017
|
#
|
1042
2018
|
def touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil)
|
1043
2019
|
list = fu_list(list)
|
@@ -1067,8 +2043,11 @@ module Bundler::FileUtils
|
|
1067
2043
|
module StreamUtils_
|
1068
2044
|
private
|
1069
2045
|
|
1070
|
-
|
1071
|
-
|
2046
|
+
case (defined?(::RbConfig) ? ::RbConfig::CONFIG['host_os'] : ::RUBY_PLATFORM)
|
2047
|
+
when /mswin|mingw/
|
2048
|
+
def fu_windows?; true end
|
2049
|
+
else
|
2050
|
+
def fu_windows?; false end
|
1072
2051
|
end
|
1073
2052
|
|
1074
2053
|
def fu_copy_stream0(src, dest, blksize = nil) #:nodoc:
|
@@ -1192,10 +2171,12 @@ module Bundler::FileUtils
|
|
1192
2171
|
|
1193
2172
|
def entries
|
1194
2173
|
opts = {}
|
1195
|
-
opts[:encoding] = ::Encoding::UTF_8
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
2174
|
+
opts[:encoding] = fu_windows? ? ::Encoding::UTF_8 : path.encoding
|
2175
|
+
|
2176
|
+
files = Dir.children(path, **opts)
|
2177
|
+
|
2178
|
+
untaint = RUBY_VERSION < '2.7'
|
2179
|
+
files.map {|n| Entry_.new(prefix(), join(rel(), untaint ? n.untaint : n)) }
|
1199
2180
|
end
|
1200
2181
|
|
1201
2182
|
def stat
|
@@ -1240,6 +2221,7 @@ module Bundler::FileUtils
|
|
1240
2221
|
else
|
1241
2222
|
File.chmod mode, path()
|
1242
2223
|
end
|
2224
|
+
rescue Errno::EOPNOTSUPP
|
1243
2225
|
end
|
1244
2226
|
|
1245
2227
|
def chown(uid, gid)
|
@@ -1250,6 +2232,22 @@ module Bundler::FileUtils
|
|
1250
2232
|
end
|
1251
2233
|
end
|
1252
2234
|
|
2235
|
+
def link(dest)
|
2236
|
+
case
|
2237
|
+
when directory?
|
2238
|
+
if !File.exist?(dest) and descendant_directory?(dest, path)
|
2239
|
+
raise ArgumentError, "cannot link directory %s to itself %s" % [path, dest]
|
2240
|
+
end
|
2241
|
+
begin
|
2242
|
+
Dir.mkdir dest
|
2243
|
+
rescue
|
2244
|
+
raise unless File.directory?(dest)
|
2245
|
+
end
|
2246
|
+
else
|
2247
|
+
File.link path(), dest
|
2248
|
+
end
|
2249
|
+
end
|
2250
|
+
|
1253
2251
|
def copy(dest)
|
1254
2252
|
lstat
|
1255
2253
|
case
|
@@ -1266,18 +2264,21 @@ module Bundler::FileUtils
|
|
1266
2264
|
end
|
1267
2265
|
when symlink?
|
1268
2266
|
File.symlink File.readlink(path()), dest
|
1269
|
-
when chardev?
|
1270
|
-
raise "cannot handle device file"
|
1271
|
-
mknod dest, ?c, 0666, lstat().rdev
|
1272
|
-
when blockdev?
|
1273
|
-
raise "cannot handle device file" unless File.respond_to?(:mknod)
|
1274
|
-
mknod dest, ?b, 0666, lstat().rdev
|
2267
|
+
when chardev?, blockdev?
|
2268
|
+
raise "cannot handle device file"
|
1275
2269
|
when socket?
|
1276
|
-
|
1277
|
-
|
2270
|
+
begin
|
2271
|
+
require 'socket'
|
2272
|
+
rescue LoadError
|
2273
|
+
raise "cannot handle socket"
|
2274
|
+
else
|
2275
|
+
raise "cannot handle socket" unless defined?(UNIXServer)
|
2276
|
+
end
|
2277
|
+
UNIXServer.new(dest).close
|
2278
|
+
File.chmod lstat().mode, dest
|
1278
2279
|
when pipe?
|
1279
2280
|
raise "cannot handle FIFO" unless File.respond_to?(:mkfifo)
|
1280
|
-
mkfifo dest,
|
2281
|
+
File.mkfifo dest, lstat().mode
|
1281
2282
|
when door?
|
1282
2283
|
raise "cannot handle door: #{path()}"
|
1283
2284
|
else
|
@@ -1315,7 +2316,7 @@ module Bundler::FileUtils
|
|
1315
2316
|
if st.symlink?
|
1316
2317
|
begin
|
1317
2318
|
File.lchmod mode, path
|
1318
|
-
rescue NotImplementedError
|
2319
|
+
rescue NotImplementedError, Errno::EOPNOTSUPP
|
1319
2320
|
end
|
1320
2321
|
else
|
1321
2322
|
File.chmod mode, path
|
@@ -1374,13 +2375,21 @@ module Bundler::FileUtils
|
|
1374
2375
|
|
1375
2376
|
def postorder_traverse
|
1376
2377
|
if directory?
|
1377
|
-
|
2378
|
+
begin
|
2379
|
+
children = entries()
|
2380
|
+
rescue Errno::EACCES
|
2381
|
+
# Failed to get the list of children.
|
2382
|
+
# Assuming there is no children, try to process the parent directory.
|
2383
|
+
yield self
|
2384
|
+
return
|
2385
|
+
end
|
2386
|
+
|
2387
|
+
children.each do |ent|
|
1378
2388
|
ent.postorder_traverse do |e|
|
1379
2389
|
yield e
|
1380
2390
|
end
|
1381
2391
|
end
|
1382
2392
|
end
|
1383
|
-
ensure
|
1384
2393
|
yield self
|
1385
2394
|
end
|
1386
2395
|
|
@@ -1396,14 +2405,14 @@ module Bundler::FileUtils
|
|
1396
2405
|
|
1397
2406
|
private
|
1398
2407
|
|
1399
|
-
|
2408
|
+
@@fileutils_rb_have_lchmod = nil
|
1400
2409
|
|
1401
2410
|
def have_lchmod?
|
1402
2411
|
# This is not MT-safe, but it does not matter.
|
1403
|
-
if
|
1404
|
-
|
2412
|
+
if @@fileutils_rb_have_lchmod == nil
|
2413
|
+
@@fileutils_rb_have_lchmod = check_have_lchmod?
|
1405
2414
|
end
|
1406
|
-
|
2415
|
+
@@fileutils_rb_have_lchmod
|
1407
2416
|
end
|
1408
2417
|
|
1409
2418
|
def check_have_lchmod?
|
@@ -1414,14 +2423,14 @@ module Bundler::FileUtils
|
|
1414
2423
|
return false
|
1415
2424
|
end
|
1416
2425
|
|
1417
|
-
|
2426
|
+
@@fileutils_rb_have_lchown = nil
|
1418
2427
|
|
1419
2428
|
def have_lchown?
|
1420
2429
|
# This is not MT-safe, but it does not matter.
|
1421
|
-
if
|
1422
|
-
|
2430
|
+
if @@fileutils_rb_have_lchown == nil
|
2431
|
+
@@fileutils_rb_have_lchown = check_have_lchown?
|
1423
2432
|
end
|
1424
|
-
|
2433
|
+
@@fileutils_rb_have_lchown
|
1425
2434
|
end
|
1426
2435
|
|
1427
2436
|
def check_have_lchown?
|
@@ -1435,7 +2444,15 @@ module Bundler::FileUtils
|
|
1435
2444
|
def join(dir, base)
|
1436
2445
|
return File.path(dir) if not base or base == '.'
|
1437
2446
|
return File.path(base) if not dir or dir == '.'
|
1438
|
-
|
2447
|
+
begin
|
2448
|
+
File.join(dir, base)
|
2449
|
+
rescue EncodingError
|
2450
|
+
if fu_windows?
|
2451
|
+
File.join(dir.encode(::Encoding::UTF_8), base.encode(::Encoding::UTF_8))
|
2452
|
+
else
|
2453
|
+
raise
|
2454
|
+
end
|
2455
|
+
end
|
1439
2456
|
end
|
1440
2457
|
|
1441
2458
|
if File::ALT_SEPARATOR
|
@@ -1443,10 +2460,13 @@ module Bundler::FileUtils
|
|
1443
2460
|
else
|
1444
2461
|
DIRECTORY_TERM = "(?=/|\\z)"
|
1445
2462
|
end
|
1446
|
-
SYSCASE = File::FNM_SYSCASE.nonzero? ? "-i" : ""
|
1447
2463
|
|
1448
2464
|
def descendant_directory?(descendant, ascendant)
|
1449
|
-
|
2465
|
+
if File::FNM_SYSCASE.nonzero?
|
2466
|
+
File.expand_path(File.dirname(descendant)).casecmp(File.expand_path(ascendant)) == 0
|
2467
|
+
else
|
2468
|
+
File.expand_path(File.dirname(descendant)) == File.expand_path(ascendant)
|
2469
|
+
end
|
1450
2470
|
end
|
1451
2471
|
end # class Entry_
|
1452
2472
|
|
@@ -1463,15 +2483,15 @@ module Bundler::FileUtils
|
|
1463
2483
|
end
|
1464
2484
|
private_module_function :fu_each_src_dest
|
1465
2485
|
|
1466
|
-
def fu_each_src_dest0(src, dest) #:nodoc:
|
2486
|
+
def fu_each_src_dest0(src, dest, target_directory = true) #:nodoc:
|
1467
2487
|
if tmp = Array.try_convert(src)
|
1468
2488
|
tmp.each do |s|
|
1469
2489
|
s = File.path(s)
|
1470
|
-
yield s, File.join(dest, File.basename(s))
|
2490
|
+
yield s, (target_directory ? File.join(dest, File.basename(s)) : dest)
|
1471
2491
|
end
|
1472
2492
|
else
|
1473
2493
|
src = File.path(src)
|
1474
|
-
if File.directory?(dest)
|
2494
|
+
if target_directory and File.directory?(dest)
|
1475
2495
|
yield src, File.join(dest, File.basename(src))
|
1476
2496
|
else
|
1477
2497
|
yield src, File.path(dest)
|
@@ -1485,16 +2505,66 @@ module Bundler::FileUtils
|
|
1485
2505
|
end
|
1486
2506
|
private_module_function :fu_same?
|
1487
2507
|
|
1488
|
-
@fileutils_output = $stderr
|
1489
|
-
@fileutils_label = ''
|
1490
|
-
|
1491
2508
|
def fu_output_message(msg) #:nodoc:
|
1492
|
-
@fileutils_output
|
1493
|
-
|
1494
|
-
|
2509
|
+
output = @fileutils_output if defined?(@fileutils_output)
|
2510
|
+
output ||= $stdout
|
2511
|
+
if defined?(@fileutils_label)
|
2512
|
+
msg = @fileutils_label + msg
|
2513
|
+
end
|
2514
|
+
output.puts msg
|
1495
2515
|
end
|
1496
2516
|
private_module_function :fu_output_message
|
1497
2517
|
|
2518
|
+
def fu_split_path(path)
|
2519
|
+
path = File.path(path)
|
2520
|
+
list = []
|
2521
|
+
until (parent, base = File.split(path); parent == path or parent == ".")
|
2522
|
+
list << base
|
2523
|
+
path = parent
|
2524
|
+
end
|
2525
|
+
list << path
|
2526
|
+
list.reverse!
|
2527
|
+
end
|
2528
|
+
private_module_function :fu_split_path
|
2529
|
+
|
2530
|
+
def fu_relative_components_from(target, base) #:nodoc:
|
2531
|
+
i = 0
|
2532
|
+
while target[i]&.== base[i]
|
2533
|
+
i += 1
|
2534
|
+
end
|
2535
|
+
Array.new(base.size-i, '..').concat(target[i..-1])
|
2536
|
+
end
|
2537
|
+
private_module_function :fu_relative_components_from
|
2538
|
+
|
2539
|
+
def fu_clean_components(*comp)
|
2540
|
+
comp.shift while comp.first == "."
|
2541
|
+
return comp if comp.empty?
|
2542
|
+
clean = [comp.shift]
|
2543
|
+
path = File.join(*clean, "") # ending with File::SEPARATOR
|
2544
|
+
while c = comp.shift
|
2545
|
+
if c == ".." and clean.last != ".." and !(fu_have_symlink? && File.symlink?(path))
|
2546
|
+
clean.pop
|
2547
|
+
path.chomp!(%r((?<=\A|/)[^/]+/\z), "")
|
2548
|
+
else
|
2549
|
+
clean << c
|
2550
|
+
path << c << "/"
|
2551
|
+
end
|
2552
|
+
end
|
2553
|
+
clean
|
2554
|
+
end
|
2555
|
+
private_module_function :fu_clean_components
|
2556
|
+
|
2557
|
+
if fu_windows?
|
2558
|
+
def fu_starting_path?(path)
|
2559
|
+
path&.start_with?(%r(\w:|/))
|
2560
|
+
end
|
2561
|
+
else
|
2562
|
+
def fu_starting_path?(path)
|
2563
|
+
path&.start_with?("/")
|
2564
|
+
end
|
2565
|
+
end
|
2566
|
+
private_module_function :fu_starting_path?
|
2567
|
+
|
1498
2568
|
# This hash table holds command options.
|
1499
2569
|
OPT_TABLE = {} #:nodoc: internal use only
|
1500
2570
|
(private_instance_methods & methods(false)).inject(OPT_TABLE) {|tbl, name|
|
@@ -1502,62 +2572,66 @@ module Bundler::FileUtils
|
|
1502
2572
|
tbl
|
1503
2573
|
}
|
1504
2574
|
|
2575
|
+
public
|
2576
|
+
|
2577
|
+
# Returns an array of the string names of \Bundler::FileUtils methods
|
2578
|
+
# that accept one or more keyword arguments:
|
1505
2579
|
#
|
1506
|
-
#
|
1507
|
-
#
|
1508
|
-
# p Bundler::FileUtils.commands #=> ["chmod", "cp", "cp_r", "install", ...]
|
2580
|
+
# Bundler::FileUtils.commands.sort.take(3) # => ["cd", "chdir", "chmod"]
|
1509
2581
|
#
|
1510
2582
|
def self.commands
|
1511
2583
|
OPT_TABLE.keys
|
1512
2584
|
end
|
1513
2585
|
|
2586
|
+
# Returns an array of the string keyword names:
|
1514
2587
|
#
|
1515
|
-
#
|
1516
|
-
#
|
1517
|
-
# p Bundler::FileUtils.options #=> ["noop", "force", "verbose", "preserve", "mode"]
|
2588
|
+
# Bundler::FileUtils.options.take(3) # => ["noop", "verbose", "force"]
|
1518
2589
|
#
|
1519
2590
|
def self.options
|
1520
2591
|
OPT_TABLE.values.flatten.uniq.map {|sym| sym.to_s }
|
1521
2592
|
end
|
1522
2593
|
|
2594
|
+
# Returns +true+ if method +mid+ accepts the given option +opt+, +false+ otherwise;
|
2595
|
+
# the arguments may be strings or symbols:
|
1523
2596
|
#
|
1524
|
-
#
|
1525
|
-
#
|
1526
|
-
# p Bundler::FileUtils.have_option?(:cp, :noop) #=> true
|
1527
|
-
# p Bundler::FileUtils.have_option?(:rm, :force) #=> true
|
1528
|
-
# p Bundler::FileUtils.have_option?(:rm, :preserve) #=> false
|
2597
|
+
# Bundler::FileUtils.have_option?(:chmod, :noop) # => true
|
2598
|
+
# Bundler::FileUtils.have_option?('chmod', 'secure') # => false
|
1529
2599
|
#
|
1530
2600
|
def self.have_option?(mid, opt)
|
1531
2601
|
li = OPT_TABLE[mid.to_s] or raise ArgumentError, "no such method: #{mid}"
|
1532
2602
|
li.include?(opt)
|
1533
2603
|
end
|
1534
2604
|
|
2605
|
+
# Returns an array of the string keyword name for method +mid+;
|
2606
|
+
# the argument may be a string or a symbol:
|
1535
2607
|
#
|
1536
|
-
#
|
1537
|
-
#
|
1538
|
-
# p Bundler::FileUtils.options_of(:rm) #=> ["noop", "verbose", "force"]
|
2608
|
+
# Bundler::FileUtils.options_of(:rm) # => ["force", "noop", "verbose"]
|
2609
|
+
# Bundler::FileUtils.options_of('mv') # => ["force", "noop", "verbose", "secure"]
|
1539
2610
|
#
|
1540
2611
|
def self.options_of(mid)
|
1541
2612
|
OPT_TABLE[mid.to_s].map {|sym| sym.to_s }
|
1542
2613
|
end
|
1543
2614
|
|
2615
|
+
# Returns an array of the string method names of the methods
|
2616
|
+
# that accept the given keyword option +opt+;
|
2617
|
+
# the argument must be a symbol:
|
1544
2618
|
#
|
1545
|
-
#
|
1546
|
-
#
|
1547
|
-
# p Bundler::FileUtils.collect_method(:preserve) #=> ["cp", "cp_r", "copy", "install"]
|
2619
|
+
# Bundler::FileUtils.collect_method(:preserve) # => ["cp", "copy", "cp_r", "install"]
|
1548
2620
|
#
|
1549
2621
|
def self.collect_method(opt)
|
1550
2622
|
OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) }
|
1551
2623
|
end
|
1552
2624
|
|
1553
|
-
|
1554
|
-
|
2625
|
+
private
|
2626
|
+
|
2627
|
+
LOW_METHODS = singleton_methods(false) - collect_method(:noop).map(&:intern) # :nodoc:
|
2628
|
+
module LowMethods # :nodoc: internal use only
|
1555
2629
|
private
|
1556
2630
|
def _do_nothing(*)end
|
1557
2631
|
::Bundler::FileUtils::LOW_METHODS.map {|name| alias_method name, :_do_nothing}
|
1558
2632
|
end
|
1559
2633
|
|
1560
|
-
METHODS = singleton_methods() - [:private_module_function,
|
2634
|
+
METHODS = singleton_methods() - [:private_module_function, # :nodoc:
|
1561
2635
|
:commands, :options, :have_option?, :options_of, :collect_method]
|
1562
2636
|
|
1563
2637
|
#
|
@@ -1567,8 +2641,6 @@ module Bundler::FileUtils
|
|
1567
2641
|
#
|
1568
2642
|
module Verbose
|
1569
2643
|
include Bundler::FileUtils
|
1570
|
-
@fileutils_output = $stderr
|
1571
|
-
@fileutils_label = ''
|
1572
2644
|
names = ::Bundler::FileUtils.collect_method(:verbose)
|
1573
2645
|
names.each do |name|
|
1574
2646
|
module_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
@@ -1592,8 +2664,6 @@ module Bundler::FileUtils
|
|
1592
2664
|
module NoWrite
|
1593
2665
|
include Bundler::FileUtils
|
1594
2666
|
include LowMethods
|
1595
|
-
@fileutils_output = $stderr
|
1596
|
-
@fileutils_label = ''
|
1597
2667
|
names = ::Bundler::FileUtils.collect_method(:noop)
|
1598
2668
|
names.each do |name|
|
1599
2669
|
module_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
@@ -1618,8 +2688,6 @@ module Bundler::FileUtils
|
|
1618
2688
|
module DryRun
|
1619
2689
|
include Bundler::FileUtils
|
1620
2690
|
include LowMethods
|
1621
|
-
@fileutils_output = $stderr
|
1622
|
-
@fileutils_label = ''
|
1623
2691
|
names = ::Bundler::FileUtils.collect_method(:noop)
|
1624
2692
|
names.each do |name|
|
1625
2693
|
module_eval(<<-EOS, __FILE__, __LINE__ + 1)
|