1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Update bundled bundler to 1.16.0.

* lib/bundler, spec/bundler: Merge bundler-1.16.0.
  * common.mk: rspec examples of bundler-1.16.0 needs require option.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60603 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
hsbt 2017-11-01 23:29:38 +00:00
parent ae49dbd392
commit be7b592912
1025 changed files with 13902 additions and 3180 deletions

View file

@ -23,7 +23,7 @@ Bundler.with_friendly_errors do
require "bundler/cli"
# Allow any command to use --help flag to show help for that command
help_flags = %w(--help -h)
help_flags = %w[--help -h]
help_flag_used = ARGV.any? {|a| help_flags.include? a }
args = help_flag_used ? Bundler::CLI.reformatted_help_args(ARGV) : ARGV

View file

@ -1185,7 +1185,7 @@ test-bundler: $(TEST_RUNNABLE)-test-bundler
yes-test-bundler: yes-test-bundler-prepare
$(gnumake_recursive)$(Q) \
$(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/rspec \
$(RSPECOPTS) spec/bundler/$(BUNDLER_SPECS)
--require spec_helper $(RSPECOPTS) spec/bundler/$(BUNDLER_SPECS)
no-test-bundler:
UNICODE_FILES = $(UNICODE_SRC_DATA_DIR)/UnicodeData.txt \

View file

@ -1,8 +1,8 @@
# coding: utf-8
# frozen_string_literal: true
lib = File.expand_path("../lib/", __FILE__)
$:.unshift lib unless $:.include?(lib)
require "bundler/version"
require File.expand_path("../bundler/version", __FILE__)
require "shellwords"
Gem::Specification.new do |s|
s.name = "bundler"
@ -27,225 +27,315 @@ Gem::Specification.new do |s|
}
end
s.required_ruby_version = ">= 1.8.7"
s.required_rubygems_version = ">= 1.3.6"
if s.version >= Gem::Version.new("2.a".dup)
s.required_ruby_version = ">= 2.3.0"
s.required_rubygems_version = ">= 2.5.0"
else
s.required_ruby_version = ">= 1.8.7"
s.required_rubygems_version = ">= 1.3.6"
end
s.add_development_dependency "automatiek", "~> 0.1.0"
s.add_development_dependency "mustache", "0.99.6"
s.add_development_dependency "rake", "~> 10.0"
s.add_development_dependency "rdiscount", "~> 2.2"
s.add_development_dependency "ronn", "~> 0.7.3"
s.add_development_dependency "rspec", "~> 3.5"
s.add_development_dependency "rspec", "~> 3.6"
s.files = [
"lib/bundler.gemspec",
"bin/bundle",
"bin/bundle_ruby",
"bin/bundler",
"lib/bundler.rb",
"lib/bundler/capistrano.rb",
"lib/bundler/cli.rb",
"lib/bundler/cli/add.rb",
"lib/bundler/cli/binstubs.rb",
"lib/bundler/cli/cache.rb",
"lib/bundler/cli/check.rb",
"lib/bundler/cli/clean.rb",
"lib/bundler/cli/common.rb",
"lib/bundler/cli/config.rb",
"lib/bundler/cli/console.rb",
"lib/bundler/cli/doctor.rb",
"lib/bundler/cli/exec.rb",
"lib/bundler/cli/gem.rb",
"lib/bundler/cli/info.rb",
"lib/bundler/cli/init.rb",
"lib/bundler/cli/inject.rb",
"lib/bundler/cli/install.rb",
"lib/bundler/cli/issue.rb",
"lib/bundler/cli/lock.rb",
"lib/bundler/cli/open.rb",
"lib/bundler/cli/outdated.rb",
"lib/bundler/cli/package.rb",
"lib/bundler/cli/platform.rb",
"lib/bundler/cli/plugin.rb",
"lib/bundler/cli/pristine.rb",
"lib/bundler/cli/show.rb",
"lib/bundler/cli/update.rb",
"lib/bundler/cli/viz.rb",
"lib/bundler/compact_index_client.rb",
"lib/bundler/compact_index_client/cache.rb",
"lib/bundler/compact_index_client/updater.rb",
"lib/bundler/constants.rb",
"lib/bundler/current_ruby.rb",
"lib/bundler/definition.rb",
"lib/bundler/dep_proxy.rb",
"lib/bundler/dependency.rb",
"lib/bundler/deployment.rb",
"lib/bundler/deprecate.rb",
"lib/bundler/dsl.rb",
"lib/bundler/endpoint_specification.rb",
"lib/bundler/env.rb",
"lib/bundler/environment_preserver.rb",
"lib/bundler/errors.rb",
"lib/bundler/feature_flag.rb",
"lib/bundler/fetcher.rb",
"lib/bundler/fetcher/base.rb",
"lib/bundler/fetcher/compact_index.rb",
"lib/bundler/fetcher/dependency.rb",
"lib/bundler/fetcher/downloader.rb",
"lib/bundler/fetcher/index.rb",
"lib/bundler/friendly_errors.rb",
"lib/bundler/gem_helper.rb",
"lib/bundler/gem_helpers.rb",
"lib/bundler/gem_remote_fetcher.rb",
"lib/bundler/gem_tasks.rb",
"lib/bundler/gem_version_promoter.rb",
"lib/bundler/gemdeps.rb",
"lib/bundler/graph.rb",
"lib/bundler/index.rb",
"lib/bundler/injector.rb",
"lib/bundler/inline.rb",
"lib/bundler/installer.rb",
"lib/bundler/installer/gem_installer.rb",
"lib/bundler/installer/parallel_installer.rb",
"lib/bundler/installer/standalone.rb",
"lib/bundler/lazy_specification.rb",
"lib/bundler/lockfile_parser.rb",
"lib/bundler/match_platform.rb",
"lib/bundler/mirror.rb",
"lib/bundler/plugin.rb",
"lib/bundler/plugin/api.rb",
"lib/bundler/plugin/api/source.rb",
"lib/bundler/plugin/dsl.rb",
"lib/bundler/plugin/index.rb",
"lib/bundler/plugin/installer.rb",
"lib/bundler/plugin/installer/git.rb",
"lib/bundler/plugin/installer/rubygems.rb",
"lib/bundler/plugin/source_list.rb",
"lib/bundler/psyched_yaml.rb",
"lib/bundler/remote_specification.rb",
"lib/bundler/resolver.rb",
"lib/bundler/retry.rb",
"lib/bundler/ruby_dsl.rb",
"lib/bundler/ruby_version.rb",
"lib/bundler/rubygems_ext.rb",
"lib/bundler/rubygems_gem_installer.rb",
"lib/bundler/rubygems_integration.rb",
"lib/bundler/runtime.rb",
"lib/bundler/settings.rb",
"lib/bundler/setup.rb",
"lib/bundler/shared_helpers.rb",
"lib/bundler/similarity_detector.rb",
"lib/bundler/source.rb",
"lib/bundler/source/gemspec.rb",
"lib/bundler/source/git.rb",
"lib/bundler/source/git/git_proxy.rb",
"lib/bundler/source/path.rb",
"lib/bundler/source/path/installer.rb",
"lib/bundler/source/rubygems.rb",
"lib/bundler/source/rubygems/remote.rb",
"lib/bundler/source_list.rb",
"lib/bundler/spec_set.rb",
"lib/bundler/ssl_certs/.document",
"lib/bundler/ssl_certs/certificate_manager.rb",
"lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem",
"lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem",
"lib/bundler/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem",
"lib/bundler/stub_specification.rb",
"lib/bundler/templates/Executable",
"lib/bundler/templates/Executable.standalone",
"lib/bundler/templates/Gemfile",
"lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt",
"lib/bundler/templates/newgem/Gemfile.tt",
"lib/bundler/templates/newgem/LICENSE.txt.tt",
"lib/bundler/templates/newgem/README.md.tt",
"lib/bundler/templates/newgem/Rakefile.tt",
"lib/bundler/templates/newgem/bin/console.tt",
"lib/bundler/templates/newgem/bin/setup.tt",
"lib/bundler/templates/newgem/exe/newgem.tt",
"lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt",
"lib/bundler/templates/newgem/ext/newgem/newgem.c.tt",
"lib/bundler/templates/newgem/ext/newgem/newgem.h.tt",
"lib/bundler/templates/newgem/gitignore.tt",
"lib/bundler/templates/newgem/lib/newgem.rb.tt",
"lib/bundler/templates/newgem/lib/newgem/version.rb.tt",
"lib/bundler/templates/newgem/newgem.gemspec.tt",
"lib/bundler/templates/newgem/rspec.tt",
"lib/bundler/templates/newgem/spec/newgem_spec.rb.tt",
"lib/bundler/templates/newgem/spec/spec_helper.rb.tt",
"lib/bundler/templates/newgem/test/newgem_test.rb.tt",
"lib/bundler/templates/newgem/test/test_helper.rb.tt",
"lib/bundler/templates/newgem/travis.yml.tt",
"lib/bundler/ui.rb",
"lib/bundler/ui/rg_proxy.rb",
"lib/bundler/ui/shell.rb",
"lib/bundler/ui/silent.rb",
"lib/bundler/uri_credentials_filter.rb",
"lib/bundler/vendor/molinillo/lib/molinillo.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/errors.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb",
"lib/bundler/vendor/molinillo/lib/molinillo/state.rb",
"lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb",
"lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb",
"lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb",
"lib/bundler/vendor/thor/lib/thor.rb",
"lib/bundler/vendor/thor/lib/thor/actions.rb",
"lib/bundler/vendor/thor/lib/thor/actions/create_file.rb",
"lib/bundler/vendor/thor/lib/thor/actions/create_link.rb",
"lib/bundler/vendor/thor/lib/thor/actions/directory.rb",
"lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb",
"lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb",
"lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb",
"lib/bundler/vendor/thor/lib/thor/base.rb",
"lib/bundler/vendor/thor/lib/thor/command.rb",
"lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb",
"lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb",
"lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb",
"lib/bundler/vendor/thor/lib/thor/error.rb",
"lib/bundler/vendor/thor/lib/thor/group.rb",
"lib/bundler/vendor/thor/lib/thor/invocation.rb",
"lib/bundler/vendor/thor/lib/thor/line_editor.rb",
"lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb",
"lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb",
"lib/bundler/vendor/thor/lib/thor/parser.rb",
"lib/bundler/vendor/thor/lib/thor/parser/argument.rb",
"lib/bundler/vendor/thor/lib/thor/parser/arguments.rb",
"lib/bundler/vendor/thor/lib/thor/parser/option.rb",
"lib/bundler/vendor/thor/lib/thor/parser/options.rb",
"lib/bundler/vendor/thor/lib/thor/rake_compat.rb",
"lib/bundler/vendor/thor/lib/thor/runner.rb",
"lib/bundler/vendor/thor/lib/thor/shell.rb",
"lib/bundler/vendor/thor/lib/thor/shell/basic.rb",
"lib/bundler/vendor/thor/lib/thor/shell/color.rb",
"lib/bundler/vendor/thor/lib/thor/shell/html.rb",
"lib/bundler/vendor/thor/lib/thor/util.rb",
"lib/bundler/vendor/thor/lib/thor/version.rb",
"lib/bundler/vendored_molinillo.rb",
"lib/bundler/vendored_persistent.rb",
"lib/bundler/vendored_thor.rb",
"lib/bundler/version.rb",
"lib/bundler/version_ranges.rb",
"lib/bundler/vlad.rb",
"lib/bundler/worker.rb",
"lib/bundler/yaml_serializer.rb"
s.files = %w[
exe/bundle
exe/bundle_ruby
exe/bundler
lib/bundler.rb
lib/bundler/build_metadata.rb
lib/bundler/capistrano.rb
lib/bundler/cli.rb
lib/bundler/cli/add.rb
lib/bundler/cli/binstubs.rb
lib/bundler/cli/cache.rb
lib/bundler/cli/check.rb
lib/bundler/cli/clean.rb
lib/bundler/cli/common.rb
lib/bundler/cli/config.rb
lib/bundler/cli/console.rb
lib/bundler/cli/doctor.rb
lib/bundler/cli/exec.rb
lib/bundler/cli/gem.rb
lib/bundler/cli/info.rb
lib/bundler/cli/init.rb
lib/bundler/cli/inject.rb
lib/bundler/cli/install.rb
lib/bundler/cli/issue.rb
lib/bundler/cli/list.rb
lib/bundler/cli/lock.rb
lib/bundler/cli/open.rb
lib/bundler/cli/outdated.rb
lib/bundler/cli/package.rb
lib/bundler/cli/platform.rb
lib/bundler/cli/plugin.rb
lib/bundler/cli/pristine.rb
lib/bundler/cli/show.rb
lib/bundler/cli/update.rb
lib/bundler/cli/viz.rb
lib/bundler/compact_index_client.rb
lib/bundler/compact_index_client/cache.rb
lib/bundler/compact_index_client/updater.rb
lib/bundler/compatibility_guard.rb
lib/bundler/constants.rb
lib/bundler/current_ruby.rb
lib/bundler/definition.rb
lib/bundler/dep_proxy.rb
lib/bundler/dependency.rb
lib/bundler/deployment.rb
lib/bundler/deprecate.rb
lib/bundler/dsl.rb
lib/bundler/endpoint_specification.rb
lib/bundler/env.rb
lib/bundler/environment_preserver.rb
lib/bundler/errors.rb
lib/bundler/feature_flag.rb
lib/bundler/fetcher.rb
lib/bundler/fetcher/base.rb
lib/bundler/fetcher/compact_index.rb
lib/bundler/fetcher/dependency.rb
lib/bundler/fetcher/downloader.rb
lib/bundler/fetcher/index.rb
lib/bundler/friendly_errors.rb
lib/bundler/gem_helper.rb
lib/bundler/gem_helpers.rb
lib/bundler/gem_remote_fetcher.rb
lib/bundler/gem_tasks.rb
lib/bundler/gem_version_promoter.rb
lib/bundler/gemdeps.rb
lib/bundler/graph.rb
lib/bundler/index.rb
lib/bundler/injector.rb
lib/bundler/inline.rb
lib/bundler/installer.rb
lib/bundler/installer/gem_installer.rb
lib/bundler/installer/parallel_installer.rb
lib/bundler/installer/standalone.rb
lib/bundler/lazy_specification.rb
lib/bundler/lockfile_generator.rb
lib/bundler/lockfile_parser.rb
lib/bundler/match_platform.rb
lib/bundler/mirror.rb
lib/bundler/plugin.rb
lib/bundler/plugin/api.rb
lib/bundler/plugin/api/source.rb
lib/bundler/plugin/dsl.rb
lib/bundler/plugin/index.rb
lib/bundler/plugin/installer.rb
lib/bundler/plugin/installer/git.rb
lib/bundler/plugin/installer/rubygems.rb
lib/bundler/plugin/source_list.rb
lib/bundler/process_lock.rb
lib/bundler/psyched_yaml.rb
lib/bundler/remote_specification.rb
lib/bundler/resolver.rb
lib/bundler/resolver/spec_group.rb
lib/bundler/retry.rb
lib/bundler/ruby_dsl.rb
lib/bundler/ruby_version.rb
lib/bundler/rubygems_ext.rb
lib/bundler/rubygems_gem_installer.rb
lib/bundler/rubygems_integration.rb
lib/bundler/runtime.rb
lib/bundler/settings.rb
lib/bundler/settings/validator.rb
lib/bundler/setup.rb
lib/bundler/shared_helpers.rb
lib/bundler/similarity_detector.rb
lib/bundler/source.rb
lib/bundler/source/gemspec.rb
lib/bundler/source/git.rb
lib/bundler/source/git/git_proxy.rb
lib/bundler/source/metadata.rb
lib/bundler/source/path.rb
lib/bundler/source/path/installer.rb
lib/bundler/source/rubygems.rb
lib/bundler/source/rubygems/remote.rb
lib/bundler/source_list.rb
lib/bundler/spec_set.rb
lib/bundler/ssl_certs/.document
lib/bundler/ssl_certs/certificate_manager.rb
lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem
lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem
lib/bundler/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem
lib/bundler/stub_specification.rb
lib/bundler/templates/Executable
lib/bundler/templates/Executable.bundler
lib/bundler/templates/Executable.standalone
lib/bundler/templates/Gemfile
lib/bundler/templates/gems.rb
lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
lib/bundler/templates/newgem/Gemfile.tt
lib/bundler/templates/newgem/LICENSE.txt.tt
lib/bundler/templates/newgem/README.md.tt
lib/bundler/templates/newgem/Rakefile.tt
lib/bundler/templates/newgem/bin/console.tt
lib/bundler/templates/newgem/bin/setup.tt
lib/bundler/templates/newgem/exe/newgem.tt
lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt
lib/bundler/templates/newgem/ext/newgem/newgem.c.tt
lib/bundler/templates/newgem/ext/newgem/newgem.h.tt
lib/bundler/templates/newgem/gitignore.tt
lib/bundler/templates/newgem/lib/newgem.rb.tt
lib/bundler/templates/newgem/lib/newgem/version.rb.tt
lib/bundler/templates/newgem/newgem.gemspec.tt
lib/bundler/templates/newgem/rspec.tt
lib/bundler/templates/newgem/spec/newgem_spec.rb.tt
lib/bundler/templates/newgem/spec/spec_helper.rb.tt
lib/bundler/templates/newgem/test/newgem_test.rb.tt
lib/bundler/templates/newgem/test/test_helper.rb.tt
lib/bundler/templates/newgem/travis.yml.tt
lib/bundler/ui.rb
lib/bundler/ui/rg_proxy.rb
lib/bundler/ui/shell.rb
lib/bundler/ui/silent.rb
lib/bundler/uri_credentials_filter.rb
lib/bundler/vendor/fileutils/lib/fileutils.rb
lib/bundler/vendor/molinillo/lib/molinillo.rb
lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb
lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb
lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb
lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb
lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb
lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb
lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb
lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb
lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb
lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb
lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb
lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb
lib/bundler/vendor/molinillo/lib/molinillo/errors.rb
lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb
lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb
lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb
lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb
lib/bundler/vendor/molinillo/lib/molinillo/state.rb
lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb
lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb
lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb
lib/bundler/vendor/thor/lib/thor.rb
lib/bundler/vendor/thor/lib/thor/actions.rb
lib/bundler/vendor/thor/lib/thor/actions/create_file.rb
lib/bundler/vendor/thor/lib/thor/actions/create_link.rb
lib/bundler/vendor/thor/lib/thor/actions/directory.rb
lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb
lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb
lib/bundler/vendor/thor/lib/thor/base.rb
lib/bundler/vendor/thor/lib/thor/command.rb
lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb
lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb
lib/bundler/vendor/thor/lib/thor/error.rb
lib/bundler/vendor/thor/lib/thor/group.rb
lib/bundler/vendor/thor/lib/thor/invocation.rb
lib/bundler/vendor/thor/lib/thor/line_editor.rb
lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb
lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb
lib/bundler/vendor/thor/lib/thor/parser.rb
lib/bundler/vendor/thor/lib/thor/parser/argument.rb
lib/bundler/vendor/thor/lib/thor/parser/arguments.rb
lib/bundler/vendor/thor/lib/thor/parser/option.rb
lib/bundler/vendor/thor/lib/thor/parser/options.rb
lib/bundler/vendor/thor/lib/thor/rake_compat.rb
lib/bundler/vendor/thor/lib/thor/runner.rb
lib/bundler/vendor/thor/lib/thor/shell.rb
lib/bundler/vendor/thor/lib/thor/shell/basic.rb
lib/bundler/vendor/thor/lib/thor/shell/color.rb
lib/bundler/vendor/thor/lib/thor/shell/html.rb
lib/bundler/vendor/thor/lib/thor/util.rb
lib/bundler/vendor/thor/lib/thor/version.rb
lib/bundler/vendored_fileutils.rb
lib/bundler/vendored_molinillo.rb
lib/bundler/vendored_persistent.rb
lib/bundler/vendored_thor.rb
lib/bundler/version.rb
lib/bundler/version_ranges.rb
lib/bundler/vlad.rb
lib/bundler/worker.rb
lib/bundler/yaml_serializer.rb
man/bundle-platform.1
man/bundle-update.1
man/bundle-init.1.txt
man/bundle-info.ronn
man/bundle-gem.ronn
man/bundle-add.1.txt
man/bundle-list.ronn
man/bundle-info.1
man/bundle-init.1
man/bundle-outdated.ronn
man/bundle-init.ronn
man/bundle.1
man/bundle-show.1.txt
man/bundle-exec.1
man/bundle-install.1.txt
man/bundle-binstubs.1.txt
man/bundle-open.1.txt
man/index.txt
man/bundle-pristine.ronn
man/bundle-install.1
man/bundle-inject.ronn
man/bundle-list.1
man/bundle-outdated.1.txt
man/bundle-list.1.txt
man/bundle-update.ronn
man/bundle-clean.1.txt
man/bundle-show.ronn
man/bundle-pristine.1.txt
man/bundle-outdated.1
man/bundle-check.1
man/bundle-show.1
man/gemfile.5
man/bundle-gem.1
man/bundle-install.ronn
man/bundle-gem.1.txt
man/bundle-open.1
man/bundle-add.ronn
man/bundle-lock.1.txt
man/bundle-open.ronn
man/bundle-lock.1
man/bundle-exec.ronn
man/bundle-check.ronn
man/bundle-info.1.txt
man/bundle-lock.ronn
man/bundle-pristine.1
man/bundle-viz.1.txt
man/bundle.ronn
man/bundle-platform.ronn
man/bundle-binstubs.ronn
man/bundle-exec.1.txt
man/bundle.1.txt
man/bundle-config.1.txt
man/bundle-package.1.txt
man/bundle-platform.1.txt
man/bundle-binstubs.1
man/bundle-viz.1
man/bundle-clean.ronn
man/bundle-package.1
man/bundle-add.1
man/bundle-config.1
man/bundle-package.ronn
man/bundle-viz.ronn
man/bundle-check.1.txt
man/bundle-clean.1
man/gemfile.5.txt
man/bundle-inject.1
man/gemfile.5.ronn
man/bundle-config.ronn
man/bundle-inject.1.txt
man/bundle-update.1.txt
CHANGELOG.md
LICENSE.md
README.md
]
s.bindir = "exe"
s.executables = %w(bundle bundler)
s.executables = %w[bundle bundler]
s.require_paths = ["lib"]
end

View file

@ -1,9 +1,11 @@
# frozen_string_literal: true
require "fileutils"
require "bundler/compatibility_guard"
require "bundler/vendored_fileutils"
require "pathname"
require "rbconfig"
require "thread"
require "tmpdir"
require "bundler/errors"
require "bundler/environment_preserver"
@ -13,9 +15,10 @@ require "bundler/rubygems_integration"
require "bundler/version"
require "bundler/constants"
require "bundler/current_ruby"
require "bundler/build_metadata"
module Bundler
environment_preserver = EnvironmentPreserver.new(ENV, %w(PATH GEM_PATH))
environment_preserver = EnvironmentPreserver.new(ENV, EnvironmentPreserver::BUNDLER_KEYS)
ORIGINAL_ENV = environment_preserver.restore
ENV.replace(environment_preserver.backup)
SUDO_MUTEX = Mutex.new
@ -40,6 +43,7 @@ module Bundler
autoload :LazySpecification, "bundler/lazy_specification"
autoload :LockfileParser, "bundler/lockfile_parser"
autoload :MatchPlatform, "bundler/match_platform"
autoload :ProcessLock, "bundler/process_lock"
autoload :RemoteSpecification, "bundler/remote_specification"
autoload :Resolver, "bundler/resolver"
autoload :Retry, "bundler/retry"
@ -58,8 +62,6 @@ module Bundler
autoload :VersionRanges, "bundler/version_ranges"
class << self
attr_writer :bundle_path
def configure
@configured ||= configure_gem_home_and_path
end
@ -75,7 +77,11 @@ module Bundler
# Returns absolute path of where gems are installed on the filesystem.
def bundle_path
@bundle_path ||= Pathname.new(settings.path).expand_path(root)
@bundle_path ||= Pathname.new(configured_bundle_path.path).expand_path(root)
end
def configured_bundle_path
@configured_bundle_path ||= settings.path.tap(&:validate!)
end
# Returns absolute location of where binstubs are installed to.
@ -113,7 +119,7 @@ module Bundler
end
def environment
SharedHelpers.major_deprecation "Bundler.environment has been removed in favor of Bundler.load"
SharedHelpers.major_deprecation 2, "Bundler.environment has been removed in favor of Bundler.load"
load
end
@ -130,6 +136,12 @@ module Bundler
end
end
def frozen?
frozen = settings[:deployment]
frozen ||= settings[:frozen] unless feature_flag.deployment_means_frozen?
frozen
end
def locked_gems
@locked_gems ||=
if defined?(@definition) && @definition
@ -168,6 +180,7 @@ module Bundler
def tmp_home_path(login, warning)
login ||= "unknown"
Kernel.send(:require, "tmpdir")
path = Pathname.new(Dir.tmpdir).join("bundler", "home")
SharedHelpers.filesystem_access(path) do |tmp_home_path|
unless tmp_home_path.exist?
@ -196,17 +209,13 @@ module Bundler
bundle_path.join("specifications")
end
def cache
bundle_path.join("cache/bundler")
end
def user_cache
user_bundle_path.join("cache")
end
def root
@root ||= begin
default_gemfile.dirname.expand_path
SharedHelpers.root
rescue GemfileNotFound
bundle_dir = default_bundle_dir
raise GemfileNotFound, "Could not locate Gemfile or .bundle/ directory" unless bundle_dir
@ -215,8 +224,8 @@ module Bundler
end
def app_config_path
if ENV["BUNDLE_APP_CONFIG"]
Pathname.new(ENV["BUNDLE_APP_CONFIG"]).expand_path(root)
if app_config = ENV["BUNDLE_APP_CONFIG"]
Pathname.new(app_config).expand_path(root)
else
root.join(".bundle")
end
@ -224,10 +233,11 @@ module Bundler
def app_cache(custom_path = nil)
path = custom_path || root
path.join(settings.app_cache_path)
Pathname.new(path).join(settings.app_cache_path)
end
def tmp(name = Process.pid.to_s)
Kernel.send(:require, "tmpdir")
Pathname.new(Dir.mktmpdir(["bundler", name]))
end
@ -257,7 +267,7 @@ EOF
# @deprecated Use `original_env` instead
# @return [Hash] Environment with all bundler-related variables removed
def clean_env
Bundler::SharedHelpers.major_deprecation("`Bundler.clean_env` has weird edge cases, use `.original_env` instead")
Bundler::SharedHelpers.major_deprecation(2, "`Bundler.clean_env` has weird edge cases, use `.original_env` instead")
env = original_env
if env.key?("BUNDLER_ORIG_MANPATH")
@ -313,21 +323,25 @@ EOF
end
def system_bindir
# Gem.bindir doesn't always return the location that Rubygems will install
# system binaries. If you put '-n foo' in your .gemrc, Rubygems will
# install binstubs there instead. Unfortunately, Rubygems doesn't expose
# Gem.bindir doesn't always return the location that RubyGems will install
# system binaries. If you put '-n foo' in your .gemrc, RubyGems will
# install binstubs there instead. Unfortunately, RubyGems doesn't expose
# that directory at all, so rather than parse .gemrc ourselves, we allow
# the directory to be set as well, via `bundle config bindir foo`.
Bundler.settings[:system_bindir] || Bundler.rubygems.gem_bindir
end
def use_system_gems?
configured_bundle_path.use_system_gems?
end
def requires_sudo?
return @requires_sudo if defined?(@requires_sudo_ran)
sudo_present = which "sudo" if settings.allow_sudo?
if sudo_present
# the bundle path and subdirectories need to be writable for Rubygems
# the bundle path and subdirectories need to be writable for RubyGems
# to be able to unpack and install gems without exploding
path = bundle_path
path = path.parent until path.exist?
@ -449,14 +463,17 @@ EOF
end
def reset_paths!
@root = nil
@settings = nil
@bin_path = nil
@bundler_major_version = nil
@bundle_path = nil
@configured = nil
@configured_bundle_path = nil
@definition = nil
@setup = nil
@load = nil
@locked_gems = nil
@bundle_path = nil
@bin_path = nil
@root = nil
@settings = nil
@setup = nil
@user_home = nil
end
@ -470,6 +487,8 @@ EOF
private
def eval_yaml_gemspec(path, contents)
Kernel.send(:require, "bundler/psyched_yaml")
# If the YAML is invalid, Syck raises an ArgumentError, and Psych
# raises a Psych::SyntaxError. See psyched_yaml.rb for more info.
Gem::Specification.from_yaml(contents)
@ -478,7 +497,7 @@ EOF
end
def eval_gemspec(path, contents)
eval(contents, TOPLEVEL_BINDING, path.expand_path.to_s)
eval(contents, TOPLEVEL_BINDING.dup, path.expand_path.to_s)
rescue ScriptError, StandardError => e
msg = "There was an error while loading `#{path.basename}`: #{e.message}"
@ -495,14 +514,14 @@ EOF
bundle_path
end
def configure_gem_path(env = ENV, settings = self.settings)
def configure_gem_path(env = ENV)
blank_home = env["GEM_HOME"].nil? || env["GEM_HOME"].empty?
if settings[:disable_shared_gems]
if !use_system_gems?
# this needs to be empty string to cause
# PathSupport.split_gem_path to only load up the
# Bundler --path setting as the GEM_PATH.
env["GEM_PATH"] = ""
elsif blank_home || Bundler.rubygems.gem_dir != bundle_path.to_s
elsif blank_home
possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path]
paths = possibles.flatten.compact.uniq.reject(&:empty?)
env["GEM_PATH"] = paths.join(File::PATH_SEPARATOR)
@ -510,14 +529,7 @@ EOF
end
def configure_gem_home
# TODO: This mkdir_p is only needed for JRuby <= 1.5 and should go away (GH #602)
begin
FileUtils.mkdir_p bundle_path.to_s
rescue
nil
end
ENV["GEM_HOME"] = File.expand_path(bundle_path, root)
Bundler::SharedHelpers.set_env "GEM_HOME", File.expand_path(bundle_path, root)
Bundler.rubygems.clear_paths
end

View file

@ -0,0 +1,36 @@
# frozen_string_literal: true
module Bundler
# Represents metadata from when the Bundler gem was built.
module BuildMetadata
# begin ivars
@release = false
# end ivars
# A hash representation of the build metadata.
def self.to_h
{
"Built At" => built_at,
"Git SHA" => git_commit_sha,
"Released Version" => release?,
}
end
# A string representing the date the bundler gem was built.
def self.built_at
@built_at ||= Time.now.utc.strftime("%Y-%m-%d").freeze
end
# The SHA for the git commit the bundler gem was built from.
def self.git_commit_sha
@git_commit_sha ||= Dir.chdir(File.expand_path("..", __FILE__)) do
`git rev-parse --short HEAD`.strip.freeze
end
end
# Whether this is an official release build of Bundler.
def self.release?
@release
end
end
end

View file

@ -1,4 +1,9 @@
# frozen_string_literal: true
require "bundler/shared_helpers"
Bundler::SharedHelpers.major_deprecation 2,
"The Bundler task for Capistrano. Please use http://github.com/capistrano/bundler"
# Capistrano task for Bundler.
#
# Add "require 'bundler/capistrano'" in your Capistrano deploy.rb, and

View file

@ -1,13 +1,18 @@
# frozen_string_literal: true
require "bundler"
require "bundler/vendored_thor"
module Bundler
class CLI < Thor
AUTO_INSTALL_CMDS = %w(show binstubs outdated exec open console licenses clean).freeze
PARSEABLE_COMMANDS = %w(
require "bundler/cli/common"
package_name "Bundler"
AUTO_INSTALL_CMDS = %w[show binstubs outdated exec open console licenses clean].freeze
PARSEABLE_COMMANDS = %w[
check config help exec platform show version
).freeze
].freeze
def self.start(*)
super
@ -30,11 +35,11 @@ module Bundler
custom_gemfile = options[:gemfile] || Bundler.settings[:gemfile]
if custom_gemfile && !custom_gemfile.empty?
ENV["BUNDLE_GEMFILE"] = File.expand_path(custom_gemfile)
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", File.expand_path(custom_gemfile)
Bundler.reset_paths!
end
Bundler.settings[:retry] = options[:retry] if options[:retry]
Bundler.settings.set_command_option_if_given :retry, options[:retry]
current_cmd = args.last[:current_command].name
auto_install if AUTO_INSTALL_CMDS.include?(current_cmd)
@ -42,7 +47,6 @@ module Bundler
raise InvalidOption, e.message
ensure
self.options ||= {}
Bundler.settings.cli_flags_given = !options.empty?
unprinted_warnings = Bundler.ui.unprinted_warnings
Bundler.ui = UI::Shell.new(options)
Bundler.ui.level = "debug" if options["verbose"]
@ -57,10 +61,41 @@ module Bundler
end
end
def self.deprecated_option(*args, &blk)
return if Bundler.feature_flag.forget_cli_options?
method_option(*args, &blk)
end
check_unknown_options!(:except => [:config, :exec])
stop_on_unknown_option! :exec
default_task :install
desc "cli_help", "Prints a summary of bundler commands", :hide => true
def cli_help
version
Bundler.ui.info "\n"
primary_commands = ["install", "update",
Bundler.feature_flag.cache_command_is_package? ? "cache" : "package",
"exec", "config", "help"]
list = self.class.printable_commands(true)
by_name = list.group_by {|name, _message| name.match(/^bundle (\w+)/)[1] }
utilities = by_name.keys.sort - primary_commands
primary_commands.map! {|name| (by_name[name] || raise("no primary command #{name}")).first }
utilities.map! {|name| by_name[name].first }
shell.say "Bundler commands:\n\n"
shell.say " Primary commands:\n"
shell.print_table(primary_commands, :indent => 4, :truncate => true)
shell.say
shell.say " Utilities:\n"
shell.print_table(utilities, :indent => 4, :truncate => true)
shell.say
self.class.send(:class_options_help, shell)
end
default_task(Bundler.feature_flag.default_cli_command)
class_option "no-color", :type => :boolean, :desc => "Disable colorization in output"
class_option "retry", :type => :numeric, :aliases => "-r", :banner => "NUM",
:desc => "Specify the number of times you wish to attempt network commands"
@ -107,7 +142,7 @@ module Bundler
Gemfile to a gem with a gemspec, the --gemspec option will automatically add each
dependency listed in the gemspec file to the newly created Gemfile.
D
method_option "gemspec", :type => :string, :banner => "Use the specified .gemspec to create the Gemfile"
deprecated_option "gemspec", :type => :string, :banner => "Use the specified .gemspec to create the Gemfile"
def init
require "bundler/cli/init"
Init.new(options.dup).run
@ -124,7 +159,7 @@ module Bundler
method_option "gemfile", :type => :string, :banner =>
"Use the specified gemfile instead of Gemfile"
method_option "path", :type => :string, :banner =>
"Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
"Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME).#{" Bundler will remember this value for future installs on this machine" unless Bundler.feature_flag.forget_cli_options?}"
map "c" => "check"
def check
require "bundler/cli/check"
@ -142,13 +177,13 @@ module Bundler
If the bundle has already been installed, bundler will tell you so and then exit.
D
method_option "binstubs", :type => :string, :lazy_default => "bin", :banner =>
deprecated_option "binstubs", :type => :string, :lazy_default => "bin", :banner =>
"Generate bin stubs for bundled gems to ./bin"
method_option "clean", :type => :boolean, :banner =>
deprecated_option "clean", :type => :boolean, :banner =>
"Run bundle clean automatically after install"
method_option "deployment", :type => :boolean, :banner =>
deprecated_option "deployment", :type => :boolean, :banner =>
"Install using defaults tuned for deployment environments"
method_option "frozen", :type => :boolean, :banner =>
deprecated_option "frozen", :type => :boolean, :banner =>
"Do not allow the Gemfile.lock to be updated after this install"
method_option "full-index", :type => :boolean, :banner =>
"Fall back to using the single-file index of all gems"
@ -158,28 +193,29 @@ module Bundler
"Specify the number of jobs to run in parallel"
method_option "local", :type => :boolean, :banner =>
"Do not attempt to fetch gems remotely and use the gem cache instead"
method_option "no-cache", :type => :boolean, :banner =>
deprecated_option "no-cache", :type => :boolean, :banner =>
"Don't update the existing gem cache."
method_option "force", :type => :boolean, :banner =>
method_option "redownload", :type => :boolean, :aliases =>
[Bundler.feature_flag.forget_cli_options? ? nil : "--force"].compact, :banner =>
"Force downloading every gem."
method_option "no-prune", :type => :boolean, :banner =>
deprecated_option "no-prune", :type => :boolean, :banner =>
"Don't remove stale gems from the cache."
method_option "path", :type => :string, :banner =>
deprecated_option "path", :type => :string, :banner =>
"Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
method_option "quiet", :type => :boolean, :banner =>
"Only output warnings and errors."
method_option "shebang", :type => :string, :banner =>
deprecated_option "shebang", :type => :string, :banner =>
"Specify a different shebang executable name than the default (usually 'ruby')"
method_option "standalone", :type => :array, :lazy_default => [], :banner =>
"Make a bundle that can work without the Bundler runtime"
method_option "system", :type => :boolean, :banner =>
deprecated_option "system", :type => :boolean, :banner =>
"Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
method_option "trust-policy", :alias => "P", :type => :string, :banner =>
"Gem trust policy (like gem install -P). Must be one of " +
Bundler.rubygems.security_policy_keys.join("|")
method_option "without", :type => :array, :banner =>
deprecated_option "without", :type => :array, :banner =>
"Exclude gems that are part of the specified named group."
method_option "with", :type => :array, :banner =>
deprecated_option "with", :type => :array, :banner =>
"Include gems that are part of the specified named group."
map "i" => "install"
def install
@ -189,7 +225,7 @@ module Bundler
end
end
desc "update [OPTIONS]", "update the current environment"
desc "update [OPTIONS]", "Update the current environment"
long_desc <<-D
Update will install the newest versions of the gems listed in the Gemfile. Use
update when you have changed the Gemfile, or if you want to get the newest
@ -223,6 +259,8 @@ module Bundler
"Do not allow any gem to be updated past latest --patch | --minor | --major"
method_option "conservative", :type => :boolean, :banner =>
"Use bundle install conservative update behavior and do not allow shared dependencies to be updated."
method_option "all", :type => :boolean, :banner =>
"Update everything."
def update(*gems)
require "bundler/cli/update"
Update.new(options, gems).run
@ -238,12 +276,24 @@ module Bundler
method_option "outdated", :type => :boolean,
:banner => "Show verbose output including whether gems are outdated."
def show(gem_name = nil)
Bundler::SharedHelpers.major_deprecation("use `bundle show` instead of `bundle list`") if ARGV[0] == "list"
Bundler::SharedHelpers.major_deprecation(2, "use `bundle list` instead of `bundle show`") if ARGV[0] == "show"
require "bundler/cli/show"
Show.new(options, gem_name).run
end
# TODO: 2.0 remove `bundle list`
map %w(list) => "show"
# TODO: 2.0 remove `bundle show`
if Bundler.feature_flag.list_command?
desc "list", "List all gems in the bundle"
method_option "name-only", :type => :boolean, :banner => "print only the gem names"
def list
require "bundler/cli/list"
List.new(options).run
end
map %w[ls] => "list"
else
map %w[list] => "show"
end
desc "info GEM [OPTIONS]", "Show information for the given gem"
method_option "path", :type => :boolean, :banner => "Print full path to gem"
@ -262,6 +312,8 @@ module Bundler
"Overwrite existing binstubs if they exist"
method_option "path", :type => :string, :lazy_default => "bin", :banner =>
"Binstub destination directory (default bin)"
method_option "shebang", :type => :string, :banner =>
"Specify a different shebang executable name than the default (usually 'ruby')"
method_option "standalone", :type => :boolean, :banner =>
"Make binstubs that can work without the Bundler runtime"
def binstubs(*gems)
@ -282,7 +334,7 @@ module Bundler
Add.new(options.dup, gem_name).run
end
desc "outdated GEM [OPTIONS]", "list installed gems with newer versions available"
desc "outdated GEM [OPTIONS]", "List installed gems with newer versions available"
long_desc <<-D
Outdated lists the names and versions of gems that have a newer version available
in the given source. Calling outdated with [GEM [GEM]] will only check for newer
@ -292,8 +344,8 @@ module Bundler
For more information on patch level options (--major, --minor, --patch,
--update-strict) see documentation on the same options on the update command.
D
method_option "group", :aliases => "--group", :type => :string, :banner => "List gems from a specific group"
method_option "groups", :aliases => "--groups", :type => :boolean, :banner => "List gems organized by groups"
method_option "group", :type => :string, :banner => "List gems from a specific group"
method_option "groups", :type => :boolean, :banner => "List gems organized by groups"
method_option "local", :type => :boolean, :banner =>
"Do not attempt to fetch gems remotely and use the gem cache instead"
method_option "pre", :type => :boolean, :banner => "Check for newer pre-release gems"
@ -315,17 +367,27 @@ module Bundler
Outdated.new(options, gems).run
end
desc "cache [OPTIONS]", "Cache all the gems to vendor/cache", :hide => true
method_option "all", :type => :boolean, :banner => "Include all sources (including path and git)."
method_option "all-platforms", :type => :boolean, :banner => "Include gems for all platforms present in the lockfile, not only the current one"
method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
def cache
require "bundler/cli/cache"
Cache.new(options).run
if Bundler.feature_flag.cache_command_is_package?
map %w[cache] => :package
else
desc "cache [OPTIONS]", "Cache all the gems to vendor/cache", :hide => true
unless Bundler.feature_flag.cache_command_is_package?
method_option "all", :type => :boolean,
:banner => "Include all sources (including path and git)."
end
method_option "all-platforms", :type => :boolean, :banner => "Include gems for all platforms present in the lockfile, not only the current one"
method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
def cache
require "bundler/cli/cache"
Cache.new(options).run
end
end
desc "package [OPTIONS]", "Locks and then caches all of the gems into vendor/cache"
method_option "all", :type => :boolean, :banner => "Include all sources (including path and git)."
desc "#{Bundler.feature_flag.cache_command_is_package? ? :cache : :package} [OPTIONS]", "Locks and then caches all of the gems into vendor/cache"
unless Bundler.feature_flag.cache_command_is_package?
method_option "all", :type => :boolean,
:banner => "Include all sources (including path and git)."
end
method_option "all-platforms", :type => :boolean, :banner => "Include gems for all platforms present in the lockfile, not only the current one"
method_option "cache-path", :type => :string, :banner =>
"Specify a different cache path than the default (vendor/cache)."
@ -347,14 +409,14 @@ module Bundler
require "bundler/cli/package"
Package.new(options).run
end
map %w(pack) => :package
map %w[pack] => :package
desc "exec [OPTIONS]", "Run the command in context of the bundle"
method_option :keep_file_descriptors, :type => :boolean, :default => false
long_desc <<-D
Exec runs a command, providing it access to the gems in the bundle. While using
bundle exec you can require and call the bundled gems as if they were installed
into the system wide Rubygems repository.
into the system wide RubyGems repository.
D
map "e" => "exec"
def exec(*args)
@ -362,7 +424,7 @@ module Bundler
Exec.new(options, args).run
end
desc "config NAME [VALUE]", "retrieve or set a configuration value"
desc "config NAME [VALUE]", "Retrieve or set a configuration value"
long_desc <<-D
Retrieves or sets a configuration value. If only one parameter is provided, retrieve the value. If two parameters are provided, replace the
existing value with the newly provided one.
@ -386,18 +448,28 @@ module Bundler
Open.new(options, name).run
end
desc "console [GROUP]", "Opens an IRB session with the bundle pre-loaded"
def console(group = nil)
# TODO: Remove for 2.0
require "bundler/cli/console"
Console.new(options, group).run
if Bundler.feature_flag.console_command?
desc "console [GROUP]", "Opens an IRB session with the bundle pre-loaded"
def console(group = nil)
require "bundler/cli/console"
Console.new(options, group).run
end
end
desc "version", "Prints the bundler's version information"
def version
Bundler.ui.info "Bundler version #{Bundler::VERSION}"
cli_help = current_command.name == "cli_help"
if cli_help || ARGV.include?("version")
build_info = " (#{BuildMetadata.built_at} commit #{BuildMetadata.git_commit_sha})"
end
if !cli_help && Bundler.feature_flag.print_only_version_number?
Bundler.ui.info "#{Bundler::VERSION}#{build_info}"
else
Bundler.ui.info "Bundler version #{Bundler::VERSION}#{build_info}"
end
end
map %w(-v --version) => :version
map %w[-v --version] => :version
desc "licenses", "Prints the license of all gems in the bundle"
def licenses
@ -413,7 +485,7 @@ module Bundler
end
end
desc "viz [OPTIONS]", "Generates a visual dependency graph"
desc "viz [OPTIONS]", "Generates a visual dependency graph", :hide => true
long_desc <<-D
Viz generates a PNG file of the current Gemfile as a dependency graph.
Viz requires the ruby-graphviz gem (and its dependencies).
@ -431,7 +503,7 @@ module Bundler
old_gem = instance_method(:gem)
desc "gem GEM [OPTIONS]", "Creates a skeleton for creating a rubygem"
desc "gem NAME [OPTIONS]", "Creates a skeleton for creating a rubygem"
method_option :exe, :type => :boolean, :default => false, :aliases => ["--bin", "-b"], :desc => "Generate a binary executable for your library."
method_option :coc, :type => :boolean, :desc => "Generate a code of conduct file. Set a default with `bundle config gem.coc true`."
method_option :edit, :type => :string, :aliases => "-e", :required => false, :banner => "EDITOR",
@ -470,7 +542,7 @@ module Bundler
File.expand_path(File.join(File.dirname(__FILE__), "templates"))
end
desc "clean [OPTIONS]", "Cleans up unused gems in your bundler directory"
desc "clean [OPTIONS]", "Cleans up unused gems in your bundler directory", :hide => true
method_option "dry-run", :type => :boolean, :default => false, :banner =>
"Only print out changes, do not clean gems"
method_option "force", :type => :boolean, :default => false, :banner =>
@ -488,13 +560,13 @@ module Bundler
Platform.new(options).run
end
desc "inject GEM VERSION", "Add the named gem, with version requirements, to the resolved Gemfile"
desc "inject GEM VERSION", "Add the named gem, with version requirements, to the resolved Gemfile", :hide => true
method_option "source", :type => :string, :banner =>
"Install gem from the given source"
method_option "group", :type => :string, :banner =>
"Install gem into a bundler group"
def inject(name, version)
SharedHelpers.major_deprecation "The `inject` command has been replaced by the `add` command"
SharedHelpers.major_deprecation 2, "The `inject` command has been replaced by the `add` command"
require "bundler/cli/inject"
Inject.new(options.dup, name, version).run
end
@ -531,7 +603,7 @@ module Bundler
desc "env", "Print information about the environment Bundler is running under"
def env
Env.new.write($stdout)
Env.write($stdout)
end
desc "doctor [OPTIONS]", "Checks the bundle for common problems"
@ -555,15 +627,20 @@ module Bundler
Issue.new.run
end
desc "pristine", "Restores installed gems to pristine condition from files located in the gem cache. Gem installed from a git repository will be issued `git checkout --force`."
def pristine
desc "pristine [GEMS...]", "Restores installed gems to pristine condition"
long_desc <<-D
Restores installed gems to pristine condition from files located in the
gem cache. Gems installed from a git repository will be issued `git
checkout --force`.
D
def pristine(*gems)
require "bundler/cli/pristine"
Pristine.new.run
Pristine.new(gems).run
end
if Bundler.feature_flag.plugins?
require "bundler/cli/plugin"
desc "plugin SUBCOMMAND ...ARGS", "manage the bundler plugins"
desc "plugin", "Manage the bundler plugins"
subcommand "plugin", Plugin
end
@ -571,14 +648,14 @@ module Bundler
# into the corresponding `bundle help #{command}` call
def self.reformatted_help_args(args)
bundler_commands = all_commands.keys
help_flags = %w(--help -h)
exec_commands = %w(e ex exe exec)
help_flags = %w[--help -h]
exec_commands = %w[e ex exe exec]
help_used = args.index {|a| help_flags.include? a }
exec_used = args.index {|a| exec_commands.include? a }
command = args.find {|a| bundler_commands.include? a }
if exec_used && help_used
if exec_used + help_used == 1
%w(help exec)
%w[help exec]
else
args
end
@ -613,16 +690,20 @@ module Bundler
end
end
def current_command
_, _, config = @_initializer
config[:current_command]
end
def print_command
return unless Bundler.ui.debug?
_, _, config = @_initializer
current_command = config[:current_command]
command_name = current_command.name
cmd = current_command
command_name = cmd.name
return if PARSEABLE_COMMANDS.include?(command_name)
command = ["bundle", command_name] + args
options_to_print = options.dup
options_to_print.delete_if do |k, v|
next unless o = current_command.options[k]
next unless o = cmd.options[k]
o.default == v
end
command << Thor::Options.to_switches(options_to_print.sort_by(&:first)).strip
@ -633,8 +714,6 @@ module Bundler
def warn_on_outdated_bundler
return if Bundler.settings[:disable_version_check]
_, _, config = @_initializer
current_command = config[:current_command]
command_name = current_command.name
return if PARSEABLE_COMMANDS.include?(command_name)
@ -649,8 +728,17 @@ module Bundler
current = Gem::Version.new(VERSION)
return if current >= latest
latest_installed = Bundler.rubygems.find_name("bundler").map(&:version).max
Bundler.ui.warn "The latest bundler is #{latest}, but you are currently running #{current}.\nTo update, run `gem install bundler#{" --pre" if latest.prerelease?}`"
installation = "To install the latest version, run `gem install bundler#{" --pre" if latest.prerelease?}`"
if latest_installed && latest_installed > current
suggestion = "To update to the most recent installed version (#{latest_installed}), run `bundle update --bundler`"
suggestion = "#{installation}\n#{suggestion}" if latest_installed < latest
else
suggestion = installation
end
Bundler.ui.warn "The latest bundler is #{latest}, but you are currently running #{current}.\n#{suggestion}"
rescue
nil
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require "bundler/cli/common"
module Bundler
class CLI::Add

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require "bundler/cli/common"
module Bundler
class CLI::Binstubs
@ -11,8 +10,10 @@ module Bundler
def run
Bundler.definition.validate_runtime!
Bundler.settings[:bin] = options["path"] if options["path"]
Bundler.settings[:bin] = nil if options["path"] && options["path"].empty?
path_option = options["path"]
path_option = nil if path_option && path_option.empty?
Bundler.settings.set_command_option :bin, path_option if options["path"]
Bundler.settings.set_command_option_if_given :shebang, options["shebang"]
installer = Installer.new(Bundler.root, Bundler.definition)
if gems.empty?
@ -28,10 +29,11 @@ module Bundler
)
end
if spec.name == "bundler"
Bundler.ui.warn "Sorry, Bundler can only be run via Rubygems."
elsif options[:standalone]
installer.generate_standalone_bundler_executable_stubs(spec)
if options[:standalone]
next Bundler.ui.warn("Sorry, Bundler can only be run via RubyGems.") if gem_name == "bundler"
Bundler.settings.temporary(:path => (Bundler.settings[:path] || Bundler.root)) do
installer.generate_standalone_bundler_executable_stubs(spec)
end
else
installer.generate_bundler_executable_stubs(spec, :force => options[:force], :binstubs_cmd => true)
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class CLI::Cache
attr_reader :options
@ -10,9 +11,9 @@ module Bundler
Bundler.definition.validate_runtime!
Bundler.definition.resolve_with_cache!
setup_cache_all
Bundler.settings[:cache_all_platforms] = options["all-platforms"] if options.key?("all-platforms")
Bundler.settings.set_command_option_if_given :cache_all_platforms, options["all-platforms"]
Bundler.load.cache
Bundler.settings[:no_prune] = true if options["no-prune"]
Bundler.settings.set_command_option_if_given :no_prune, options["no-prune"]
Bundler.load.lock
rescue GemNotFound => e
Bundler.ui.error(e.message)
@ -23,9 +24,9 @@ module Bundler
private
def setup_cache_all
Bundler.settings[:cache_all] = options[:all] if options.key?("all")
Bundler.settings.set_command_option_if_given :cache_all, options[:all]
if Bundler.definition.has_local_dependencies? && !Bundler.settings[:cache_all]
if Bundler.definition.has_local_dependencies? && !Bundler.feature_flag.cache_all?
Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \
"to package them as well, please pass the --all flag. This will be the default " \
"on Bundler 2.0."

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class CLI::Check
attr_reader :options
@ -8,10 +9,7 @@ module Bundler
end
def run
if options[:path]
Bundler.settings[:path] = File.expand_path(options[:path])
Bundler.settings[:disable_shared_gems] = true
end
Bundler.settings.set_command_option_if_given :path, options[:path]
begin
definition = Bundler.definition
@ -28,7 +26,7 @@ module Bundler
not_installed.each {|s| Bundler.ui.error " * #{s.name} (#{s.version})" }
Bundler.ui.warn "Install missing gems with `bundle install`"
exit 1
elsif !Bundler.default_lockfile.file? && Bundler.settings[:frozen]
elsif !Bundler.default_lockfile.file? && Bundler.frozen?
Bundler.ui.error "This bundle has been frozen, but there is no #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} present"
exit 1
else

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class CLI::Clean
attr_reader :options
@ -15,12 +16,10 @@ module Bundler
protected
def require_path_or_force
if !Bundler.settings[:path] && !options[:force]
Bundler.ui.error "Cleaning all the gems on your system is dangerous! " \
"If you're sure you want to remove every system gem not in this " \
"bundle, run `bundle clean --force`."
exit 1
end
return unless Bundler.use_system_gems? && !options[:force]
raise InvalidOption, "Cleaning all the gems on your system is dangerous! " \
"If you're sure you want to remove every system gem not in this " \
"bundle, run `bundle clean --force`."
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
module CLI::Common
def self.output_post_install_messages(messages)
@ -14,12 +15,12 @@ module Bundler
end
def self.output_without_groups_message
return unless Bundler.settings.without.any?
return if Bundler.settings[:without].empty?
Bundler.ui.confirm without_groups_message
end
def self.without_groups_message
groups = Bundler.settings.without
groups = Bundler.settings[:without]
group_list = [groups[0...-1].join(", "), groups[-1..-1]].
reject {|s| s.to_s.empty? }.join(" and ")
group_str = (groups.size == 1) ? "group" : "groups"
@ -89,5 +90,13 @@ module Bundler
def self.patch_level_options(options)
[:major, :minor, :patch].select {|v| options.keys.include?(v.to_s) }
end
def self.clean_after_install?
clean = Bundler.settings[:clean]
return clean unless clean.nil?
clean ||= Bundler.feature_flag.auto_clean_without_path? && Bundler.settings[:path].nil?
clean &&= !Bundler.use_system_gems?
clean
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class CLI::Config
attr_reader :name, :options, :scope, :thor
@ -112,7 +113,7 @@ module Bundler
end
def valid_scope?(scope)
%w(delete local global).include?(scope)
%w[delete local global].include?(scope)
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class CLI::Console
attr_reader :options, :group
@ -8,7 +9,7 @@ module Bundler
end
def run
Bundler::SharedHelpers.major_deprecation "bundle console will be replaced " \
Bundler::SharedHelpers.major_deprecation 2, "bundle console will be replaced " \
"by `bin/console` generated by `bundle gem <name>`"
group ? Bundler.require(:default, *(group.split.map!(&:to_sym))) : Bundler.require

View file

@ -62,6 +62,7 @@ module Bundler
def run
Bundler.ui.level = "error" if options[:quiet]
Bundler.settings.validate!
check!
definition = Bundler.definition

View file

@ -1,11 +1,12 @@
# frozen_string_literal: true
require "bundler/current_ruby"
module Bundler
class CLI::Exec
attr_reader :options, :args, :cmd
RESERVED_SIGNALS = %w(SEGV BUS ILL FPE VTALRM KILL STOP).freeze
RESERVED_SIGNALS = %w[SEGV BUS ILL FPE VTALRM KILL STOP].freeze
def initialize(options, args)
@options = options
@ -72,7 +73,7 @@ module Bundler
signals = Signal.list.keys - RESERVED_SIGNALS
signals.each {|s| trap(s, "DEFAULT") }
Kernel.load(file)
rescue SystemExit
rescue SystemExit, SignalException
raise
rescue Exception => e # rubocop:disable Lint/RescueException
Bundler.ui = ui

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "pathname"
module Bundler
@ -71,10 +72,10 @@ module Bundler
"bin/setup.tt" => "bin/setup"
}
executables = %w(
executables = %w[
bin/console
bin/setup
)
]
templates.merge!("gitignore.tt" => ".gitignore") if Bundler.git_present?

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require "bundler/cli/common"
module Bundler
class CLI::Info

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class CLI::Init
attr_reader :options
@ -7,8 +8,8 @@ module Bundler
end
def run
if File.exist?("Gemfile")
Bundler.ui.error "Gemfile already exists at #{SharedHelpers.pwd}/Gemfile"
if File.exist?(gemfile)
Bundler.ui.error "#{gemfile} already exists at #{File.expand_path(gemfile)}"
exit 1
end
@ -21,14 +22,24 @@ module Bundler
spec = Bundler.load_gemspec_uncached(gemspec)
puts "Writing new Gemfile to #{SharedHelpers.pwd}/Gemfile"
File.open("Gemfile", "wb") do |file|
File.open(gemfile, "wb") do |file|
file << "# Generated from #{gemspec}\n"
file << spec.to_gemfile
end
else
puts "Writing new Gemfile to #{SharedHelpers.pwd}/Gemfile"
FileUtils.cp(File.expand_path("../../templates/Gemfile", __FILE__), "Gemfile")
FileUtils.cp(File.expand_path("../../templates/#{gemfile}", __FILE__), gemfile)
end
puts "Writing new #{gemfile} to #{SharedHelpers.pwd}/#{gemfile}"
end
private
def gemfile
@gemfile ||= begin
Bundler.default_gemfile
rescue GemfileNotFound
Bundler.feature_flag.init_gems_rb? ? "gems.rb" : "Gemfile"
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class CLI::Inject
attr_reader :options, :name, :version, :group, :source, :gems

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require "bundler/cli/common"
module Bundler
class CLI::Install
@ -13,17 +12,9 @@ module Bundler
warn_if_root
[:with, :without].each do |option|
if options[option]
options[option] = options[option].join(":").tr(" ", ":").split(":")
end
end
check_for_group_conflicts
normalize_groups
ENV["RB_USER_INSTALL"] = "1" if Bundler::FREEBSD
Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Bundler::FREEBSD
# Disable color in deployment mode
Bundler.ui.shell = Thor::Shell::Basic.new if options[:deployment]
@ -32,22 +23,28 @@ module Bundler
check_trust_policy
if options[:deployment] || options[:frozen]
if options[:deployment] || options[:frozen] || Bundler.frozen?
unless Bundler.default_lockfile.exist?
flag = options[:deployment] ? "--deployment" : "--frozen"
raise ProductionError, "The #{flag} flag requires a #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}. Please make " \
flag = "--deployment flag" if options[:deployment]
flag ||= "--frozen flag" if options[:frozen]
flag ||= "deployment setting"
raise ProductionError, "The #{flag} requires a #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}. Please make " \
"sure you have checked your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} into version control " \
"before deploying."
end
options[:local] = true if Bundler.app_cache.exist?
Bundler.settings[:frozen] = "1"
if Bundler.feature_flag.deployment_means_frozen?
Bundler.settings.set_command_option :deployment, true
else
Bundler.settings.set_command_option :frozen, true
end
end
# When install is called with --no-deployment, disable deployment mode
if options[:deployment] == false
Bundler.settings.delete(:frozen)
Bundler.settings.set_command_option :frozen, nil
options[:system] = true
end
@ -56,7 +53,7 @@ module Bundler
Bundler::Fetcher.disable_endpoint = options["full-index"]
if options["binstubs"]
Bundler::SharedHelpers.major_deprecation \
Bundler::SharedHelpers.major_deprecation 2,
"The --binstubs option will be removed in favor of `bundle binstubs`"
end
@ -66,24 +63,24 @@ module Bundler
definition.validate_runtime!
installer = Installer.install(Bundler.root, definition, options)
Bundler.load.cache if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.settings[:frozen]
Bundler.load.cache if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.frozen?
Bundler.ui.confirm "Bundle complete! #{dependencies_count_for(definition)}, #{gems_installed_for(definition)}."
Bundler::CLI::Common.output_without_groups_message
if Bundler.settings[:path]
absolute_path = File.expand_path(Bundler.settings[:path])
relative_path = absolute_path.sub(File.expand_path(".") + File::SEPARATOR, "." + File::SEPARATOR)
Bundler.ui.confirm "Bundled gems are installed into #{relative_path}."
else
if Bundler.use_system_gems?
Bundler.ui.confirm "Use `bundle info [gemname]` to see where a bundled gem is installed."
else
absolute_path = File.expand_path(Bundler.configured_bundle_path.base_path)
relative_path = absolute_path.sub(File.expand_path(".") + File::SEPARATOR, "." + File::SEPARATOR)
Bundler.ui.confirm "Bundled gems are installed into `#{relative_path}`"
end
Bundler::CLI::Common.output_post_install_messages installer.post_install_messages
warn_ambiguous_gems
if Bundler.settings[:clean] && Bundler.settings[:path]
if CLI::Common.clean_after_install?
require "bundler/cli/clean"
Bundler::CLI::Clean.new(options).run
end
@ -124,15 +121,11 @@ module Bundler
"#{count} #{count == 1 ? "gem" : "gems"} now installed"
end
def check_for_group_conflicts
if options[:without] && options[:with]
conflicting_groups = options[:without] & options[:with]
unless conflicting_groups.empty?
Bundler.ui.error "You can't list a group in both, --with and --without." \
" The offending groups are: #{conflicting_groups.join(", ")}."
exit 1
end
end
def check_for_group_conflicts_in_cli_options
conflicting_groups = Array(options[:without]) & Array(options[:with])
return if conflicting_groups.empty?
raise InvalidOption, "You can't list a group in both with and without." \
" The offending groups are: #{conflicting_groups.join(", ")}."
end
def check_for_options_conflicts
@ -145,28 +138,29 @@ module Bundler
end
def check_trust_policy
if options["trust-policy"]
unless Bundler.rubygems.security_policies.keys.include?(options["trust-policy"])
Bundler.ui.error "Rubygems doesn't know about trust policy '#{options["trust-policy"]}'. " \
"The known policies are: #{Bundler.rubygems.security_policies.keys.join(", ")}."
exit 1
end
Bundler.settings["trust-policy"] = options["trust-policy"]
else
Bundler.settings["trust-policy"] = nil if Bundler.settings["trust-policy"]
trust_policy = options["trust-policy"]
unless Bundler.rubygems.security_policies.keys.unshift(nil).include?(trust_policy)
raise InvalidOption, "RubyGems doesn't know about trust policy '#{trust_policy}'. " \
"The known policies are: #{Bundler.rubygems.security_policies.keys.join(", ")}."
end
Bundler.settings.set_command_option_if_given :"trust-policy", trust_policy
end
def normalize_groups
Bundler.settings.with = [] if options[:with] && options[:with].empty?
Bundler.settings.without = [] if options[:without] && options[:without].empty?
options[:with] &&= options[:with].join(":").tr(" ", ":").split(":")
options[:without] &&= options[:without].join(":").tr(" ", ":").split(":")
with = options.fetch("with", [])
with |= Bundler.settings.with.map(&:to_s)
check_for_group_conflicts_in_cli_options
Bundler.settings.set_command_option :with, nil if options[:with] == []
Bundler.settings.set_command_option :without, nil if options[:without] == []
with = options.fetch(:with, [])
with |= Bundler.settings[:with].map(&:to_s)
with -= options[:without] if options[:without]
without = options.fetch("without", [])
without |= Bundler.settings.without.map(&:to_s)
without = options.fetch(:without, [])
without |= Bundler.settings[:without].map(&:to_s)
without -= options[:with] if options[:with]
options[:with] = with
@ -174,28 +168,34 @@ module Bundler
end
def normalize_settings
Bundler.settings[:path] = nil if options[:system]
Bundler.settings[:path] = "vendor/bundle" if options[:deployment]
Bundler.settings[:path] = options["path"] if options["path"]
Bundler.settings[:path] ||= "bundle" if options["standalone"]
Bundler.settings.set_command_option :path, nil if options[:system]
Bundler.settings.set_command_option :path, "vendor/bundle" if options[:deployment]
Bundler.settings.set_command_option_if_given :path, options["path"]
Bundler.settings.set_command_option :path, "bundle" if options["standalone"] && Bundler.settings[:path].nil?
Bundler.settings[:bin] = options["binstubs"] if options["binstubs"]
Bundler.settings[:bin] = nil if options["binstubs"] && options["binstubs"].empty?
bin_option = options["binstubs"]
bin_option = nil if bin_option && bin_option.empty?
Bundler.settings.set_command_option :bin, bin_option if options["binstubs"]
Bundler.settings[:shebang] = options["shebang"] if options["shebang"]
Bundler.settings.set_command_option_if_given :shebang, options["shebang"]
Bundler.settings[:jobs] = options["jobs"] if options["jobs"]
Bundler.settings.set_command_option_if_given :jobs, options["jobs"]
Bundler.settings[:no_prune] = true if options["no-prune"]
Bundler.settings.set_command_option_if_given :no_prune, options["no-prune"]
Bundler.settings[:no_install] = true if options["no-install"]
Bundler.settings.set_command_option_if_given :no_install, options["no-install"]
Bundler.settings[:clean] = options["clean"] if options["clean"]
Bundler.settings.set_command_option_if_given :clean, options["clean"]
Bundler.settings.without = options[:without]
Bundler.settings.with = options[:with]
unless Bundler.settings[:without] == options[:without] && Bundler.settings[:with] == options[:with]
# need to nil them out first to get around validation for backwards compatibility
Bundler.settings.set_command_option :without, nil
Bundler.settings.set_command_option :with, nil
Bundler.settings.set_command_option :without, options[:without] - options[:with]
Bundler.settings.set_command_option :with, options[:with]
end
Bundler.settings[:disable_shared_gems] = Bundler.settings[:path] ? true : nil
options[:force] = options[:redownload]
end
def warn_ambiguous_gems

View file

@ -26,7 +26,7 @@ module Bundler
EOS
Bundler.ui.info Bundler::Env.new.report
Bundler.ui.info Bundler::Env.report
Bundler.ui.info "\n## Bundle Doctor"
doctor

22
lib/bundler/cli/list.rb Normal file
View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
module Bundler
class CLI::List
def initialize(options)
@options = options
end
def run
specs = Bundler.load.specs.reject {|s| s.name == "bundler" }.sort_by(&:name)
return specs.each {|s| Bundler.ui.info s.name } if @options["name-only"]
return Bundler.ui.info "No gems in the Gemfile" if specs.empty?
Bundler.ui.info "Gems included by the bundle:"
specs.each do |s|
Bundler.ui.info " * #{s.name} (#{s.version}#{s.git_version})"
end
Bundler.ui.info "Use `bundle info` to print more detailed information about a gem"
end
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require "bundler/cli/common"
module Bundler
class CLI::Lock

View file

@ -1,5 +1,5 @@
# frozen_string_literal: true
require "bundler/cli/common"
require "shellwords"
module Bundler
@ -17,7 +17,7 @@ module Bundler
path = spec.full_gem_path
Dir.chdir(path) do
command = Shellwords.split(editor) + [path]
Bundler.with_clean_env do
Bundler.with_original_env do
system(*command)
end || Bundler.ui.info("Could not run '#{command.join(" ")}'")
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require "bundler/cli/common"
module Bundler
class CLI::Outdated
@ -46,7 +45,7 @@ module Bundler
Bundler::CLI::Common.patch_level_options(options).any?
filter_options_patch = options.keys &
%w(filter-major filter-minor filter-patch)
%w[filter-major filter-minor filter-patch]
definition_resolution = proc do
options[:local] ? definition.resolve_with_cache! : definition.resolve_remotely!
@ -214,13 +213,19 @@ module Bundler
end
def check_for_deployment_mode
if Bundler.settings[:frozen]
raise ProductionError, "You are trying to check outdated gems in " \
"deployment mode. Run `bundle outdated` elsewhere.\n" \
"\nIf this is a development machine, remove the " \
"#{Bundler.default_gemfile} freeze" \
"\nby running `bundle install --no-deployment`."
return unless Bundler.frozen?
suggested_command = if Bundler.settings.locations("frozen")[:global]
"bundle config --delete frozen"
elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any?
"bundle config --delete deployment"
else
"bundle install --no-deployment"
end
raise ProductionError, "You are trying to check outdated gems in " \
"deployment mode. Run `bundle outdated` elsewhere.\n" \
"\nIf this is a development machine, remove the " \
"#{Bundler.default_gemfile} freeze" \
"\nby running `#{suggested_command}`."
end
def update_present_via_semver_portions(current_spec, active_spec, options)

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class CLI::Package
attr_reader :options
@ -9,15 +10,15 @@ module Bundler
def run
Bundler.ui.level = "error" if options[:quiet]
Bundler.settings[:path] = File.expand_path(options[:path]) if options[:path]
Bundler.settings[:cache_all_platforms] = options["all-platforms"] if options.key?("all-platforms")
Bundler.settings[:cache_path] = options["cache-path"] if options.key?("cache-path")
Bundler.settings.set_command_option_if_given :path, options[:path]
Bundler.settings.set_command_option_if_given :cache_all_platforms, options["all-platforms"]
Bundler.settings.set_command_option_if_given :cache_path, options["cache-path"]
setup_cache_all
install
# TODO: move cache contents here now that all bundles are locked
custom_path = Pathname.new(options[:path]) if options[:path]
custom_path = Bundler.settings[:path] if options[:path]
Bundler.load.cache(custom_path)
end
@ -34,9 +35,11 @@ module Bundler
end
def setup_cache_all
Bundler.settings[:cache_all] = options[:all] if options.key?("all")
all = options.fetch(:all, Bundler.feature_flag.cache_command_is_package? || nil)
if Bundler.definition.has_local_dependencies? && !Bundler.settings[:cache_all]
Bundler.settings.set_command_option_if_given :cache_all, all
if Bundler.definition.has_local_dependencies? && !Bundler.feature_flag.cache_all?
Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \
"to package them as well, please pass the --all flag. This will be the default " \
"on Bundler 2.0."

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class CLI::Platform
attr_reader :options

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/vendored_thor"
module Bundler
class CLI::Plugin < Thor

View file

@ -1,15 +1,20 @@
# frozen_string_literal: true
require "bundler/cli/common"
module Bundler
class CLI::Pristine
def initialize(gems)
@gems = gems
end
def run
CLI::Common.ensure_all_gems_in_lockfile!(@gems)
definition = Bundler.definition
definition.validate_runtime!
installer = Bundler::Installer.new(Bundler.root, definition)
Bundler.load.specs.each do |spec|
next if spec.name == "bundler" # Source::Rubygems doesn't install bundler
next if !@gems.empty? && !@gems.include?(spec.name)
gem_name = "#{spec.name} (#{spec.version}#{spec.git_version})"
gem_name += " (#{spec.platform})" if !spec.platform.nil? && spec.platform != Gem::Platform::RUBY
@ -21,13 +26,15 @@ module Bundler
Bundler.ui.error("Failed to pristine #{gem_name}. Cached gem #{cached_gem} does not exist.")
next
end
FileUtils.rm_rf spec.full_gem_path
when Source::Git
source.remote!
FileUtils.rm_rf spec.full_gem_path
else
Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.")
next
end
FileUtils.rm_rf spec.full_gem_path
Bundler::GemInstaller.new(spec, installer, false, 0, true).install_from_spec
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require "bundler/cli/common"
module Bundler
class CLI::Show

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require "bundler/cli/common"
module Bundler
class CLI::Update
@ -17,7 +16,18 @@ module Bundler
sources = Array(options[:source])
groups = Array(options[:group]).map(&:to_sym)
if gems.empty? && sources.empty? && groups.empty? && !options[:ruby] && !options[:bundler]
full_update = gems.empty? && sources.empty? && groups.empty? && !options[:ruby] && !options[:bundler]
if full_update && !options[:all]
if Bundler.feature_flag.update_requires_all_flag?
raise InvalidOption, "To update everything, pass the `--all` flag."
end
SharedHelpers.major_deprecation 2, "Pass --all to `bundle update` to update everything"
elsif !full_update && options[:all]
raise InvalidOption, "Cannot specify --all along with specific options."
end
if full_update
# We're doing a full update
Bundler.definition(true)
else
@ -33,7 +43,8 @@ module Bundler
end
Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby],
:lock_shared_dependencies => options[:conservative])
:lock_shared_dependencies => options[:conservative],
:bundler => options[:bundler])
end
Bundler::CLI::Common.configure_gem_version_promoter(Bundler.definition, options)
@ -44,17 +55,32 @@ module Bundler
opts["update"] = true
opts["local"] = options[:local]
Bundler.settings[:jobs] = opts["jobs"] if opts["jobs"]
Bundler.settings.set_command_option_if_given :jobs, opts["jobs"]
Bundler.definition.validate_runtime!
installer = Installer.install Bundler.root, Bundler.definition, opts
Bundler.load.cache if Bundler.app_cache.exist?
if Bundler.settings[:clean] && Bundler.settings[:path]
if CLI::Common.clean_after_install?
require "bundler/cli/clean"
Bundler::CLI::Clean.new(options).run
end
if locked_gems = Bundler.definition.locked_gems
gems.each do |name|
locked_version = locked_gems.specs.find {|s| s.name == name }.version
new_version = Bundler.definition.specs[name].first
new_version &&= new_version.version
if !new_version
Bundler.ui.warn "Bundler attempted to update #{name} but it was removed from the bundle"
elsif new_version < locked_version
Bundler.ui.warn "Bundler attempted to update #{name} but its version regressed from #{locked_version} to #{new_version}"
elsif new_version == locked_version
Bundler.ui.warn "Bundler attempted to update #{name} but its version stayed the same"
end
end
end
Bundler.ui.confirm "Bundle updated!"
Bundler::CLI::Common.output_without_groups_message
Bundler::CLI::Common.output_post_install_messages installer.post_install_messages

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class CLI::Viz
attr_reader :options, :gem_name

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "pathname"
require "set"

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require "digest/md5"
module Bundler
class CompactIndexClient
@ -68,7 +67,7 @@ module Bundler
def info_path(name)
name = name.to_s
if name =~ /[^a-z0-9_-]/
name += "-#{Digest::MD5.hexdigest(name).downcase}"
name += "-#{SharedHelpers.digest(:MD5).hexdigest(name).downcase}"
info_roots.last.join(name)
else
info_roots.first.join(name)

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
require "fileutils"
require "bundler/vendored_fileutils"
require "stringio"
require "tmpdir"
require "zlib"
module Bundler
@ -22,6 +22,7 @@ module Bundler
def initialize(fetcher)
@fetcher = fetcher
require "tmpdir"
end
def update(local_path, remote_path, retrying = nil)
@ -98,7 +99,7 @@ module Bundler
# because we need to preserve \n line endings on windows when calculating
# the checksum
SharedHelpers.filesystem_access(path, :read) do
Digest::MD5.hexdigest(IO.read(path))
SharedHelpers.digest(:MD5).hexdigest(IO.read(path))
end
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: false
require "rubygems"
require "bundler/version"
if Bundler::VERSION.split(".").first.to_i >= 2
if Gem::Version.new(Object::RUBY_VERSION.dup) < Gem::Version.new("2.3")
abort "Bundler 2 requires Ruby 2.3 or later. Either install bundler 1 or update to a supported Ruby version."
end
if Gem::Version.new(Gem::VERSION.dup) < Gem::Version.new("2.5")
abort "Bundler 2 requires RubyGems 2.5 or later. Either install bundler 1 or update to a supported RubyGems version."
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
WINDOWS = RbConfig::CONFIG["host_os"] =~ /(msdos|mswin|djgpp|mingw)/
FREEBSD = RbConfig::CONFIG["host_os"] =~ /bsd/

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
# Returns current version of Ruby
#
@ -8,7 +9,7 @@ module Bundler
end
class CurrentRuby
KNOWN_MINOR_VERSIONS = %w(
KNOWN_MINOR_VERSIONS = %w[
1.8
1.9
2.0
@ -17,11 +18,11 @@ module Bundler
2.3
2.4
2.5
).freeze
].freeze
KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze
KNOWN_PLATFORMS = %w(
KNOWN_PLATFORMS = %w[
jruby
maglev
mingw
@ -31,7 +32,7 @@ module Bundler
rbx
ruby
x64_mingw
).freeze
].freeze
def ruby?
!mswin? && (!defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx" || RUBY_ENGINE == "maglev")

View file

@ -1,6 +1,6 @@
# frozen_string_literal: true
require "bundler/lockfile_parser"
require "digest/sha1"
require "set"
module Bundler
@ -14,7 +14,9 @@ module Bundler
:locked_gems,
:platforms,
:requires,
:ruby_version
:ruby_version,
:lockfile,
:gemfiles
)
# Given a gemfile and lockfile creates a Bundler definition
@ -51,8 +53,16 @@ module Bundler
# to be updated or true if all gems should be updated
# @param ruby_version [Bundler::RubyVersion, nil] Requested Ruby Version
# @param optional_groups [Array(String)] A list of optional groups
def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [])
@unlocking = unlock == true || !unlock.empty?
def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [], gemfiles = [])
if [true, false].include?(unlock)
@unlocking_bundler = false
@unlocking = unlock
else
unlock = unlock.dup
@unlocking_bundler = unlock.delete(:bundler)
unlock.delete_if {|_k, v| Array(v).empty? }
@unlocking = !unlock.empty?
end
@dependencies = dependencies
@sources = sources
@ -61,6 +71,7 @@ module Bundler
@remote = false
@specs = nil
@ruby_version = ruby_version
@gemfiles = gemfiles
@lockfile = lockfile
@lockfile_contents = String.new
@ -102,7 +113,7 @@ module Bundler
end
@unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
add_current_platform unless Bundler.settings[:frozen]
add_current_platform unless Bundler.frozen?
converge_path_sources_to_gemspec_sources
@path_changes = converge_paths
@ -167,9 +178,8 @@ module Bundler
"to a different version of #{locked_gem} that hasn't been removed in order to install."
end
unless specs["bundler"].any?
local = Bundler.settings[:frozen] ? rubygems_index : index
bundler = local.search(Gem::Dependency.new("bundler", VERSION)).last
specs["bundler"] = bundler if bundler
bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
specs["bundler"] = bundler
end
specs
@ -194,10 +204,19 @@ module Bundler
missing
end
def missing_dependencies
missing = []
resolve.materialize(current_dependencies, missing)
missing
def missing_specs?
missing = missing_specs
return false if missing.empty?
Bundler.ui.debug "The definition is missing #{missing.map(&:full_name)}"
true
rescue BundlerError => e
@index = nil
@resolve = nil
@specs = nil
@gem_version_promoter = create_gem_version_promoter
Bundler.ui.debug "The definition is missing dependencies, failed to resolve & materialize locally (#{e})"
true
end
def requested_specs
@ -226,7 +245,10 @@ module Bundler
def resolve
@resolve ||= begin
last_resolve = converge_locked_specs
if Bundler.settings[:frozen] || (!unlocking? && nothing_changed?)
if Bundler.frozen?
Bundler.ui.debug "Frozen, using resolution from the lockfile"
last_resolve
elsif !unlocking? && nothing_changed?
Bundler.ui.debug("Found no changes, using resolution from the lockfile")
last_resolve
else
@ -242,25 +264,44 @@ module Bundler
dependency_names = @dependencies.map(&:name)
sources.all_sources.each do |source|
source.dependency_names = dependency_names.dup
source.dependency_names = dependency_names - pinned_spec_names(source)
idx.add_source source.specs
dependency_names -= pinned_spec_names(source.specs)
dependency_names.concat(source.unmet_deps).uniq!
end
idx << Gem::Specification.new("ruby\0", RubyVersion.system.to_gem_version_with_patchlevel)
idx << Gem::Specification.new("rubygems\0", Gem::VERSION)
double_check_for_index(idx, dependency_names)
end
end
# used when frozen is enabled so we can find the bundler
# spec, even if (say) a git gem is not checked out.
def rubygems_index
@rubygems_index ||= Index.build do |idx|
sources.rubygems_sources.each do |rubygems|
idx.add_source rubygems.specs
# Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
# sources A and B. At this point, the API request will have found all the versions of Bar in source A,
# but will not have found any versions of Bar from source B, which is a problem if the requested version
# of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
# each spec we found, we add all possible versions from all sources to the index.
def double_check_for_index(idx, dependency_names)
pinned_names = pinned_spec_names
loop do
idxcount = idx.size
names = :names # do this so we only have to traverse to get dependency_names from the index once
unmet_dependency_names = lambda do
return names unless names == :names
new_names = sources.all_sources.map(&:dependency_names_to_double_check)
return names = nil if new_names.compact!
names = new_names.flatten(1).concat(dependency_names)
names.uniq!
names -= pinned_names
names
end
sources.all_sources.each do |source|
source.double_check_for(unmet_dependency_names, :override_dupes)
end
break if idxcount == idx.size
end
end
private :double_check_for_index
def has_rubygems_remotes?
sources.rubygems_sources.any? {|s| s.remotes.any? }
@ -295,10 +336,10 @@ module Bundler
end
end
preserve_unknown_sections ||= !updating_major && (Bundler.settings[:frozen] || !unlocking?)
preserve_unknown_sections ||= !updating_major && (Bundler.frozen? || !(unlocking? || @unlocking_bundler))
return if lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
if Bundler.settings[:frozen]
if Bundler.frozen?
Bundler.ui.error "Cannot write a changed lockfile while frozen."
return
end
@ -338,51 +379,8 @@ module Bundler
end
def to_lock
out = String.new
sources.lock_sources.each do |source|
# Add the source header
out << source.to_lock
# Find all specs for this source
resolve.
select {|s| source.can_lock?(s) }.
# This needs to be sorted by full name so that
# gems with the same name, but different platform
# are ordered consistently
sort_by(&:full_name).
each do |spec|
next if spec.name == "bundler"
out << spec.to_lock
end
out << "\n"
end
out << "PLATFORMS\n"
platforms.map(&:to_s).sort.each do |p|
out << " #{p}\n"
end
out << "\n"
out << "DEPENDENCIES\n"
handled = []
dependencies.sort_by(&:to_s).each do |dep|
next if handled.include?(dep.name)
out << dep.to_lock
handled << dep.name
end
if locked_ruby_version
out << "\nRUBY VERSION\n"
out << " #{locked_ruby_version}\n"
end
# Record the version of Bundler that was used to create the lockfile
out << "\nBUNDLED WITH\n"
out << " #{locked_bundler_version}\n"
out
require "bundler/lockfile_generator"
LockfileGenerator.generate(self)
end
def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false)
@ -392,8 +390,13 @@ module Bundler
"updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control."
unless explicit_flag
suggested_command = Bundler.settings.locations("frozen")[:global] == "1" ? "bundle config --delete frozen" : "bundle install --no-deployment"
suggested_command = if Bundler.settings.locations("frozen")[:global]
"bundle config --delete frozen"
elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any?
"bundle config --delete deployment"
else
"bundle install --no-deployment"
end
msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
"freeze \nby running `#{suggested_command}`."
end
@ -417,8 +420,8 @@ module Bundler
# Check if it is possible that the source is only changed thing
if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
new_sources.reject! {|source| source.is_a_path? && source.path.exist? }
deleted_sources.reject! {|source| source.is_a_path? && source.path.exist? }
new_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
deleted_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
end
if @locked_sources != gemfile_sources
@ -511,7 +514,7 @@ module Bundler
def add_current_platform
current_platform = Bundler.local_platform
add_platform(current_platform) if Bundler.settings[:specific_platform]
add_platform(current_platform) if Bundler.feature_flag.specific_platform?
add_platform(generic(current_platform))
end
@ -558,10 +561,7 @@ module Bundler
end
def pretty_dep(dep, source = false)
msg = String.new(dep.name)
msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default
msg << " from the `#{dep.source}` source" if source && dep.source
msg
SharedHelpers.pretty_dependency(dep, source)
end
# Check if the specs of the given source changed
@ -585,6 +585,9 @@ module Bundler
# order here matters, since Index#== is checking source.specs.include?(locked_index)
locked_index != source.specs
rescue PathError, GitError => e
Bundler.ui.debug "Assuming that #{source} has not changed since fetching its specs errored (#{e})"
false
end
# Get all locals and override their matching sources.
@ -632,22 +635,32 @@ module Bundler
end
end
def converge_sources
def converge_rubygems_sources
return false if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
changes = false
# Get the Rubygems sources from the Gemfile.lock
# Get the RubyGems sources from the Gemfile.lock
locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
# Get the Rubygems remotes from the Gemfile
# Get the RubyGems remotes from the Gemfile
actual_remotes = sources.rubygems_remotes
# If there is a Rubygems source in both
# If there is a RubyGems source in both
if !locked_gem_sources.empty? && !actual_remotes.empty?
locked_gem_sources.each do |locked_gem|
# Merge the remotes from the Gemfile into the Gemfile.lock
changes |= locked_gem.replace_remotes(actual_remotes)
changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
end
end
changes
end
def converge_sources
changes = false
changes |= converge_rubygems_sources
# Replace the sources from the Gemfile with the sources from the Gemfile.lock,
# if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
# source in the Gemfile.lock, use the one from the Gemfile.
@ -669,7 +682,7 @@ module Bundler
end
def converge_dependencies
frozen = Bundler.settings[:frozen]
frozen = Bundler.frozen?
(@dependencies + @locked_deps.values).each do |dep|
locked_source = @locked_deps[dep.name]
# This is to make sure that if bundler is installing in deployment mode and
@ -739,6 +752,8 @@ module Bundler
end
end
unlock_source_unlocks_spec = Bundler.feature_flag.unlock_source_unlocks_spec?
converged = []
@locked_specs.each do |s|
# Replace the locked dependency's source with the equivalent source from the Gemfile
@ -746,21 +761,33 @@ module Bundler
s.source = (dep && dep.source) || sources.get(s.source)
# Don't add a spec to the list if its source is expired. For example,
# if you change a Git gem to Rubygems.
# if you change a Git gem to RubyGems.
next if s.source.nil?
next if @unlock[:sources].include?(s.source.name)
# XXX This is a backwards-compatibility fix to preserve the ability to
# unlock a single gem by passing its name via `--source`. See issue #3759
# TODO: delete in Bundler 2
next if @unlock[:sources].include?(s.name)
next if unlock_source_unlocks_spec && @unlock[:sources].include?(s.name)
# If the spec is from a path source and it doesn't exist anymore
# then we unlock it.
# Path sources have special logic
if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
other = s.source.specs[s].first
other_sources_specs = begin
s.source.specs
rescue PathError, GitError
# if we won't need the source (according to the lockfile),
# don't error if the path/git source isn't available
next if @locked_specs.
for(requested_dependencies, [], false, true, false).
none? {|locked_spec| locked_spec.source == s.source }
raise
end
other = other_sources_specs[s].first
# If the spec is no longer in the path source, unlock it. This
# commonly happens if the version changed in the gemspec
@ -807,17 +834,21 @@ module Bundler
# the metadata dependencies here
def expanded_dependencies
@expanded_dependencies ||= begin
expand_dependencies(dependencies + metadata_dependencies, @remote)
end
end
def metadata_dependencies
@metadata_dependencies ||= begin
ruby_versions = concat_ruby_version_requirements(@ruby_version)
if ruby_versions.empty? || !@ruby_version.exact?
concat_ruby_version_requirements(RubyVersion.system)
concat_ruby_version_requirements(locked_ruby_version_object) unless @unlock[:ruby]
end
metadata_dependencies = [
[
Dependency.new("ruby\0", ruby_versions),
Dependency.new("rubygems\0", Gem::VERSION),
]
expand_dependencies(dependencies + metadata_dependencies, @remote)
end
end
@ -838,11 +869,12 @@ module Bundler
end
def expand_dependencies(dependencies, remote = false)
sorted_platforms = Resolver.sort_platforms(@platforms)
deps = []
dependencies.each do |dep|
dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
next if !remote && !dep.current_platform?
platforms = dep.gem_platforms(@platforms)
platforms = dep.gem_platforms(sorted_platforms)
if platforms.empty?
mapped_platforms = dep.platforms.map {|p| Dependency::PLATFORM_MAP[p] }
Bundler.ui.warn \
@ -872,30 +904,33 @@ module Bundler
# Record the specs available in each gem's source, so that those
# specs will be available later when the resolver knows where to
# look for that gemspec (or its dependencies)
source_requirements = {}
default = sources.default_source
source_requirements = { :default => default }
default = nil unless Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
dependencies.each do |dep|
next unless dep.source
source_requirements[dep.name] = dep.source.specs
next unless source = dep.source || default
source_requirements[dep.name] = source
end
metadata_dependencies.each do |dep|
source_requirements[dep.name] = sources.metadata_source
end
source_requirements["bundler"] = sources.metadata_source # needs to come last to override
source_requirements
end
def pinned_spec_names(specs)
names = []
specs.each do |s|
# TODO: when two sources without blocks is an error, we can change
# this check to !s.source.is_a?(Source::LocalRubygems). For now,
# we need to ask every Rubygems for every gem name.
if s.source.is_a?(Source::Git) || s.source.is_a?(Source::Path)
names << s.name
end
def pinned_spec_names(skip = nil)
pinned_names = []
default = Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? && sources.default_source
@dependencies.each do |dep|
next unless dep_source = dep.source || default
next if dep_source == skip
pinned_names << dep.name
end
names.uniq!
names
pinned_names
end
def requested_groups
groups - Bundler.settings.without - @optional_groups + Bundler.settings.with
groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
end
def lockfiles_equal?(current, proposed, preserve_unknown_sections)
@ -930,11 +965,20 @@ module Bundler
def additional_base_requirements_for_resolve
return [] unless @locked_gems && Bundler.feature_flag.only_update_to_newer_versions?
dependencies_by_name = dependencies.group_by(&:name)
@locked_gems.specs.reduce({}) do |requirements, locked_spec|
dep = Gem::Dependency.new(locked_spec.name, ">= #{locked_spec.version}")
requirements[locked_spec.name] = DepProxy.new(dep, locked_spec.platform)
name = locked_spec.name
next requirements if @locked_deps[name] != dependencies_by_name[name]
dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
requirements[name] = DepProxy.new(dep, locked_spec.platform)
requirements
end.values
end
def equivalent_rubygems_remotes?(source)
return false unless source.is_a?(Source::Rubygems)
Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class DepProxy
attr_reader :__platform, :dep
@ -13,6 +14,7 @@ module Bundler
end
def ==(other)
return if other.nil?
dep == other.dep && __platform == other.__platform
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "rubygems/dependency"
require "bundler/shared_helpers"
require "bundler/rubygems_ext"
@ -90,16 +91,14 @@ module Bundler
@autorequire = Array(options["require"] || []) if options.key?("require")
end
# Returns the platforms this dependency is valid for, in the same order as
# passed in the `valid_platforms` parameter
def gem_platforms(valid_platforms)
return valid_platforms if @platforms.empty?
platforms = []
@platforms.each do |p|
platform = PLATFORM_MAP[p]
next unless valid_platforms.include?(platform)
platforms |= [platform]
end
platforms
@gem_platforms ||= @platforms.map {|pl| PLATFORM_MAP[pl] }.compact.uniq
valid_platforms & @gem_platforms
end
def should_include?

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
require "bundler/shared_helpers"
Bundler::SharedHelpers.major_deprecation "Bundler no longer integrates with " \
Bundler::SharedHelpers.major_deprecation 2, "Bundler no longer integrates with " \
"Capistrano, but Capistrano provides its own integration with " \
"Bundler via the capistrano-bundler gem. Use it instead."

View file

@ -1,11 +1,22 @@
# frozen_string_literal: true
begin
require "rubygems/deprecate"
rescue LoadError
# it's fine if it doesn't exist on the current RubyGems...
nil
end
module Bundler
if defined? ::Deprecate
if defined? Bundler::Deprecate
# nothing to do!
elsif defined? ::Deprecate
Deprecate = ::Deprecate
elsif defined? Gem::Deprecate
Deprecate = Gem::Deprecate
else
class Deprecate; end
class Deprecate
end
end
unless Deprecate.respond_to?(:skip_during)
@ -20,7 +31,7 @@ module Bundler
unless Deprecate.respond_to?(:skip)
def Deprecate.skip
@skip
@skip ||= false
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/dependency"
require "bundler/ruby_dsl"
@ -14,6 +15,9 @@ module Bundler
VALID_PLATFORMS = Bundler::Dependency::PLATFORM_MAP.keys.freeze
VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules
platform platforms type source install_if].freeze
attr_reader :gemspecs
attr_accessor :dependencies
@ -30,14 +34,16 @@ module Bundler
@ruby_version = nil
@gemspecs = []
@gemfile = nil
@gemfiles = []
add_git_sources
end
def eval_gemfile(gemfile, contents = nil)
expanded_gemfile_path = Pathname.new(gemfile).expand_path
expanded_gemfile_path = Pathname.new(gemfile).expand_path(@gemfile && @gemfile.parent)
original_gemfile = @gemfile
@gemfile = expanded_gemfile_path
contents ||= Bundler.read_file(gemfile.to_s)
@gemfiles << expanded_gemfile_path
contents ||= Bundler.read_file(@gemfile.to_s)
instance_eval(contents.dup.untaint, gemfile.to_s, 1)
rescue Exception => e
message = "There was an error " \
@ -95,10 +101,10 @@ module Bundler
# if there's already a dependency with this name we try to prefer one
if current = @dependencies.find {|d| d.name == dep.name }
deleted_dep = @dependencies.delete(current) if current.type == :development
if current.requirement != dep.requirement
if current.type == :development
@dependencies.delete current
else
unless deleted_dep
return if dep.type == :development
raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \
"You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})"
@ -111,9 +117,7 @@ module Bundler
end
if current.source != dep.source
if current.type == :development
@dependencies.delete current
else
unless deleted_dep
return if dep.type == :development
raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
"You specified that #{dep.name} (#{dep.requirement}) should come from " \
@ -128,10 +132,12 @@ module Bundler
def source(source, *args, &blk)
options = args.last.is_a?(Hash) ? args.pop.dup : {}
options = normalize_hash(options)
source = normalize_source(source)
if options.key?("type")
options["type"] = options["type"].to_s
unless Plugin.source?(options["type"])
raise "No sources available for #{options["type"]}"
raise InvalidOption, "No plugin sources available for #{options["type"]}"
end
unless block_given?
@ -141,12 +147,10 @@ module Bundler
source_opts = options.merge("uri" => source)
with_source(@sources.add_plugin_source(options["type"], source_opts), &blk)
elsif block_given?
source = normalize_source(source)
with_source(@sources.add_rubygems_source("remotes" => source), &blk)
else
source = normalize_source(source)
check_primary_source_safety(@sources)
@sources.add_rubygems_remote(source)
@sources.global_rubygems_source = source
end
end
@ -164,6 +168,19 @@ module Bundler
end
def path(path, options = {}, &blk)
unless block_given?
msg = "You can no longer specify a path source by itself. Instead, \n" \
"either use the :path option on a gem, or specify the gems that \n" \
"bundler should find in the path source by passing a block to \n" \
"the path method, like: \n\n" \
" path 'dir/containing/rails' do\n" \
" gem 'rails'\n" \
" end\n\n"
raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource?
SharedHelpers.major_deprecation(2, msg.strip)
end
source_options = normalize_hash(options).merge(
"path" => Pathname.new(path),
"root_path" => gemfile_root,
@ -190,6 +207,7 @@ module Bundler
def github(repo, options = {})
raise ArgumentError, "GitHub sources require a block" unless block_given?
raise DeprecatedError, "The #github method has been removed" if Bundler.feature_flag.skip_default_git_sources?
github_uri = @git_sources["github"].call(repo)
git_options = normalize_hash(options).merge("uri" => github_uri)
git_source = @sources.add_git_source(git_options)
@ -197,16 +215,16 @@ module Bundler
end
def to_definition(lockfile, unlock)
Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups)
Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles)
end
def group(*args, &blk)
opts = Hash === args.last ? args.pop.dup : {}
normalize_group_options(opts, args)
options = args.last.is_a?(Hash) ? args.pop.dup : {}
normalize_group_options(options, args)
@groups.concat args
if opts["optional"]
if options["optional"]
optional_groups = args - @optional_groups
@optional_groups.concat optional_groups
end
@ -216,9 +234,9 @@ module Bundler
args.each { @groups.pop }
end
def install_if(*args, &blk)
def install_if(*args)
@install_conditionals.concat args
blk.call
yield
ensure
args.each { @install_conditionals.pop }
end
@ -250,7 +268,12 @@ module Bundler
private
def add_git_sources
return if Bundler.feature_flag.skip_default_git_sources?
git_source(:github) do |repo_name|
warn_deprecated_git_source(:github, <<-'RUBY'.strip, 'Change any "reponame" :github sources to "username/reponame".')
"https://github.com/#{repo_name}.git"
RUBY
# It would be better to use https instead of the git protocol, but this
# can break deployment of existing locked bundles when switching between
# different versions of Bundler. The change will be made in 2.0, which
@ -267,23 +290,29 @@ module Bundler
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
# TODO: 2.0 upgrade this setting to the default
if Bundler.settings["github.https"]
Bundler::SharedHelpers.major_deprecation 2, "The `github.https` setting will be removed"
"https://github.com/#{repo_name}.git"
else
warn_github_source_change(repo_name)
"git://github.com/#{repo_name}.git"
end
end
# TODO: 2.0 remove this deprecated git source
git_source(:gist) do |repo_name|
warn_deprecated_git_source(:gist, 'https://gist.github.com/#{repo_name}.git')
warn_deprecated_git_source(:gist, '"https://gist.github.com/#{repo_name}.git"')
"https://gist.github.com/#{repo_name}.git"
end
# TODO: 2.0 remove this deprecated git source
git_source(:bitbucket) do |repo_name|
user_name, repo_name = repo_name.split "/"
warn_deprecated_git_source(:bitbucket, 'https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git')
warn_deprecated_git_source(:bitbucket, <<-'RUBY'.strip)
user_name, repo_name = repo_name.split("/")
repo_name ||= user_name
"https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
RUBY
user_name, repo_name = repo_name.split("/")
repo_name ||= user_name
"https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
end
@ -308,7 +337,7 @@ module Bundler
end
def valid_keys
@valid_keys ||= %w(group groups git path glob name branch ref tag require submodules platform platforms type source install_if)
@valid_keys ||= VALID_KEYS
end
def normalize_options(name, version, opts)
@ -318,6 +347,9 @@ module Bundler
if name =~ /\s/
raise GemfileError, %('#{name}' is not a valid gem name because it contains whitespace)
end
if name.empty?
raise GemfileError, %(an empty gem name is not valid)
end
normalize_hash(opts)
@ -355,7 +387,7 @@ module Bundler
opts["git"] = @git_sources[git_name].call(opts[git_name])
end
%w(git path).each do |type|
%w[git path].each do |type|
next unless param = opts[type]
if version.first && version.first =~ /^\s*=?\s*(\d[^\s]*)\s*$/
options = opts.merge("name" => name, "version" => $1)
@ -366,8 +398,8 @@ module Bundler
opts["source"] = source
end
opts["source"] ||= @source
opts["env"] ||= @env
opts["source"] ||= @source
opts["env"] ||= @env
opts["platforms"] = platforms.dup
opts["group"] = groups
opts["should_include"] = install_if
@ -377,7 +409,7 @@ module Bundler
normalize_hash(opts)
groups = groups.map {|group| ":#{group}" }.join(", ")
validate_keys("group #{groups}", opts, %w(optional))
validate_keys("group #{groups}", opts, %w[optional])
opts["optional"] ||= false
end
@ -390,25 +422,25 @@ module Bundler
raise GemfileError, %(The `branch` option for `#{command}` is not allowed. Only gems with a git source can specify a branch)
end
if invalid_keys.any?
message = String.new
message << "You passed #{invalid_keys.map {|k| ":" + k }.join(", ")} "
message << if invalid_keys.size > 1
"as options for #{command}, but they are invalid."
else
"as an option for #{command}, but it is invalid."
end
return true unless invalid_keys.any?
message << " Valid options are: #{valid_keys.join(", ")}."
message << " You may be able to resolve this by upgrading Bundler to the newest version."
raise InvalidOption, message
end
message = String.new
message << "You passed #{invalid_keys.map {|k| ":" + k }.join(", ")} "
message << if invalid_keys.size > 1
"as options for #{command}, but they are invalid."
else
"as an option for #{command}, but it is invalid."
end
message << " Valid options are: #{valid_keys.join(", ")}."
message << " You may be able to resolve this by upgrading Bundler to the newest version."
raise InvalidOption, message
end
def normalize_source(source)
case source
when :gemcutter, :rubygems, :rubyforge
Bundler::SharedHelpers.major_deprecation "The source :#{source} is deprecated because HTTP " \
Bundler::SharedHelpers.major_deprecation 2, "The source :#{source} is deprecated because HTTP " \
"requests are insecure.\nPlease change your source to 'https://" \
"rubygems.org' if possible, or 'http://rubygems.org' if not."
"http://rubygems.org"
@ -419,17 +451,20 @@ module Bundler
end
end
def check_primary_source_safety(source)
return unless source.rubygems_primary_remotes.any?
def check_primary_source_safety(source_list)
return if source_list.rubygems_primary_remotes.empty? && source_list.global_rubygems_source.nil?
# TODO: 2.0 upgrade from setting to default
if Bundler.settings[:disable_multisource]
raise GemfileError, "Warning: this Gemfile contains multiple primary sources. " \
if Bundler.feature_flag.disable_multisource?
msg = "This Gemfile contains multiple primary sources. " \
"Each source after the first must include a block to indicate which gems " \
"should come from that source. To downgrade this error to a warning, run " \
"`bundle config --delete disable_multisource`"
"should come from that source"
unless Bundler.feature_flag.bundler_2_mode?
msg += ". To downgrade this error to a warning, run " \
"`bundle config --delete disable_multisource`"
end
raise GemfileEvalError, msg
else
Bundler::SharedHelpers.major_deprecation "Your Gemfile contains multiple primary sources. " \
Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
"a block to indicate which gems should come from the secondary source. " \
@ -438,20 +473,20 @@ module Bundler
end
end
def warn_github_source_change(repo_name)
def warn_deprecated_git_source(name, replacement, additional_message = nil)
# TODO: 2.0 remove deprecation
Bundler::SharedHelpers.major_deprecation "The :github option uses the git: protocol, which is not secure. " \
"Bundler 2.0 will use the https: protocol, which is secure. Enable this change now by " \
"running `bundle config github.https true`."
end
additional_message &&= " #{additional_message}"
replacement = if replacement.count("\n").zero?
"{|repo_name| #{replacement} }"
else
"do |repo_name|\n#{replacement.to_s.gsub(/^/, " ")}\n end"
end
Bundler::SharedHelpers.major_deprecation 2, <<-EOS
The :#{name} git source is deprecated, and will be removed in Bundler 2.0.#{additional_message} Add this code to the top of your Gemfile to ensure it continues to work:
git_source(:#{name}) #{replacement}
def warn_deprecated_git_source(name, repo_string)
# TODO: 2.0 remove deprecation
Bundler::SharedHelpers.major_deprecation <<-EOS
The :#{name} git source is deprecated, and will be removed in Bundler 2.0. Add this code to your Gemfile to ensure it continues to work:
git_source(:#{name}) do |repo_name|
"#{repo_string}"
end
EOS
end
@ -530,7 +565,7 @@ The :#{name} git source is deprecated, and will be removed in Bundler 2.0. Add t
lines = contents.lines.to_a
indent = " # "
indicator = indent.tr("#", ">")
first_line = (line_numer.zero?)
first_line = line_numer.zero?
last_line = (line_numer == (lines.count - 1))
m << "\n"

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
# used for Creating Specifications from the Gemcutter Endpoint
class EndpointSpecification < Gem::Specification
@ -9,11 +10,15 @@ module Bundler
attr_accessor :source, :remote, :dependencies
def initialize(name, version, platform, dependencies, metadata = nil)
super()
@name = name
@version = Gem::Version.create version
@platform = platform
@dependencies = dependencies.map {|dep, reqs| build_dependency(dep, reqs) }
@loaded_from = nil
@remote_specification = nil
parse_metadata(metadata)
end
@ -71,6 +76,8 @@ module Bundler
@remote_specification.post_install_message
elsif _local_specification
_local_specification.post_install_message
else
super
end
end
@ -80,6 +87,8 @@ module Bundler
@remote_specification.extensions
elsif _local_specification
_local_specification.extensions
else
super
end
end

View file

@ -1,33 +1,21 @@
# frozen_string_literal: true
require "bundler/rubygems_integration"
require "bundler/source/git/git_proxy"
module Bundler
class Env
def write(io)
def self.write(io)
io.write report
end
def report(options = {})
def self.report(options = {})
print_gemfile = options.delete(:print_gemfile) { true }
print_gemspecs = options.delete(:print_gemspecs) { true }
out = String.new("## Environment\n\n```\n")
out << "Bundler #{Bundler::VERSION}\n"
out << "Rubygems #{Gem::VERSION}\n"
out << "Ruby #{ruby_version}"
out << "GEM_HOME #{ENV["GEM_HOME"]}\n" unless ENV["GEM_HOME"].nil? || ENV["GEM_HOME"].empty?
out << "GEM_PATH #{ENV["GEM_PATH"]}\n" unless ENV["GEM_PATH"] == ENV["GEM_HOME"]
out << "RVM #{ENV["rvm_version"]}\n" if ENV["rvm_version"]
out << "Git #{git_version}\n"
out << "Platform #{Gem::Platform.local}\n"
out << "OpenSSL #{OpenSSL::OPENSSL_VERSION}\n" if defined?(OpenSSL::OPENSSL_VERSION)
%w(rubygems-bundler open_gem).each do |name|
specs = Bundler.rubygems.find_name(name)
out << "#{name} (#{specs.map(&:version).join(",")})\n" unless specs.empty?
end
out << "```\n"
out = String.new
append_formatted_table("Environment", environment, out)
append_formatted_table("Bundler Build Metadata", BuildMetadata.to_h, out)
unless Bundler.settings.all.empty?
out << "\n## Bundler settings\n\n```\n"
@ -43,9 +31,18 @@ module Bundler
return out unless SharedHelpers.in_bundle?
if print_gemfile
gemfiles = [Bundler.default_gemfile]
begin
gemfiles = Bundler.definition.gemfiles
rescue GemfileNotFound
nil
end
out << "\n## Gemfile\n"
out << "\n### #{Bundler.default_gemfile.relative_path_from(SharedHelpers.pwd)}\n\n"
out << "```ruby\n" << read_file(Bundler.default_gemfile).chomp << "\n```\n"
gemfiles.each do |gemfile|
out << "\n### #{Pathname.new(gemfile).relative_path_from(SharedHelpers.pwd)}\n\n"
out << "```ruby\n" << read_file(gemfile).chomp << "\n```\n"
end
out << "\n### #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}\n\n"
out << "```\n" << read_file(Bundler.default_lockfile).chomp << "\n```\n"
@ -63,9 +60,7 @@ module Bundler
out
end
private
def read_file(filename)
def self.read_file(filename)
File.read(filename.to_s).strip
rescue Errno::ENOENT
"<No #{filename} found>"
@ -73,22 +68,86 @@ module Bundler
"#{e.class}: #{e.message}"
end
def ruby_version
def self.ruby_version
str = String.new("#{RUBY_VERSION}")
if RUBY_VERSION < "1.9"
str << " (#{RUBY_RELEASE_DATE}"
str << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
str << ") [#{RUBY_PLATFORM}]\n"
str << ") [#{RUBY_PLATFORM}]"
else
str << "p#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
str << " (#{RUBY_RELEASE_DATE} revision #{RUBY_REVISION}) [#{RUBY_PLATFORM}]\n"
str << " (#{RUBY_RELEASE_DATE} revision #{RUBY_REVISION}) [#{RUBY_PLATFORM}]"
end
end
def git_version
def self.git_version
Bundler::Source::Git::GitProxy.new(nil, nil, nil).full_version
rescue Bundler::Source::Git::GitNotInstalledError
"not installed"
end
def self.version_of(script)
return "not installed" unless Bundler.which(script)
`#{script} --version`
end
def self.chruby_version
return "not installed" unless Bundler.which("chruby-exec")
`chruby-exec -- chruby --version`.
sub(/.*^chruby: (#{Gem::Version::VERSION_PATTERN}).*/m, '\1')
end
def self.environment
out = []
out << ["Bundler", Bundler::VERSION]
out << [" Platforms", Gem.platforms.join(", ")]
out << ["Ruby", ruby_version]
out << [" Full Path", Gem.ruby]
out << [" Config Dir", Pathname.new(Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE).dirname]
out << ["RubyGems", Gem::VERSION]
out << [" Gem Home", ENV.fetch("GEM_HOME") { Gem.dir }]
out << [" Gem Path", ENV.fetch("GEM_PATH") { Gem.path.join(File::PATH_SEPARATOR) }]
out << [" User Path", Gem.user_dir]
out << [" Bin Dir", Gem.bindir]
out << ["OpenSSL"] if defined?(OpenSSL)
out << [" Compiled", OpenSSL::OPENSSL_VERSION] if defined?(OpenSSL::OPENSSL_VERSION)
out << [" Loaded", OpenSSL::OPENSSL_LIBRARY_VERSION] if defined?(OpenSSL::OPENSSL_LIBRARY_VERSION)
out << [" Cert File", OpenSSL::X509::DEFAULT_CERT_FILE] if defined?(OpenSSL::X509::DEFAULT_CERT_FILE)
out << [" Cert Dir", OpenSSL::X509::DEFAULT_CERT_DIR] if defined?(OpenSSL::X509::DEFAULT_CERT_DIR)
out << ["Tools"]
out << [" Git", git_version]
out << [" RVM", ENV.fetch("rvm_version") { version_of("rvm") }]
out << [" rbenv", version_of("rbenv")]
out << [" chruby", chruby_version]
%w[rubygems-bundler open_gem].each do |name|
specs = Bundler.rubygems.find_name(name)
out << [" #{name}", "(#{specs.map(&:version).join(",")})"] unless specs.empty?
end
if (exe = caller.last.split(":").first) && exe =~ %r{(exe|bin)/bundler?\z}
shebang = File.read(exe).lines.first
shebang.sub!(/^#!\s*/, "")
unless shebang.start_with?(Gem.ruby, "/usr/bin/env ruby")
out << ["Gem.ruby", Gem.ruby]
out << ["bundle #!", shebang]
end
end
out
end
def self.append_formatted_table(title, pairs, out)
return if pairs.empty?
out << "\n" unless out.empty?
out << "## #{title}\n\n```\n"
ljust = pairs.map {|k, _v| k.to_s.length }.max
pairs.each do |k, v|
out << "#{k.to_s.ljust(ljust)} #{v}\n"
end
out << "```\n"
end
private_class_method :read_file, :ruby_version, :git_version, :append_formatted_table, :version_of, :chruby_version
end
end

View file

@ -1,12 +1,29 @@
# frozen_string_literal: true
module Bundler
class EnvironmentPreserver
INTENTIONALLY_NIL = "BUNDLER_ENVIRONMENT_PRESERVER_INTENTIONALLY_NIL".freeze
BUNDLER_KEYS = %w[
BUNDLE_BIN_PATH
BUNDLE_GEMFILE
BUNDLER_ORIG_MANPATH
BUNDLER_VERSION
GEM_HOME
GEM_PATH
MANPATH
PATH
RB_USER_INSTALL
RUBYLIB
RUBYOPT
].map(&:freeze).freeze
BUNDLER_PREFIX = "BUNDLER_ORIG_".freeze
# @param env [ENV]
# @param keys [Array<String>]
def initialize(env, keys)
@original = env.to_hash
@keys = keys
@prefix = "BUNDLER_ORIG_"
@prefix = BUNDLER_PREFIX
end
# @return [Hash]
@ -14,9 +31,10 @@ module Bundler
env = @original.clone
@keys.each do |key|
value = env[key]
original_value = env[@prefix + key]
if !value.nil? && !value.empty? && original_value.nil?
env[@prefix + key] = value
if !value.nil? && !value.empty?
env[@prefix + key] ||= value
elsif value.nil?
env[@prefix + key] ||= INTENTIONALLY_NIL
end
end
env
@ -27,10 +45,13 @@ module Bundler
env = @original.clone
@keys.each do |key|
value_original = env[@prefix + key]
unless value_original.nil? || value_original.empty?
next if value_original.nil? || value_original.empty?
if value_original == INTENTIONALLY_NIL
env.delete(key)
else
env[key] = value_original
env.delete(@prefix + key)
end
env.delete(@prefix + key)
end
env
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class BundlerError < StandardError
def self.status_code(code)

View file

@ -1,22 +1,59 @@
# frozen_string_literal: true
module Bundler
class FeatureFlag
def self.settings_flag(flag, &default)
unless Bundler::Settings::BOOL_KEYS.include?(flag.to_s)
raise "Cannot use `#{flag}` as a settings feature flag since it isn't a bool key"
end
define_method("#{flag}?") do
value = Bundler.settings[flag]
settings_method("#{flag}?", flag, &default)
end
private_class_method :settings_flag
def self.settings_option(key, &default)
settings_method(key, key, &default)
end
private_class_method :settings_option
def self.settings_method(name, key, &default)
define_method(name) do
value = Bundler.settings[key]
value = instance_eval(&default) if value.nil? && !default.nil?
value
end
end
private_class_method :settings_method
(1..10).each {|v| define_method("bundler_#{v}_mode?") { major_version >= v } }
settings_flag(:allow_bundler_dependency_conflicts) { bundler_2_mode? }
settings_flag(:allow_offline_install) { bundler_2_mode? }
settings_flag(:auto_clean_without_path) { bundler_2_mode? }
settings_flag(:cache_all) { bundler_2_mode? }
settings_flag(:cache_command_is_package) { bundler_2_mode? }
settings_flag(:console_command) { !bundler_2_mode? }
settings_flag(:default_install_uses_path) { bundler_2_mode? }
settings_flag(:deployment_means_frozen) { bundler_2_mode? }
settings_flag(:disable_multisource) { bundler_2_mode? }
settings_flag(:error_on_stderr) { bundler_2_mode? }
settings_flag(:forget_cli_options) { bundler_2_mode? }
settings_flag(:global_gem_cache) { bundler_2_mode? }
settings_flag(:init_gems_rb) { bundler_2_mode? }
settings_flag(:list_command) { bundler_2_mode? }
settings_flag(:lockfile_uses_separate_rubygems_sources) { bundler_2_mode? }
settings_flag(:only_update_to_newer_versions) { bundler_2_mode? }
settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") }
settings_flag(:prefer_gems_rb) { bundler_2_mode? }
settings_flag(:print_only_version_number) { bundler_2_mode? }
settings_flag(:setup_makes_kernel_gem_public) { !bundler_2_mode? }
settings_flag(:skip_default_git_sources) { bundler_2_mode? }
settings_flag(:specific_platform) { bundler_2_mode? }
settings_flag(:suppress_install_using_messages) { bundler_2_mode? }
settings_flag(:unlock_source_unlocks_spec) { !bundler_2_mode? }
settings_flag(:update_requires_all_flag) { bundler_2_mode? }
settings_option(:default_cli_command) { bundler_2_mode? ? :cli_help : :install }
def initialize(bundler_version)
@bundler_version = Gem::Version.create(bundler_version)
@ -26,7 +63,5 @@ module Bundler
@bundler_version.segments.first
end
private :major_version
class << self; private :settings_flag; end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/vendored_persistent"
require "cgi"
require "securerandom"
@ -237,7 +238,7 @@ module Bundler
Bundler.settings[:ssl_client_cert]
raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
con = Bundler::Persistent::Net::HTTP::Persistent.new "bundler", :ENV
con = PersistentHTTP.new "bundler", :ENV
if gem_proxy = Bundler.rubygems.configuration[:http_proxy]
con.proxy = URI.parse(gem_proxy) if gem_proxy != :no_proxy
end
@ -248,8 +249,11 @@ module Bundler
con.cert_store = bundler_cert_store
end
if Bundler.settings[:ssl_client_cert]
pem = File.read(Bundler.settings[:ssl_client_cert])
ssl_client_cert = Bundler.settings[:ssl_client_cert] ||
(Bundler.rubygems.configuration.ssl_client_cert if
Bundler.rubygems.configuration.respond_to?(:ssl_client_cert))
if ssl_client_cert
pem = File.read(ssl_client_cert)
con.cert = OpenSSL::X509::Certificate.new(pem)
con.key = OpenSSL::PKey::RSA.new(pem)
end
@ -273,16 +277,19 @@ module Bundler
Timeout::Error, EOFError, SocketError, Errno::ENETDOWN, Errno::ENETUNREACH,
Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN,
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
Bundler::Persistent::Net::HTTP::Persistent::Error, Zlib::BufError, Errno::EHOSTUNREACH
PersistentHTTP::Error, Zlib::BufError, Errno::EHOSTUNREACH
].freeze
def bundler_cert_store
store = OpenSSL::X509::Store.new
if Bundler.settings[:ssl_ca_cert]
if File.directory? Bundler.settings[:ssl_ca_cert]
store.add_path Bundler.settings[:ssl_ca_cert]
ssl_ca_cert = Bundler.settings[:ssl_ca_cert] ||
(Bundler.rubygems.configuration.ssl_ca_cert if
Bundler.rubygems.configuration.respond_to?(:ssl_ca_cert))
if ssl_ca_cert
if File.directory? ssl_ca_cert
store.add_path ssl_ca_cert
else
store.add_file Bundler.settings[:ssl_ca_cert]
store.add_file ssl_ca_cert
end
else
store.set_default_paths

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class Fetcher
class Base

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/fetcher/base"
require "bundler/worker"
@ -61,7 +62,7 @@ module Bundler
compact_index_request :fetch_spec
def available?
return nil unless md5_available?
return nil unless SharedHelpers.md5_available?
user_home = Bundler.user_home
return nil unless user_home.directory? && user_home.writable?
# Read info file checksums out of /versions, so we can know if gems are up to date
@ -120,16 +121,6 @@ module Bundler
Net::HTTPNotModified.new(nil, nil, nil)
end
end
def md5_available?
require "openssl"
OpenSSL::Digest::MD5.digest("")
true
rescue LoadError
true
rescue OpenSSL::Digest::DigestError
false
end
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/fetcher/base"
require "cgi"
@ -6,7 +7,7 @@ module Bundler
class Fetcher
class Dependency < Base
def available?
fetch_uri.scheme != "file" && downloader.fetch(dependency_api_uri)
@available ||= fetch_uri.scheme != "file" && downloader.fetch(dependency_api_uri)
rescue NetworkDownError => e
raise HTTPError, e.message
rescue AuthenticationRequiredError

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class Fetcher
class Downloader

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/fetcher/base"
require "rubygems/remote_fetcher"

View file

@ -1,5 +1,6 @@
# encoding: utf-8
# frozen_string_literal: true
require "cgi"
require "bundler/vendored_thor"
@ -92,7 +93,7 @@ module Bundler
#{e.backtrace && e.backtrace.join("\n ").chomp}
```
#{Bundler::Env.new.report}
#{Bundler::Env.report}
--- TEMPLATE END ----------------------------------------------------------------
EOS
@ -119,6 +120,8 @@ module Bundler
def self.with_friendly_errors
yield
rescue SignalException
raise
rescue Exception => e
FriendlyErrors.log_error(e)
exit FriendlyErrors.exit_status(e)

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/vendored_thor" unless defined?(Thor)
require "bundler"
@ -50,8 +51,8 @@ module Bundler
install_gem(built_gem_path, :local)
end
desc "Create tag #{version_tag} and build and push #{name}-#{version}.gem to Rubygems\n" \
"To prevent publishing in Rubygems use `gem_push=no rake release`"
desc "Create tag #{version_tag} and build and push #{name}-#{version}.gem to #{gem_push_host}\n" \
"To prevent publishing in RubyGems use `gem_push=no rake release`"
task "release", [:remote] => ["build", "release:guard_clean",
"release:source_control_push", "release:rubygem_push"] do
end
@ -92,18 +93,14 @@ module Bundler
protected
def rubygem_push(path)
allowed_push_host = nil
gem_command = "gem push '#{path}'"
gem_command += " --key #{gem_key}" if gem_key
if @gemspec.respond_to?(:metadata)
allowed_push_host = @gemspec.metadata["allowed_push_host"]
gem_command += " --host #{allowed_push_host}" if allowed_push_host
end
gem_command += " --host #{allowed_push_host}" if allowed_push_host
unless allowed_push_host || Bundler.user_home.join(".gem/credentials").file?
raise "Your rubygems.org credentials aren't set. Run `gem push` to set them."
end
sh(gem_command)
Bundler.ui.confirm "Pushed #{name} #{version} to #{allowed_push_host ? allowed_push_host : "rubygems.org."}"
Bundler.ui.confirm "Pushed #{name} #{version} to #{gem_push_host}"
end
def built_gem_path
@ -116,6 +113,18 @@ module Bundler
Bundler.ui.confirm "Pushed git commits and tags."
end
def allowed_push_host
@gemspec.metadata["allowed_push_host"] if @gemspec.respond_to?(:metadata)
end
def gem_push_host
env_rubygems_host = ENV["RUBYGEMS_HOST"]
env_rubygems_host = nil if
env_rubygems_host && env_rubygems_host.empty?
allowed_push_host || env_rubygems_host || "rubygems.org"
end
def perform_git_push(options = "")
cmd = "git push #{options}"
out, code = sh_with_code(cmd)
@ -187,7 +196,7 @@ module Bundler
end
def gem_push?
!%w(n no nil false off 0).include?(ENV["gem_push"].to_s.downcase)
!%w[n no nil false off 0].include?(ENV["gem_push"].to_s.downcase)
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
module GemHelpers
GENERIC_CACHE = {} # rubocop:disable MutableConstant

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "rubygems/remote_fetcher"
module Bundler

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "rake/clean"
CLOBBER.include "pkg"

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
# This class contains all of the logic for determining the next version of a
# Gem to update to based on the requested level (patch, minor, major).

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class Gemdeps
def initialize(runtime)

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "set"
module Bundler
class Graph

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "set"
module Bundler
@ -111,6 +112,13 @@ module Bundler
spec_sets.values.each(&blk)
end
sources.each {|s| s.each(&blk) }
self
end
def spec_names
names = specs.keys + sources.map(&:spec_names)
names.uniq!
names
end
# returns a list of the dependencies
@ -191,14 +199,6 @@ module Bundler
end
end
wants_prerelease = dependency.requirement.prerelease?
wants_prerelease ||= base && base.any? {|base_spec| base_spec.version.prerelease? }
only_prerelease = specs.all? {|spec| spec.version.prerelease? }
unless wants_prerelease || only_prerelease
found.reject! {|spec| spec.version.prerelease? }
end
found
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class Injector
def self.inject(new_deps, options = {})
@ -12,38 +13,40 @@ module Bundler
end
def inject(gemfile_path, lockfile_path)
if Bundler.settings[:frozen]
if Bundler.frozen?
# ensure the lock and Gemfile are synced
Bundler.definition.ensure_equivalent_gemfile_and_lockfile(true)
# temporarily remove frozen while we inject
frozen = Bundler.settings.delete(:frozen)
end
# evaluate the Gemfile we have now
builder = Dsl.new
builder.eval_gemfile(gemfile_path)
# temporarily unfreeze
Bundler.settings.temporary(:deployment => false, :frozen => false) do
# evaluate the Gemfile we have now
builder = Dsl.new
builder.eval_gemfile(gemfile_path)
# don't inject any gems that are already in the Gemfile
@new_deps -= builder.dependencies
# don't inject any gems that are already in the Gemfile
@new_deps -= builder.dependencies
# add new deps to the end of the in-memory Gemfile
# Set conservative versioining to false because we want to let the resolver resolve the version first
builder.eval_gemfile("injected gems", build_gem_lines(false)) if @new_deps.any?
# add new deps to the end of the in-memory Gemfile
# Set conservative versioning to false because we want to let the resolver resolve the version first
builder.eval_gemfile("injected gems", build_gem_lines(false)) if @new_deps.any?
# resolve to see if the new deps broke anything
@definition = builder.to_definition(lockfile_path, {})
@definition.resolve_remotely!
# resolve to see if the new deps broke anything
@definition = builder.to_definition(lockfile_path, {})
@definition.resolve_remotely!
# since nothing broke, we can add those gems to the gemfile
append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @new_deps.any?
# since nothing broke, we can add those gems to the gemfile
append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @new_deps.any?
# since we resolved successfully, write out the lockfile
@definition.lock(Bundler.default_lockfile)
# since we resolved successfully, write out the lockfile
@definition.lock(Bundler.default_lockfile)
# return an array of the deps that we added
return @new_deps
ensure
Bundler.settings[:frozen] = "1" if frozen
# invalidate the cached Bundler.definition
Bundler.reset_paths!
# return an array of the deps that we added
@new_deps
end
end
private

View file

@ -1,4 +1,7 @@
# frozen_string_literal: true
require "bundler/compatibility_guard"
# Allows for declaring a Gemfile inline in a ruby script, optionally installing
# any gems that aren't already installed on the user's system.
#
@ -39,7 +42,7 @@ def gemfile(install = false, options = {}, &gemfile)
def Bundler.root
Bundler::SharedHelpers.pwd.expand_path
end
ENV["BUNDLE_GEMFILE"] = "Gemfile"
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", "Gemfile"
Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
builder = Bundler::Dsl.new
@ -50,12 +53,7 @@ def gemfile(install = false, options = {}, &gemfile)
definition.validate_runtime!
missing_specs = proc do
begin
!definition.missing_specs.empty?
rescue Bundler::GemNotFound, Bundler::GitError
definition.instance_variable_set(:@index, nil)
true
end
definition.missing_specs?
end
Bundler.ui = ui if install

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "erb"
require "rubygems/dependency_installer"
require "bundler/worker"
@ -33,25 +34,26 @@ module Bundler
# Runs the install procedures for a specific Gemfile.
#
# Firstly, this method will check to see if Bundler.bundle_path exists
# and if not then will create it. This is usually the location of gems
# on the system, be it RVM or at a system path.
# Firstly, this method will check to see if `Bundler.bundle_path` exists
# and if not then Bundler will create the directory. This is usually the same
# location as RubyGems which typically is the `~/.gem` directory
# unless other specified.
#
# Secondly, it checks if Bundler has been configured to be "frozen"
# Secondly, it checks if Bundler has been configured to be "frozen".
# Frozen ensures that the Gemfile and the Gemfile.lock file are matching.
# This stops a situation where a developer may update the Gemfile but may not run
# `bundle install`, which leads to the Gemfile.lock file not being correctly updated.
# If this file is not correctly updated then any other developer running
# `bundle install` will potentially not install the correct gems.
#
# Thirdly, Bundler checks if there are any dependencies specified in the Gemfile using
# Bundler::Environment#dependencies. If there are no dependencies specified then
# Bundler returns a warning message stating so and this method returns.
# Thirdly, Bundler checks if there are any dependencies specified in the Gemfile.
# If there are no dependencies specified then Bundler returns a warning message stating
# so and this method returns.
#
# Fourthly, Bundler checks if the default lockfile (Gemfile.lock) exists, and if so
# then proceeds to set up a definition based on the default gemfile (Gemfile) and the
# default lock file (Gemfile.lock). However, this is not the case if the platform is different
# to that which is specified in Gemfile.lock, or if there are any missing specs for the gems.
# Fourthly, Bundler checks if the Gemfile.lock exists, and if so
# then proceeds to set up a definition based on the Gemfile and the Gemfile.lock.
# During this step Bundler will also download information about any new gems
# that are not in the Gemfile.lock and resolve any dependencies if needed.
#
# Fifthly, Bundler resolves the dependencies either through a cache of gems or by remote.
# This then leads into the gems being installed, along with stubs for their executables,
@ -61,26 +63,36 @@ module Bundler
# Sixthly, a new Gemfile.lock is created from the installed gems to ensure that the next time
# that a user runs `bundle install` they will receive any updates from this process.
#
# Finally: TODO add documentation for how the standalone process works.
# Finally, if the user has specified the standalone flag, Bundler will generate the needed
# require paths and save them in a `setup.rb` file. See `bundle standalone --help` for more
# information.
def run(options)
create_bundle_path
if Bundler.settings[:frozen]
@definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
ProcessLock.lock do
if Bundler.frozen?
@definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
end
if @definition.dependencies.empty?
Bundler.ui.warn "The Gemfile specifies no dependencies"
lock
return
end
if resolve_if_needed(options)
ensure_specs_are_compatible!
warn_on_incompatible_bundler_deps
load_plugins
options.delete(:jobs)
else
options[:jobs] = 1 # to avoid the overhead of Bundler::Worker
end
install(options)
lock unless Bundler.frozen?
Standalone.new(options[:standalone], @definition).generate if options[:standalone]
end
if @definition.dependencies.empty?
Bundler.ui.warn "The Gemfile specifies no dependencies"
lock
return
end
resolve_if_need(options)
ensure_specs_are_compatible!
install(options)
lock unless Bundler.settings[:frozen]
Standalone.new(options[:standalone], @definition).generate if options[:standalone]
end
def generate_bundler_executable_stubs(spec, options = {})
@ -101,15 +113,21 @@ module Bundler
end
# double-assignment to avoid warnings about variables that will be used by ERB
bin_path = bin_path = Bundler.bin_path
template = template = File.read(File.expand_path("../templates/Executable", __FILE__))
relative_gemfile_path = relative_gemfile_path = Bundler.default_gemfile.relative_path_from(bin_path)
ruby_command = ruby_command = Thor::Util.ruby_command
bin_path = Bundler.bin_path
bin_path = bin_path
relative_gemfile_path = Bundler.default_gemfile.relative_path_from(bin_path)
relative_gemfile_path = relative_gemfile_path
ruby_command = Thor::Util.ruby_command
ruby_command = ruby_command
template_path = File.expand_path("../templates/Executable", __FILE__)
if spec.name == "bundler"
template_path += ".bundler"
spec.executables = %(bundle)
end
template = File.read(template_path)
exists = []
spec.executables.each do |executable|
next if executable == "bundle"
binstub_path = "#{bin_path}/#{executable}"
if File.exist?(binstub_path) && !options[:force]
exists << executable
@ -139,13 +157,19 @@ module Bundler
def generate_standalone_bundler_executable_stubs(spec)
# double-assignment to avoid warnings about variables that will be used by ERB
bin_path = Bundler.bin_path
standalone_path = standalone_path = Bundler.root.join(Bundler.settings[:path]).relative_path_from(bin_path)
unless path = Bundler.settings[:path]
raise "Can't standalone without an explicit path set"
end
standalone_path = Bundler.root.join(path).relative_path_from(bin_path)
standalone_path = standalone_path
template = File.read(File.expand_path("../templates/Executable.standalone", __FILE__))
ruby_command = ruby_command = Thor::Util.ruby_command
ruby_command = Thor::Util.ruby_command
ruby_command = ruby_command
spec.executables.each do |executable|
next if executable == "bundle"
executable_path = executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
executable_path = executable_path
File.open "#{bin_path}/#{executable}", "w", 0o755 do |f|
f.puts ERB.new(template, nil, "-").result(binding)
end
@ -159,13 +183,32 @@ module Bundler
# that said, it's a rare situation (other than rake), and parallel
# installation is SO MUCH FASTER. so we let people opt in.
def install(options)
Bundler.rubygems.load_plugins
force = options["force"]
jobs = 1
jobs = [Bundler.settings[:jobs].to_i - 1, 1].max if can_install_in_parallel?
jobs = options.delete(:jobs) do
if can_install_in_parallel?
[Bundler.settings[:jobs].to_i - 1, 1].max
else
1
end
end
install_in_parallel jobs, options[:standalone], force
end
def load_plugins
Bundler.rubygems.load_plugins
requested_path_gems = @definition.requested_specs.select {|s| s.source.is_a?(Source::Path) }
path_plugin_files = requested_path_gems.map do |spec|
begin
Bundler.rubygems.spec_matches_for_glob(spec, "rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
rescue TypeError
error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
raise Gem::InvalidSpecificationException, error_message
end
end.flatten
Bundler.rubygems.load_plugin_files(path_plugin_files)
end
def ensure_specs_are_compatible!
system_ruby = Bundler::RubyVersion.system
rubygems_version = Gem::Version.create(Gem::VERSION)
@ -184,12 +227,28 @@ module Bundler
end
end
def warn_on_incompatible_bundler_deps
bundler_version = Gem::Version.create(Bundler::VERSION)
@definition.specs.each do |spec|
spec.dependencies.each do |dep|
next if dep.type == :development
next unless dep.name == "bundler".freeze
next if dep.requirement.satisfied_by?(bundler_version)
Bundler.ui.warn "#{spec.name} (#{spec.version}) has dependency" \
" #{SharedHelpers.pretty_dependency(dep)}" \
", which is unsatisfied by the current bundler version #{VERSION}" \
", so the dependency is being ignored"
end
end
end
def can_install_in_parallel?
if Bundler.rubygems.provides?(">= 2.1.0")
true
else
Bundler.ui.warn "Rubygems #{Gem::VERSION} is not threadsafe, so your "\
"gems will be installed one at a time. Upgrade to Rubygems 2.1.0 " \
Bundler.ui.warn "RubyGems #{Gem::VERSION} is not threadsafe, so your "\
"gems will be installed one at a time. Upgrade to RubyGems 2.1.0 " \
"or higher to enable parallel gem installation."
false
end
@ -207,23 +266,18 @@ module Bundler
Bundler.mkdir_p(p)
end unless Bundler.bundle_path.exist?
rescue Errno::EEXIST
raise PathError, "Could not install to path `#{Bundler.settings[:path]}` " \
raise PathError, "Could not install to path `#{Bundler.bundle_path}` " \
"because a file already exists at that path. Either remove or rename the file so the directory can be created."
end
def resolve_if_need(options)
if !options["update"] && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
local = Bundler.ui.silence do
begin
tmpdef = Definition.build(Bundler.default_gemfile, Bundler.default_lockfile, nil)
true unless tmpdef.new_platform? || tmpdef.missing_dependencies.any?
rescue BundlerError
end
end
# returns whether or not a re-resolve was needed
def resolve_if_needed(options)
if !@definition.unlocking? && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
return false if @definition.nothing_changed? && !@definition.missing_specs?
end
return if local
options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely!
true
end
def lock(opts = {})

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class GemInstaller
attr_reader :spec, :standalone, :worker, :force, :installer
@ -65,6 +66,7 @@ module Bundler
end
def generate_executable_stubs
return if Bundler.feature_flag.forget_cli_options?
return if Bundler.settings[:inline]
if Bundler.settings[:bin] && standalone
installer.generate_standalone_bundler_executable_stubs(spec)

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/worker"
require "bundler/installer/gem_installer"
@ -77,11 +78,6 @@ module Bundler
new(*args).call
end
# Returns max number of threads machine can handle with a min of 1
def self.max_threads
[Bundler.settings[:jobs].to_i - 1, 1].max
end
attr_reader :size
def initialize(installer, all_specs, size, standalone, force)
@ -99,49 +95,19 @@ module Bundler
require "bundler/gem_remote_fetcher" if RUBY_VERSION < "1.9"
check_for_corrupt_lockfile
enqueue_specs
process_specs until @specs.all?(&:installed?) || @specs.any?(&:failed?)
if @size > 1
install_with_worker
else
install_serially
end
handle_error if @specs.any?(&:failed?)
@specs
ensure
worker_pool && worker_pool.stop
end
def worker_pool
@worker_pool ||= Bundler::Worker.new @size, "Parallel Installer", lambda { |spec_install, worker_num|
gem_installer = Bundler::GemInstaller.new(
spec_install.spec, @installer, @standalone, worker_num, @force
)
success, message = gem_installer.install_from_spec
if success && !message.nil?
spec_install.post_install_message = message
elsif !success
spec_install.state = :failed
spec_install.error = "#{message}\n\n#{require_tree_for_spec(spec_install.spec)}"
end
spec_install
}
end
# Dequeue a spec and save its post-install message and then enqueue the
# remaining specs.
# Some specs might've had to wait til this spec was installed to be
# processed so the call to `enqueue_specs` is important after every
# dequeue.
def process_specs
spec = worker_pool.deq
spec.state = :installed unless spec.failed?
enqueue_specs
end
def handle_error
errors = @specs.select(&:failed?).map(&:error)
if exception = errors.find {|e| e.is_a?(Bundler::BundlerError) }
raise exception
end
raise Bundler::InstallError, errors.map(&:to_s).join("\n\n")
end
def check_for_corrupt_lockfile
missing_dependencies = @specs.map do |s|
[
@ -167,6 +133,71 @@ module Bundler
Bundler.ui.warn(warning.join("\n"))
end
private
def install_with_worker
enqueue_specs
process_specs until finished_installing?
end
def install_serially
until finished_installing?
raise "failed to find a spec to enqueue while installing serially" unless spec_install = @specs.find(&:ready_to_enqueue?)
spec_install.state = :enqueued
do_install(spec_install, 0)
end
end
def worker_pool
@worker_pool ||= Bundler::Worker.new @size, "Parallel Installer", lambda { |spec_install, worker_num|
do_install(spec_install, worker_num)
}
end
def do_install(spec_install, worker_num)
gem_installer = Bundler::GemInstaller.new(
spec_install.spec, @installer, @standalone, worker_num, @force
)
success, message = begin
gem_installer.install_from_spec
rescue => e
raise e, "#{e}\n\n#{require_tree_for_spec(spec_install.spec)}"
end
if success
spec_install.state = :installed
spec_install.post_install_message = message unless message.nil?
else
spec_install.state = :failed
spec_install.error = "#{message}\n\n#{require_tree_for_spec(spec_install.spec)}"
end
spec_install
end
# Dequeue a spec and save its post-install message and then enqueue the
# remaining specs.
# Some specs might've had to wait til this spec was installed to be
# processed so the call to `enqueue_specs` is important after every
# dequeue.
def process_specs
worker_pool.deq
enqueue_specs
end
def finished_installing?
@specs.all? do |spec|
return true if spec.failed?
spec.installed?
end
end
def handle_error
errors = @specs.select(&:failed?).map(&:error)
if exception = errors.find {|e| e.is_a?(Bundler::BundlerError) }
raise exception
end
raise Bundler::InstallError, errors.map(&:to_s).join("\n\n")
end
def require_tree_for_spec(spec)
tree = @spec_set.what_required(spec)
t = String.new("In #{File.basename(SharedHelpers.default_gemfile)}:\n")

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class Standalone
def initialize(groups, definition)

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "uri"
require "bundler/match_platform"
@ -68,7 +69,7 @@ module Bundler
end
def __materialize__
search_object = Bundler.settings[:specific_platform] || Bundler.settings[:force_ruby_platform] ? self : Dependency.new(name, version)
search_object = Bundler.feature_flag.specific_platform? || Bundler.settings[:force_ruby_platform] ? self : Dependency.new(name, version)
@specification = if source.is_a?(Source::Gemspec) && source.gemspec.name == name
source.gemspec.tap {|s| s.source = source }
else

View file

@ -0,0 +1,95 @@
# frozen_string_literal: true
module Bundler
class LockfileGenerator
attr_reader :definition
attr_reader :out
# @private
def initialize(definition)
@definition = definition
@out = String.new
end
def self.generate(definition)
new(definition).generate!
end
def generate!
add_sources
add_platforms
add_dependencies
add_locked_ruby_version
add_bundled_with
out
end
private
def add_sources
definition.send(:sources).lock_sources.each_with_index do |source, idx|
out << "\n" unless idx.zero?
# Add the source header
out << source.to_lock
# Find all specs for this source
specs = definition.resolve.select {|s| source.can_lock?(s) }
add_specs(specs)
end
end
def add_specs(specs)
# This needs to be sorted by full name so that
# gems with the same name, but different platform
# are ordered consistently
specs.sort_by(&:full_name).each do |spec|
next if spec.name == "bundler".freeze
out << spec.to_lock
end
end
def add_platforms
add_section("PLATFORMS", definition.platforms)
end
def add_dependencies
out << "\nDEPENDENCIES\n"
handled = []
definition.dependencies.sort_by(&:to_s).each do |dep|
next if handled.include?(dep.name)
out << dep.to_lock
handled << dep.name
end
end
def add_locked_ruby_version
return unless locked_ruby_version = definition.locked_ruby_version
add_section("RUBY VERSION", locked_ruby_version.to_s)
end
def add_bundled_with
add_section("BUNDLED WITH", definition.locked_bundler_version.to_s)
end
def add_section(name, value)
out << "\n#{name}\n"
case value
when Array
value.map(&:to_s).sort.each do |val|
out << " #{val}\n"
end
when Hash
value.to_a.sort_by {|k, _| k.to_s }.each do |key, val|
out << " #{key}: #{val}\n"
end
when String
out << " #{value}\n"
else
raise ArgumentError, "#{value.inspect} can't be serialized in a lockfile"
end
end
end
end

View file

@ -90,7 +90,7 @@ module Bundler
send("parse_#{@state}", line)
end
end
@sources << @rubygems_aggregate
@sources << @rubygems_aggregate unless Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
@specs = @specs.values.sort_by(&:identifier)
warn_for_outdated_bundler_version
rescue ArgumentError => e
@ -141,10 +141,16 @@ module Bundler
@sources << @current_source
end
when GEM
Array(@opts["remote"]).each do |url|
@rubygems_aggregate.add_remote(url)
if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
@opts["remotes"] = @opts.delete("remote")
@current_source = TYPES[@type].from_lock(@opts)
@sources << @current_source
else
Array(@opts["remote"]).each do |url|
@rubygems_aggregate.add_remote(url)
end
@current_source = @rubygems_aggregate
end
@current_source = @rubygems_aggregate
when PLUGIN
@current_source = Plugin.source_from_lock(@opts)
@sources << @current_source

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/gem_helpers"
module Bundler

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "socket"
module Bundler
@ -37,7 +38,7 @@ module Bundler
mirror = if config.all?
@all
else
(@mirrors[config.uri] = @mirrors[config.uri] || Mirror.new)
@mirrors[config.uri] ||= Mirror.new
end
config.update_mirror(mirror)
end
@ -45,7 +46,9 @@ module Bundler
private
def fetch_valid_mirror_for(uri)
mirror = (@mirrors[URI(uri.to_s.downcase)] || @mirrors[URI(uri.to_s).host] || Mirror.new(uri)).validate!(@prober)
downcased = uri.to_s.downcase
mirror = @mirrors[downcased] || @mirrors[URI(downcased).host] || Mirror.new(uri)
mirror.validate!(@prober)
mirror = Mirror.new(uri) unless mirror.valid?
mirror
end
@ -117,7 +120,7 @@ module Bundler
def initialize(config_line, value)
uri, fallback =
config_line.match(%r{^mirror\.(all|.+?)(\.fallback_timeout)?\/?$}).captures
config_line.match(%r{\Amirror\.(all|.+?)(\.fallback_timeout)?\/?\z}).captures
@fallback = !fallback.nil?
@all = false
if uri == "all"

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/plugin/api"
module Bundler

View file

@ -1,6 +1,6 @@
# frozen_string_literal: true
require "uri"
require "digest/sha1"
module Bundler
module Plugin
@ -271,7 +271,7 @@ module Bundler
end
def uri_hash
Digest::SHA1.hexdigest(uri)
SharedHelpers.digest(:SHA1).hexdigest(uri)
end
# Note: Do not override if you don't know what you are doing.
@ -293,6 +293,13 @@ module Bundler
def bundler_plugin_api_source?
true
end
# @private
# This API on source might not be stable, and for now we expect plugins
# to download all specs in `#specs`, so we implement the method for
# compatibility purposes and leave it undocumented (and don't support)
# overriding it)
def double_check_for(*); end
end
end
end

View file

@ -13,12 +13,13 @@ module Bundler
def install(names, options)
version = options[:version] || [">= 0"]
if options[:git]
install_git(names, version, options)
else
sources = options[:source] || Bundler.rubygems.sources
install_rubygems(names, version, sources)
Bundler.settings.temporary(:lockfile_uses_separate_rubygems_sources => false, :disable_multisource => false) do
if options[:git]
install_git(names, version, options)
else
sources = options[:source] || Bundler.rubygems.sources
install_rubygems(names, version, sources)
end
end
end

View file

@ -5,13 +5,6 @@ module Bundler
# approptiate options to be used with Source classes for plugin installation
module Plugin
class SourceList < Bundler::SourceList
def initialize
@path_sources = []
@git_sources = []
@rubygems_aggregate = Plugin::Installer::Rubygems.new
@rubygems_sources = []
end
def add_git_source(options = {})
add_source_to_list Plugin::Installer::Git.new(options), git_sources
end
@ -21,7 +14,13 @@ module Bundler
end
def all_sources
path_sources + git_sources + rubygems_sources
path_sources + git_sources + rubygems_sources + [metadata_source]
end
private
def rubygems_aggregate_class
Plugin::Installer::Rubygems
end
end
end

View file

@ -0,0 +1,24 @@
# frozen_string_literal: true
module Bundler
class ProcessLock
def self.lock(bundle_path = Bundler.bundle_path)
lock_file_path = File.join(bundle_path, "bundler.lock")
has_lock = false
File.open(lock_file_path, "w") do |f|
f.flock(File::LOCK_EX)
has_lock = true
yield
f.flock(File::LOCK_UN)
end
rescue Errno::EACCES, Errno::ENOLCK
# In the case the user does not have access to
# create the lock file or is using NFS where
# locks are not available we skip locking.
yield
ensure
FileUtils.rm_f(lock_file_path) if has_lock
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
# Psych could be a gem, so try to ask for it
begin
gem "psych"
@ -25,3 +26,12 @@ module Bundler
YamlLibrarySyntaxError = ::ArgumentError
end
end
require "bundler/deprecate"
begin
Bundler::Deprecate.skip_during do
require "rubygems/safe_yaml"
end
rescue LoadError
# it's OK if the file isn't there
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "uri"
module Bundler

View file

@ -1,178 +1,9 @@
# frozen_string_literal: true
module Bundler
class Resolver
require "bundler/vendored_molinillo"
class Molinillo::VersionConflict
def printable_dep(dep)
if dep.is_a?(Bundler::Dependency)
DepProxy.new(dep, dep.platforms.join(", ")).to_s.strip
else
dep.to_s
end
end
def message
conflicts.sort.reduce(String.new) do |o, (name, conflict)|
o << %(\nBundler could not find compatible versions for gem "#{name}":\n)
if conflict.locked_requirement
o << %( In snapshot (#{Bundler.default_lockfile.basename}):\n)
o << %( #{printable_dep(conflict.locked_requirement)}\n)
o << %(\n)
end
o << %( In Gemfile:\n)
trees = conflict.requirement_trees
maximal = 1.upto(trees.size).map do |size|
trees.map(&:last).flatten(1).combination(size).to_a
end.flatten(1).select do |deps|
Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
end.min_by(&:size)
trees.reject! {|t| !maximal.include?(t.last) } if maximal
o << trees.sort_by {|t| t.reverse.map(&:name) }.map do |tree|
t = String.new
depth = 2
tree.each do |req|
t << " " * depth << req.to_s
unless tree.last == req
if spec = conflict.activated_by_name[req.name]
t << %( was resolved to #{spec.version}, which)
end
t << %( depends on)
end
t << %(\n)
depth += 1
end
t
end.join("\n")
if name == "bundler"
o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new Bundler::VERSION)
end
if name == "bundler" && other_bundler_required
o << "\n"
o << "This Gemfile requires a different version of Bundler.\n"
o << "Perhaps you need to update Bundler by running `gem install bundler`?\n"
end
if conflict.locked_requirement
o << "\n"
o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
o << %(the gems in your Gemfile, which may resolve the conflict.\n)
elsif !conflict.existing
o << "\n"
if conflict.requirement_trees.first.size > 1
o << "Could not find gem '#{conflict.requirement}', which is required by "
o << "gem '#{conflict.requirement_trees.first[-2]}', in any of the sources."
else
o << "Could not find gem '#{conflict.requirement}' in any of the sources\n"
end
end
o
end.strip
end
end
class SpecGroup < Array
include GemHelpers
attr_reader :activated
def initialize(a)
super
@required_by = []
@activated_platforms = []
@dependencies = nil
@specs = Hash.new do |specs, platform|
specs[platform] = select_best_platform_match(self, platform)
end
end
def initialize_copy(o)
super
@activated_platforms = o.activated.dup
end
def to_specs
@activated_platforms.map do |p|
next unless s = @specs[p]
lazy_spec = LazySpecification.new(name, version, s.platform, source)
lazy_spec.dependencies.replace s.dependencies
lazy_spec
end.compact
end
def activate_platform!(platform)
return unless for?(platform)
return if @activated_platforms.include?(platform)
@activated_platforms << platform
end
def name
@name ||= first.name
end
def version
@version ||= first.version
end
def source
@source ||= first.source
end
def for?(platform)
spec = @specs[platform]
!spec.nil?
end
def to_s
"#{name} (#{version})"
end
def dependencies_for_activated_platforms
dependencies = @activated_platforms.map {|p| __dependencies[p] }
metadata_dependencies = @activated_platforms.map do |platform|
metadata_dependencies(@specs[platform], platform)
end
dependencies.concat(metadata_dependencies).flatten
end
def platforms_for_dependency_named(dependency)
__dependencies.select {|_, deps| deps.map(&:name).include? dependency }.keys
end
private
def __dependencies
@dependencies = Hash.new do |dependencies, platform|
dependencies[platform] = []
if spec = @specs[platform]
spec.dependencies.each do |dep|
next if dep.type == :development
dependencies[platform] << DepProxy.new(dep, platform)
end
end
dependencies[platform]
end
end
def metadata_dependencies(spec, platform)
return [] unless spec
# Only allow endpoint specifications since they won't hit the network to
# fetch the full gemspec when calling required_ruby_version
return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
dependencies = []
if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
dependencies << DepProxy.new(Gem::Dependency.new("ruby\0", spec.required_ruby_version), platform)
end
if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
dependencies << DepProxy.new(Gem::Dependency.new("rubygems\0", spec.required_rubygems_version), platform)
end
dependencies
end
end
require "bundler/resolver/spec_group"
# Figures out the best possible configuration of gems that satisfies
# the list of passed dependencies and any child dependencies without
@ -206,16 +37,22 @@ module Bundler
additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
@platforms = platforms
@gem_version_promoter = gem_version_promoter
@allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts?
@lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
end
def start(requirements)
@prerelease_specified = {}
requirements.each {|dep| @prerelease_specified[dep.name] ||= dep.prerelease? }
verify_gemfile_dependencies_are_found!(requirements)
dg = @resolver.resolve(requirements, @base_dg)
dg.map(&:payload).
reject {|sg| sg.name.end_with?("\0") }.
map(&:to_specs).flatten
rescue Molinillo::VersionConflict => e
raise VersionConflict.new(e.conflicts.keys.uniq, e.message)
message = version_conflict_message(e)
raise VersionConflict.new(e.conflicts.keys.uniq, message)
rescue Molinillo::CircularDependencyError => e
names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
raise CyclicDependencyError, "Your bundle requires gems that depend" \
@ -266,6 +103,14 @@ module Bundler
search = @search_for[dependency] ||= begin
index = index_for(dependency)
results = index.search(dependency, @base[dependency.name])
unless @prerelease_specified[dependency.name]
# Move prereleases to the beginning of the list, so they're considered
# last during resolution.
pre, results = results.partition {|spec| spec.version.prerelease? }
results = pre + results
end
if vertex = @base_dg.vertex_named(dependency.name)
locked_requirement = vertex.payload.requirement
end
@ -281,7 +126,9 @@ module Bundler
end
nested.reduce([]) do |groups, (version, specs)|
next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
groups << SpecGroup.new(specs)
spec_group = SpecGroup.new(specs)
spec_group.ignores_bundler_dependencies = @allow_bundler_dependency_conflicts
groups << spec_group
end
else
[]
@ -298,7 +145,20 @@ module Bundler
end
def index_for(dependency)
@source_requirements[dependency.name] || @index
source = @source_requirements[dependency.name]
if source
source.specs
elsif @lockfile_uses_separate_rubygems_sources
Index.build do |idx|
if dependency.all_sources
dependency.all_sources.each {|s| idx.add_source(s.specs) if s }
else
idx.add_source @source_requirements[:default].specs
end
end
else
@index
end
end
def name_for(dependency)
@ -319,23 +179,53 @@ module Bundler
def requirement_satisfied_by?(requirement, activated, spec)
return false unless requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
if spec.version.prerelease? && !requirement.prerelease? && search_for(requirement).any? {|sg| !sg.version.prerelease? }
vertex = activated.vertex_named(spec.name)
return false if vertex.requirements.none?(&:prerelease?)
end
spec.activate_platform!(requirement.__platform) if !@platforms || @platforms.include?(requirement.__platform)
true
end
def relevant_sources_for_vertex(vertex)
if vertex.root?
[@source_requirements[vertex.name]]
elsif @lockfile_uses_separate_rubygems_sources
vertex.recursive_predecessors.map do |v|
@source_requirements[v.name]
end << @source_requirements[:default]
end
end
def sort_dependencies(dependencies, activated, conflicts)
dependencies.sort_by do |dependency|
dependency.all_sources = relevant_sources_for_vertex(activated.vertex_named(dependency.name))
name = name_for(dependency)
vertex = activated.vertex_named(name)
[
@base_dg.vertex_named(name) ? 0 : 1,
activated.vertex_named(name).payload ? 0 : 1,
vertex.payload ? 0 : 1,
vertex.root? ? 0 : 1,
amount_constrained(dependency),
conflicts[name] ? 0 : 1,
activated.vertex_named(name).payload ? 0 : search_for(dependency).count,
vertex.payload ? 0 : search_for(dependency).count,
self.class.platform_sort_key(dependency.__platform),
]
end
end
# Sort platforms from most general to most specific
def self.sort_platforms(platforms)
platforms.sort_by do |platform|
platform_sort_key(platform)
end
end
def self.platform_sort_key(platform)
return ["", "", ""] if Gem::Platform::RUBY == platform
platform.to_a.map {|part| part || "" }
end
private
# returns an integer \in (-\infty, 0]
@ -364,32 +254,34 @@ module Bundler
def verify_gemfile_dependencies_are_found!(requirements)
requirements.each do |requirement|
next if requirement.name == "bundler"
name = requirement.name
next if name == "bundler"
next unless search_for(requirement).empty?
if (base = @base[requirement.name]) && !base.empty?
version = base.first.version
message = "You have requested:\n" \
" #{requirement.name} #{requirement.requirement}\n\n" \
"The bundle currently has #{requirement.name} locked at #{version}.\n" \
"Try running `bundle update #{requirement.name}`\n\n" \
"If you are updating multiple gems in your Gemfile at once,\n" \
"try passing them all to `bundle update`"
elsif requirement.source
name = requirement.name
specs = @source_requirements[name][name]
versions_with_platforms = specs.map {|s| [s.version, s.platform] }
message = String.new("Could not find gem '#{requirement}' in #{requirement.source}.\n")
message << if versions_with_platforms.any?
"Source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}"
else
"Source does not contain any versions of '#{requirement}'"
end
else
cache_message = begin
cache_message = begin
" or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
rescue GemfileNotFound
nil
end
if (base = @base[name]) && !base.empty?
version = base.first.version
message = "You have requested:\n" \
" #{name} #{requirement.requirement}\n\n" \
"The bundle currently has #{name} locked at #{version}.\n" \
"Try running `bundle update #{name}`\n\n" \
"If you are updating multiple gems in your Gemfile at once,\n" \
"try passing them all to `bundle update`"
elsif source = @source_requirements[name]
specs = source.specs[name]
versions_with_platforms = specs.map {|s| [s.version, s.platform] }
message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source}#{cache_message}.\n")
message << if versions_with_platforms.any?
"The source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}"
else
"The source does not contain any versions of '#{name}'"
end
else
message = "Could not find gem '#{requirement}' in any of the gem sources " \
"listed in your Gemfile#{cache_message}."
end
@ -402,9 +294,76 @@ module Bundler
version = vwp.first
platform = vwp.last
version_platform_str = String.new(version.to_s)
version_platform_str << " #{platform}" unless platform.nil?
version_platform_str << " #{platform}" unless platform.nil? || platform == Gem::Platform::RUBY
version_platform_str
end
version_platform_strs.join(", ")
end
def version_conflict_message(e)
e.message_with_trees(
:solver_name => "Bundler",
:possibility_type => "gem",
:reduce_trees => lambda do |trees|
maximal = 1.upto(trees.size).map do |size|
trees.map(&:last).flatten(1).combination(size).to_a
end.flatten(1).select do |deps|
Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
end.min_by(&:size)
trees.reject! {|t| !maximal.include?(t.last) } if maximal
trees = trees.sort_by {|t| t.flatten.map(&:to_s) }
trees.uniq! {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
trees.sort_by {|t| t.reverse.map(&:name) }
end,
:printable_requirement => lambda {|req| SharedHelpers.pretty_dependency(req) },
:additional_message_for_conflict => lambda do |o, name, conflict|
if name == "bundler"
o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new Bundler::VERSION)
end
if name == "bundler" && other_bundler_required
o << "\n"
o << "This Gemfile requires a different version of Bundler.\n"
o << "Perhaps you need to update Bundler by running `gem install bundler`?\n"
end
if conflict.locked_requirement
o << "\n"
o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
o << %(the gems in your Gemfile, which may resolve the conflict.\n)
elsif !conflict.existing
o << "\n"
relevant_sources = if conflict.requirement.source
[conflict.requirement.source]
elsif conflict.requirement.all_sources
conflict.requirement.all_sources
elsif @lockfile_uses_separate_rubygems_sources
# every conflict should have an explicit group of sources when we
# enforce strict pinning
raise "no source set for #{conflict}"
else
[]
end.compact.map(&:to_s).uniq.sort
o << "Could not find gem '#{SharedHelpers.pretty_dependency(conflict.requirement)}'"
if conflict.requirement_trees.first.size > 1
o << ", which is required by "
o << "gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}',"
end
o << " "
o << if relevant_sources.empty?
"in any of the sources.\n"
else
"in any of the relevant sources:\n #{relevant_sources * "\n "}\n"
end
end
end,
:version_for_spec => lambda {|spec| spec.version }
)
end
end
end

View file

@ -0,0 +1,111 @@
# frozen_string_literal: true
module Bundler
class Resolver
class SpecGroup
include GemHelpers
attr_accessor :name, :version, :source
attr_accessor :ignores_bundler_dependencies
def initialize(all_specs)
raise ArgumentError, "cannot initialize with an empty value" unless exemplary_spec = all_specs.first
@name = exemplary_spec.name
@version = exemplary_spec.version
@source = exemplary_spec.source
@required_by = []
@activated_platforms = []
@dependencies = nil
@specs = Hash.new do |specs, platform|
specs[platform] = select_best_platform_match(all_specs, platform)
end
@ignores_bundler_dependencies = true
end
def to_specs
@activated_platforms.map do |p|
next unless s = @specs[p]
lazy_spec = LazySpecification.new(name, version, s.platform, source)
lazy_spec.dependencies.replace s.dependencies
lazy_spec
end.compact
end
def activate_platform!(platform)
return unless for?(platform)
return if @activated_platforms.include?(platform)
@activated_platforms << platform
end
def for?(platform)
spec = @specs[platform]
!spec.nil?
end
def to_s
@to_s ||= "#{name} (#{version})"
end
def dependencies_for_activated_platforms
dependencies = @activated_platforms.map {|p| __dependencies[p] }
metadata_dependencies = @activated_platforms.map do |platform|
metadata_dependencies(@specs[platform], platform)
end
dependencies.concat(metadata_dependencies).flatten
end
def platforms_for_dependency_named(dependency)
__dependencies.select {|_, deps| deps.map(&:name).include? dependency }.keys
end
def ==(other)
return unless other.is_a?(SpecGroup)
name == other.name &&
version == other.version &&
source == other.source
end
def eql?(other)
name.eql?(other.name) &&
version.eql?(other.version) &&
source.eql?(other.source)
end
def hash
to_s.hash ^ source.hash
end
private
def __dependencies
@dependencies = Hash.new do |dependencies, platform|
dependencies[platform] = []
if spec = @specs[platform]
spec.dependencies.each do |dep|
next if dep.type == :development
next if @ignores_bundler_dependencies && dep.name == "bundler".freeze
dependencies[platform] << DepProxy.new(dep, platform)
end
end
dependencies[platform]
end
end
def metadata_dependencies(spec, platform)
return [] unless spec
# Only allow endpoint specifications since they won't hit the network to
# fetch the full gemspec when calling required_ruby_version
return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
dependencies = []
if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
dependencies << DepProxy.new(Gem::Dependency.new("ruby\0", spec.required_ruby_version), platform)
end
if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
dependencies << DepProxy.new(Gem::Dependency.new("rubygems\0", spec.required_rubygems_version), platform)
end
dependencies
end
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
# General purpose class for retrying code that may fail
class Retry

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
module RubyDsl
def ruby(*ruby_version)

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class RubyVersion
attr_reader :versions,

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "pathname"
if defined?(Gem::QuickLoader)
@ -14,7 +15,7 @@ begin
# shouldn't be deferred.
require "rubygems/source"
rescue LoadError
# Not available before Rubygems 2.0.0, ignore
# Not available before RubyGems 2.0.0, ignore
nil
end
@ -135,7 +136,7 @@ module Gem
end
class Dependency
attr_accessor :source, :groups
attr_accessor :source, :groups, :all_sources
alias_method :eql?, :==
@ -146,7 +147,7 @@ module Gem
end
def to_yaml_properties
instance_variables.reject {|p| ["@source", "@groups"].include?(p.to_s) }
instance_variables.reject {|p| ["@source", "@groups", "@all_sources"].include?(p.to_s) }
end
def to_lock
@ -158,7 +159,7 @@ module Gem
out
end
# Backport of performance enhancement added to Rubygems 1.4
# Backport of performance enhancement added to RubyGems 1.4
def matches_spec?(spec)
# name can be a Regexp, so use ===
return false unless name === spec.name

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "rubygems/installer"
module Bundler
@ -17,6 +18,28 @@ module Bundler
super && validate_bundler_checksum(options[:bundler_expected_checksum])
end
def build_extensions
extension_cache_path = options[:bundler_extension_cache_path]
return super unless extension_cache_path && extension_dir = Bundler.rubygems.spec_extension_dir(spec)
extension_dir = Pathname.new(extension_dir)
build_complete = SharedHelpers.filesystem_access(extension_cache_path.join("gem.build_complete"), :read, &:file?)
if build_complete && !options[:force]
SharedHelpers.filesystem_access(extension_dir.parent, &:mkpath)
SharedHelpers.filesystem_access(extension_cache_path) do
FileUtils.cp_r extension_cache_path, spec.extension_dir
end
else
super
if extension_dir.directory? # not made for gems without extensions
SharedHelpers.filesystem_access(extension_cache_path.parent, &:mkpath)
SharedHelpers.filesystem_access(extension_cache_path) do
FileUtils.cp_r extension_dir, extension_cache_path
end
end
end
end
private
def validate_bundler_checksum(checksum)
@ -25,7 +48,7 @@ module Bundler
return true unless source = @package.instance_variable_get(:@gem)
return true unless source.respond_to?(:with_read_io)
digest = source.with_read_io do |io|
digest = Digest::SHA256.new
digest = SharedHelpers.digest(:SHA256).new
digest << io.read(16_384) until io.eof?
io.rewind
send(checksum_type(checksum), digest)

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "monitor"
require "rubygems"
require "rubygems/config_file"
@ -84,6 +85,19 @@ module Bundler
spec.respond_to?(:default_gem?) && spec.default_gem?
end
def spec_matches_for_glob(spec, glob)
return spec.matches_for_glob(glob) if spec.respond_to?(:matches_for_glob)
spec.load_paths.map do |lp|
Dir["#{lp}/#{glob}#{suffix_pattern}"]
end.flatten(1)
end
def spec_extension_dir(spec)
return unless spec.respond_to?(:extension_dir)
spec.extension_dir
end
def stub_set_spec(stub, spec)
stub.instance_variable_set(:@spec, spec)
end
@ -158,6 +172,10 @@ module Bundler
Gem.post_reset_hooks
end
def suffix_pattern
Gem.suffix_pattern
end
def gem_cache
gem_path.map {|p| File.expand_path("cache", p) }
end
@ -165,7 +183,7 @@ module Bundler
def spec_cache_dirs
@spec_cache_dirs ||= begin
dirs = gem_path.map {|dir| File.join(dir, "specifications") }
dirs << Gem.spec_cache_dir if Gem.respond_to?(:spec_cache_dir) # Not in Rubygems 2.0.3 or earlier
dirs << Gem.spec_cache_dir if Gem.respond_to?(:spec_cache_dir) # Not in RubyGems 2.0.3 or earlier
dirs.uniq.select {|dir| File.directory? dir }
end
end
@ -179,7 +197,7 @@ module Bundler
end
def repository_subdirectories
%w(cache doc gems specifications)
%w[cache doc gems specifications]
end
def clear_paths
@ -190,8 +208,12 @@ module Bundler
Gem.bin_path(gem, bin, ver)
end
def path_separator
File::PATH_SEPARATOR
end
def preserve_paths
# this is a no-op outside of Rubygems 1.8
# this is a no-op outside of RubyGems 1.8
yield
end
@ -212,6 +234,10 @@ module Bundler
Gem.load_plugins if Gem.respond_to?(:load_plugins)
end
def load_plugin_files(files)
Gem.load_plugin_files(files) if Gem.respond_to?(:load_plugin_files)
end
def ui=(obj)
Gem::DefaultUserInteraction.ui = obj
end
@ -233,9 +259,9 @@ module Bundler
{} # if we can't download them, there aren't any
end
# TODO: This is for older versions of Rubygems... should we support the
# TODO: This is for older versions of RubyGems... should we support the
# X-Gemfile-Source header on these old versions?
# Maybe the newer implementation will work on older Rubygems?
# Maybe the newer implementation will work on older RubyGems?
# It seems difficult to keep this implementation and still send the header.
def fetch_all_remote_specs(remote)
old_sources = Bundler.rubygems.sources
@ -273,6 +299,7 @@ module Bundler
def spec_from_gem(path, policy = nil)
require "rubygems/security"
require "bundler/psyched_yaml"
gem_from_path(path, security_policies[policy]).spec
rescue Gem::Package::FormatError
raise GemspecError, "Could not read gem at #{path}. It may be corrupted."
@ -306,7 +333,7 @@ module Bundler
end
def security_policy_keys
%w(High Medium Low AlmostNo No).map {|level| "#{level}Security" }
%w[High Medium Low AlmostNo No].map {|level| "#{level}Security" }
end
def security_policies
@ -377,9 +404,8 @@ module Bundler
raise e
end
# TODO: delete this in 2.0, it's a backwards compatibility shim
# see https://github.com/bundler/bundler/issues/5102
kernel_class.send(:public, :gem)
# backwards compatibility shim, see https://github.com/bundler/bundler/issues/5102
kernel_class.send(:public, :gem) if Bundler.feature_flag.setup_makes_kernel_gem_public?
end
end
@ -434,9 +460,9 @@ module Bundler
raise Gem::Exception, "no default executable for #{spec.full_name}" unless exec_name ||= spec.default_executable
unless spec.name == name
Bundler::SharedHelpers.major_deprecation \
"Bundler is using a binstub that was created for a different gem.\n" \
unless spec.name == gem_name
Bundler::SharedHelpers.major_deprecation 2,
"Bundler is using a binstub that was created for a different gem (#{spec.name}).\n" \
"You should run `bundle binstub #{gem_name}` " \
"to work around a system/bundle conflict."
end
@ -476,7 +502,7 @@ module Bundler
redefine_method(gem_class, :refresh) {}
end
# Replace or hook into Rubygems to provide a bundlerized view
# Replace or hook into RubyGems to provide a bundlerized view
# of the world.
def replace_entrypoints(specs)
specs_by_name = specs.reduce({}) do |h, s|
@ -492,8 +518,8 @@ module Bundler
Gem.clear_paths
end
# This backports the correct segment generation code from Rubygems 1.4+
# by monkeypatching it into the method in Rubygems 1.3.6 and 1.3.7.
# This backports the correct segment generation code from RubyGems 1.4+
# by monkeypatching it into the method in RubyGems 1.3.6 and 1.3.7.
def backport_segment_generation
redefine_method(Gem::Version, :segments) do
@segments ||= @version.scan(/[0-9]+|[a-z]+/i).map do |s|
@ -512,7 +538,7 @@ module Bundler
end
# This backports base_dir which replaces installation path
# Rubygems 1.8+
# RubyGems 1.8+
def backport_base_dir
redefine_method(Gem::Specification, :base_dir) do
return Gem.dir unless loaded_from
@ -581,7 +607,7 @@ module Bundler
end
end
# Rubygems 1.4 through 1.6
# RubyGems 1.4 through 1.6
class Legacy < RubygemsIntegration
def initialize
super
@ -592,7 +618,7 @@ module Bundler
end
def stub_rubygems(specs)
# Rubygems versions lower than 1.7 use SourceIndex#from_gems_in
# RubyGems versions lower than 1.7 use SourceIndex#from_gems_in
source_index_class = (class << Gem::SourceIndex; self; end)
redefine_method(source_index_class, :from_gems_in) do |*args|
Gem::SourceIndex.new.tap do |source_index|
@ -624,7 +650,7 @@ module Bundler
end
end
# Rubygems versions 1.3.6 and 1.3.7
# RubyGems versions 1.3.6 and 1.3.7
class Ancient < Legacy
def initialize
super
@ -632,7 +658,7 @@ module Bundler
end
end
# Rubygems 1.7
# RubyGems 1.7
class Transitional < Legacy
def stub_rubygems(specs)
stub_source_index(specs)
@ -646,7 +672,7 @@ module Bundler
end
end
# Rubygems 1.8.5-1.8.19
# RubyGems 1.8.5-1.8.19
class Modern < RubygemsIntegration
def stub_rubygems(specs)
Gem::Specification.all = specs
@ -667,9 +693,9 @@ module Bundler
end
end
# Rubygems 1.8.0 to 1.8.4
# RubyGems 1.8.0 to 1.8.4
class AlmostModern < Modern
# Rubygems [>= 1.8.0, < 1.8.5] has a bug that changes Gem.dir whenever
# RubyGems [>= 1.8.0, < 1.8.5] has a bug that changes Gem.dir whenever
# you call Gem::Installer#install with an :install_dir set. We have to
# change it back for our sudo mode to work.
def preserve_paths
@ -680,9 +706,9 @@ module Bundler
end
end
# Rubygems 1.8.20+
# RubyGems 1.8.20+
class MoreModern < Modern
# Rubygems 1.8.20 and adds the skip_validation parameter, so that's
# RubyGems 1.8.20 and adds the skip_validation parameter, so that's
# when we start passing it through.
def build(spec, skip_validation = false)
require "rubygems/builder"
@ -690,7 +716,7 @@ module Bundler
end
end
# Rubygems 2.0
# RubyGems 2.0
class Future < RubygemsIntegration
def stub_rubygems(specs)
Gem::Specification.all = specs
@ -767,6 +793,10 @@ module Bundler
def install_with_build_args(args)
yield
end
def path_separator
Gem.path_separator
end
end
# RubyGems 2.1.0
@ -855,7 +885,7 @@ module Bundler
RubygemsIntegration::Transitional.new
elsif RubygemsIntegration.provides?(">= 1.4.0")
RubygemsIntegration::Legacy.new
else # Rubygems 1.3.6 and 1.3.7
else # RubyGems 1.3.6 and 1.3.7
RubygemsIntegration::Ancient.new
end
end

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require "digest/sha1"
module Bundler
class Runtime
@ -11,7 +10,7 @@ module Bundler
end
def setup(*groups)
@definition.ensure_equivalent_gemfile_and_lockfile if Bundler.settings[:frozen]
@definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen?
groups.map!(&:to_sym)
@ -262,9 +261,6 @@ module Bundler
end
def setup_manpath
# Store original MANPATH for restoration later in with_clean_env()
ENV["BUNDLER_ORIG_MANPATH"] = ENV["MANPATH"]
# Add man/ subdirectories from activated bundles to MANPATH for man(1)
manuals = $LOAD_PATH.map do |path|
man_subdir = path.sub(/lib$/, "man")
@ -272,7 +268,7 @@ module Bundler
end.compact
return if manuals.empty?
ENV["MANPATH"] = manuals.concat(
Bundler::SharedHelpers.set_env "MANPATH", manuals.concat(
ENV["MANPATH"].to_s.split(File::PATH_SEPARATOR)
).uniq.join(File::PATH_SEPARATOR)
end

View file

@ -1,60 +1,89 @@
# frozen_string_literal: true
require "uri"
module Bundler
class Settings
autoload :Mirror, "bundler/mirror"
autoload :Mirrors, "bundler/mirror"
autoload :Validator, "bundler/settings/validator"
BOOL_KEYS = %w(
BOOL_KEYS = %w[
allow_bundler_dependency_conflicts
allow_deployment_source_credential_changes
allow_offline_install
auto_clean_without_path
auto_install
cache_all
cache_all_platforms
cache_command_is_package
console_command
default_install_uses_path
deployment
deployment_means_frozen
disable_checksum_validation
disable_exec_load
disable_local_branch_check
disable_multisource
disable_shared_gems
disable_version_check
error_on_stderr
force_ruby_platform
forget_cli_options
frozen
gem.coc
gem.mit
global_gem_cache
ignore_messages
init_gems_rb
list_command
lockfile_uses_separate_rubygems_sources
major_deprecations
no_install
no_prune
only_update_to_newer_versions
path.system
plugins
prefer_gems_rb
print_only_version_number
setup_makes_kernel_gem_public
silence_root_warning
).freeze
skip_default_git_sources
specific_platform
suppress_install_using_messages
unlock_source_unlocks_spec
update_requires_all_flag
].freeze
NUMBER_KEYS = %w(
NUMBER_KEYS = %w[
redirect
retry
ssl_verify_mode
timeout
).freeze
].freeze
ARRAY_KEYS = %w[
with
without
].freeze
DEFAULT_CONFIG = {
:disable_version_check => true,
:redirect => 5,
:retry => 3,
:timeout => 10,
}.freeze
attr_accessor :cli_flags_given
def initialize(root = nil)
@root = root
@local_config = load_config(local_config_file)
@global_config = load_config(global_config_file)
@cli_flags_given = false
@temporary = {}
end
def [](name)
key = key_for(name)
value = @temporary.fetch(name) do
value = @temporary.fetch(key) do
@local_config.fetch(key) do
ENV.fetch(key) do
@global_config.fetch(key) do
@ -65,48 +94,59 @@ module Bundler
converted_value(value, name)
end
def []=(key, value)
if cli_flags_given
def set_command_option(key, value)
if Bundler.feature_flag.forget_cli_options?
temporary(key => value)
value
else
command = if value.nil?
"bundle config --delete #{key}"
else
"bundle config #{key} #{Array(value).join(":")}"
end
Bundler::SharedHelpers.major_deprecation \
Bundler::SharedHelpers.major_deprecation 2,\
"flags passed to commands " \
"will no longer be automatically remembered. Instead please set flags " \
"you want remembered between commands using `bundle config " \
"<setting name> <setting value>`, i.e. `#{command}`"
set_local(key, value)
end
end
def set_command_option_if_given(key, value)
return if value.nil?
set_command_option(key, value)
end
def set_local(key, value)
local_config_file || raise(GemfileNotFound, "Could not locate Gemfile")
set_key(key, value, @local_config, local_config_file)
end
alias_method :set_local, :[]=
def temporary(update)
existing = Hash[update.map {|k, _| [k, @temporary[k]] }]
@temporary.update(update)
existing = Hash[update.map {|k, _| [k, @temporary[key_for(k)]] }]
update.each do |k, v|
set_key(k, v, @temporary, nil)
end
return unless block_given?
begin
yield
ensure
existing.each {|k, v| v.nil? ? @temporary.delete(k) : @temporary[k] = v }
existing.each {|k, v| set_key(k, v, @temporary, nil) }
end
end
def delete(key)
@local_config.delete(key_for(key))
end
def set_global(key, value)
set_key(key, value, @global_config, global_config_file)
end
def all
env_keys = ENV.keys.select {|k| k =~ /BUNDLE_.*/ }
env_keys = ENV.keys.grep(/\ABUNDLE_.+/)
keys = @global_config.keys | @local_config.keys | env_keys
keys = @temporary.keys | @global_config.keys | @local_config.keys | env_keys
keys.map do |key|
key.sub(/^BUNDLE_/, "").gsub(/__/, ".").downcase
@ -132,7 +172,7 @@ module Bundler
def gem_mirrors
all.inject(Mirrors.new) do |mirrors, k|
mirrors.parse(k, self[k]) if k =~ /^mirror\./
mirrors.parse(k, self[k]) if k.start_with?("mirror.")
mirrors
end
end
@ -140,6 +180,7 @@ module Bundler
def locations(key)
key = key_for(key)
locations = {}
locations[:temporary] = @temporary[key] if @temporary.key?(key)
locations[:local] = @local_config[key] if @local_config.key?(key)
locations[:env] = ENV[key] if ENV[key]
locations[:global] = @global_config[key] if @global_config.key?(key)
@ -151,6 +192,11 @@ module Bundler
key = key_for(exposed_key)
locations = []
if @temporary.key?(key)
locations << "Set for the current command: #{converted_value(@temporary[key], exposed_key).inspect}"
end
if @local_config.key?(key)
locations << "Set for your local app (#{local_config_file}): #{converted_value(@local_config[key], exposed_key).inspect}"
end
@ -167,37 +213,56 @@ module Bundler
locations
end
def without=(array)
set_array(:without, array)
end
def with=(array)
set_array(:with, array)
end
def without
get_array(:without)
end
def with
get_array(:with)
end
# @local_config["BUNDLE_PATH"] should be prioritized over ENV["BUNDLE_PATH"]
# for legacy reasons, the ruby scope isnt appended when the setting comes from ENV or the global config,
# nor do we respect :disable_shared_gems
def path
key = key_for(:path)
path = ENV[key] || @global_config[key]
return path if path && !@local_config.key?(key)
if path && !@temporary.key?(key) && !@local_config.key?(key)
return Path.new(path, false, false, false)
end
if path = self[:path]
"#{path}/#{Bundler.ruby_scope}"
else
Bundler.rubygems.gem_dir
system_path = self["path.system"] || (self[:disable_shared_gems] == false)
Path.new(self[:path], true, system_path, Bundler.feature_flag.default_install_uses_path?)
end
Path = Struct.new(:explicit_path, :append_ruby_scope, :system_path, :default_install_uses_path) do
def path
path = base_path
path = File.join(path, Bundler.ruby_scope) if append_ruby_scope && !use_system_gems?
path
end
def use_system_gems?
return true if system_path
return false if explicit_path
!default_install_uses_path
end
def base_path
path = explicit_path
path ||= ".bundle" unless use_system_gems?
path ||= Bundler.rubygems.gem_dir
path
end
def validate!
return unless explicit_path && system_path
path = Bundler.settings.pretty_values_for(:path)
path.unshift(nil, "path:") unless path.empty?
system_path = Bundler.settings.pretty_values_for("path.system")
system_path.unshift(nil, "path.system:") unless system_path.empty?
disable_shared_gems = Bundler.settings.pretty_values_for(:disable_shared_gems)
disable_shared_gems.unshift(nil, "disable_shared_gems:") unless disable_shared_gems.empty?
raise InvalidOption,
"Using a custom path while using system gems is unsupported.\n#{path.join("\n")}\n#{system_path.join("\n")}\n#{disable_shared_gems.join("\n")}"
end
end
def allow_sudo?
!@local_config.key?(key_for(:path))
key = key_for(:path)
path_configured = @temporary.key?(key) || @local_config.key?(key)
!path_configured
end
def ignore_config?
@ -205,14 +270,17 @@ module Bundler
end
def app_cache_path
@app_cache_path ||= begin
path = self[:cache_path] || "vendor/cache"
raise InvalidOption, "Cache path must be relative to the bundle path" if path.start_with?("/")
path
end
@app_cache_path ||= self[:cache_path] || "vendor/cache"
end
private
def validate!
all.each do |raw_key|
[@local_config, ENV, @global_config].each do |settings|
value = converted_value(settings[key_for(raw_key)], raw_key)
Validator.validate!(raw_key, value, settings.to_hash.dup)
end
end
end
def key_for(key)
key = Settings.normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key
@ -220,15 +288,17 @@ module Bundler
"BUNDLE_#{key}"
end
private
def parent_setting_for(name)
split_specfic_setting_for(name)[0]
split_specific_setting_for(name)[0]
end
def specfic_gem_for(name)
split_specfic_setting_for(name)[1]
def specific_gem_for(name)
split_specific_setting_for(name)[1]
end
def split_specfic_setting_for(name)
def split_specific_setting_for(name)
name.split(".")
end
@ -245,43 +315,57 @@ module Bundler
end
end
def is_num(value)
NUMBER_KEYS.include?(value.to_s)
def is_num(key)
NUMBER_KEYS.include?(key.to_s)
end
def get_array(key)
self[key] ? self[key].split(":").map(&:to_sym) : []
def is_array(key)
ARRAY_KEYS.include?(key.to_s)
end
def set_array(key, array)
self[key] = (array.empty? ? nil : array.join(":")) if array
def to_array(value)
return [] unless value
value.split(":").map(&:to_sym)
end
def set_key(key, value, hash, file)
key = key_for(key)
def array_to_s(array)
array = Array(array)
return nil if array.empty?
array.join(":").tr(" ", ":")
end
unless hash[key] == value
hash[key] = value
hash.delete(key) if value.nil?
SharedHelpers.filesystem_access(file) do |p|
FileUtils.mkdir_p(p.dirname)
require "bundler/yaml_serializer"
p.open("w") {|f| f.write(YAMLSerializer.dump(hash)) }
end
def set_key(raw_key, value, hash, file)
raw_key = raw_key.to_s
value = array_to_s(value) if is_array(raw_key)
key = key_for(raw_key)
return if hash[key] == value
hash[key] = value
hash.delete(key) if value.nil?
Validator.validate!(raw_key, converted_value(value, raw_key), hash)
return unless file
SharedHelpers.filesystem_access(file) do |p|
FileUtils.mkdir_p(p.dirname)
require "bundler/yaml_serializer"
p.open("w") {|f| f.write(YAMLSerializer.dump(hash)) }
end
value
end
def converted_value(value, key)
if value.nil?
if is_array(key)
to_array(value)
elsif value.nil?
nil
elsif is_bool(key) || value == "false"
to_bool(value)
elsif is_num(key)
value.to_i
else
value
value.to_s
end
end
@ -325,16 +409,34 @@ module Bundler
end
end
PER_URI_OPTIONS = %w[
fallback_timeout
].freeze
NORMALIZE_URI_OPTIONS_PATTERN =
/
\A
(\w+\.)? # optional prefix key
(https?.*?) # URI
(\.#{Regexp.union(PER_URI_OPTIONS)})? # optional suffix key
\z
/ix
# TODO: duplicates Rubygems#normalize_uri
# TODO: is this the correct place to validate mirror URIs?
def self.normalize_uri(uri)
uri = uri.to_s
uri = "#{uri}/" unless uri =~ %r{/\Z}
if uri =~ NORMALIZE_URI_OPTIONS_PATTERN
prefix = $1
uri = $2
suffix = $3
end
uri = "#{uri}/" unless uri.end_with?("/")
uri = URI(uri)
unless uri.absolute?
raise ArgumentError, format("Gem sources must be absolute. You provided '%s'.", uri)
end
uri
"#{prefix}#{uri}#{suffix}"
end
end
end

View file

@ -0,0 +1,79 @@
# frozen_string_literal: true
module Bundler
class Settings
class Validator
class Rule
attr_reader :description
def initialize(keys, description, &validate)
@keys = keys
@description = description
@validate = validate
end
def validate!(key, value, settings)
instance_exec(key, value, settings, &@validate)
end
def fail!(key, value, *reasons)
reasons.unshift @description
raise InvalidOption, "Setting `#{key}` to #{value.inspect} failed:\n#{reasons.map {|r| " - #{r}" }.join("\n")}"
end
def set(settings, key, value, *reasons)
hash_key = k(key)
return if settings[hash_key] == value
reasons.unshift @description
Bundler.ui.info "Setting `#{key}` to #{value.inspect}, since #{reasons.join(", ")}"
if value.nil?
settings.delete(hash_key)
else
settings[hash_key] = value
end
end
def k(key)
Bundler.settings.key_for(key)
end
end
def self.rules
@rules ||= Hash.new {|h, k| h[k] = [] }
end
private_class_method :rules
def self.rule(keys, description, &blk)
rule = Rule.new(keys, description, &blk)
keys.each {|k| rules[k] << rule }
end
private_class_method :rule
def self.validate!(key, value, settings)
rules_to_validate = rules[key]
rules_to_validate.each {|rule| rule.validate!(key, value, settings) }
end
rule %w[path path.system], "path and path.system are mutually exclusive" do |key, value, settings|
if key == "path" && value
set(settings, "path.system", nil)
elsif key == "path.system" && value
set(settings, :path, nil)
end
end
rule %w[with without], "a group cannot be in both `with` & `without` simultaneously" do |key, value, settings|
with = settings.fetch(k(:with), "").split(":").map(&:to_sym)
without = settings.fetch(k(:without), "").split(":").map(&:to_sym)
other_key = key == "with" ? :without : :with
other_setting = key == "with" ? without : with
conflicting = with & without
if conflicting.any?
fail!(key, value, "`#{other_key}` is current set to #{other_setting.inspect}", "the `#{conflicting.join("`, `")}` groups conflict")
end
end
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
require "bundler/shared_helpers"
if Bundler::SharedHelpers.in_bundle?

View file

@ -1,7 +1,11 @@
# frozen_string_literal: true
require "bundler/compatibility_guard"
require "pathname"
require "rubygems"
require "bundler/version"
require "bundler/constants"
require "bundler/rubygems_integration"
require "bundler/current_ruby"
@ -19,10 +23,16 @@ end
module Bundler
module SharedHelpers
def default_gemfile
def root
gemfile = find_gemfile
raise GemfileNotFound, "Could not locate Gemfile" unless gemfile
Pathname.new(gemfile).untaint
Pathname.new(gemfile).untaint.expand_path.parent
end
def default_gemfile
gemfile = find_gemfile(:order_matters)
raise GemfileNotFound, "Could not locate Gemfile" unless gemfile
Pathname.new(gemfile).untaint.expand_path
end
def default_lockfile
@ -63,7 +73,7 @@ module Bundler
end
def with_clean_git_env(&block)
keys = %w(GIT_DIR GIT_WORK_TREE)
keys = %w[GIT_DIR GIT_WORK_TREE]
old_env = keys.inject({}) do |h, k|
h.update(k => ENV[k])
end
@ -129,20 +139,34 @@ module Bundler
namespace.const_get(constant_name)
end
def major_deprecation(message)
def major_deprecation(major_version, message)
if Bundler.bundler_major_version >= major_version
require "bundler/errors"
raise DeprecatedError, "[REMOVED FROM #{major_version}.0] #{message}"
end
return unless prints_major_deprecations?
@major_deprecation_ui ||= Bundler::UI::Shell.new("no-color" => true)
ui = Bundler.ui.is_a?(@major_deprecation_ui.class) ? Bundler.ui : @major_deprecation_ui
ui.warn("[DEPRECATED FOR #{Bundler::VERSION.split(".").first.to_i + 1}.0] #{message}")
ui.warn("[DEPRECATED FOR #{major_version}.0] #{message}")
end
def print_major_deprecations!
deprecate_gemfile(find_gemfile) if find_gemfile == find_file("Gemfile")
multiple_gemfiles = search_up(".") do |dir|
gemfiles = gemfile_names.select {|gf| File.file? File.expand_path(gf, dir) }
next if gemfiles.empty?
break false if gemfiles.size == 1
end
if multiple_gemfiles && Bundler.bundler_major_version == 1
Bundler::SharedHelpers.major_deprecation 2, \
"gems.rb and gems.locked will be preferred to Gemfile and Gemfile.lock."
end
if RUBY_VERSION < "2"
major_deprecation("Bundler will only support ruby >= 2.0, you are running #{RUBY_VERSION}")
major_deprecation(2, "Bundler will only support ruby >= 2.0, you are running #{RUBY_VERSION}")
end
return if Bundler.rubygems.provides?(">= 2")
major_deprecation("Bundler will only support rubygems >= 2.0, you are running #{Bundler.rubygems.version}")
major_deprecation(2, "Bundler will only support rubygems >= 2.0, you are running #{Bundler.rubygems.version}")
end
def trap(signal, override = false, &block)
@ -170,23 +194,59 @@ module Bundler
"\nEither installing with `--full-index` or running `bundle update #{spec.name}` should fix the problem."
end
def pretty_dependency(dep, print_source = false)
msg = String.new(dep.name)
msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default
if dep.is_a?(Bundler::Dependency)
platform_string = dep.platforms.join(", ")
msg << " " << platform_string if !platform_string.empty? && platform_string != Gem::Platform::RUBY
end
msg << " from the `#{dep.source}` source" if print_source && dep.source
msg
end
def md5_available?
return @md5_available if defined?(@md5_available)
@md5_available = begin
require "openssl"
OpenSSL::Digest::MD5.digest("")
true
rescue LoadError
true
rescue OpenSSL::Digest::DigestError
false
end
end
def digest(name)
require "digest"
Digest(name)
end
private
def validate_bundle_path
return unless Bundler.bundle_path.to_s.include?(File::PATH_SEPARATOR)
message = "Your bundle path contains a '#{File::PATH_SEPARATOR}', " \
path_separator = Bundler.rubygems.path_separator
return unless Bundler.bundle_path.to_s.split(path_separator).size > 1
message = "Your bundle path contains text matching #{path_separator.inspect}, " \
"which is the path separator for your system. Bundler cannot " \
"function correctly when the Bundle path contains the " \
"system's PATH separator. Please change your " \
"bundle path to not include '#{File::PATH_SEPARATOR}'." \
"bundle path to not match #{path_separator.inspect}." \
"\nYour current bundle path is '#{Bundler.bundle_path}'."
raise Bundler::PathError, message
end
def find_gemfile
def find_gemfile(order_matters = false)
given = ENV["BUNDLE_GEMFILE"]
return given if given && !given.empty?
find_file("Gemfile", "gems.rb")
names = gemfile_names
names.reverse! if order_matters && Bundler.feature_flag.prefer_gems_rb?
find_file(*names)
end
def gemfile_names
["Gemfile", "gems.rb"]
end
def find_file(*names)
@ -226,40 +286,51 @@ module Bundler
end
end
def set_env(key, value)
raise ArgumentError, "new key #{key}" unless EnvironmentPreserver::BUNDLER_KEYS.include?(key)
orig_key = "#{EnvironmentPreserver::BUNDLER_PREFIX}#{key}"
orig = ENV[key]
orig ||= EnvironmentPreserver::INTENTIONALLY_NIL
ENV[orig_key] ||= orig
ENV[key] = value
end
public :set_env
def set_bundle_variables
begin
ENV["BUNDLE_BIN_PATH"] = Bundler.rubygems.bin_path("bundler", "bundle", VERSION)
Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", Bundler.rubygems.bin_path("bundler", "bundle", VERSION)
rescue Gem::GemNotFoundException
if File.exist?(File.expand_path("../../../exe/bundle", __FILE__))
ENV["BUNDLE_BIN_PATH"] = File.expand_path("../../../exe/bundle", __FILE__)
Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", File.expand_path("../../../exe/bundle", __FILE__)
else
ENV["BUNDLE_BIN_PATH"] = File.expand_path("../../../../bin/bundle", __FILE__)
Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", File.expand_path("../../../../bin/bundle", __FILE__)
end
end
# Set BUNDLE_GEMFILE
ENV["BUNDLE_GEMFILE"] = find_gemfile.to_s
ENV["BUNDLER_VERSION"] = Bundler::VERSION
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", find_gemfile(:order_matters).to_s
Bundler::SharedHelpers.set_env "BUNDLER_VERSION", Bundler::VERSION
end
def set_path
validate_bundle_path
paths = (ENV["PATH"] || "").split(File::PATH_SEPARATOR)
paths.unshift "#{Bundler.bundle_path}/bin"
ENV["PATH"] = paths.uniq.join(File::PATH_SEPARATOR)
Bundler::SharedHelpers.set_env "PATH", paths.uniq.join(File::PATH_SEPARATOR)
end
def set_rubyopt
rubyopt = [ENV["RUBYOPT"]].compact
return if !rubyopt.empty? && rubyopt.first =~ %r{-rbundler/setup}
rubyopt.unshift %(-rbundler/setup)
ENV["RUBYOPT"] = rubyopt.join(" ")
Bundler::SharedHelpers.set_env "RUBYOPT", rubyopt.join(" ")
end
def set_rubylib
rubylib = (ENV["RUBYLIB"] || "").split(File::PATH_SEPARATOR)
rubylib.unshift bundler_ruby_lib
ENV["RUBYLIB"] = rubylib.uniq.join(File::PATH_SEPARATOR)
Bundler::SharedHelpers.set_env "RUBYLIB", rubylib.uniq.join(File::PATH_SEPARATOR)
end
def bundler_ruby_lib
@ -290,12 +361,6 @@ module Bundler
true
end
def deprecate_gemfile(gemfile)
return unless gemfile && File.basename(gemfile) == "Gemfile"
Bundler::SharedHelpers.major_deprecation \
"gems.rb and gems.locked will be preferred to Gemfile and Gemfile.lock."
end
extend self
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class SimilarityDetector
SimilarityScore = Struct.new(:string, :distance)

View file

@ -1,8 +1,10 @@
# frozen_string_literal: true
module Bundler
class Source
autoload :Gemspec, "bundler/source/gemspec"
autoload :Git, "bundler/source/git"
autoload :Metadata, "bundler/source/metadata"
autoload :Path, "bundler/source/path"
autoload :Rubygems, "bundler/source/rubygems"
@ -31,6 +33,15 @@ module Bundler
spec.source == self
end
# it's possible that gems from one source depend on gems from some
# other source, so now we download gemspecs and iterate over those
# dependencies, looking for gems we don't have info on yet.
def double_check_for(*); end
def dependency_names_to_double_check
specs.dependency_names
end
def include?(other)
other == self
end
@ -39,6 +50,10 @@ module Bundler
"#<#{self.class}:0x#{object_id} #{self}>"
end
def path?
instance_of?(Bundler::Source::Path)
end
private
def version_color(spec_version, locked_spec_version)
@ -54,5 +69,26 @@ module Bundler
def earlier_version?(spec_version, locked_spec_version)
Gem::Version.new(spec_version) < Gem::Version.new(locked_spec_version)
end
def print_using_message(message)
if !message.include?("(was ") && Bundler.feature_flag.suppress_install_using_messages?
Bundler.ui.debug message
else
Bundler.ui.info message
end
end
def extension_cache_path(spec)
return unless Bundler.feature_flag.global_gem_cache?
return unless source_slug = extension_cache_slug(spec)
Bundler.user_cache.join(
"extensions", Gem::Platform.local.to_s, Bundler.ruby_scope,
source_slug, spec.full_name
)
end
def extension_cache_slug(_)
nil
end
end
end

View file

@ -1,4 +1,5 @@
# frozen_string_literal: true
module Bundler
class Source
class Gemspec < Path

Some files were not shown because too many files have changed in this diff Show more