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

Merge Bundler 2.1.0.pre.1 as developed version from upstream.

a53709556b

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67539 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
hsbt 2019-04-14 06:01:35 +00:00
parent d636809c05
commit 68ddd4d300
290 changed files with 5820 additions and 6161 deletions

View file

@ -5,7 +5,6 @@ require "bundler/compatibility_guard"
require "bundler/vendored_fileutils" require "bundler/vendored_fileutils"
require "pathname" require "pathname"
require "rbconfig" require "rbconfig"
require "thread"
require "bundler/errors" require "bundler/errors"
require "bundler/environment_preserver" require "bundler/environment_preserver"
@ -119,7 +118,7 @@ module Bundler
end end
def environment def environment
SharedHelpers.major_deprecation 3, "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 load
end end
@ -280,10 +279,19 @@ EOF
ORIGINAL_ENV.clone ORIGINAL_ENV.clone
end end
# @deprecated Use `original_env` instead # @deprecated Use `unbundled_env` instead
# @return [Hash] Environment with all bundler-related variables removed
def clean_env def clean_env
Bundler::SharedHelpers.major_deprecation(3, "`Bundler.clean_env` has weird edge cases, use `.original_env` instead") Bundler::SharedHelpers.major_deprecation(
2,
"`Bundler.clean_env` has been deprecated in favor of `Bundler.unbundled_env`. " \
"If you instead want the environment before bundler was originally loaded, use `Bundler.original_env`"
)
unbundled_env
end
# @return [Hash] Environment with all bundler-related variables removed
def unbundled_env
env = original_env env = original_env
if env.key?("BUNDLER_ORIG_MANPATH") if env.key?("BUNDLER_ORIG_MANPATH")
@ -305,20 +313,67 @@ EOF
env env
end end
# Run block with environment present before Bundler was activated
def with_original_env def with_original_env
with_env(original_env) { yield } with_env(original_env) { yield }
end end
# @deprecated Use `with_unbundled_env` instead
def with_clean_env def with_clean_env
with_env(clean_env) { yield } Bundler::SharedHelpers.major_deprecation(
2,
"`Bundler.with_clean_env` has been deprecated in favor of `Bundler.with_unbundled_env`. " \
"If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env`"
)
with_env(unbundled_env) { yield }
end end
# Run block with all bundler-related variables removed
def with_unbundled_env
with_env(unbundled_env) { yield }
end
# Run subcommand with the environment present before Bundler was activated
def original_system(*args)
with_original_env { Kernel.system(*args) }
end
# @deprecated Use `unbundled_system` instead
def clean_system(*args) def clean_system(*args)
with_clean_env { Kernel.system(*args) } Bundler::SharedHelpers.major_deprecation(
2,
"`Bundler.clean_system` has been deprecated in favor of `Bundler.unbundled_system`. " \
"If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system`"
)
with_env(unbundled_env) { Kernel.system(*args) }
end end
# Run subcommand in an environment with all bundler related variables removed
def unbundled_system(*args)
with_unbundled_env { Kernel.system(*args) }
end
# Run a `Kernel.exec` to a subcommand with the environment present before Bundler was activated
def original_exec(*args)
with_original_env { Kernel.exec(*args) }
end
# @deprecated Use `unbundled_exec` instead
def clean_exec(*args) def clean_exec(*args)
with_clean_env { Kernel.exec(*args) } Bundler::SharedHelpers.major_deprecation(
2,
"`Bundler.clean_exec` has been deprecated in favor of `Bundler.unbundled_exec`. " \
"If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec`"
)
with_env(unbundled_env) { Kernel.exec(*args) }
end
# Run a `Kernel.exec` to a subcommand in an environment with all bundler related variables removed
def unbundled_exec(*args)
with_env(unbundled_env) { Kernel.exec(*args) }
end end
def local_platform def local_platform
@ -343,7 +398,7 @@ EOF
# system binaries. If you put '-n foo' in your .gemrc, RubyGems will # system binaries. If you put '-n foo' in your .gemrc, RubyGems will
# install binstubs there instead. Unfortunately, RubyGems doesn't expose # install binstubs there instead. Unfortunately, RubyGems doesn't expose
# that directory at all, so rather than parse .gemrc ourselves, we allow # that directory at all, so rather than parse .gemrc ourselves, we allow
# the directory to be set as well, via `bundle config bindir foo`. # the directory to be set as well, via `bundle config set bindir foo`.
Bundler.settings[:system_bindir] || Bundler.rubygems.gem_bindir Bundler.settings[:system_bindir] || Bundler.rubygems.gem_bindir
end end
@ -523,7 +578,7 @@ EOF
rescue ScriptError, StandardError => e rescue ScriptError, StandardError => e
msg = "There was an error while loading `#{path.basename}`: #{e.message}" msg = "There was an error while loading `#{path.basename}`: #{e.message}"
if e.is_a?(LoadError) && RUBY_VERSION >= "1.9" if e.is_a?(LoadError)
msg += "\nDoes it try to require a relative path? That's been removed in Ruby 1.9" msg += "\nDoes it try to require a relative path? That's been removed in Ruby 1.9"
end end

View file

@ -1,4 +1,3 @@
# coding: utf-8
# frozen_string_literal: true # frozen_string_literal: true
begin begin
@ -19,16 +18,16 @@ Gem::Specification.new do |s|
"Yehuda Katz" "Yehuda Katz"
] ]
s.email = ["team@bundler.io"] s.email = ["team@bundler.io"]
s.homepage = "http://bundler.io" s.homepage = "https://bundler.io"
s.summary = "The best way to manage your application's dependencies" s.summary = "The best way to manage your application's dependencies"
s.description = "Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably" s.description = "Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably"
if s.respond_to?(:metadata=) if s.respond_to?(:metadata=)
s.metadata = { s.metadata = {
"bug_tracker_uri" => "http://github.com/bundler/bundler/issues", "bug_tracker_uri" => "https://github.com/bundler/bundler/issues",
"changelog_uri" => "https://github.com/bundler/bundler/blob/master/CHANGELOG.md", "changelog_uri" => "https://github.com/bundler/bundler/blob/master/CHANGELOG.md",
"homepage_uri" => "https://bundler.io/", "homepage_uri" => "https://bundler.io/",
"source_code_uri" => "http://github.com/bundler/bundler/", "source_code_uri" => "https://github.com/bundler/bundler/",
} }
end end
@ -41,14 +40,12 @@ Gem::Specification.new do |s|
end end
s.add_development_dependency "automatiek", "~> 0.1.0" s.add_development_dependency "automatiek", "~> 0.1.0"
s.add_development_dependency "mustache", "0.99.6" s.add_development_dependency "rake", "~> 12.0"
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 "ronn", "~> 0.7.3"
s.add_development_dependency "rspec", "~> 3.6" s.add_development_dependency "rspec", "~> 3.6"
s.add_development_dependency "rubocop", "= 0.65.0"
# base_dir = File.dirname(__FILE__).gsub(%r{([^A-Za-z0-9_\-.,:\/@\n])}, "\\\\\\1") # s.files = Dir.glob("{lib,exe}/**/*", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
# s.files = IO.popen("git -C #{base_dir} ls-files -z", &:read).split("\x0").select {|f| f.match(%r{^(lib|exe)/}) }
# we don't check in man pages, but we need to ship them because # we don't check in man pages, but we need to ship them because
# we use them to generate the long-form help for each command. # we use them to generate the long-form help for each command.

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "bundler/shared_helpers" require "bundler/shared_helpers"
Bundler::SharedHelpers.major_deprecation 3, Bundler::SharedHelpers.major_deprecation 2,
"The Bundler task for Capistrano. Please use http://github.com/capistrano/bundler" "The Bundler task for Capistrano. Please use http://github.com/capistrano/bundler"
# Capistrano task for Bundler. # Capistrano task for Bundler.

View file

@ -16,7 +16,7 @@ module Bundler
def self.start(*) def self.start(*)
super super
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
Bundler.ui = UI::Shell.new Bundler.ui = UI::Shell.new
raise e raise e
ensure ensure
@ -61,11 +61,6 @@ module Bundler
end end
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]) check_unknown_options!(:except => [:config, :exec])
stop_on_unknown_option! :exec stop_on_unknown_option! :exec
@ -142,7 +137,7 @@ module Bundler
Gemfile to a gem with a gemspec, the --gemspec option will automatically add each 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. dependency listed in the gemspec file to the newly created Gemfile.
D D
deprecated_option "gemspec", :type => :string, :banner => "Use the specified .gemspec to create the Gemfile" method_option "gemspec", :type => :string, :banner => "Use the specified .gemspec to create the Gemfile"
def init def init
require "bundler/cli/init" require "bundler/cli/init"
Init.new(options.dup).run Init.new(options.dup).run
@ -188,13 +183,13 @@ module Bundler
If the bundle has already been installed, bundler will tell you so and then exit. If the bundle has already been installed, bundler will tell you so and then exit.
D D
deprecated_option "binstubs", :type => :string, :lazy_default => "bin", :banner => method_option "binstubs", :type => :string, :lazy_default => "bin", :banner =>
"Generate bin stubs for bundled gems to ./bin" "Generate bin stubs for bundled gems to ./bin"
deprecated_option "clean", :type => :boolean, :banner => method_option "clean", :type => :boolean, :banner =>
"Run bundle clean automatically after install" "Run bundle clean automatically after install"
deprecated_option "deployment", :type => :boolean, :banner => method_option "deployment", :type => :boolean, :banner =>
"Install using defaults tuned for deployment environments" "Install using defaults tuned for deployment environments"
deprecated_option "frozen", :type => :boolean, :banner => method_option "frozen", :type => :boolean, :banner =>
"Do not allow the Gemfile.lock to be updated after this install" "Do not allow the Gemfile.lock to be updated after this install"
method_option "full-index", :type => :boolean, :banner => method_option "full-index", :type => :boolean, :banner =>
"Fall back to using the single-file index of all gems" "Fall back to using the single-file index of all gems"
@ -204,32 +199,37 @@ module Bundler
"Specify the number of jobs to run in parallel" "Specify the number of jobs to run in parallel"
method_option "local", :type => :boolean, :banner => method_option "local", :type => :boolean, :banner =>
"Do not attempt to fetch gems remotely and use the gem cache instead" "Do not attempt to fetch gems remotely and use the gem cache instead"
deprecated_option "no-cache", :type => :boolean, :banner => method_option "no-cache", :type => :boolean, :banner =>
"Don't update the existing gem cache." "Don't update the existing gem cache."
method_option "redownload", :type => :boolean, :aliases => "--force", :banner => method_option "redownload", :type => :boolean, :aliases => "--force", :banner =>
"Force downloading every gem." "Force downloading every gem."
deprecated_option "no-prune", :type => :boolean, :banner => method_option "no-prune", :type => :boolean, :banner =>
"Don't remove stale gems from the cache." "Don't remove stale gems from the cache."
deprecated_option "path", :type => :string, :banner => 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"
method_option "quiet", :type => :boolean, :banner => method_option "quiet", :type => :boolean, :banner =>
"Only output warnings and errors." "Only output warnings and errors."
deprecated_option "shebang", :type => :string, :banner => method_option "shebang", :type => :string, :banner =>
"Specify a different shebang executable name than the default (usually 'ruby')" "Specify a different shebang executable name than the default (usually 'ruby')"
method_option "standalone", :type => :array, :lazy_default => [], :banner => method_option "standalone", :type => :array, :lazy_default => [], :banner =>
"Make a bundle that can work without the Bundler runtime" "Make a bundle that can work without the Bundler runtime"
deprecated_option "system", :type => :boolean, :banner => method_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" "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 => method_option "trust-policy", :alias => "P", :type => :string, :banner =>
"Gem trust policy (like gem install -P). Must be one of " + "Gem trust policy (like gem install -P). Must be one of " +
Bundler.rubygems.security_policy_keys.join("|") Bundler.rubygems.security_policy_keys.join("|")
deprecated_option "without", :type => :array, :banner => method_option "without", :type => :array, :banner =>
"Exclude gems that are part of the specified named group." "Exclude gems that are part of the specified named group."
deprecated_option "with", :type => :array, :banner => method_option "with", :type => :array, :banner =>
"Include gems that are part of the specified named group." "Include gems that are part of the specified named group."
map "i" => "install" map "i" => "install"
def install def install
SharedHelpers.major_deprecation(3, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force") SharedHelpers.major_deprecation(2, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force")
%w[clean deployment frozen no-cache no-prune path shebang system without with].each do |option|
remembered_flag_deprecation(option)
end
require "bundler/cli/install" require "bundler/cli/install"
Bundler.settings.temporary(:no_install => false) do Bundler.settings.temporary(:no_install => false) do
Install.new(options.dup).run Install.new(options.dup).run
@ -275,57 +275,60 @@ module Bundler
method_option "all", :type => :boolean, :banner => method_option "all", :type => :boolean, :banner =>
"Update everything." "Update everything."
def update(*gems) def update(*gems)
SharedHelpers.major_deprecation(3, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force") SharedHelpers.major_deprecation(2, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force")
require "bundler/cli/update" require "bundler/cli/update"
Update.new(options, gems).run Bundler.settings.temporary(:no_install => false) do
Update.new(options, gems).run
end
end end
desc "show GEM [OPTIONS]", "Shows all gems that are part of the bundle, or the path to a given gem" unless Bundler.feature_flag.bundler_3_mode?
long_desc <<-D desc "show GEM [OPTIONS]", "Shows all gems that are part of the bundle, or the path to a given gem"
Show lists the names and versions of all gems that are required by your Gemfile. long_desc <<-D
Calling show with [GEM] will list the exact location of that gem on your machine. Show lists the names and versions of all gems that are required by your Gemfile.
D Calling show with [GEM] will list the exact location of that gem on your machine.
method_option "paths", :type => :boolean, D
:banner => "List the paths of all gems that are required by your Gemfile." method_option "paths", :type => :boolean,
method_option "outdated", :type => :boolean, :banner => "List the paths of all gems that are required by your Gemfile."
:banner => "Show verbose output including whether gems are outdated." method_option "outdated", :type => :boolean,
def show(gem_name = nil) :banner => "Show verbose output including whether gems are outdated."
if ARGV[0] == "show" def show(gem_name = nil)
rest = ARGV[1..-1] if ARGV[0] == "show"
rest = ARGV[1..-1]
new_command = rest.find {|arg| !arg.start_with?("--") } ? "info" : "list" if flag = rest.find{|arg| ["--verbose", "--outdated"].include?(arg) }
Bundler::SharedHelpers.major_deprecation(2, "the `#{flag}` flag to `bundle show` was undocumented and will be removed without replacement")
else
new_command = rest.find {|arg| !arg.start_with?("--") } ? "info" : "list"
new_arguments = rest.map do |arg| new_arguments = rest.map do |arg|
next arg if arg != "--paths" next arg if arg != "--paths"
next "--path" if new_command == "info" next "--path" if new_command == "info"
end
old_argv = ARGV.join(" ")
new_argv = [new_command, *new_arguments.compact].join(" ")
Bundler::SharedHelpers.major_deprecation(2, "use `bundle #{new_argv}` instead of `bundle #{old_argv}`")
end
end end
require "bundler/cli/show"
old_argv = ARGV.join(" ") Show.new(options, gem_name).run
new_argv = [new_command, *new_arguments.compact].join(" ")
Bundler::SharedHelpers.major_deprecation(3, "use `bundle #{new_argv}` instead of `bundle #{old_argv}`")
end end
require "bundler/cli/show"
Show.new(options, gem_name).run
end end
# TODO: 2.0 remove `bundle show`
if Bundler.feature_flag.list_command? desc "list", "List all gems in the bundle"
desc "list", "List all gems in the bundle" method_option "name-only", :type => :boolean, :banner => "print only the gem names"
method_option "name-only", :type => :boolean, :banner => "print only the gem names" method_option "only-group", :type => :string, :banner => "print gems from a particular group"
method_option "only-group", :type => :string, :banner => "print gems from a particular group" method_option "without-group", :type => :string, :banner => "print all gems except from a group"
method_option "without-group", :type => :string, :banner => "print all gems expect from a group" method_option "paths", :type => :boolean, :banner => "print the path to each gem in the bundle"
method_option "paths", :type => :boolean, :banner => "print the path to each gem in the bundle" def list
def list require "bundler/cli/list"
require "bundler/cli/list" List.new(options).run
List.new(options).run
end
map %w[ls] => "list"
else
map %w[list] => "show"
end end
map %w[ls] => "list"
desc "info GEM [OPTIONS]", "Show information for the given gem" desc "info GEM [OPTIONS]", "Show information for the given gem"
method_option "path", :type => :boolean, :banner => "Print full path to gem" method_option "path", :type => :boolean, :banner => "Print full path to gem"
def info(gem_name) def info(gem_name)
@ -386,9 +389,10 @@ module Bundler
"Do not attempt to fetch gems remotely and use the gem cache instead" "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" method_option "pre", :type => :boolean, :banner => "Check for newer pre-release gems"
method_option "source", :type => :array, :banner => "Check against a specific source" method_option "source", :type => :array, :banner => "Check against a specific source"
method_option "strict", :type => :boolean, :banner => strict_is_update = Bundler.feature_flag.forget_cli_options?
method_option "filter-strict", :type => :boolean, :aliases => strict_is_update ? [] : %w[--strict], :banner =>
"Only list newer versions allowed by your Gemfile requirements" "Only list newer versions allowed by your Gemfile requirements"
method_option "update-strict", :type => :boolean, :banner => method_option "update-strict", :type => :boolean, :aliases => strict_is_update ? %w[--strict] : [], :banner =>
"Strict conservative resolution, do not allow any gem to be updated past latest --patch | --minor | --major" "Strict conservative resolution, do not allow any gem to be updated past latest --patch | --minor | --major"
method_option "minor", :type => :boolean, :banner => "Prefer updating only to next minor version" method_option "minor", :type => :boolean, :banner => "Prefer updating only to next minor version"
method_option "major", :type => :boolean, :banner => "Prefer updating to next major version (default)" method_option "major", :type => :boolean, :banner => "Prefer updating to next major version (default)"
@ -475,11 +479,8 @@ module Bundler
will show the current value, as well as any superceded values and will show the current value, as well as any superceded values and
where they were specified. where they were specified.
D D
method_option "parseable", :type => :boolean, :banner => "Use minimal formatting for more parseable output" require "bundler/cli/config"
def config(*args) subcommand "config", Config
require "bundler/cli/config"
Config.new(options, args, self).run
end
desc "open GEM", "Opens the source directory of the given bundled gem" desc "open GEM", "Opens the source directory of the given bundled gem"
def open(name) def open(name)
@ -487,7 +488,7 @@ module Bundler
Open.new(options, name).run Open.new(options, name).run
end end
if Bundler.feature_flag.console_command? unless Bundler.feature_flag.bundler_3_mode?
desc "console [GROUP]", "Opens an IRB session with the bundle pre-loaded" desc "console [GROUP]", "Opens an IRB session with the bundle pre-loaded"
def console(group = nil) def console(group = nil)
require "bundler/cli/console" require "bundler/cli/console"
@ -524,7 +525,7 @@ module Bundler
end end
end end
if Bundler.feature_flag.viz_command? unless Bundler.feature_flag.bundler_3_mode?
desc "viz [OPTIONS]", "Generates a visual dependency graph", :hide => true desc "viz [OPTIONS]", "Generates a visual dependency graph", :hide => true
long_desc <<-D long_desc <<-D
Viz generates a PNG file of the current Gemfile as a dependency graph. Viz generates a PNG file of the current Gemfile as a dependency graph.
@ -537,7 +538,7 @@ module Bundler
method_option :version, :type => :boolean, :default => false, :aliases => "-v", :desc => "Set to show each gem version." method_option :version, :type => :boolean, :default => false, :aliases => "-v", :desc => "Set to show each gem version."
method_option :without, :type => :array, :default => [], :aliases => "-W", :banner => "GROUP[ GROUP...]", :desc => "Exclude gems that are part of the specified named group." method_option :without, :type => :array, :default => [], :aliases => "-W", :banner => "GROUP[ GROUP...]", :desc => "Exclude gems that are part of the specified named group."
def viz def viz
SharedHelpers.major_deprecation 3, "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz" SharedHelpers.major_deprecation 2, "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz"
require "bundler/cli/viz" require "bundler/cli/viz"
Viz.new(options.dup).run Viz.new(options.dup).run
end end
@ -547,14 +548,14 @@ module Bundler
desc "gem NAME [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 :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 :coc, :type => :boolean, :desc => "Generate a code of conduct file. Set a default with `bundle config set gem.coc true`."
method_option :edit, :type => :string, :aliases => "-e", :required => false, :banner => "EDITOR", method_option :edit, :type => :string, :aliases => "-e", :required => false, :banner => "EDITOR",
:lazy_default => [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }, :lazy_default => [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? },
:desc => "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)" :desc => "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)"
method_option :ext, :type => :boolean, :default => false, :desc => "Generate the boilerplate for C extension code" method_option :ext, :type => :boolean, :default => false, :desc => "Generate the boilerplate for C extension code"
method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config gem.mit true`." method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config set gem.mit true`."
method_option :test, :type => :string, :lazy_default => "rspec", :aliases => "-t", :banner => "rspec", method_option :test, :type => :string, :lazy_default => "rspec", :aliases => "-t", :banner => "rspec",
:desc => "Generate a test directory for your library, either rspec or minitest. Set a default with `bundle config gem.test rspec`." :desc => "Generate a test directory for your library, either rspec or minitest. Set a default with `bundle config set gem.test rspec`."
def gem(name) def gem(name)
end end
@ -608,7 +609,7 @@ module Bundler
method_option "group", :type => :string, :banner => method_option "group", :type => :string, :banner =>
"Install gem into a bundler group" "Install gem into a bundler group"
def inject(name, version) def inject(name, version)
SharedHelpers.major_deprecation 3, "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" require "bundler/cli/inject"
Inject.new(options.dup, name, version).run Inject.new(options.dup, name, version).run
end end
@ -620,6 +621,8 @@ module Bundler
"do not attempt to fetch remote gemspecs and use the local gem cache only" "do not attempt to fetch remote gemspecs and use the local gem cache only"
method_option "print", :type => :boolean, :default => false, :banner => method_option "print", :type => :boolean, :default => false, :banner =>
"print the lockfile to STDOUT instead of writing to the file system" "print the lockfile to STDOUT instead of writing to the file system"
method_option "gemfile", :type => :string, :banner =>
"Use the specified gemfile instead of Gemfile"
method_option "lockfile", :type => :string, :default => nil, :banner => method_option "lockfile", :type => :string, :default => nil, :banner =>
"the path the lockfile should be written to" "the path the lockfile should be written to"
method_option "full-index", :type => :boolean, :default => false, :banner => method_option "full-index", :type => :boolean, :default => false, :banner =>
@ -714,7 +717,7 @@ module Bundler
# Automatically invoke `bundle install` and resume if # Automatically invoke `bundle install` and resume if
# Bundler.settings[:auto_install] exists. This is set through config cmd # Bundler.settings[:auto_install] exists. This is set through config cmd
# `bundle config auto_install 1`. # `bundle config set auto_install 1`.
# #
# Note that this method `nil`s out the global Definition object, so it # Note that this method `nil`s out the global Definition object, so it
# should be called first, before you instantiate anything like an # should be called first, before you instantiate anything like an
@ -786,5 +789,22 @@ module Bundler
rescue RuntimeError rescue RuntimeError
nil nil
end end
def remembered_flag_deprecation(name)
option = current_command.options[name]
flag_name = option.switch_name
name_index = ARGV.find {|arg| flag_name == arg }
return unless name_index
value = options[name]
value = value.join(" ").to_s if option.type == :array
Bundler::SharedHelpers.major_deprecation 2,\
"The `#{flag_name}` flag is deprecated because it relies on being " \
"remembered accross bundler invokations, which bundler will no longer " \
"do in future versions. Instead please use `bundle config #{name} " \
"'#{value}'`, and stop using this flag"
end
end end
end end

View file

@ -29,7 +29,7 @@ module Bundler
if Bundler.definition.has_local_dependencies? && !Bundler.feature_flag.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 " \ 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 " \ "to package them as well, please pass the --all flag. This will be the default " \
"on Bundler 2.0." "on Bundler 3.0."
end end
end end
end end

View file

@ -23,7 +23,7 @@ module Bundler
groups = Bundler.settings[:without] groups = Bundler.settings[:without]
group_list = [groups[0...-1].join(", "), groups[-1..-1]]. group_list = [groups[0...-1].join(", "), groups[-1..-1]].
reject {|s| s.to_s.empty? }.join(" and ") reject {|s| s.to_s.empty? }.join(" and ")
group_str = (groups.size == 1) ? "group" : "groups" group_str = groups.size == 1 ? "group" : "groups"
"Gems in the #{group_str} #{group_list} were not installed." "Gems in the #{group_str} #{group_list} were not installed."
end end
@ -49,10 +49,6 @@ module Bundler
end end
def self.ask_for_spec_from(specs) def self.ask_for_spec_from(specs)
if !$stdout.tty? && ENV["BUNDLE_SPEC_RUN"].nil?
raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
end
specs.each_with_index do |spec, index| specs.each_with_index do |spec, index|
Bundler.ui.info "#{index.succ} : #{spec.name}", true Bundler.ui.info "#{index.succ} : #{spec.name}", true
end end
@ -72,7 +68,7 @@ module Bundler
end end
def self.ensure_all_gems_in_lockfile!(names, locked_gems = Bundler.locked_gems) def self.ensure_all_gems_in_lockfile!(names, locked_gems = Bundler.locked_gems)
locked_names = locked_gems.specs.map(&:name) locked_names = locked_gems.specs.map(&:name).uniq
names.-(locked_names).each do |g| names.-(locked_names).each do |g|
raise GemNotFound, gem_not_found_message(g, locked_names) raise GemNotFound, gem_not_found_message(g, locked_names)
end end
@ -80,10 +76,12 @@ module Bundler
def self.configure_gem_version_promoter(definition, options) def self.configure_gem_version_promoter(definition, options)
patch_level = patch_level_options(options) patch_level = patch_level_options(options)
patch_level << :patch if patch_level.empty? && Bundler.settings[:prefer_patch]
raise InvalidOption, "Provide only one of the following options: #{patch_level.join(", ")}" unless patch_level.length <= 1 raise InvalidOption, "Provide only one of the following options: #{patch_level.join(", ")}" unless patch_level.length <= 1
definition.gem_version_promoter.tap do |gvp| definition.gem_version_promoter.tap do |gvp|
gvp.level = patch_level.first || :major gvp.level = patch_level.first || :major
gvp.strict = options[:strict] || options["update-strict"] gvp.strict = options[:strict] || options["update-strict"] || options["filter-strict"]
end end
end end

View file

@ -1,119 +1,194 @@
# frozen_string_literal: true # frozen_string_literal: true
module Bundler module Bundler
class CLI::Config class CLI::Config < Thor
attr_reader :name, :options, :scope, :thor class_option :parseable, :type => :boolean, :banner => "Use minimal formatting for more parseable output"
attr_accessor :args
def initialize(options, args, thor) def self.scope_options
@options = options method_option :global, :type => :boolean, :banner => "Only change the global config"
@args = args method_option :local, :type => :boolean, :banner => "Only change the local config"
@thor = thor end
@name = peek = args.shift private_class_method :scope_options
@scope = "global"
return unless peek && peek.start_with?("--") desc "base NAME [VALUE]", "The Bundler 1 config interface", :hide => true
@name = args.shift scope_options
@scope = peek[2..-1] method_option :delete, :type => :boolean, :banner => "delete"
def base(name = nil, *value)
new_args =
if ARGV.size == 1
["config", "list"]
elsif ARGV.include?("--delete")
ARGV.map {|arg| arg == "--delete" ? "unset" : arg }
elsif ARGV.include?("--global") || ARGV.include?("--local") || ARGV.size == 3
["config", "set", *ARGV[1..-1]]
else
["config", "get", ARGV[1]]
end
SharedHelpers.major_deprecation 2,
"Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle #{new_args.join(" ")}` instead."
Base.new(options, name, value, self).run
end end
def run desc "list", "List out all configured settings"
unless name def list
confirm_all Base.new(options, nil, nil, self).run
return end
desc "get NAME", "Returns the value for the given key"
def get(name)
Base.new(options, name, nil, self).run
end
desc "set NAME VALUE", "Sets the given value for the given key"
scope_options
def set(name, value, *value_)
Base.new(options, name, value_.unshift(value), self).run
end
desc "unset NAME", "Unsets the value for the given key"
scope_options
def unset(name)
options[:delete] = true
Base.new(options, name, nil, self).run
end
default_task :base
class Base
attr_reader :name, :value, :options, :scope, :thor
def initialize(options, name, value, thor)
@options = options
@name = name
value = Array(value)
@value = value.empty? ? nil : value.join(" ")
@thor = thor
validate_scope!
end end
unless valid_scope?(scope) def run
Bundler.ui.error "Invalid scope --#{scope} given. Please use --local or --global." unless name
exit 1 warn_unused_scope "Ignoring --#{scope}"
end confirm_all
return
end
if scope == "delete" if options[:delete]
Bundler.settings.set_local(name, nil) if !explicit_scope? || scope != "global"
Bundler.settings.set_global(name, nil) Bundler.settings.set_local(name, nil)
return end
end if !explicit_scope? || scope != "local"
Bundler.settings.set_global(name, nil)
if args.empty?
if options[:parseable]
if value = Bundler.settings[name]
Bundler.ui.info("#{name}=#{value}")
end end
return return
end end
confirm(name) if value.nil?
return warn_unused_scope "Ignoring --#{scope} since no value to set was given"
if options[:parseable]
if value = Bundler.settings[name]
Bundler.ui.info("#{name}=#{value}")
end
return
end
confirm(name)
return
end
Bundler.ui.info(message) if message
Bundler.settings.send("set_#{scope}", name, new_value)
end end
Bundler.ui.info(message) if message def confirm_all
Bundler.settings.send("set_#{scope}", name, new_value) if @options[:parseable]
end thor.with_padding do
Bundler.settings.all.each do |setting|
private val = Bundler.settings[setting]
Bundler.ui.info "#{setting}=#{val}"
def confirm_all end
if @options[:parseable] end
thor.with_padding do else
Bundler.ui.confirm "Settings are listed in order of priority. The top value will be used.\n"
Bundler.settings.all.each do |setting| Bundler.settings.all.each do |setting|
val = Bundler.settings[setting] Bundler.ui.confirm "#{setting}"
Bundler.ui.info "#{setting}=#{val}" show_pretty_values_for(setting)
Bundler.ui.confirm ""
end end
end end
else end
Bundler.ui.confirm "Settings are listed in order of priority. The top value will be used.\n"
Bundler.settings.all.each do |setting| def confirm(name)
Bundler.ui.confirm "#{setting}" Bundler.ui.confirm "Settings for `#{name}` in order of priority. The top value will be used"
show_pretty_values_for(setting) show_pretty_values_for(name)
Bundler.ui.confirm "" end
def new_value
pathname = Pathname.new(value)
if name.start_with?("local.") && pathname.directory?
pathname.expand_path.to_s
else
value
end end
end end
end
def confirm(name) def message
Bundler.ui.confirm "Settings for `#{name}` in order of priority. The top value will be used" locations = Bundler.settings.locations(name)
show_pretty_values_for(name) if @options[:parseable]
end "#{name}=#{new_value}" if new_value
elsif scope == "global"
def new_value if !locations[:local].nil?
pathname = Pathname.new(args.join(" ")) "Your application has set #{name} to #{locations[:local].inspect}. " \
if name.start_with?("local.") && pathname.directory? "This will override the global value you are currently setting"
pathname.expand_path.to_s elsif locations[:env]
else "You have a bundler environment variable for #{name} set to " \
args.join(" ") "#{locations[:env].inspect}. This will take precedence over the global value you are setting"
end elsif !locations[:global].nil? && locations[:global] != value
end "You are replacing the current global value of #{name}, which is currently " \
"#{locations[:global].inspect}"
def message end
locations = Bundler.settings.locations(name) elsif scope == "local" && !locations[:local].nil? && locations[:local] != value
if @options[:parseable] "You are replacing the current local value of #{name}, which is currently " \
"#{name}=#{new_value}" if new_value "#{locations[:local].inspect}"
elsif scope == "global"
if locations[:local]
"Your application has set #{name} to #{locations[:local].inspect}. " \
"This will override the global value you are currently setting"
elsif locations[:env]
"You have a bundler environment variable for #{name} set to " \
"#{locations[:env].inspect}. This will take precedence over the global value you are setting"
elsif locations[:global] && locations[:global] != args.join(" ")
"You are replacing the current global value of #{name}, which is currently " \
"#{locations[:global].inspect}"
end
elsif scope == "local" && locations[:local] != args.join(" ")
"You are replacing the current local value of #{name}, which is currently " \
"#{locations[:local].inspect}"
end
end
def show_pretty_values_for(setting)
thor.with_padding do
Bundler.settings.pretty_values_for(setting).each do |line|
Bundler.ui.info line
end end
end end
end
def valid_scope?(scope) def show_pretty_values_for(setting)
%w[delete local global].include?(scope) thor.with_padding do
Bundler.settings.pretty_values_for(setting).each do |line|
Bundler.ui.info line
end
end
end
def explicit_scope?
@explicit_scope
end
def warn_unused_scope(msg)
return unless explicit_scope?
return if options[:parseable]
Bundler.ui.warn(msg)
end
def validate_scope!
@explicit_scope = true
scopes = %w[global local].select {|s| options[s] }
case scopes.size
when 0
@scope = "global"
@explicit_scope = false
when 1
@scope = scopes.first
else
raise InvalidOption,
"The options #{scopes.join " and "} were specified. Please only use one of the switches at a time."
end
end
end end
end end
end end

View file

@ -9,10 +9,10 @@ module Bundler
end end
def run def run
Bundler::SharedHelpers.major_deprecation 3, "bundle console will be replaced " \ Bundler::SharedHelpers.major_deprecation 2, "bundle console will be replaced " \
"by `bin/console` generated by `bundle gem <name>`" "by `bin/console` generated by `bundle gem <name>`"
group ? Bundler.require(:default, *(group.split.map!(&:to_sym))) : Bundler.require group ? Bundler.require(:default, *group.split.map!(&:to_sym)) : Bundler.require
ARGV.clear ARGV.clear
console = get_console(Bundler.settings[:console] || "irb") console = get_console(Bundler.settings[:console] || "irb")

View file

@ -4,8 +4,8 @@ require "rbconfig"
module Bundler module Bundler
class CLI::Doctor class CLI::Doctor
DARWIN_REGEX = /\s+(.+) \(compatibility / DARWIN_REGEX = /\s+(.+) \(compatibility /.freeze
LDD_REGEX = /\t\S+ => (\S+) \(\S+\)/ LDD_REGEX = /\t\S+ => (\S+) \(\S+\)/.freeze
attr_reader :options attr_reader :options

View file

@ -11,7 +11,7 @@ module Bundler
class CLI::Gem class CLI::Gem
TEST_FRAMEWORK_VERSIONS = { TEST_FRAMEWORK_VERSIONS = {
"rspec" => "3.0", "rspec" => "3.0",
"minitest" => "5.0" "minitest" => "5.0",
}.freeze }.freeze
attr_reader :options, :gem_name, :thor, :name, :target attr_reader :options, :gem_name, :thor, :name, :target
@ -57,7 +57,7 @@ module Bundler
:ext => options[:ext], :ext => options[:ext],
:exe => options[:exe], :exe => options[:exe],
:bundler_version => bundler_dependency_version, :bundler_version => bundler_dependency_version,
:github_username => github_username.empty? ? "[USERNAME]" : github_username :github_username => github_username.empty? ? "[USERNAME]" : github_username,
} }
ensure_safe_gem_name(name, constant_array) ensure_safe_gem_name(name, constant_array)
@ -69,7 +69,7 @@ module Bundler
"Rakefile.tt" => "Rakefile", "Rakefile.tt" => "Rakefile",
"README.md.tt" => "README.md", "README.md.tt" => "README.md",
"bin/console.tt" => "bin/console", "bin/console.tt" => "bin/console",
"bin/setup.tt" => "bin/setup" "bin/setup.tt" => "bin/setup",
} }
executables = %w[ executables = %w[

View file

@ -9,18 +9,24 @@ module Bundler
end end
def run def run
Bundler.ui.silence do
Bundler.definition.validate_runtime!
Bundler.load.lock
end
spec = spec_for_gem(gem_name) spec = spec_for_gem(gem_name)
spec_not_found(gem_name) unless spec if spec
return print_gem_path(spec) if @options[:path] return print_gem_path(spec) if @options[:path]
print_gem_info(spec) print_gem_info(spec)
end
end end
private private
def spec_for_gem(gem_name) def spec_for_gem(gem_name)
spec = Bundler.definition.specs.find {|s| s.name == gem_name } spec = Bundler.definition.specs.find {|s| s.name == gem_name }
spec || default_gem_spec(gem_name) spec || default_gem_spec(gem_name) || Bundler::CLI::Common.select_spec(gem_name, :regex_match)
end end
def default_gem_spec(gem_name) def default_gem_spec(gem_name)
@ -34,7 +40,13 @@ module Bundler
end end
def print_gem_path(spec) def print_gem_path(spec)
Bundler.ui.info spec.full_gem_path path = if spec.name == "bundler"
File.expand_path("../../../..", __FILE__)
else
spec.full_gem_path
end
Bundler.ui.info path
end end
def print_gem_info(spec) def print_gem_info(spec)

View file

@ -41,7 +41,7 @@ module Bundler
private private
def gemfile def gemfile
@gemfile ||= Bundler.feature_flag.init_gems_rb? ? "gems.rb" : "Gemfile" @gemfile ||= Bundler.settings[:init_gems_rb] ? "gems.rb" : "Gemfile"
end end
end end
end end

View file

@ -53,7 +53,7 @@ module Bundler
Bundler::Fetcher.disable_endpoint = options["full-index"] Bundler::Fetcher.disable_endpoint = options["full-index"]
if options["binstubs"] if options["binstubs"]
Bundler::SharedHelpers.major_deprecation 3, Bundler::SharedHelpers.major_deprecation 2,
"The --binstubs option will be removed in favor of `bundle binstubs`" "The --binstubs option will be removed in favor of `bundle binstubs`"
end end
@ -202,15 +202,16 @@ module Bundler
end end
def warn_ambiguous_gems def warn_ambiguous_gems
# TODO: remove this when we drop Bundler 1.x support
Installer.ambiguous_gems.to_a.each do |name, installed_from_uri, *also_found_in_uris| Installer.ambiguous_gems.to_a.each do |name, installed_from_uri, *also_found_in_uris|
Bundler.ui.error "Warning: the gem '#{name}' was found in multiple sources." Bundler.ui.warn "Warning: the gem '#{name}' was found in multiple sources."
Bundler.ui.error "Installed from: #{installed_from_uri}" Bundler.ui.warn "Installed from: #{installed_from_uri}"
Bundler.ui.error "Also found in:" Bundler.ui.warn "Also found in:"
also_found_in_uris.each {|uri| Bundler.ui.error " * #{uri}" } also_found_in_uris.each {|uri| Bundler.ui.warn " * #{uri}" }
Bundler.ui.error "You should add a source requirement to restrict this gem to your preferred source." Bundler.ui.warn "You should add a source requirement to restrict this gem to your preferred source."
Bundler.ui.error "For example:" Bundler.ui.warn "For example:"
Bundler.ui.error " gem '#{name}', :source => '#{installed_from_uri}'" Bundler.ui.warn " gem '#{name}', :source => '#{installed_from_uri}'"
Bundler.ui.error "Then uninstall the gem '#{name}' (or delete all bundled gems) and then install again." Bundler.ui.warn "Then uninstall the gem '#{name}' (or delete all bundled gems) and then install again."
end end
end end
end end

View file

@ -13,10 +13,10 @@ module Bundler
https://github.com/bundler/bundler/blob/master/doc/TROUBLESHOOTING.md https://github.com/bundler/bundler/blob/master/doc/TROUBLESHOOTING.md
2. Instructions for common Bundler uses can be found on the documentation 2. Instructions for common Bundler uses can be found on the documentation
site: http://bundler.io/ site: https://bundler.io/
3. Information about each Bundler command can be found in the Bundler 3. Information about each Bundler command can be found in the Bundler
man pages: http://bundler.io/man/bundle.1.html man pages: https://bundler.io/man/bundle.1.html
Hopefully the troubleshooting steps above resolved your problem! If things Hopefully the troubleshooting steps above resolved your problem! If things
still aren't working the way you expect them to, please let us know so still aren't working the way you expect them to, please let us know so

View file

@ -41,7 +41,7 @@ module Bundler
# the patch level options imply strict is also true. It wouldn't make # the patch level options imply strict is also true. It wouldn't make
# sense otherwise. # sense otherwise.
strict = options[:strict] || strict = options["filter-strict"] ||
Bundler::CLI::Common.patch_level_options(options).any? Bundler::CLI::Common.patch_level_options(options).any?
filter_options_patch = options.keys & filter_options_patch = options.keys &
@ -124,7 +124,7 @@ module Bundler
[nil, ordered_groups].flatten.each do |groups| [nil, ordered_groups].flatten.each do |groups|
gems = outdated_gems_by_groups[groups] gems = outdated_gems_by_groups[groups]
contains_group = if groups contains_group = if groups
groups.split(",").include?(options[:group]) groups.split(", ").include?(options[:group])
else else
options[:group] == "group" options[:group] == "group"
end end
@ -221,9 +221,9 @@ module Bundler
def check_for_deployment_mode def check_for_deployment_mode
return unless Bundler.frozen_bundle? return unless Bundler.frozen_bundle?
suggested_command = if Bundler.settings.locations("frozen")[:global] suggested_command = if Bundler.settings.locations("frozen")[:global]
"bundle config --delete frozen" "bundle config unset frozen"
elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any? elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any?
"bundle config --delete deployment" "bundle config unset deployment"
else else
"bundle install --no-deployment" "bundle install --no-deployment"
end end

View file

@ -42,7 +42,7 @@ module Bundler
if Bundler.definition.has_local_dependencies? && !Bundler.feature_flag.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 " \ 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 " \ "to package them as well, please pass the --all flag. This will be the default " \
"on Bundler 2.0." "on Bundler 3.0."
end end
end end
end end

View file

@ -5,7 +5,7 @@ module Bundler
class CLI::Plugin < Thor class CLI::Plugin < Thor
desc "install PLUGINS", "Install the plugin from the source" desc "install PLUGINS", "Install the plugin from the source"
long_desc <<-D long_desc <<-D
Install plugins either from the rubygems source provided (with --source option) or from a git source provided with (--git option). If no sources are provided, it uses Gem.sources Install plugins either from the rubygems source provided (with --source option) or from a git source provided with --git (for remote repos) or --local_git (for local repos). If no sources are provided, it uses Gem.sources
D D
method_option "source", :type => :string, :default => nil, :banner => method_option "source", :type => :string, :default => nil, :banner =>
"URL of the RubyGems source to fetch the plugin from" "URL of the RubyGems source to fetch the plugin from"
@ -13,6 +13,8 @@ module Bundler
"The version of the plugin to fetch" "The version of the plugin to fetch"
method_option "git", :type => :string, :default => nil, :banner => method_option "git", :type => :string, :default => nil, :banner =>
"URL of the git repo to fetch from" "URL of the git repo to fetch from"
method_option "local_git", :type => :string, :default => nil, :banner =>
"Path of the local git repo to fetch from"
method_option "branch", :type => :string, :default => nil, :banner => method_option "branch", :type => :string, :default => nil, :banner =>
"The git branch to checkout" "The git branch to checkout"
method_option "ref", :type => :string, :default => nil, :banner => method_option "ref", :type => :string, :default => nil, :banner =>
@ -20,5 +22,10 @@ module Bundler
def install(*plugins) def install(*plugins)
Bundler::Plugin.install(plugins, options) Bundler::Plugin.install(plugins, options)
end end
desc "list", "List the installed plugins and available commands"
def list
Bundler::Plugin.list
end
end end
end end

View file

@ -33,7 +33,7 @@ module Bundler
if extension_cache_path = source.extension_cache_path(spec) if extension_cache_path = source.extension_cache_path(spec)
FileUtils.rm_rf extension_cache_path FileUtils.rm_rf extension_cache_path
end end
FileUtils.rm_rf spec.extension_dir if spec.respond_to?(:extension_dir) FileUtils.rm_rf spec.extension_dir
FileUtils.rm_rf spec.full_gem_path FileUtils.rm_rf spec.full_gem_path
else else
Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.") Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.")

View file

@ -24,7 +24,7 @@ module Bundler
return unless spec return unless spec
path = spec.full_gem_path path = spec.full_gem_path
unless File.directory?(path) unless File.directory?(path)
Bundler.ui.warn "The gem #{gem_name} has been deleted. It was installed at:" return Bundler.ui.warn "The gem #{gem_name} has been deleted. It was installed at: #{path}"
end end
end end
return Bundler.ui.info(path) return Bundler.ui.info(path)

View file

@ -22,7 +22,7 @@ module Bundler
if Bundler.feature_flag.update_requires_all_flag? if Bundler.feature_flag.update_requires_all_flag?
raise InvalidOption, "To update everything, pass the `--all` flag." raise InvalidOption, "To update everything, pass the `--all` flag."
end end
SharedHelpers.major_deprecation 3, "Pass --all to `bundle update` to update everything" SharedHelpers.major_deprecation 2, "Pass --all to `bundle update` to update everything"
elsif !full_update && options[:all] elsif !full_update && options[:all]
raise InvalidOption, "Cannot specify --all along with specific options." raise InvalidOption, "Cannot specify --all along with specific options."
end end

View file

@ -18,11 +18,6 @@ module Bundler
attr_reader :directory attr_reader :directory
# @return [Lambda] A lambda that takes an array of inputs and a block, and
# maps the inputs with the block in parallel.
#
attr_accessor :in_parallel
def initialize(directory, fetcher) def initialize(directory, fetcher)
@directory = Pathname.new(directory) @directory = Pathname.new(directory)
@updater = Updater.new(fetcher) @updater = Updater.new(fetcher)
@ -31,7 +26,28 @@ module Bundler
@info_checksums_by_name = {} @info_checksums_by_name = {}
@parsed_checksums = false @parsed_checksums = false
@mutex = Mutex.new @mutex = Mutex.new
@in_parallel = lambda do |inputs, &blk| end
def execution_mode=(block)
Bundler::CompactIndexClient.debug { "execution_mode=" }
@endpoints = Set.new
@execution_mode = block
end
# @return [Lambda] A lambda that takes an array of inputs and a block, and
# maps the inputs with the block in parallel.
#
def execution_mode
@execution_mode || sequentially
end
def sequential_execution_mode!
self.execution_mode = sequentially
end
def sequentially
@sequentially ||= lambda do |inputs, &blk|
inputs.map(&blk) inputs.map(&blk)
end end
end end
@ -51,7 +67,7 @@ module Bundler
def dependencies(names) def dependencies(names)
Bundler::CompactIndexClient.debug { "dependencies(#{names})" } Bundler::CompactIndexClient.debug { "dependencies(#{names})" }
in_parallel.call(names) do |name| execution_mode.call(names) do |name|
update_info(name) update_info(name)
@cache.dependencies(name).map {|d| d.unshift(name) } @cache.dependencies(name).map {|d| d.unshift(name) }
end.flatten(1) end.flatten(1)

View file

@ -95,11 +95,7 @@ module Bundler
end end
def slice_body(body, range) def slice_body(body, range)
if body.respond_to?(:byteslice) body.byteslice(range)
body.byteslice(range)
else # pre-1.9.3
body.unpack("@#{range.first}a#{range.end + 1}").first
end
end end
def checksum_for_file(path) def checksum_for_file(path)

View file

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

View file

@ -331,7 +331,7 @@ module Bundler
# i.e., Windows with `git config core.autocrlf=true` # i.e., Windows with `git config core.autocrlf=true`
contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match("\r\n") contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match("\r\n")
if @locked_bundler_version && Bundler.feature_flag.lockfile_upgrade_warning? if @locked_bundler_version
locked_major = @locked_bundler_version.segments.first locked_major = @locked_bundler_version.segments.first
current_major = Gem::Version.create(Bundler::VERSION).segments.first current_major = Gem::Version.create(Bundler::VERSION).segments.first
@ -397,9 +397,9 @@ module Bundler
unless explicit_flag unless explicit_flag
suggested_command = if Bundler.settings.locations("frozen")[:global] suggested_command = if Bundler.settings.locations("frozen")[:global]
"bundle config --delete frozen" "bundle config unset frozen"
elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any? elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any?
"bundle config --delete deployment" "bundle config unset deployment"
else else
"bundle install --no-deployment" "bundle install --no-deployment"
end end
@ -643,7 +643,7 @@ module Bundler
end end
def converge_rubygems_sources def converge_rubygems_sources
return false if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? return false if Bundler.feature_flag.disable_multisource?
changes = false changes = false
@ -855,8 +855,8 @@ module Bundler
concat_ruby_version_requirements(locked_ruby_version_object) unless @unlock[:ruby] concat_ruby_version_requirements(locked_ruby_version_object) unless @unlock[:ruby]
end end
[ [
Dependency.new("ruby\0", ruby_versions), Dependency.new("Ruby\0", ruby_versions),
Dependency.new("rubygems\0", Gem::VERSION), Dependency.new("RubyGems\0", Gem::VERSION),
] ]
end end
end end
@ -915,7 +915,7 @@ module Bundler
# look for that gemspec (or its dependencies) # look for that gemspec (or its dependencies)
default = sources.default_source default = sources.default_source
source_requirements = { :default => default } source_requirements = { :default => default }
default = nil unless Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? default = nil unless Bundler.feature_flag.disable_multisource?
dependencies.each do |dep| dependencies.each do |dep|
next unless source = dep.source || default next unless source = dep.source || default
source_requirements[dep.name] = source source_requirements[dep.name] = source
@ -929,7 +929,7 @@ module Bundler
def pinned_spec_names(skip = nil) def pinned_spec_names(skip = nil)
pinned_names = [] pinned_names = []
default = Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? && sources.default_source default = Bundler.feature_flag.disable_multisource? && sources.default_source
@dependencies.each do |dep| @dependencies.each do |dep|
next unless dep_source = dep.source || default next unless dep_source = dep.source || default
next if dep_source == skip next if dep_source == skip
@ -977,7 +977,9 @@ module Bundler
dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) } dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
@locked_gems.specs.reduce({}) do |requirements, locked_spec| @locked_gems.specs.reduce({}) do |requirements, locked_spec|
name = locked_spec.name name = locked_spec.name
next requirements if @locked_gems.dependencies[name] != dependencies_by_name[name] dependency = dependencies_by_name[name]
next requirements if @locked_gems.dependencies[name] != dependency
next requirements if dependency && dependency.source.is_a?(Source::Path)
dep = Gem::Dependency.new(name, ">= #{locked_spec.version}") dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
requirements[name] = DepProxy.new(dep, locked_spec.platform) requirements[name] = DepProxy.new(dep, locked_spec.platform)
requirements requirements

View file

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

View file

@ -45,7 +45,7 @@ module Bundler
@gemfiles << expanded_gemfile_path @gemfiles << expanded_gemfile_path
contents ||= Bundler.read_file(@gemfile.to_s) contents ||= Bundler.read_file(@gemfile.to_s)
instance_eval(contents.dup.untaint, gemfile.to_s, 1) instance_eval(contents.dup.untaint, gemfile.to_s, 1)
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
message = "There was an error " \ message = "There was an error " \
"#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \ "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
"`#{File.basename gemfile.to_s}`: #{e.message}" "`#{File.basename gemfile.to_s}`: #{e.message}"
@ -194,7 +194,7 @@ module Bundler
" end\n\n" " end\n\n"
raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource? raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource?
SharedHelpers.major_deprecation(3, msg.strip) SharedHelpers.major_deprecation(2, msg.strip)
end end
source_options = normalize_hash(options).merge( source_options = normalize_hash(options).merge(
@ -290,37 +290,21 @@ module Bundler
warn_deprecated_git_source(:github, <<-'RUBY'.strip, 'Change any "reponame" :github sources to "username/reponame".') warn_deprecated_git_source(:github, <<-'RUBY'.strip, 'Change any "reponame" :github sources to "username/reponame".')
"https://github.com/#{repo_name}.git" "https://github.com/#{repo_name}.git"
RUBY 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
# does not guarantee compatibility with the 1.x series.
#
# See https://github.com/bundler/bundler/pull/2569 for discussion
#
# This can be overridden by adding this code to your Gemfiles:
#
# git_source(:github) do |repo_name|
# repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
# "https://github.com/#{repo_name}.git"
# end
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
# TODO: 2.0 upgrade this setting to the default if Bundler.feature_flag.github_https?
if Bundler.settings["github.https"]
Bundler::SharedHelpers.major_deprecation 3, "The `github.https` setting will be removed"
"https://github.com/#{repo_name}.git" "https://github.com/#{repo_name}.git"
else else
Bundler::SharedHelpers.major_deprecation 2, "Setting `github.https` to false is deprecated and won't be supported in the future."
"git://github.com/#{repo_name}.git" "git://github.com/#{repo_name}.git"
end end
end end
# TODO: 2.0 remove this deprecated git source
git_source(:gist) do |repo_name| 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" "https://gist.github.com/#{repo_name}.git"
end end
# TODO: 2.0 remove this deprecated git source
git_source(:bitbucket) do |repo_name| git_source(:bitbucket) do |repo_name|
warn_deprecated_git_source(:bitbucket, <<-'RUBY'.strip) warn_deprecated_git_source(:bitbucket, <<-'RUBY'.strip)
user_name, repo_name = repo_name.split("/") user_name, repo_name = repo_name.split("/")
@ -363,9 +347,7 @@ repo_name ||= user_name
if name =~ /\s/ if name =~ /\s/
raise GemfileError, %('#{name}' is not a valid gem name because it contains whitespace) raise GemfileError, %('#{name}' is not a valid gem name because it contains whitespace)
end end
if name.empty? raise GemfileError, %(an empty gem name is not valid) if name.empty?
raise GemfileError, %(an empty gem name is not valid)
end
normalize_hash(opts) normalize_hash(opts)
@ -443,10 +425,10 @@ repo_name ||= user_name
message = String.new message = String.new
message << "You passed #{invalid_keys.map {|k| ":" + k }.join(", ")} " message << "You passed #{invalid_keys.map {|k| ":" + k }.join(", ")} "
message << if invalid_keys.size > 1 message << if invalid_keys.size > 1
"as options for #{command}, but they are invalid." "as options for #{command}, but they are invalid."
else else
"as an option for #{command}, but it is invalid." "as an option for #{command}, but it is invalid."
end end
message << " Valid options are: #{valid_keys.join(", ")}." message << " Valid options are: #{valid_keys.join(", ")}."
message << " You may be able to resolve this by upgrading Bundler to the newest version." message << " You may be able to resolve this by upgrading Bundler to the newest version."
@ -456,7 +438,7 @@ repo_name ||= user_name
def normalize_source(source) def normalize_source(source)
case source case source
when :gemcutter, :rubygems, :rubyforge when :gemcutter, :rubygems, :rubyforge
Bundler::SharedHelpers.major_deprecation 3, "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://" \ "requests are insecure.\nPlease change your source to 'https://" \
"rubygems.org' if possible, or 'http://rubygems.org' if not." "rubygems.org' if possible, or 'http://rubygems.org' if not."
"http://rubygems.org" "http://rubygems.org"
@ -474,23 +456,22 @@ repo_name ||= user_name
msg = "This Gemfile contains multiple primary sources. " \ msg = "This Gemfile contains multiple primary sources. " \
"Each source after the first must include a block to indicate which gems " \ "Each source after the first must include a block to indicate which gems " \
"should come from that source" "should come from that source"
unless Bundler.feature_flag.bundler_3_mode? unless Bundler.feature_flag.bundler_2_mode?
msg += ". To downgrade this error to a warning, run " \ msg += ". To downgrade this error to a warning, run " \
"`bundle config --delete disable_multisource`" "`bundle config unset disable_multisource`"
end end
raise GemfileEvalError, msg raise GemfileEvalError, msg
else else
Bundler::SharedHelpers.major_deprecation 3, "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 " \ "Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \ "may result in installing unexpected gems. To resolve this warning, use " \
"a block to indicate which gems should come from the secondary source. " \ "a block to indicate which gems should come from the secondary source. " \
"To upgrade this warning to an error, run `bundle config " \ "To upgrade this warning to an error, run `bundle config set " \
"disable_multisource true`." "disable_multisource true`."
end end
end end
def warn_deprecated_git_source(name, replacement, additional_message = nil) def warn_deprecated_git_source(name, replacement, additional_message = nil)
# TODO: 2.0 remove deprecation
additional_message &&= " #{additional_message}" additional_message &&= " #{additional_message}"
replacement = if replacement.count("\n").zero? replacement = if replacement.count("\n").zero?
"{|repo_name| #{replacement} }" "{|repo_name| #{replacement} }"
@ -499,7 +480,7 @@ repo_name ||= user_name
end end
Bundler::SharedHelpers.major_deprecation 3, <<-EOS Bundler::SharedHelpers.major_deprecation 3, <<-EOS
The :#{name} git source is deprecated, and will be removed in Bundler 3.0.#{additional_message} Add this code to the top of your Gemfile to ensure it continues to work: The :#{name} git source is deprecated, and will be removed in the future.#{additional_message} Add this code to the top of your Gemfile to ensure it continues to work:
git_source(:#{name}) #{replacement} git_source(:#{name}) #{replacement}
@ -601,7 +582,7 @@ The :#{name} git source is deprecated, and will be removed in Bundler 3.0.#{addi
description = self.description description = self.description
if dsl_path && description =~ /((#{Regexp.quote File.expand_path(dsl_path)}|#{Regexp.quote dsl_path.to_s}):\d+)/ if dsl_path && description =~ /((#{Regexp.quote File.expand_path(dsl_path)}|#{Regexp.quote dsl_path.to_s}):\d+)/
trace_line = Regexp.last_match[1] trace_line = Regexp.last_match[1]
description = description.sub(/#{Regexp.quote trace_line}:\s*/, "").sub("\n", " - ") description = description.sub(/\n.*\n(\.\.\.)? *\^~+$/, "").sub(/#{Regexp.quote trace_line}:\s*/, "").sub("\n", " - ")
end end
[trace_line, description] [trace_line, description]
end end

View file

@ -70,14 +70,8 @@ module Bundler
def self.ruby_version def self.ruby_version
str = String.new("#{RUBY_VERSION}") str = String.new("#{RUBY_VERSION}")
if RUBY_VERSION < "1.9" str << "p#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
str << " (#{RUBY_RELEASE_DATE}" str << " (#{RUBY_RELEASE_DATE} revision #{RUBY_REVISION}) [#{RUBY_PLATFORM}]"
str << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
str << ") [#{RUBY_PLATFORM}]"
else
str << "p#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
str << " (#{RUBY_RELEASE_DATE} revision #{RUBY_REVISION}) [#{RUBY_PLATFORM}]"
end
end end
def self.git_version def self.git_version

View file

@ -19,7 +19,7 @@ module Bundler
def self.settings_method(name, key, &default) def self.settings_method(name, key, &default)
define_method(name) do define_method(name) do
value = Bundler.settings[key] value = Bundler.settings[key]
value = instance_eval(&default) if value.nil? && !default.nil? value = instance_eval(&default) if value.nil?
value value
end end
end end
@ -33,7 +33,6 @@ module Bundler
settings_flag(:auto_config_jobs) { bundler_3_mode? } settings_flag(:auto_config_jobs) { bundler_3_mode? }
settings_flag(:cache_all) { bundler_3_mode? } settings_flag(:cache_all) { bundler_3_mode? }
settings_flag(:cache_command_is_package) { bundler_3_mode? } settings_flag(:cache_command_is_package) { bundler_3_mode? }
settings_flag(:console_command) { !bundler_3_mode? }
settings_flag(:default_install_uses_path) { bundler_3_mode? } settings_flag(:default_install_uses_path) { bundler_3_mode? }
settings_flag(:deployment_means_frozen) { bundler_3_mode? } settings_flag(:deployment_means_frozen) { bundler_3_mode? }
settings_flag(:disable_multisource) { bundler_3_mode? } settings_flag(:disable_multisource) { bundler_3_mode? }
@ -41,23 +40,17 @@ module Bundler
settings_flag(:forget_cli_options) { bundler_3_mode? } settings_flag(:forget_cli_options) { bundler_3_mode? }
settings_flag(:global_path_appends_ruby_scope) { bundler_3_mode? } settings_flag(:global_path_appends_ruby_scope) { bundler_3_mode? }
settings_flag(:global_gem_cache) { bundler_3_mode? } settings_flag(:global_gem_cache) { bundler_3_mode? }
settings_flag(:init_gems_rb) { bundler_3_mode? }
settings_flag(:list_command) { bundler_3_mode? }
settings_flag(:lockfile_uses_separate_rubygems_sources) { bundler_3_mode? }
settings_flag(:lockfile_upgrade_warning) { bundler_3_mode? }
settings_flag(:only_update_to_newer_versions) { bundler_3_mode? } settings_flag(:only_update_to_newer_versions) { bundler_3_mode? }
settings_flag(:path_relative_to_cwd) { bundler_3_mode? } settings_flag(:path_relative_to_cwd) { bundler_3_mode? }
settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") } settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") }
settings_flag(:prefer_gems_rb) { bundler_3_mode? }
settings_flag(:print_only_version_number) { bundler_3_mode? } settings_flag(:print_only_version_number) { bundler_3_mode? }
settings_flag(:setup_makes_kernel_gem_public) { !bundler_3_mode? } settings_flag(:setup_makes_kernel_gem_public) { !bundler_3_mode? }
settings_flag(:skip_default_git_sources) { bundler_3_mode? } settings_flag(:skip_default_git_sources) { bundler_4_mode? }
settings_flag(:specific_platform) { bundler_3_mode? } settings_flag(:specific_platform) { bundler_3_mode? }
settings_flag(:suppress_install_using_messages) { bundler_3_mode? } settings_flag(:suppress_install_using_messages) { bundler_3_mode? }
settings_flag(:unlock_source_unlocks_spec) { !bundler_3_mode? } settings_flag(:unlock_source_unlocks_spec) { !bundler_3_mode? }
settings_flag(:update_requires_all_flag) { bundler_3_mode? } settings_flag(:update_requires_all_flag) { bundler_3_mode? }
settings_flag(:use_gem_version_promoter_for_major_updates) { bundler_3_mode? } settings_flag(:use_gem_version_promoter_for_major_updates) { bundler_3_mode? }
settings_flag(:viz_command) { !bundler_3_mode? }
settings_option(:default_cli_command) { bundler_3_mode? ? :cli_help : :install } settings_option(:default_cli_command) { bundler_3_mode? ? :cli_help : :install }

View file

@ -4,6 +4,7 @@ require "bundler/vendored_persistent"
require "cgi" require "cgi"
require "securerandom" require "securerandom"
require "zlib" require "zlib"
require "rubygems/request"
module Bundler module Bundler
# Handles all the fetching with the rubygems server # Handles all the fetching with the rubygems server
@ -15,6 +16,8 @@ module Bundler
# This error is raised when it looks like the network is down # This error is raised when it looks like the network is down
class NetworkDownError < HTTPError; end class NetworkDownError < HTTPError; end
# This error is raised if we should rate limit our requests to the API
class TooManyRequestsError < HTTPError; end
# This error is raised if the API returns a 413 (only printed in verbose) # This error is raised if the API returns a 413 (only printed in verbose)
class FallbackError < HTTPError; end class FallbackError < HTTPError; end
# This is the error raised if OpenSSL fails the cert verification # This is the error raised if OpenSSL fails the cert verification
@ -44,7 +47,7 @@ module Bundler
remote_uri = filter_uri(remote_uri) remote_uri = filter_uri(remote_uri)
super "Authentication is required for #{remote_uri}.\n" \ super "Authentication is required for #{remote_uri}.\n" \
"Please supply credentials for this source. You can do this by running:\n" \ "Please supply credentials for this source. You can do this by running:\n" \
" bundle config #{remote_uri} username:password" " bundle config set #{remote_uri} username:password"
end end
end end
# This error is raised if HTTP authentication is provided, but incorrect. # This error is raised if HTTP authentication is provided, but incorrect.
@ -226,7 +229,7 @@ module Bundler
"GO_SERVER_URL" => "go", "GO_SERVER_URL" => "go",
"SNAP_CI" => "snap", "SNAP_CI" => "snap",
"CI_NAME" => ENV["CI_NAME"], "CI_NAME" => ENV["CI_NAME"],
"CI" => "ci" "CI" => "ci",
} }
env_cis.find_all {|env, _| ENV[env] }.map {|_, ci| ci } env_cis.find_all {|env, _| ENV[env] }.map {|_, ci| ci }
end end
@ -293,8 +296,7 @@ module Bundler
end end
else else
store.set_default_paths store.set_default_paths
certs = File.expand_path("../ssl_certs/*/*.pem", __FILE__) Gem::Request.get_cert_files.each {|c| store.add_file c }
Dir.glob(certs).each {|c| store.add_file c }
end end
store store
end end

View file

@ -39,7 +39,13 @@ module Bundler
until remaining_gems.empty? until remaining_gems.empty?
log_specs "Looking up gems #{remaining_gems.inspect}" log_specs "Looking up gems #{remaining_gems.inspect}"
deps = compact_index_client.dependencies(remaining_gems) deps = begin
parallel_compact_index_client.dependencies(remaining_gems)
rescue TooManyRequestsError
@bundle_worker.stop if @bundle_worker
@bundle_worker = nil # reset it. Not sure if necessary
serial_compact_index_client.dependencies(remaining_gems)
end
next_gems = deps.map {|d| d[3].map(&:first).flatten(1) }.flatten(1).uniq next_gems = deps.map {|d| d[3].map(&:first).flatten(1) }.flatten(1).uniq
deps.each {|dep| gem_info << dep } deps.each {|dep| gem_info << dep }
complete_gems.concat(deps.map(&:first)).uniq! complete_gems.concat(deps.map(&:first)).uniq!
@ -80,18 +86,26 @@ module Bundler
private private
def compact_index_client def compact_index_client
@compact_index_client ||= begin @compact_index_client ||=
SharedHelpers.filesystem_access(cache_path) do SharedHelpers.filesystem_access(cache_path) do
CompactIndexClient.new(cache_path, client_fetcher) CompactIndexClient.new(cache_path, client_fetcher)
end.tap do |client|
client.in_parallel = lambda do |inputs, &blk|
func = lambda {|object, _index| blk.call(object) }
worker = bundle_worker(func)
inputs.each {|input| worker.enq(input) }
inputs.map { worker.deq }
end
end end
end
def parallel_compact_index_client
compact_index_client.execution_mode = lambda do |inputs, &blk|
func = lambda {|object, _index| blk.call(object) }
worker = bundle_worker(func)
inputs.each {|input| worker.enq(input) }
inputs.map { worker.deq }
end end
compact_index_client
end
def serial_compact_index_client
compact_index_client.sequential_execution_mode!
compact_index_client
end end
def bundle_worker(func = nil) def bundle_worker(func = nil)

View file

@ -34,10 +34,12 @@ module Bundler
fetch(uri, new_headers) fetch(uri, new_headers)
when Net::HTTPRequestEntityTooLarge when Net::HTTPRequestEntityTooLarge
raise FallbackError, response.body raise FallbackError, response.body
when Net::HTTPTooManyRequests
raise TooManyRequestsError, response.body
when Net::HTTPUnauthorized when Net::HTTPUnauthorized
raise AuthenticationRequiredError, uri.host raise AuthenticationRequiredError, uri.host
when Net::HTTPNotFound when Net::HTTPNotFound
raise FallbackError, "Net::HTTPNotFound" raise FallbackError, "Net::HTTPNotFound: #{URICredentialsFilter.credential_filtered_uri(uri)}"
else else
raise HTTPError, "#{response.class}#{": #{response.body}" unless response.body.empty?}" raise HTTPError, "#{response.class}#{": #{response.body}" unless response.body.empty?}"
end end

View file

@ -1,4 +1,3 @@
# encoding: utf-8
# frozen_string_literal: true # frozen_string_literal: true
require "cgi" require "cgi"
@ -45,7 +44,7 @@ module Bundler
"Alternatively, you can increase the amount of memory the JVM is able to use by running Bundler with jruby -J-Xmx1024m -S bundle (JRuby defaults to 500MB)." "Alternatively, you can increase the amount of memory the JVM is able to use by running Bundler with jruby -J-Xmx1024m -S bundle (JRuby defaults to 500MB)."
else request_issue_report_for(error) else request_issue_report_for(error)
end end
rescue rescue StandardError
raise error raise error
end end
@ -124,7 +123,7 @@ module Bundler
yield yield
rescue SignalException rescue SignalException
raise raise
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
FriendlyErrors.log_error(e) FriendlyErrors.log_error(e)
exit FriendlyErrors.exit_status(e) exit FriendlyErrors.exit_status(e)
end end

View file

@ -2,6 +2,7 @@
require "bundler/vendored_thor" unless defined?(Thor) require "bundler/vendored_thor" unless defined?(Thor)
require "bundler" require "bundler"
require "shellwords"
module Bundler module Bundler
class GemHelper class GemHelper
@ -75,7 +76,7 @@ module Bundler
def build_gem def build_gem
file_name = nil file_name = nil
gem = ENV["BUNDLE_GEM"] ? ENV["BUNDLE_GEM"] : "gem" gem = ENV["BUNDLE_GEM"] ? ENV["BUNDLE_GEM"] : "gem"
sh("#{gem} build -V '#{spec_path}'") do sh(%W[#{gem} build -V #{spec_path}]) do
file_name = File.basename(built_gem_path) file_name = File.basename(built_gem_path)
SharedHelpers.filesystem_access(File.join(base, "pkg")) {|p| FileUtils.mkdir_p(p) } SharedHelpers.filesystem_access(File.join(base, "pkg")) {|p| FileUtils.mkdir_p(p) }
FileUtils.mv(built_gem_path, "pkg") FileUtils.mv(built_gem_path, "pkg")
@ -87,17 +88,21 @@ module Bundler
def install_gem(built_gem_path = nil, local = false) def install_gem(built_gem_path = nil, local = false)
built_gem_path ||= build_gem built_gem_path ||= build_gem
gem = ENV["BUNDLE_GEM"] ? ENV["BUNDLE_GEM"] : "gem" gem = ENV["BUNDLE_GEM"] ? ENV["BUNDLE_GEM"] : "gem"
out, _ = sh_with_code("#{gem} install '#{built_gem_path}'#{" --local" if local}") cmd = %W[#{gem} install #{built_gem_path}]
raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output" unless out[/Successfully installed/] cmd << "--local" if local
out, status = sh_with_status(cmd)
unless status.success? && out[/Successfully installed/]
raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output"
end
Bundler.ui.confirm "#{name} (#{version}) installed." Bundler.ui.confirm "#{name} (#{version}) installed."
end end
protected protected
def rubygem_push(path) def rubygem_push(path)
gem_command = "gem push '#{path}'" gem_command = %W[gem push #{path}]
gem_command += " --key #{gem_key}" if gem_key gem_command << "--key" << gem_key if gem_key
gem_command += " --host #{allowed_push_host}" if allowed_push_host gem_command << "--host" << allowed_push_host if allowed_push_host
unless allowed_push_host || Bundler.user_home.join(".gem/credentials").file? 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." raise "Your rubygems.org credentials aren't set. Run `gem push` to set them."
end end
@ -129,12 +134,14 @@ module Bundler
def perform_git_push(options = "") def perform_git_push(options = "")
cmd = "git push #{options}" cmd = "git push #{options}"
out, code = sh_with_code(cmd) out, status = sh_with_status(cmd)
raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n" unless code == 0 return if status.success?
cmd = cmd.shelljoin if cmd.respond_to?(:shelljoin)
raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n"
end end
def already_tagged? def already_tagged?
return false unless sh("git tag").split(/\n/).include?(version_tag) return false unless sh(%w[git tag]).split(/\n/).include?(version_tag)
Bundler.ui.confirm "Tag #{version_tag} has already been created." Bundler.ui.confirm "Tag #{version_tag} has already been created."
true true
end end
@ -144,20 +151,20 @@ module Bundler
end end
def clean? def clean?
sh_with_code("git diff --exit-code")[1] == 0 sh_with_status(%w[git diff --exit-code])[1].success?
end end
def committed? def committed?
sh_with_code("git diff-index --quiet --cached HEAD")[1] == 0 sh_with_status(%w[git diff-index --quiet --cached HEAD])[1].success?
end end
def tag_version def tag_version
sh "git tag -m \"Version #{version}\" #{version_tag}" sh %W[git tag -m Version\ #{version} #{version_tag}]
Bundler.ui.confirm "Tagged #{version_tag}." Bundler.ui.confirm "Tagged #{version_tag}."
yield if block_given? yield if block_given?
rescue RuntimeError rescue RuntimeError
Bundler.ui.error "Untagging #{version_tag} due to error." Bundler.ui.error "Untagging #{version_tag} due to error."
sh_with_code "git tag -d #{version_tag}" sh_with_status %W[git tag -d #{version_tag}]
raise raise
end end
@ -174,21 +181,20 @@ module Bundler
end end
def sh(cmd, &block) def sh(cmd, &block)
out, code = sh_with_code(cmd, &block) out, status = sh_with_status(cmd, &block)
unless code.zero? unless status.success?
cmd = cmd.shelljoin if cmd.respond_to?(:shelljoin)
raise(out.empty? ? "Running `#{cmd}` failed. Run this command directly for more detailed output." : out) raise(out.empty? ? "Running `#{cmd}` failed. Run this command directly for more detailed output." : out)
end end
out out
end end
def sh_with_code(cmd, &block) def sh_with_status(cmd, &block)
cmd += " 2>&1"
outbuf = String.new
Bundler.ui.debug(cmd) Bundler.ui.debug(cmd)
SharedHelpers.chdir(base) do SharedHelpers.chdir(base) do
outbuf = `#{cmd}` outbuf = IO.popen(cmd, :err => [:child, :out], &:read)
status = $?.exitstatus status = $?
block.call(outbuf) if status.zero? && block block.call(outbuf) if status.success? && block
[outbuf, status] [outbuf, status]
end end
end end

View file

@ -10,7 +10,7 @@ module Bundler
[Gem::Platform.new("universal-mingw32"), Gem::Platform.new("universal-mingw32")], [Gem::Platform.new("universal-mingw32"), Gem::Platform.new("universal-mingw32")],
[Gem::Platform.new("x64-mingw32"), Gem::Platform.new("x64-mingw32")], [Gem::Platform.new("x64-mingw32"), Gem::Platform.new("x64-mingw32")],
[Gem::Platform.new("x86_64-mingw32"), Gem::Platform.new("x64-mingw32")], [Gem::Platform.new("x86_64-mingw32"), Gem::Platform.new("x64-mingw32")],
[Gem::Platform.new("mingw32"), Gem::Platform.new("x86-mingw32")] [Gem::Platform.new("mingw32"), Gem::Platform.new("x86-mingw32")],
].freeze ].freeze
def generic(p) def generic(p)

View file

@ -109,7 +109,7 @@ module Bundler
must_match = minor? ? [0] : [0, 1] must_match = minor? ? [0] : [0, 1]
matches = must_match.map {|idx| gsv.segments[idx] == lsv.segments[idx] } matches = must_match.map {|idx| gsv.segments[idx] == lsv.segments[idx] }
(matches.uniq == [true]) ? (gsv >= lsv) : false matches.uniq == [true] ? (gsv >= lsv) : false
else else
true true
end end

View file

@ -117,7 +117,7 @@ module Bundler
:style => "filled", :style => "filled",
:fillcolor => "#B9B9D5", :fillcolor => "#B9B9D5",
:shape => "box3d", :shape => "box3d",
:fontsize => 16 :fontsize => 16,
}.merge(@node_options[group]) }.merge(@node_options[group])
) )
end end
@ -142,7 +142,7 @@ module Bundler
g.output @output_format.to_sym => "#{@output_file}.#{@output_format}" g.output @output_format.to_sym => "#{@output_file}.#{@output_format}"
Bundler.ui.info "#{@output_file}.#{@output_format}" Bundler.ui.info "#{@output_file}.#{@output_format}"
rescue ArgumentError => e rescue ArgumentError => e
$stderr.puts "Unsupported output format. See Ruby-Graphviz/lib/graphviz/constants.rb" warn "Unsupported output format. See Ruby-Graphviz/lib/graphviz/constants.rb"
raise e raise e
end end
end end

View file

@ -123,7 +123,7 @@ module Bundler
end end
end end
# evalutes a gemfile to remove the specified gem # evaluates a gemfile to remove the specified gem
# from it. # from it.
def remove_deps(gemfile_path) def remove_deps(gemfile_path)
initial_gemfile = IO.readlines(gemfile_path) initial_gemfile = IO.readlines(gemfile_path)
@ -136,8 +136,8 @@ module Bundler
removed_deps = remove_gems_from_dependencies(builder, @deps, gemfile_path) removed_deps = remove_gems_from_dependencies(builder, @deps, gemfile_path)
# abort the opertion if no gems were removed # abort the operation if no gems were removed
# no need to operate on gemfile furthur # no need to operate on gemfile further
return [] if removed_deps.empty? return [] if removed_deps.empty?
cleaned_gemfile = remove_gems_from_gemfile(@deps, gemfile_path) cleaned_gemfile = remove_gems_from_gemfile(@deps, gemfile_path)
@ -153,8 +153,8 @@ module Bundler
# @param [Dsl] builder Dsl object of current Gemfile. # @param [Dsl] builder Dsl object of current Gemfile.
# @param [Array] gems Array of names of gems to be removed. # @param [Array] gems Array of names of gems to be removed.
# @param [Pathname] path of the Gemfile # @param [Pathname] gemfile_path Path of the Gemfile.
# @return [Array] removed_deps Array of removed dependencies. # @return [Array] Array of removed dependencies.
def remove_gems_from_dependencies(builder, gems, gemfile_path) def remove_gems_from_dependencies(builder, gems, gemfile_path)
removed_deps = [] removed_deps = []
@ -206,7 +206,7 @@ module Bundler
nested_blocks -= 1 nested_blocks -= 1
gemfile.each_with_index do |line, index| gemfile.each_with_index do |line, index|
next unless !line.nil? && line.include?(block_name) next unless !line.nil? && line.strip.start_with?(block_name)
if gemfile[index + 1] =~ /^\s*end\s*$/ if gemfile[index + 1] =~ /^\s*end\s*$/
gemfile[index] = nil gemfile[index] = nil
gemfile[index + 1] = nil gemfile[index + 1] = nil
@ -222,7 +222,7 @@ module Bundler
# @param [Array] removed_deps Array of removed dependencies. # @param [Array] removed_deps Array of removed dependencies.
# @param [Array] initial_gemfile Contents of original Gemfile before any operation. # @param [Array] initial_gemfile Contents of original Gemfile before any operation.
def cross_check_for_errors(gemfile_path, original_deps, removed_deps, initial_gemfile) def cross_check_for_errors(gemfile_path, original_deps, removed_deps, initial_gemfile)
# evalute the new gemfile to look for any failure cases # evaluate the new gemfile to look for any failure cases
builder = Dsl.new builder = Dsl.new
builder.eval_gemfile(gemfile_path) builder.eval_gemfile(gemfile_path)

View file

@ -36,6 +36,7 @@ def gemfile(install = false, options = {}, &gemfile)
opts = options.dup opts = options.dup
ui = opts.delete(:ui) { Bundler::UI::Shell.new } ui = opts.delete(:ui) { Bundler::UI::Shell.new }
ui.level = "silent" if opts.delete(:quiet)
raise ArgumentError, "Unknown options: #{opts.keys.join(", ")}" unless opts.empty? raise ArgumentError, "Unknown options: #{opts.keys.join(", ")}" unless opts.empty?
old_root = Bundler.method(:root) old_root = Bundler.method(:root)

View file

@ -221,7 +221,7 @@ module Bundler
def processor_count def processor_count
require "etc" require "etc"
Etc.nprocessors Etc.nprocessors
rescue rescue StandardError
1 1
end end
@ -275,14 +275,7 @@ module Bundler
end end
def can_install_in_parallel? def can_install_in_parallel?
if Bundler.rubygems.provides?(">= 2.1.0") true
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 " \
"or higher to enable parallel gem installation."
false
end
end end
def install_in_parallel(size, standalone, force = false) def install_in_parallel(size, standalone, force = false)

View file

@ -1,5 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "shellwords"
module Bundler module Bundler
class GemInstaller class GemInstaller
attr_reader :spec, :standalone, :worker, :force, :installer attr_reader :spec, :standalone, :worker, :force, :installer
@ -56,7 +58,9 @@ module Bundler
def spec_settings def spec_settings
# Fetch the build settings, if there are any # Fetch the build settings, if there are any
Bundler.settings["build.#{spec.name}"] if settings = Bundler.settings["build.#{spec.name}"]
Shellwords.shellsplit(settings)
end
end end
def install def install

View file

@ -91,10 +91,6 @@ module Bundler
end end
def call def call
# Since `autoload` has the potential for threading issues on 1.8.7
# TODO: remove in bundler 2.0
require "bundler/gem_remote_fetcher" if RUBY_VERSION < "1.9"
check_for_corrupt_lockfile check_for_corrupt_lockfile
if @size > 1 if @size > 1
@ -115,7 +111,7 @@ module Bundler
s, s,
s.missing_lockfile_dependencies(@specs.map(&:name)), s.missing_lockfile_dependencies(@specs.map(&:name)),
] ]
end.reject { |a| a.last.empty? } end.reject {|a| a.last.empty? }
return if missing_dependencies.empty? return if missing_dependencies.empty?
warning = [] warning = []
@ -150,7 +146,7 @@ module Bundler
end end
def worker_pool def worker_pool
@worker_pool ||= Bundler::Worker.new @size, "Parallel Installer", lambda { |spec_install, worker_num| @worker_pool ||= Bundler::Worker.new @size, "Parallel Installer", lambda {|spec_install, worker_num|
do_install(spec_install, worker_num) do_install(spec_install, worker_num)
} }
end end

View file

@ -77,7 +77,7 @@ module Bundler
if search && Gem::Platform.new(search.platform) != Gem::Platform.new(platform) && !search.runtime_dependencies.-(dependencies.reject {|d| d.type == :development }).empty? if search && Gem::Platform.new(search.platform) != Gem::Platform.new(platform) && !search.runtime_dependencies.-(dependencies.reject {|d| d.type == :development }).empty?
Bundler.ui.warn "Unable to use the platform-specific (#{search.platform}) version of #{name} (#{version}) " \ Bundler.ui.warn "Unable to use the platform-specific (#{search.platform}) version of #{name} (#{version}) " \
"because it has different dependencies from the #{platform} version. " \ "because it has different dependencies from the #{platform} version. " \
"To use the platform-specific version of the gem, run `bundle config specific_platform true` and install again." "To use the platform-specific version of the gem, run `bundle config set specific_platform true` and install again."
search = source.specs.search(self).last search = source.specs.search(self).last
end end
search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification)) search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))

View file

@ -23,16 +23,14 @@ module Bundler
PATH = "PATH".freeze PATH = "PATH".freeze
PLUGIN = "PLUGIN SOURCE".freeze PLUGIN = "PLUGIN SOURCE".freeze
SPECS = " specs:".freeze SPECS = " specs:".freeze
OPTIONS = /^ ([a-z]+): (.*)$/i OPTIONS = /^ ([a-z]+): (.*)$/i.freeze
SOURCE = [GIT, GEM, PATH, PLUGIN].freeze SOURCE = [GIT, GEM, PATH, PLUGIN].freeze
SECTIONS_BY_VERSION_INTRODUCED = { SECTIONS_BY_VERSION_INTRODUCED = {
# The strings have to be dup'ed for old RG on Ruby 2.3+ Gem::Version.create("1.0") => [DEPENDENCIES, PLATFORMS, GIT, GEM, PATH].freeze,
# TODO: remove dup in Bundler 2.0 Gem::Version.create("1.10") => [BUNDLED].freeze,
Gem::Version.create("1.0".dup) => [DEPENDENCIES, PLATFORMS, GIT, GEM, PATH].freeze, Gem::Version.create("1.12") => [RUBY].freeze,
Gem::Version.create("1.10".dup) => [BUNDLED].freeze, Gem::Version.create("1.13") => [PLUGIN].freeze,
Gem::Version.create("1.12".dup) => [RUBY].freeze,
Gem::Version.create("1.13".dup) => [PLUGIN].freeze,
}.freeze }.freeze
KNOWN_SECTIONS = SECTIONS_BY_VERSION_INTRODUCED.values.flatten.freeze KNOWN_SECTIONS = SECTIONS_BY_VERSION_INTRODUCED.values.flatten.freeze
@ -90,7 +88,7 @@ module Bundler
send("parse_#{@state}", line) send("parse_#{@state}", line)
end end
end end
@sources << @rubygems_aggregate unless Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? @sources << @rubygems_aggregate unless Bundler.feature_flag.disable_multisource?
@specs = @specs.values.sort_by(&:identifier) @specs = @specs.values.sort_by(&:identifier)
warn_for_outdated_bundler_version warn_for_outdated_bundler_version
rescue ArgumentError => e rescue ArgumentError => e
@ -109,9 +107,9 @@ module Bundler
when 0 when 0
if current_version < bundler_version if current_version < bundler_version
Bundler.ui.warn "Warning: the running version of Bundler (#{current_version}) is older " \ Bundler.ui.warn "Warning: the running version of Bundler (#{current_version}) is older " \
"than the version that created the lockfile (#{bundler_version}). We suggest you " \ "than the version that created the lockfile (#{bundler_version}). We suggest you to " \
"upgrade to the latest version of Bundler by running `gem " \ "upgrade to the version that created the lockfile by running `gem install " \
"install bundler#{prerelease_text}`.\n" "bundler:#{bundler_version}#{prerelease_text}`.\n"
end end
end end
end end
@ -141,7 +139,7 @@ module Bundler
@sources << @current_source @sources << @current_source
end end
when GEM when GEM
if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? if Bundler.feature_flag.disable_multisource?
@opts["remotes"] = @opts.delete("remote") @opts["remotes"] = @opts.delete("remote")
@current_source = TYPES[@type].from_lock(@opts) @current_source = TYPES[@type].from_lock(@opts)
@sources << @current_source @sources << @current_source
@ -185,7 +183,7 @@ module Bundler
(?:-(.*))?\))? # Optional platform (?:-(.*))?\))? # Optional platform
(!)? # Optional pinned marker (!)? # Optional pinned marker
$ # Line end $ # Line end
/xo /xo.freeze
def parse_dependency(line) def parse_dependency(line)
return unless line =~ NAME_VERSION return unless line =~ NAME_VERSION

View file

@ -47,26 +47,48 @@ module Bundler
Bundler.ui.error "Failed to install plugin #{name}: #{e.message}\n #{e.backtrace.join("\n ")}" Bundler.ui.error "Failed to install plugin #{name}: #{e.message}\n #{e.backtrace.join("\n ")}"
end end
# List installed plugins and commands
#
def list
installed_plugins = index.installed_plugins
if installed_plugins.any?
output = String.new
installed_plugins.each do |plugin|
output << "#{plugin}\n"
output << "-----\n"
index.plugin_commands(plugin).each do |command|
output << " #{command}\n"
end
output << "\n"
end
else
output = "No plugins installed"
end
Bundler.ui.info output
end
# Evaluates the Gemfile with a limited DSL and installs the plugins # Evaluates the Gemfile with a limited DSL and installs the plugins
# specified by plugin method # specified by plugin method
# #
# @param [Pathname] gemfile path # @param [Pathname] gemfile path
# @param [Proc] block that can be evaluated for (inline) Gemfile # @param [Proc] block that can be evaluated for (inline) Gemfile
def gemfile_install(gemfile = nil, &inline) def gemfile_install(gemfile = nil, &inline)
builder = DSL.new Bundler.settings.temporary(:frozen => false, :deployment => false) do
if block_given? builder = DSL.new
builder.instance_eval(&inline) if block_given?
else builder.instance_eval(&inline)
builder.eval_gemfile(gemfile) else
builder.eval_gemfile(gemfile)
end
definition = builder.to_definition(nil, true)
return if definition.dependencies.empty?
plugins = definition.dependencies.map(&:name).reject {|p| index.installed? p }
installed_specs = Installer.new.install_definition(definition)
save_plugins plugins, installed_specs, builder.inferred_plugins
end end
definition = builder.to_definition(nil, true)
return if definition.dependencies.empty?
plugins = definition.dependencies.map(&:name).reject {|p| index.installed? p }
installed_specs = Installer.new.install_definition(definition)
save_plugins plugins, installed_specs, builder.inferred_plugins
rescue RuntimeError => e rescue RuntimeError => e
unless e.is_a?(GemfileError) unless e.is_a?(GemfileError)
Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}" Bundler.ui.error "Failed to install plugin: #{e.message}\n #{e.backtrace[0]}"

View file

@ -37,7 +37,7 @@ module Bundler
# #
# @!attribute [rw] dependency_names # @!attribute [rw] dependency_names
# @return [Array<String>] Names of dependencies that the source should # @return [Array<String>] Names of dependencies that the source should
# try to resolve. It is not necessary to use this list intenally. This # try to resolve. It is not necessary to use this list internally. This
# is present to be compatible with `Definition` and is used by # is present to be compatible with `Definition` and is used by
# rubygems source. # rubygems source.
module Source module Source

View file

@ -58,7 +58,10 @@ module Bundler
raise SourceConflict.new(name, common) unless common.empty? raise SourceConflict.new(name, common) unless common.empty?
sources.each {|k| @sources[k] = name } sources.each {|k| @sources[k] = name }
hooks.each {|e| (@hooks[e] ||= []) << name } hooks.each do |event|
event_hooks = (@hooks[event] ||= []) << name
event_hooks.uniq!
end
@plugin_paths[name] = path @plugin_paths[name] = path
@load_paths[name] = load_paths @load_paths[name] = load_paths
@ -100,6 +103,14 @@ module Bundler
@plugin_paths[name] @plugin_paths[name]
end end
def installed_plugins
@plugin_paths.keys
end
def plugin_commands(plugin)
@commands.find_all {|_, n| n == plugin }.map(&:first)
end
def source?(source) def source?(source)
@sources.key? source @sources.key? source
end end

View file

@ -12,10 +12,15 @@ module Bundler
autoload :Git, "bundler/plugin/installer/git" autoload :Git, "bundler/plugin/installer/git"
def install(names, options) def install(names, options)
check_sources_consistency!(options)
version = options[:version] || [">= 0"] version = options[:version] || [">= 0"]
Bundler.settings.temporary(:lockfile_uses_separate_rubygems_sources => false, :disable_multisource => false) do
Bundler.settings.temporary(:disable_multisource => false) do
if options[:git] if options[:git]
install_git(names, version, options) install_git(names, version, options)
elsif options[:local_git]
install_local_git(names, version, options)
else else
sources = options[:source] || Bundler.rubygems.sources sources = options[:source] || Bundler.rubygems.sources
install_rubygems(names, version, sources) install_rubygems(names, version, sources)
@ -38,22 +43,24 @@ module Bundler
private private
def check_sources_consistency!(options)
if options.key?(:git) && options.key?(:local_git)
raise InvalidOption, "Remote and local plugin git sources can't be both specified"
end
end
def install_git(names, version, options) def install_git(names, version, options)
uri = options.delete(:git) uri = options.delete(:git)
options["uri"] = uri options["uri"] = uri
source_list = SourceList.new install_all_sources(names, version, options, options[:source])
source_list.add_git_source(options) end
# To support both sources def install_local_git(names, version, options)
if options[:source] uri = options.delete(:local_git)
source_list.add_rubygems_source("remotes" => options[:source]) options["uri"] = uri
end
deps = names.map {|name| Dependency.new name, version } install_all_sources(names, version, options, options[:source])
definition = Definition.new(nil, deps, source_list, true)
install_definition(definition)
end end
# Installs the plugin from rubygems source and returns the path where the # Installs the plugin from rubygems source and returns the path where the
@ -65,10 +72,16 @@ module Bundler
# #
# @return [Hash] map of names to the specs of plugins installed # @return [Hash] map of names to the specs of plugins installed
def install_rubygems(names, version, sources) def install_rubygems(names, version, sources)
deps = names.map {|name| Dependency.new name, version } install_all_sources(names, version, nil, sources)
end
def install_all_sources(names, version, git_source_options, rubygems_source)
source_list = SourceList.new source_list = SourceList.new
source_list.add_rubygems_source("remotes" => sources)
source_list.add_git_source(git_source_options) if git_source_options
source_list.add_rubygems_source("remotes" => rubygems_source) if rubygems_source
deps = names.map {|name| Dependency.new name, version }
definition = Definition.new(nil, deps, source_list, true) definition = Definition.new(nil, deps, source_list, true)
install_definition(definition) install_definition(definition)

View file

@ -38,8 +38,8 @@ module Bundler
@platforms = platforms @platforms = platforms
@gem_version_promoter = gem_version_promoter @gem_version_promoter = gem_version_promoter
@allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts? @allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts?
@lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
@use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major? @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
@lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.disable_multisource?
end end
def start(requirements) def start(requirements)
@ -48,9 +48,12 @@ module Bundler
verify_gemfile_dependencies_are_found!(requirements) verify_gemfile_dependencies_are_found!(requirements)
dg = @resolver.resolve(requirements, @base_dg) dg = @resolver.resolve(requirements, @base_dg)
dg.map(&:payload). dg.
tap {|resolved| validate_resolved_specs!(resolved) }.
map(&:payload).
reject {|sg| sg.name.end_with?("\0") }. reject {|sg| sg.name.end_with?("\0") }.
map(&:to_specs).flatten map(&:to_specs).
flatten
rescue Molinillo::VersionConflict => e rescue Molinillo::VersionConflict => e
message = version_conflict_message(e) message = version_conflict_message(e)
raise VersionConflict.new(e.conflicts.keys.uniq, message) raise VersionConflict.new(e.conflicts.keys.uniq, message)
@ -169,13 +172,13 @@ module Bundler
def name_for_explicit_dependency_source def name_for_explicit_dependency_source
Bundler.default_gemfile.basename.to_s Bundler.default_gemfile.basename.to_s
rescue rescue StandardError
"Gemfile" "Gemfile"
end end
def name_for_locking_dependency_source def name_for_locking_dependency_source
Bundler.default_lockfile.basename.to_s Bundler.default_lockfile.basename.to_s
rescue rescue StandardError
"Gemfile.lock" "Gemfile.lock"
end end
@ -276,10 +279,10 @@ module Bundler
versions_with_platforms = specs.map {|s| [s.version, s.platform] } 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 = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source}#{cache_message}.\n")
message << if versions_with_platforms.any? message << if versions_with_platforms.any?
"The source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}" "The source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}"
else else
"The source does not contain any versions of '#{name}'" "The source does not contain any versions of '#{name}'"
end end
else else
message = "Could not find gem '#{requirement}' in any of the gem sources " \ message = "Could not find gem '#{requirement}' in any of the gem sources " \
"listed in your Gemfile#{cache_message}." "listed in your Gemfile#{cache_message}."
@ -300,9 +303,19 @@ module Bundler
end end
def version_conflict_message(e) def version_conflict_message(e)
# only show essential conflicts, if possible
conflicts = e.conflicts.dup
conflicts.delete_if do |_name, conflict|
deps = conflict.requirement_trees.map(&:last).flatten(1)
!Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
end
e = Molinillo::VersionConflict.new(conflicts, e.specification_provider) unless conflicts.empty?
solver_name = "Bundler"
possibility_type = "gem"
e.message_with_trees( e.message_with_trees(
:solver_name => "Bundler", :solver_name => solver_name,
:possibility_type => "gem", :possibility_type => possibility_type,
:reduce_trees => lambda do |trees| :reduce_trees => lambda do |trees|
# called first, because we want to reduce the amount of work required to find maximal empty sets # called first, because we want to reduce the amount of work required to find maximal empty sets
trees = trees.uniq {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } } trees = trees.uniq {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
@ -314,10 +327,8 @@ module Bundler
end.flatten(1).select do |deps| end.flatten(1).select do |deps|
Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement))) Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
end.min_by(&:size) end.min_by(&:size)
trees.reject! {|t| !maximal.include?(t.last) } if maximal
trees = trees.sort_by {|t| t.flatten.map(&:to_s) } trees.reject! {|t| !maximal.include?(t.last) } if maximal
trees.uniq! {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
trees.sort_by {|t| t.reverse.map(&:name) } trees.sort_by {|t| t.reverse.map(&:name) }
end, end,
@ -325,7 +336,7 @@ module Bundler
:additional_message_for_conflict => lambda do |o, name, conflict| :additional_message_for_conflict => lambda do |o, name, conflict|
if name == "bundler" if name == "bundler"
o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION})) o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new Bundler::VERSION) other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION))
end end
if name == "bundler" && other_bundler_required if name == "bundler" && other_bundler_required
@ -352,7 +363,11 @@ module Bundler
[] []
end.compact.map(&:to_s).uniq.sort end.compact.map(&:to_s).uniq.sort
o << "Could not find gem '#{SharedHelpers.pretty_dependency(conflict.requirement)}'" metadata_requirement = name.end_with?("\0")
o << "Could not find gem '" unless metadata_requirement
o << SharedHelpers.pretty_dependency(conflict.requirement)
o << "'" unless metadata_requirement
if conflict.requirement_trees.first.size > 1 if conflict.requirement_trees.first.size > 1
o << ", which is required by " o << ", which is required by "
o << "gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}'," o << "gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}',"
@ -360,14 +375,47 @@ module Bundler
o << " " o << " "
o << if relevant_sources.empty? o << if relevant_sources.empty?
"in any of the sources.\n" "in any of the sources.\n"
else elsif metadata_requirement
"in any of the relevant sources:\n #{relevant_sources * "\n "}\n" "is not available in #{relevant_sources.join(" or ")}"
end else
"in any of the relevant sources:\n #{relevant_sources * "\n "}\n"
end
end end
end, end,
:version_for_spec => lambda {|spec| spec.version } :version_for_spec => lambda {|spec| spec.version },
:incompatible_version_message_for_conflict => lambda do |name, _conflict|
if name.end_with?("\0")
%(#{solver_name} found conflicting requirements for the #{name} version:)
else
%(#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":)
end
end
) )
end end
def validate_resolved_specs!(resolved_specs)
resolved_specs.each do |v|
name = v.name
next unless sources = relevant_sources_for_vertex(v)
sources.compact!
if default_index = sources.index(@source_requirements[:default])
sources.delete_at(default_index)
end
sources.reject! {|s| s.specs[name].empty? }
sources.uniq!
next if sources.size <= 1
multisource_disabled = Bundler.feature_flag.disable_multisource?
msg = ["The gem '#{name}' was found in multiple relevant sources."]
msg.concat sources.map {|s| " * #{s}" }.sort
msg << "You #{multisource_disabled ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
msg = msg.join("\n")
raise SecurityError, msg if multisource_disabled
Bundler.ui.warn "Warning: #{msg}"
end
end
end end
end end

View file

@ -94,10 +94,10 @@ module Bundler
return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification) return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
dependencies = [] dependencies = []
if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none? if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
dependencies << DepProxy.new(Gem::Dependency.new("ruby\0", spec.required_ruby_version), platform) dependencies << DepProxy.new(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
end end
if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none? if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
dependencies << DepProxy.new(Gem::Dependency.new("rubygems\0", spec.required_rubygems_version), platform) dependencies << DepProxy.new(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
end end
dependencies dependencies
end end

View file

@ -35,10 +35,10 @@ module Bundler
private private
def run(&block) def run(&block)
@failed = false @failed = false
@current_run += 1 @current_run += 1
@result = block.call @result = block.call
rescue => e rescue StandardError => e
fail_attempt(e) fail_attempt(e)
end end

View file

@ -49,7 +49,7 @@ module Bundler
([\d.]+) # ruby version ([\d.]+) # ruby version
(?:p(-?\d+))? # optional patchlevel (?:p(-?\d+))? # optional patchlevel
(?:\s\((\S+)\s(.+)\))? # optional engine info (?:\s\((\S+)\s(.+)\))? # optional engine info
/xo /xo.freeze
# Returns a RubyVersion from the given string. # Returns a RubyVersion from the given string.
# @param [String] the version string to match. # @param [String] the version string to match.
@ -74,7 +74,7 @@ module Bundler
@host ||= [ @host ||= [
RbConfig::CONFIG["host_cpu"], RbConfig::CONFIG["host_cpu"],
RbConfig::CONFIG["host_vendor"], RbConfig::CONFIG["host_vendor"],
RbConfig::CONFIG["host_os"] RbConfig::CONFIG["host_os"],
].join("-") ].join("-")
end end

View file

@ -2,12 +2,6 @@
require "pathname" require "pathname"
if defined?(Gem::QuickLoader)
# Gem Prelude makes me a sad panda :'(
Gem::QuickLoader.load_full_rubygems_library
end
require "rubygems"
require "rubygems/specification" require "rubygems/specification"
begin begin
@ -27,14 +21,16 @@ module Gem
class Specification class Specification
attr_accessor :remote, :location, :relative_loaded_from attr_accessor :remote, :location, :relative_loaded_from
if instance_methods(false).map(&:to_sym).include?(:source) if instance_methods(false).include?(:source)
remove_method :source remove_method :source
attr_writer :source attr_writer :source
def source def source
(defined?(@source) && @source) || Gem::Source::Installed.new (defined?(@source) && @source) || Gem::Source::Installed.new
end end
else else
# rubocop:disable Lint/DuplicateMethods
attr_accessor :source attr_accessor :source
# rubocop:enable Lint/DuplicateMethods
end end
alias_method :rg_full_gem_path, :full_gem_path alias_method :rg_full_gem_path, :full_gem_path
@ -85,10 +81,7 @@ module Gem
end end
end end
# RubyGems 1.8+ used only. remove_method :gem_dir if instance_methods(false).include?(:gem_dir)
methods = instance_methods(false)
gem_dir = methods.first.is_a?(String) ? "gem_dir" : :gem_dir
remove_method :gem_dir if methods.include?(gem_dir)
def gem_dir def gem_dir
full_gem_path full_gem_path
end end

View file

@ -66,7 +66,7 @@ module Bundler
If you wish to continue installing the downloaded gem, and are certain it does not pose a \ If you wish to continue installing the downloaded gem, and are certain it does not pose a \
security issue despite the mismatching checksum, do the following: security issue despite the mismatching checksum, do the following:
1. run `bundle config disable_checksum_validation true` to turn off checksum verification 1. run `bundle config set disable_checksum_validation true` to turn off checksum verification
2. run `bundle install` 2. run `bundle install`
(More info: The expected SHA256 checksum was #{checksum.inspect}, but the \ (More info: The expected SHA256 checksum was #{checksum.inspect}, but the \

View file

@ -1,8 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "monitor" require "monitor"
require "rubygems"
require "rubygems/config_file"
module Bundler module Bundler
class RubygemsIntegration class RubygemsIntegration
@ -307,7 +305,7 @@ module Bundler
gem_from_path(path, security_policies[policy]).spec gem_from_path(path, security_policies[policy]).spec
rescue Gem::Package::FormatError rescue Gem::Package::FormatError
raise GemspecError, "Could not read gem at #{path}. It may be corrupted." raise GemspecError, "Could not read gem at #{path}. It may be corrupted."
rescue Exception, Gem::Exception, Gem::Security::Exception => e rescue Exception, Gem::Exception, Gem::Security::Exception => e # rubocop:disable Lint/RescueException
if e.is_a?(Gem::Security::Exception) || if e.is_a?(Gem::Security::Exception) ||
e.message =~ /unknown trust policy|unsigned gem/i || e.message =~ /unknown trust policy|unsigned gem/i ||
e.message =~ /couldn't verify (meta)?data signature/i e.message =~ /couldn't verify (meta)?data signature/i
@ -436,40 +434,42 @@ module Bundler
# Used to make bin stubs that are not created by bundler work # Used to make bin stubs that are not created by bundler work
# under bundler. The new Gem.bin_path only considers gems in # under bundler. The new Gem.bin_path only considers gems in
# +specs+ # +specs+
def replace_bin_path(specs, specs_by_name) def replace_bin_path(specs_by_name)
gem_class = (class << Gem; self; end) gem_class = (class << Gem; self; end)
redefine_method(gem_class, :find_spec_for_exe) do |gem_name, *args| redefine_method(gem_class, :find_spec_for_exe) do |gem_name, *args|
exec_name = args.first exec_name = args.first
raise ArgumentError, "you must supply exec_name" unless exec_name
spec_with_name = specs_by_name[gem_name] spec_with_name = specs_by_name[gem_name]
spec = if exec_name matching_specs_by_exec_name = specs_by_name.values.select {|s| s.executables.include?(exec_name) }
if spec_with_name && spec_with_name.executables.include?(exec_name) spec = matching_specs_by_exec_name.delete(spec_with_name)
spec_with_name
else
specs.find {|s| s.executables.include?(exec_name) }
end
else
spec_with_name
end
unless spec unless spec || !matching_specs_by_exec_name.empty?
message = "can't find executable #{exec_name} for gem #{gem_name}" message = "can't find executable #{exec_name} for gem #{gem_name}"
if !exec_name || spec_with_name.nil? if spec_with_name.nil?
message += ". #{gem_name} is not currently included in the bundle, " \ message += ". #{gem_name} is not currently included in the bundle, " \
"perhaps you meant to add it to your #{Bundler.default_gemfile.basename}?" "perhaps you meant to add it to your #{Bundler.default_gemfile.basename}?"
end end
raise Gem::Exception, message raise Gem::Exception, message
end end
raise Gem::Exception, "no default executable for #{spec.full_name}" unless exec_name ||= spec.default_executable unless spec
spec = matching_specs_by_exec_name.shift
unless spec.name == gem_name warn \
Bundler::SharedHelpers.major_deprecation 3,
"Bundler is using a binstub that was created for a different gem (#{spec.name}).\n" \ "Bundler is using a binstub that was created for a different gem (#{spec.name}).\n" \
"You should run `bundle binstub #{gem_name}` " \ "You should run `bundle binstub #{gem_name}` " \
"to work around a system/bundle conflict." "to work around a system/bundle conflict."
end end
unless matching_specs_by_exec_name.empty?
conflicting_names = matching_specs_by_exec_name.map(&:name).join(", ")
warn \
"The `#{exec_name}` executable in the `#{spec.name}` gem is being loaded, but it's also present in other gems (#{conflicting_names}).\n" \
"If you meant to run the executable for another gem, make sure you use a project specific binstub (`bundle binstub <gem_name>`).\n" \
"If you plan to use multiple conflicting executables, generate binstubs for them and disambiguate their names."
end
spec spec
end end
@ -514,9 +514,18 @@ module Bundler
h h
end end
Bundler.rubygems.default_stubs.each do |stub|
default_spec = stub.to_spec
default_spec_name = default_spec.name
next if specs_by_name.key?(default_spec_name)
specs << default_spec
specs_by_name[default_spec_name] = default_spec
end
replace_gem(specs, specs_by_name) replace_gem(specs, specs_by_name)
stub_rubygems(specs) stub_rubygems(specs)
replace_bin_path(specs, specs_by_name) replace_bin_path(specs_by_name)
replace_refresh replace_refresh
Gem.clear_paths Gem.clear_paths
@ -850,6 +859,16 @@ module Bundler
end end
end end
if Gem::Specification.respond_to?(:default_stubs)
def default_stubs
Gem::Specification.default_stubs("*.gemspec")
end
else
def default_stubs
Gem::Specification.send(:default_stubs, "*.gemspec")
end
end
def use_gemdeps(gemfile) def use_gemdeps(gemfile)
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(gemfile) ENV["BUNDLE_GEMFILE"] ||= File.expand_path(gemfile)
require "bundler/gemdeps" require "bundler/gemdeps"

View file

@ -163,7 +163,7 @@ module Bundler
gem_dirs = Dir["#{Gem.dir}/gems/*"] gem_dirs = Dir["#{Gem.dir}/gems/*"]
gem_files = Dir["#{Gem.dir}/cache/*.gem"] gem_files = Dir["#{Gem.dir}/cache/*.gem"]
gemspec_files = Dir["#{Gem.dir}/specifications/*.gemspec"] gemspec_files = Dir["#{Gem.dir}/specifications/*.gemspec"]
extension_dirs = Dir["#{Gem.dir}/extensions/*/*/*"] extension_dirs = Dir["#{Gem.dir}/extensions/*/*/*"] + Dir["#{Gem.dir}/bundler/gems/extensions/*/*/*"]
spec_gem_paths = [] spec_gem_paths = []
# need to keep git sources around # need to keep git sources around
spec_git_paths = @definition.spec_git_paths spec_git_paths = @definition.spec_git_paths

View file

@ -18,7 +18,6 @@ module Bundler
cache_all cache_all
cache_all_platforms cache_all_platforms
cache_command_is_package cache_command_is_package
console_command
default_install_uses_path default_install_uses_path
deployment deployment
deployment_means_frozen deployment_means_frozen
@ -35,23 +34,21 @@ module Bundler
frozen frozen
gem.coc gem.coc
gem.mit gem.mit
github.https
global_path_appends_ruby_scope global_path_appends_ruby_scope
global_gem_cache global_gem_cache
ignore_messages ignore_messages
init_gems_rb init_gems_rb
list_command
lockfile_upgrade_warning
lockfile_uses_separate_rubygems_sources
major_deprecations
no_install no_install
no_prune no_prune
only_update_to_newer_versions only_update_to_newer_versions
path_relative_to_cwd path_relative_to_cwd
path.system path.system
plugins plugins
prefer_gems_rb prefer_patch
print_only_version_number print_only_version_number
setup_makes_kernel_gem_public setup_makes_kernel_gem_public
silence_deprecations
silence_root_warning silence_root_warning
skip_default_git_sources skip_default_git_sources
specific_platform specific_platform
@ -59,7 +56,6 @@ module Bundler
unlock_source_unlocks_spec unlock_source_unlocks_spec
update_requires_all_flag update_requires_all_flag
use_gem_version_promoter_for_major_updates use_gem_version_promoter_for_major_updates
viz_command
].freeze ].freeze
NUMBER_KEYS = %w[ NUMBER_KEYS = %w[
@ -76,7 +72,9 @@ module Bundler
].freeze ].freeze
DEFAULT_CONFIG = { DEFAULT_CONFIG = {
:silence_deprecations => false,
:disable_version_check => true, :disable_version_check => true,
:prefer_patch => false,
:redirect => 5, :redirect => 5,
:retry => 3, :retry => 3,
:timeout => 10, :timeout => 10,
@ -107,18 +105,6 @@ module Bundler
temporary(key => value) temporary(key => value)
value value
else else
command = if value.nil?
"bundle config --delete #{key}"
else
"bundle config #{key} #{Array(value).join(":")}"
end
Bundler::SharedHelpers.major_deprecation 3,\
"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) set_local(key, value)
end end
end end
@ -407,20 +393,6 @@ module Bundler
Pathname.new(@root).join("config") if @root Pathname.new(@root).join("config") if @root
end end
CONFIG_REGEX = %r{ # rubocop:disable Style/RegexpLiteral
^
(BUNDLE_.+):\s # the key
(?: !\s)? # optional exclamation mark found with ruby 1.9.3
(['"]?) # optional opening quote
(.* # contents of the value
(?: # optionally, up until the next key
(\n(?!BUNDLE).+)*
)
)
\2 # matching closing quote
$
}xo
def load_config(config_file) def load_config(config_file)
return {} if !config_file || ignore_config? return {} if !config_file || ignore_config?
SharedHelpers.filesystem_access(config_file, :read) do |file| SharedHelpers.filesystem_access(config_file, :read) do |file|
@ -442,7 +414,7 @@ module Bundler
(https?.*?) # URI (https?.*?) # URI
(\.#{Regexp.union(PER_URI_OPTIONS)})? # optional suffix key (\.#{Regexp.union(PER_URI_OPTIONS)})? # optional suffix key
\z \z
/ix /ix.freeze
# TODO: duplicates Rubygems#normalize_uri # TODO: duplicates Rubygems#normalize_uri
# TODO: is this the correct place to validate mirror URIs? # TODO: is this the correct place to validate mirror URIs?

View file

@ -6,13 +6,14 @@ if Bundler::SharedHelpers.in_bundle?
require "bundler" require "bundler"
if STDOUT.tty? || ENV["BUNDLER_FORCE_TTY"] if STDOUT.tty? || ENV["BUNDLER_FORCE_TTY"]
Bundler.ui = Bundler::UI::Shell.new
begin begin
Bundler.setup Bundler.setup
rescue Bundler::BundlerError => e rescue Bundler::BundlerError => e
puts "\e[31m#{e.message}\e[0m" Bundler.ui.warn "\e[31m#{e.message}\e[0m"
puts e.backtrace.join("\n") if ENV["DEBUG"] Bundler.ui.warn e.backtrace.join("\n") if ENV["DEBUG"]
if e.is_a?(Bundler::GemNotFound) if e.is_a?(Bundler::GemNotFound)
puts "\e[33mRun `bundle install` to install missing gems.\e[0m" Bundler.ui.warn "\e[33mRun `bundle install` to install missing gems.\e[0m"
end end
exit e.status_code exit e.status_code
end end

View file

@ -3,6 +3,7 @@
require "bundler/compatibility_guard" require "bundler/compatibility_guard"
require "pathname" require "pathname"
require "rbconfig"
require "rubygems" require "rubygems"
require "bundler/version" require "bundler/version"
@ -10,17 +11,6 @@ require "bundler/constants"
require "bundler/rubygems_integration" require "bundler/rubygems_integration"
require "bundler/current_ruby" require "bundler/current_ruby"
module Gem
class Dependency
# This is only needed for RubyGems < 1.4
unless method_defined? :requirement
def requirement
version_requirements
end
end
end
end
module Bundler module Bundler
module SharedHelpers module SharedHelpers
def root def root
@ -140,33 +130,28 @@ module Bundler
end end
def major_deprecation(major_version, message) def major_deprecation(major_version, message)
if Bundler.bundler_major_version >= major_version bundler_major_version = Bundler.bundler_major_version
if bundler_major_version > major_version
require "bundler/errors" require "bundler/errors"
raise DeprecatedError, "[REMOVED FROM #{major_version}.0] #{message}" raise DeprecatedError, "[REMOVED] #{message}"
end end
return unless prints_major_deprecations? return unless bundler_major_version >= major_version && prints_major_deprecations?
@major_deprecation_ui ||= Bundler::UI::Shell.new("no-color" => true) @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 = Bundler.ui.is_a?(@major_deprecation_ui.class) ? Bundler.ui : @major_deprecation_ui
ui.warn("[DEPRECATED FOR #{major_version}.0] #{message}") ui.warn("[DEPRECATED] #{message}")
end end
def print_major_deprecations! def print_major_deprecations!
multiple_gemfiles = search_up(".") do |dir| multiple_gemfiles = search_up(".") do |dir|
gemfiles = gemfile_names.select {|gf| File.file? File.expand_path(gf, dir) } gemfiles = gemfile_names.select {|gf| File.file? File.expand_path(gf, dir) }
next if gemfiles.empty? next if gemfiles.empty?
break false if gemfiles.size == 1 break gemfiles.size != 1
end end
if multiple_gemfiles && Bundler.bundler_major_version == 2 return unless multiple_gemfiles
Bundler::SharedHelpers.major_deprecation 3, \ message = "Multiple gemfiles (gems.rb and Gemfile) detected. " \
"gems.rb and gems.locked will be preferred to Gemfile and Gemfile.lock." "Make sure you remove Gemfile and Gemfile.lock since bundler is ignoring them in favor of gems.rb and gems.rb.locked."
end Bundler.ui.warn message
if RUBY_VERSION < "2"
major_deprecation(2, "Bundler will only support ruby >= 2.0, you are running #{RUBY_VERSION}")
end
return if Bundler.rubygems.provides?(">= 2")
major_deprecation(2, "Bundler will only support rubygems >= 2.0, you are running #{Bundler.rubygems.version}")
end end
def trap(signal, override = false, &block) def trap(signal, override = false, &block)
@ -246,13 +231,11 @@ module Bundler
def find_gemfile(order_matters = false) def find_gemfile(order_matters = false)
given = ENV["BUNDLE_GEMFILE"] given = ENV["BUNDLE_GEMFILE"]
return given if given && !given.empty? return given if given && !given.empty?
names = gemfile_names find_file(*gemfile_names)
names.reverse! if order_matters && Bundler.feature_flag.prefer_gems_rb?
find_file(*names)
end end
def gemfile_names def gemfile_names
["Gemfile", "gems.rb"] ["gems.rb", "Gemfile"]
end end
def find_file(*names) def find_file(*names)
@ -349,9 +332,6 @@ module Bundler
end end
def clean_load_path def clean_load_path
# handle 1.9 where system gems are always on the load path
return unless defined?(::Gem)
bundler_lib = bundler_ruby_lib bundler_lib = bundler_ruby_lib
loaded_gem_paths = Bundler.rubygems.loaded_gem_paths loaded_gem_paths = Bundler.rubygems.loaded_gem_paths
@ -372,8 +352,7 @@ module Bundler
def prints_major_deprecations? def prints_major_deprecations?
require "bundler" require "bundler"
deprecation_release = Bundler::VERSION.split(".").drop(1).include?("99") return false if Bundler.settings[:silence_deprecations]
return false if !deprecation_release && !Bundler.settings[:major_deprecations]
require "bundler/deprecate" require "bundler/deprecate"
return false if Bundler::Deprecate.skip return false if Bundler::Deprecate.skip
true true

View file

@ -51,7 +51,7 @@ module Bundler
dm[i][j] = [ dm[i][j] = [
dm[i - 1][j - 1] + (this[j - 1] == that[i - 1] ? 0 : sub), dm[i - 1][j - 1] + (this[j - 1] == that[i - 1] ? 0 : sub),
dm[i][j - 1] + ins, dm[i][j - 1] + ins,
dm[i - 1][j] + del dm[i - 1][j] + del,
].min ].min
end end
end end

View file

@ -118,18 +118,19 @@ module Bundler
def local_override!(path) def local_override!(path)
return false if local? return false if local?
original_path = path
path = Pathname.new(path) path = Pathname.new(path)
path = path.expand_path(Bundler.root) unless path.relative? path = path.expand_path(Bundler.root) unless path.relative?
unless options["branch"] || Bundler.settings[:disable_local_branch_check] unless options["branch"] || Bundler.settings[:disable_local_branch_check]
raise GitError, "Cannot use local override for #{name} at #{path} because " \ raise GitError, "Cannot use local override for #{name} at #{path} because " \
":branch is not specified in Gemfile. Specify a branch or use " \ ":branch is not specified in Gemfile. Specify a branch or run " \
"`bundle config --delete` to remove the local override" "`bundle config unset local.#{override_for(original_path)}` to remove the local override"
end end
unless path.exist? unless path.exist?
raise GitError, "Cannot use local override for #{name} because #{path} " \ raise GitError, "Cannot use local override for #{name} because #{path} " \
"does not exist. Check `bundle config --delete` to remove the local override" "does not exist. Run `bundle config unset local.#{override_for(original_path)}` to remove the local override"
end end
set_local!(path) set_local!(path)
@ -260,7 +261,11 @@ module Bundler
end end
def requires_checkout? def requires_checkout?
allow_git_ops? && !local? allow_git_ops? && !local? && !cached_revision_checked_out?
end
def cached_revision_checked_out?
cached_revision && cached_revision == revision && install_path.exist?
end end
def base_name def base_name
@ -324,6 +329,10 @@ module Bundler
def extension_cache_slug(_) def extension_cache_slug(_)
extension_dir_name extension_dir_name
end end
def override_for(path)
Bundler.settings.local_overrides.key(path)
end
end end
end end
end end

View file

@ -253,7 +253,7 @@ module Bundler
ensure ensure
STDERR.reopen backup_stderr STDERR.reopen backup_stderr
end end
$stderr.puts URICredentialsFilter.credential_filtered_string(captured_err, uri) if uri && !captured_err.empty? Bundler.ui.warn URICredentialsFilter.credential_filtered_string(captured_err, uri) if uri && !captured_err.empty?
return_value return_value
end end
end end

View file

@ -5,8 +5,10 @@ module Bundler
class Metadata < Source class Metadata < Source
def specs def specs
@specs ||= Index.build do |idx| @specs ||= Index.build do |idx|
idx << Gem::Specification.new("ruby\0", RubyVersion.system.to_gem_version_with_patchlevel) idx << Gem::Specification.new("Ruby\0", RubyVersion.system.to_gem_version_with_patchlevel)
idx << Gem::Specification.new("rubygems\0", Gem::VERSION) idx << Gem::Specification.new("RubyGems\0", Gem::VERSION) do |s|
s.required_rubygems_version = Gem::Requirement.default
end
idx << Gem::Specification.new do |s| idx << Gem::Specification.new do |s|
s.name = "bundler" s.name = "bundler"

View file

@ -191,10 +191,10 @@ module Bundler
else else
message = String.new("The path `#{expanded_path}` ") message = String.new("The path `#{expanded_path}` ")
message << if File.exist?(expanded_path) message << if File.exist?(expanded_path)
"is not a directory." "is not a directory."
else else
"does not exist." "does not exist."
end end
raise PathError, message raise PathError, message
end end

View file

@ -51,7 +51,7 @@ module Bundler
end end
def can_lock?(spec) def can_lock?(spec)
return super if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? return super if Bundler.feature_flag.disable_multisource?
spec.source.is_a?(Rubygems) spec.source.is_a?(Rubygems)
end end
@ -106,7 +106,7 @@ module Bundler
end end
end end
if installed?(spec) && !force if (installed?(spec) || Plugin.installed?(spec.name)) && !force
print_using_message "Using #{version_message(spec)}" print_using_message "Using #{version_message(spec)}"
return nil # no post-install message return nil # no post-install message
end end
@ -120,8 +120,14 @@ module Bundler
uris.uniq! uris.uniq!
Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1 Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1
s = Bundler.rubygems.spec_from_gem(fetch_gem(spec), Bundler.settings["trust-policy"]) path = fetch_gem(spec)
spec.__swap__(s) begin
s = Bundler.rubygems.spec_from_gem(path, Bundler.settings["trust-policy"])
spec.__swap__(s)
rescue StandardError
Bundler.rm_rf(path)
raise
end
end end
unless Bundler.settings[:no_install] unless Bundler.settings[:no_install]

View file

@ -1,5 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "set"
module Bundler module Bundler
class SourceList class SourceList
attr_reader :path_sources, attr_reader :path_sources,
@ -41,17 +43,14 @@ module Bundler
end end
def global_rubygems_source=(uri) def global_rubygems_source=(uri)
if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? if Bundler.feature_flag.disable_multisource?
@global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri) @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
end end
add_rubygems_remote(uri) add_rubygems_remote(uri)
end end
def add_rubygems_remote(uri) def add_rubygems_remote(uri)
if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? return if Bundler.feature_flag.disable_multisource?
return if Bundler.feature_flag.disable_multisource?
raise InvalidOption, "`lockfile_uses_separate_rubygems_sources` cannot be set without `disable_multisource` being set"
end
@rubygems_aggregate.add_remote(uri) @rubygems_aggregate.add_remote(uri)
@rubygems_aggregate @rubygems_aggregate
end end
@ -77,12 +76,10 @@ module Bundler
end end
def lock_sources def lock_sources
if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
[[default_source], @rubygems_sources, git_sources, path_sources, plugin_sources].map do |sources| if Bundler.feature_flag.disable_multisource?
sources.sort_by(&:to_s) lock_sources + rubygems_sources.sort_by(&:to_s)
end.flatten(1)
else else
lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
lock_sources << combine_rubygems_sources lock_sources << combine_rubygems_sources
end end
end end
@ -97,7 +94,7 @@ module Bundler
end end
end end
replacement_rubygems = !Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? && replacement_rubygems = !Bundler.feature_flag.disable_multisource? &&
replacement_sources.detect {|s| s.is_a?(Source::Rubygems) } replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
@rubygems_aggregate = replacement_rubygems if replacement_rubygems @rubygems_aggregate = replacement_rubygems if replacement_rubygems
@ -150,7 +147,7 @@ module Bundler
if source.uri =~ /^git\:/ if source.uri =~ /^git\:/
Bundler.ui.warn "The git source `#{source.uri}` uses the `git` protocol, " \ Bundler.ui.warn "The git source `#{source.uri}` uses the `git` protocol, " \
"which transmits data without encryption. Disable this warning with " \ "which transmits data without encryption. Disable this warning with " \
"`bundle config git.allow_insecure true`, or switch to the `https` " \ "`bundle config set git.allow_insecure true`, or switch to the `https` " \
"protocol to keep your data secure." "protocol to keep your data secure."
end end
end end

View file

@ -60,7 +60,6 @@ module Bundler
@specs << value @specs << value
@lookup = nil @lookup = nil
@sorted = nil @sorted = nil
value
end end
def sort! def sort!

View file

@ -1 +0,0 @@
# Ignore all files in this directory

View file

@ -1,66 +0,0 @@
# frozen_string_literal: true
require "bundler/vendored_fileutils"
require "net/https"
require "openssl"
module Bundler
module SSLCerts
class CertificateManager
attr_reader :bundler_cert_path, :bundler_certs, :rubygems_certs
def self.update_from!(rubygems_path)
new(rubygems_path).update!
end
def initialize(rubygems_path = nil)
if rubygems_path
rubygems_cert_path = File.join(rubygems_path, "lib/rubygems/ssl_certs")
@rubygems_certs = certificates_in(rubygems_cert_path)
end
@bundler_cert_path = File.expand_path("..", __FILE__)
@bundler_certs = certificates_in(bundler_cert_path)
end
def up_to_date?
rubygems_certs.all? do |rc|
bundler_certs.find do |bc|
File.basename(bc) == File.basename(rc) && FileUtils.compare_file(bc, rc)
end
end
end
def update!
return if up_to_date?
FileUtils.rm bundler_certs
FileUtils.cp rubygems_certs, bundler_cert_path
end
def connect_to(host)
http = Net::HTTP.new(host, 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.cert_store = store
http.head("/")
end
private
def certificates_in(path)
Dir[File.join(path, "**/*.pem")].sort
end
def store
@store ||= begin
store = OpenSSL::X509::Store.new
bundler_certs.each do |cert|
store.add_file cert
end
store
end
end
end
end
end

View file

@ -1,21 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----

View file

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----

View file

@ -1,25 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
-----END CERTIFICATE-----

View file

@ -13,17 +13,13 @@ module Bundler
attr_accessor :stub, :ignored attr_accessor :stub, :ignored
# Pre 2.2.0 did not include extension_dir def source=(source)
# https://github.com/rubygems/rubygems/commit/9485ca2d101b82a946d6f327f4bdcdea6d4946ea super
if Bundler.rubygems.provides?(">= 2.2.0") # Stub has no concept of source, which means that extension_dir may be wrong
def source=(source) # This is the case for git-based gems. So, instead manually assign the extension dir
super return unless source.respond_to?(:extension_dir_name)
# Stub has no concept of source, which means that extension_dir may be wrong path = File.join(stub.extensions_dir, source.extension_dir_name)
# This is the case for git-based gems. So, instead manually assign the extension dir stub.extension_dir = File.expand_path(path)
return unless source.respond_to?(:extension_dir_name)
path = File.join(stub.extensions_dir, source.extension_dir_name)
stub.extension_dir = File.expand_path(path)
end
end end
def to_yaml def to_yaml
@ -32,11 +28,9 @@ module Bundler
# @!group Stub Delegates # @!group Stub Delegates
if Bundler.rubygems.provides?(">= 2.3") # This is defined directly to avoid having to load every installed spec
# This is defined directly to avoid having to load every installed spec def missing_extensions?
def missing_extensions? stub.missing_extensions?
stub.missing_extensions?
end
end end
def activated def activated
@ -57,16 +51,14 @@ module Bundler
stub.full_gem_path || method_missing(:full_gem_path) stub.full_gem_path || method_missing(:full_gem_path)
end end
if Bundler.rubygems.provides?(">= 2.2.0") def full_require_paths
def full_require_paths stub.full_require_paths
stub.full_require_paths end
end
# This is what we do in bundler/rubygems_ext # This is what we do in bundler/rubygems_ext
# full_require_paths is always implemented in >= 2.2.0 # full_require_paths is always implemented
def load_paths def load_paths
full_require_paths full_require_paths
end
end end
def loaded_from def loaded_from

View file

@ -11,7 +11,7 @@
require "rubygems" require "rubygems"
m = Module.new do m = Module.new do
module_function module_function
def invoked_as_script? def invoked_as_script?
File.expand_path($0) == File.expand_path(__FILE__) File.expand_path($0) == File.expand_path(__FILE__)

View file

@ -14,7 +14,7 @@ gem '<%= config[:name] %>'
And then execute: And then execute:
$ bundle $ bundle install
Or install it yourself as: Or install it yourself as:

View file

@ -1,8 +1,4 @@
<%- if RUBY_VERSION < "2.0.0" -%> lib = File.expand_path("lib", __dir__)
# coding: utf-8
<%- end -%>
lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "<%= config[:namespaced_path] %>/version" require "<%= config[:namespaced_path] %>/version"
@ -19,18 +15,11 @@ Gem::Specification.new do |spec|
spec.license = "MIT" spec.license = "MIT"
<%- end -%> <%- end -%>
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
# to allow pushing to a single host or delete this section to allow pushing to any host.
if spec.respond_to?(:metadata)
spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
spec.metadata["homepage_uri"] = spec.homepage spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
else
raise "RubyGems 2.0 or newer is required to protect against " \
"public gem pushes."
end
# Specify which files should be added to the gem when it is released. # Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git. # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@ -45,7 +34,7 @@ Gem::Specification.new do |spec|
<%- end -%> <%- end -%>
spec.add_development_dependency "bundler", "~> <%= config[:bundler_version] %>" spec.add_development_dependency "bundler", "~> <%= config[:bundler_version] %>"
spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "rake", "~> 12.0"
<%- if config[:ext] -%> <%- if config[:ext] -%>
spec.add_development_dependency "rake-compiler" spec.add_development_dependency "rake-compiler"
<%- end -%> <%- end -%>

View file

@ -1,4 +1,4 @@
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__) $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
require "<%= config[:namespaced_path] %>" require "<%= config[:namespaced_path] %>"
require "minitest/autorun" require "minitest/autorun"

View file

@ -1,5 +1,4 @@
--- ---
sudo: false
language: ruby language: ruby
cache: bundler cache: bundler
rvm: rvm:

View file

@ -1,4 +1,13 @@
# frozen_string_literal: true # frozen_string_literal: true
begin
require 'rbconfig'
rescue LoadError
# for make mjit-headers
end
require "bundler/vendor/fileutils/lib/fileutils/version"
# #
# = fileutils.rb # = fileutils.rb
# #
@ -56,7 +65,7 @@
# #
# There are some `low level' methods, which do not accept any option: # There are some `low level' methods, which do not accept any option:
# #
# Bundler::FileUtils.copy_entry(src, dest, preserve = false, dereference = false) # Bundler::FileUtils.copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
# Bundler::FileUtils.copy_file(src, dest, preserve = false, dereference = true) # Bundler::FileUtils.copy_file(src, dest, preserve = false, dereference = true)
# Bundler::FileUtils.copy_stream(srcstream, deststream) # Bundler::FileUtils.copy_stream(srcstream, deststream)
# Bundler::FileUtils.remove_entry(path, force = false) # Bundler::FileUtils.remove_entry(path, force = false)
@ -84,7 +93,6 @@
# files/directories. This equates to passing the <tt>:noop</tt> and # files/directories. This equates to passing the <tt>:noop</tt> and
# <tt>:verbose</tt> flags to methods in Bundler::FileUtils. # <tt>:verbose</tt> flags to methods in Bundler::FileUtils.
# #
module Bundler::FileUtils module Bundler::FileUtils
def self.private_module_function(name) #:nodoc: def self.private_module_function(name) #:nodoc:
@ -106,19 +114,22 @@ module Bundler::FileUtils
# #
# Changes the current directory to the directory +dir+. # Changes the current directory to the directory +dir+.
# #
# If this method is called with block, resumes to the old # If this method is called with block, resumes to the previous
# working directory after the block execution finished. # working directory after the block execution has finished.
# #
# Bundler::FileUtils.cd('/', :verbose => true) # chdir and report it # Bundler::FileUtils.cd('/') # change directory
# #
# Bundler::FileUtils.cd('/') do # chdir # Bundler::FileUtils.cd('/', :verbose => true) # change directory and report it
#
# Bundler::FileUtils.cd('/') do # change directory
# # ... # do something # # ... # do something
# end # return to original directory # end # return to original directory
# #
def cd(dir, verbose: nil, &block) # :yield: dir def cd(dir, verbose: nil, &block) # :yield: dir
fu_output_message "cd #{dir}" if verbose fu_output_message "cd #{dir}" if verbose
Dir.chdir(dir, &block) result = Dir.chdir(dir, &block)
fu_output_message 'cd -' if verbose and block fu_output_message 'cd -' if verbose and block
result
end end
module_function :cd module_function :cd
@ -245,15 +256,15 @@ module Bundler::FileUtils
fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if verbose fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if verbose
return if noop return if noop
list.each do |dir| list.each do |dir|
begin Dir.rmdir(dir = remove_trailing_slash(dir))
Dir.rmdir(dir = remove_trailing_slash(dir)) if parents
if parents begin
until (parent = File.dirname(dir)) == '.' or parent == dir until (parent = File.dirname(dir)) == '.' or parent == dir
dir = parent dir = parent
Dir.rmdir(dir) Dir.rmdir(dir)
end end
rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
end end
rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
end end
end end
end end
@ -293,6 +304,39 @@ module Bundler::FileUtils
alias link ln alias link ln
module_function :link module_function :link
#
# :call-seq:
# Bundler::FileUtils.cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false)
#
# Hard link +src+ to +dest+. If +src+ is a directory, this method links
# all its contents recursively. If +dest+ is a directory, links
# +src+ to +dest/src+.
#
# +src+ can be a list of files.
#
# # Installing the library "mylib" under the site_ruby directory.
# Bundler::FileUtils.rm_r site_ruby + '/mylib', :force => true
# Bundler::FileUtils.cp_lr 'lib/', site_ruby + '/mylib'
#
# # Examples of linking several files to target directory.
# Bundler::FileUtils.cp_lr %w(mail.rb field.rb debug/), site_ruby + '/tmail'
# Bundler::FileUtils.cp_lr Dir.glob('*.rb'), '/home/aamine/lib/ruby', :noop => true, :verbose => true
#
# # If you want to link all contents of a directory instead of the
# # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
# # use the following code.
# Bundler::FileUtils.cp_lr 'src/.', 'dest' # cp_lr('src', 'dest') makes dest/src, but this doesn't.
#
def cp_lr(src, dest, noop: nil, verbose: nil,
dereference_root: true, remove_destination: false)
fu_output_message "cp -lr#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest(src, dest) do |s, d|
link_entry s, d, dereference_root, remove_destination
end
end
module_function :cp_lr
# #
# :call-seq: # :call-seq:
# Bundler::FileUtils.ln_s(target, link, force: nil, noop: nil, verbose: nil) # Bundler::FileUtils.ln_s(target, link, force: nil, noop: nil, verbose: nil)
@ -339,6 +383,26 @@ module Bundler::FileUtils
end end
module_function :ln_sf module_function :ln_sf
#
# Hard links a file system entry +src+ to +dest+.
# If +src+ is a directory, this method links its contents recursively.
#
# Both of +src+ and +dest+ must be a path name.
# +src+ must exist, +dest+ must not exist.
#
# If +dereference_root+ is true, this method dereferences the tree root.
#
# If +remove_destination+ is true, this method removes each destination file before copy.
#
def link_entry(src, dest, dereference_root = false, remove_destination = false)
Entry_.new(src, nil, dereference_root).traverse do |ent|
destent = Entry_.new(dest, ent.rel, false)
File.unlink destent.path if remove_destination && File.file?(destent.path)
ent.link destent.path
end
end
module_function :link_entry
# #
# Copies a file content +src+ to +dest+. If +dest+ is a directory, # Copies a file content +src+ to +dest+. If +dest+ is a directory,
# copies +src+ to +dest/src+. # copies +src+ to +dest/src+.
@ -412,7 +476,7 @@ module Bundler::FileUtils
def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false) def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
Entry_.new(src, nil, dereference_root).wrap_traverse(proc do |ent| Entry_.new(src, nil, dereference_root).wrap_traverse(proc do |ent|
destent = Entry_.new(dest, ent.rel, false) destent = Entry_.new(dest, ent.rel, false)
File.unlink destent.path if remove_destination && File.file?(destent.path) File.unlink destent.path if remove_destination && (File.file?(destent.path) || File.symlink?(destent.path))
ent.copy destent.path ent.copy destent.path
end, proc do |ent| end, proc do |ent|
destent = Entry_.new(dest, ent.rel, false) destent = Entry_.new(dest, ent.rel, false)
@ -461,13 +525,12 @@ module Bundler::FileUtils
if destent.exist? if destent.exist?
if destent.directory? if destent.directory?
raise Errno::EEXIST, d raise Errno::EEXIST, d
else
destent.remove_file if rename_cannot_overwrite_file?
end end
end end
begin begin
File.rename s, d File.rename s, d
rescue Errno::EXDEV rescue Errno::EXDEV,
Errno::EPERM # move from unencrypted to encrypted dir (ext4)
copy_entry s, d, true copy_entry s, d, true
if secure if secure
remove_entry_secure s, force remove_entry_secure s, force
@ -485,11 +548,6 @@ module Bundler::FileUtils
alias move mv alias move mv
module_function :move module_function :move
def rename_cannot_overwrite_file? #:nodoc:
/emx/ =~ RUBY_PLATFORM
end
private_module_function :rename_cannot_overwrite_file?
# #
# Remove file(s) specified in +list+. This method cannot remove directories. # Remove file(s) specified in +list+. This method cannot remove directories.
# All StandardErrors are ignored when the :force option is set. # All StandardErrors are ignored when the :force option is set.
@ -601,8 +659,8 @@ module Bundler::FileUtils
# #
# For details of this security vulnerability, see Perl's case: # For details of this security vulnerability, see Perl's case:
# #
# * http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448 # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448
# * http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452 # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452
# #
# For fileutils.rb, this vulnerability is reported in [ruby-dev:26100]. # For fileutils.rb, this vulnerability is reported in [ruby-dev:26100].
# #
@ -626,22 +684,38 @@ module Bundler::FileUtils
unless parent_st.sticky? unless parent_st.sticky?
raise ArgumentError, "parent directory is world writable, Bundler::FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})" raise ArgumentError, "parent directory is world writable, Bundler::FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})"
end end
# freeze tree root # freeze tree root
euid = Process.euid euid = Process.euid
File.open(fullpath + '/.') {|f| dot_file = fullpath + "/."
unless fu_stat_identical_entry?(st, f.stat) begin
# symlink (TOC-to-TOU attack?) File.open(dot_file) {|f|
File.unlink fullpath unless fu_stat_identical_entry?(st, f.stat)
return # symlink (TOC-to-TOU attack?)
end File.unlink fullpath
f.chown euid, -1 return
f.chmod 0700 end
unless fu_stat_identical_entry?(st, File.lstat(fullpath)) f.chown euid, -1
# TOC-to-TOU attack? f.chmod 0700
File.unlink fullpath }
return rescue Errno::EISDIR # JRuby in non-native mode can't open files as dirs
end File.lstat(dot_file).tap {|fstat|
} unless fu_stat_identical_entry?(st, fstat)
# symlink (TOC-to-TOU attack?)
File.unlink fullpath
return
end
File.chown euid, -1, dot_file
File.chmod 0700, dot_file
}
end
unless fu_stat_identical_entry?(st, File.lstat(fullpath))
# TOC-to-TOU attack?
File.unlink fullpath
return
end
# ---- tree root is frozen ---- # ---- tree root is frozen ----
root = Entry_.new(path) root = Entry_.new(path)
root.preorder_traverse do |ent| root.preorder_traverse do |ent|
@ -742,8 +816,15 @@ module Bundler::FileUtils
# #
def compare_stream(a, b) def compare_stream(a, b)
bsize = fu_stream_blksize(a, b) bsize = fu_stream_blksize(a, b)
sa = String.new(capacity: bsize)
sb = String.new(capacity: bsize) if RUBY_VERSION > "2.4"
sa = String.new(capacity: bsize)
sb = String.new(capacity: bsize)
else
sa = String.new
sb = String.new
end
begin begin
a.read(bsize, sa) a.read(bsize, sa)
b.read(bsize, sb) b.read(bsize, sb)
@ -1001,11 +1082,6 @@ module Bundler::FileUtils
end end
module_function :chown_R module_function :chown_R
begin
require 'etc'
rescue LoadError # rescue LoadError for miniruby
end
def fu_get_uid(user) #:nodoc: def fu_get_uid(user) #:nodoc:
return nil unless user return nil unless user
case user case user
@ -1014,6 +1090,7 @@ module Bundler::FileUtils
when /\A\d+\z/ when /\A\d+\z/
user.to_i user.to_i
else else
require 'etc'
Etc.getpwnam(user) ? Etc.getpwnam(user).uid : nil Etc.getpwnam(user) ? Etc.getpwnam(user).uid : nil
end end
end end
@ -1027,6 +1104,7 @@ module Bundler::FileUtils
when /\A\d+\z/ when /\A\d+\z/
group.to_i group.to_i
else else
require 'etc'
Etc.getgrnam(group) ? Etc.getgrnam(group).gid : nil Etc.getgrnam(group) ? Etc.getgrnam(group).gid : nil
end end
end end
@ -1067,8 +1145,11 @@ module Bundler::FileUtils
module StreamUtils_ module StreamUtils_
private private
def fu_windows? case (defined?(::RbConfig) ? ::RbConfig::CONFIG['host_os'] : ::RUBY_PLATFORM)
/mswin|mingw|bccwin|emx/ =~ RUBY_PLATFORM when /mswin|mingw/
def fu_windows?; true end
else
def fu_windows?; false end
end end
def fu_copy_stream0(src, dest, blksize = nil) #:nodoc: def fu_copy_stream0(src, dest, blksize = nil) #:nodoc:
@ -1193,9 +1274,15 @@ module Bundler::FileUtils
def entries def entries
opts = {} opts = {}
opts[:encoding] = ::Encoding::UTF_8 if fu_windows? opts[:encoding] = ::Encoding::UTF_8 if fu_windows?
Dir.entries(path(), opts)\
.reject {|n| n == '.' or n == '..' }\ files = if Dir.respond_to?(:children)
.map {|n| Entry_.new(prefix(), join(rel(), n.untaint)) } Dir.children(path, opts)
else
Dir.entries(path(), opts)
.reject {|n| n == '.' or n == '..' }
end
files.map {|n| Entry_.new(prefix(), join(rel(), n.untaint)) }
end end
def stat def stat
@ -1250,6 +1337,22 @@ module Bundler::FileUtils
end end
end end
def link(dest)
case
when directory?
if !File.exist?(dest) and descendant_directory?(dest, path)
raise ArgumentError, "cannot link directory %s to itself %s" % [path, dest]
end
begin
Dir.mkdir dest
rescue
raise unless File.directory?(dest)
end
else
File.link path(), dest
end
end
def copy(dest) def copy(dest)
lstat lstat
case case

View file

@ -0,0 +1,5 @@
# frozen_string_literal: true
module Bundler::FileUtils
VERSION = "1.2.0"
end

View file

@ -50,14 +50,25 @@ module Bundler::Molinillo
incoming_edges.map(&:origin) incoming_edges.map(&:origin)
end end
# @return [Array<Vertex>] the vertices of {#graph} where `self` is a # @return [Set<Vertex>] the vertices of {#graph} where `self` is a
# {#descendent?} # {#descendent?}
def recursive_predecessors def recursive_predecessors
vertices = predecessors _recursive_predecessors
vertices += Compatibility.flat_map(vertices, &:recursive_predecessors) end
vertices.uniq!
# @param [Set<Vertex>] vertices the set to add the predecessors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is a
# {#descendent?}
def _recursive_predecessors(vertices = Set.new)
incoming_edges.each do |edge|
vertex = edge.origin
next unless vertices.add?(vertex)
vertex._recursive_predecessors(vertices)
end
vertices vertices
end end
protected :_recursive_predecessors
# @return [Array<Vertex>] the vertices of {#graph} that have an edge with # @return [Array<Vertex>] the vertices of {#graph} that have an edge with
# `self` as their {Edge#origin} # `self` as their {Edge#origin}
@ -65,14 +76,25 @@ module Bundler::Molinillo
outgoing_edges.map(&:destination) outgoing_edges.map(&:destination)
end end
# @return [Array<Vertex>] the vertices of {#graph} where `self` is an # @return [Set<Vertex>] the vertices of {#graph} where `self` is an
# {#ancestor?} # {#ancestor?}
def recursive_successors def recursive_successors
vertices = successors _recursive_successors
vertices += Compatibility.flat_map(vertices, &:recursive_successors) end
vertices.uniq!
# @param [Set<Vertex>] vertices the set to add the successors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is an
# {#ancestor?}
def _recursive_successors(vertices = Set.new)
outgoing_edges.each do |edge|
vertex = edge.destination
next unless vertices.add?(vertex)
vertex._recursive_successors(vertices)
end
vertices vertices
end end
protected :_recursive_successors
# @return [String] a string suitable for debugging # @return [String] a string suitable for debugging
def inspect def inspect

View file

@ -113,8 +113,10 @@ class Bundler::Thor
# the script started). # the script started).
# #
def relative_to_original_destination_root(path, remove_dot = true) def relative_to_original_destination_root(path, remove_dot = true)
path = path.dup root = @destination_stack[0]
if path.gsub!(@destination_stack[0], ".") if path.start_with?(root) && [File::SEPARATOR, File::ALT_SEPARATOR, nil, ''].include?(path[root.size..root.size])
path = path.dup
path[0...root.size] = '.'
remove_dot ? (path[2..-1] || "") : path remove_dot ? (path[2..-1] || "") : path
else else
path path
@ -217,6 +219,7 @@ class Bundler::Thor
shell.padding += 1 if verbose shell.padding += 1 if verbose
contents = if is_uri contents = if is_uri
require "open-uri"
open(path, "Accept" => "application/x-thor-template", &:read) open(path, "Accept" => "application/x-thor-template", &:read)
else else
open(path, &:read) open(path, &:read)
@ -252,9 +255,16 @@ class Bundler::Thor
say_status :run, desc, config.fetch(:verbose, true) say_status :run, desc, config.fetch(:verbose, true)
unless options[:pretend] return if options[:pretend]
config[:capture] ? `#{command}` : system(command.to_s)
result = config[:capture] ? `#{command}` : system(command.to_s)
if config[:abort_on_failure]
success = config[:capture] ? $?.success? : result
abort unless success
end end
result
end end
# Executes a ruby script (taking into account WIN32 platform quirks). # Executes a ruby script (taking into account WIN32 platform quirks).

View file

@ -60,6 +60,9 @@ class Bundler::Thor
# destination. If a block is given instead of destination, the content of # destination. If a block is given instead of destination, the content of
# the url is yielded and used as location. # the url is yielded and used as location.
# #
# +get+ relies on open-uri, so passing application user input would provide
# a command injection attack vector.
#
# ==== Parameters # ==== Parameters
# source<String>:: the address of the given content. # source<String>:: the address of the given content.
# destination<String>:: the relative path to the destination root. # destination<String>:: the relative path to the destination root.
@ -117,7 +120,13 @@ class Bundler::Thor
context = config.delete(:context) || instance_eval("binding") context = config.delete(:context) || instance_eval("binding")
create_file destination, nil, config do create_file destination, nil, config do
content = CapturableERB.new(::File.binread(source), nil, "-", "@output_buffer").tap do |erb| match = ERB.version.match(/(\d+\.\d+\.\d+)/)
capturable_erb = if match && match[1] >= "2.2.0" # Ruby 2.6+
CapturableERB.new(::File.binread(source), :trim_mode => "-", :eoutvar => "@output_buffer")
else
CapturableERB.new(::File.binread(source), nil, "-", "@output_buffer")
end
content = capturable_erb.tap do |erb|
erb.filename = source erb.filename = source
end.result(context) end.result(context)
content = yield(content) if block content = yield(content) if block
@ -301,7 +310,7 @@ class Bundler::Thor
def comment_lines(path, flag, *args) def comment_lines(path, flag, *args)
flag = flag.respond_to?(:source) ? flag.source : flag flag = flag.respond_to?(:source) ? flag.source : flag
gsub_file(path, /^(\s*)([^#|\n]*#{flag})/, '\1# \2', *args) gsub_file(path, /^(\s*)([^#\n]*#{flag})/, '\1# \2', *args)
end end
# Removes a file at the given location. # Removes a file at the given location.

View file

@ -113,7 +113,7 @@ class Bundler::Thor
end end
# Whenever a class inherits from Bundler::Thor or Bundler::Thor::Group, we should track the # Whenever a class inherits from Bundler::Thor or Bundler::Thor::Group, we should track the
# class and the file on Bundler::Thor::Base. This is the method responsable for it. # class and the file on Bundler::Thor::Base. This is the method responsible for it.
# #
def register_klass_file(klass) #:nodoc: def register_klass_file(klass) #:nodoc:
file = caller[1].match(/(.*):\d+/)[1] file = caller[1].match(/(.*):\d+/)[1]
@ -466,13 +466,13 @@ class Bundler::Thor
dispatch(nil, given_args.dup, nil, config) dispatch(nil, given_args.dup, nil, config)
rescue Bundler::Thor::Error => e rescue Bundler::Thor::Error => e
config[:debug] || ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message) config[:debug] || ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message)
exit(1) if exit_on_failure? exit(false) if exit_on_failure?
rescue Errno::EPIPE rescue Errno::EPIPE
# This happens if a thor command is piped to something like `head`, # This happens if a thor command is piped to something like `head`,
# which closes the pipe when it's done reading. This will also # which closes the pipe when it's done reading. This will also
# mean that if the pipe is closed, further unnecessary # mean that if the pipe is closed, further unnecessary
# computation will not occur. # computation will not occur.
exit(0) exit(true)
end end
# Allows to use private methods from parent in child classes as commands. # Allows to use private methods from parent in child classes as commands.
@ -493,8 +493,7 @@ class Bundler::Thor
alias_method :public_task, :public_command alias_method :public_task, :public_command
def handle_no_command_error(command, has_namespace = $thor_runner) #:nodoc: def handle_no_command_error(command, has_namespace = $thor_runner) #:nodoc:
raise UndefinedCommandError, "Could not find command #{command.inspect} in #{namespace.inspect} namespace." if has_namespace raise UndefinedCommandError.new(command, all_commands.keys, (namespace if has_namespace))
raise UndefinedCommandError, "Could not find command #{command.inspect}."
end end
alias_method :handle_no_task_error, :handle_no_command_error alias_method :handle_no_task_error, :handle_no_command_error

View file

@ -1,4 +1,23 @@
class Bundler::Thor class Bundler::Thor
Correctable =
begin
require 'did_you_mean'
# In order to support versions of Ruby that don't have keyword
# arguments, we need our own spell checker class that doesn't take key
# words. Even though this code wouldn't be hit because of the check
# above, it's still necessary because the interpreter would otherwise be
# unable to parse the file.
class NoKwargSpellChecker < DidYouMean::SpellChecker # :nodoc:
def initialize(dictionary)
@dictionary = dictionary
end
end
DidYouMean::Correctable
rescue LoadError, NameError
end
# Bundler::Thor::Error is raised when it's caused by wrong usage of thor classes. Those # Bundler::Thor::Error is raised when it's caused by wrong usage of thor classes. Those
# errors have their backtrace suppressed and are nicely shown to the user. # errors have their backtrace suppressed and are nicely shown to the user.
# #
@ -10,6 +29,35 @@ class Bundler::Thor
# Raised when a command was not found. # Raised when a command was not found.
class UndefinedCommandError < Error class UndefinedCommandError < Error
class SpellChecker
attr_reader :error
def initialize(error)
@error = error
end
def corrections
@corrections ||= spell_checker.correct(error.command).map(&:inspect)
end
def spell_checker
NoKwargSpellChecker.new(error.all_commands)
end
end
attr_reader :command, :all_commands
def initialize(command, all_commands, namespace)
@command = command
@all_commands = all_commands
message = "Could not find command #{command.inspect}"
message = namespace ? "#{message} in #{namespace.inspect} namespace." : "#{message}."
super(message)
end
prepend Correctable if Correctable
end end
UndefinedTaskError = UndefinedCommandError UndefinedTaskError = UndefinedCommandError
@ -22,6 +70,33 @@ class Bundler::Thor
end end
class UnknownArgumentError < Error class UnknownArgumentError < Error
class SpellChecker
attr_reader :error
def initialize(error)
@error = error
end
def corrections
@corrections ||=
error.unknown.flat_map { |unknown| spell_checker.correct(unknown) }.uniq.map(&:inspect)
end
def spell_checker
@spell_checker ||= NoKwargSpellChecker.new(error.switches)
end
end
attr_reader :switches, :unknown
def initialize(switches, unknown)
@switches = switches
@unknown = unknown
super("Unknown switches #{unknown.map(&:inspect).join(', ')}")
end
prepend Correctable if Correctable
end end
class RequiredArgumentMissingError < InvocationError class RequiredArgumentMissingError < InvocationError
@ -29,4 +104,11 @@ class Bundler::Thor
class MalformattedArgumentError < InvocationError class MalformattedArgumentError < InvocationError
end end
if Correctable
DidYouMean::SPELL_CHECKERS.merge!(
'Bundler::Thor::UndefinedCommandError' => UndefinedCommandError::SpellChecker,
'Bundler::Thor::UnknownArgumentError' => UnknownArgumentError::SpellChecker
)
end
end end

View file

@ -61,7 +61,7 @@ class Bundler::Thor::Group
invocations[name] = false invocations[name] = false
invocation_blocks[name] = block if block_given? invocation_blocks[name] = block if block_given?
class_eval <<-METHOD, __FILE__, __LINE__ class_eval <<-METHOD, __FILE__, __LINE__ + 1
def _invoke_#{name.to_s.gsub(/\W/, '_')} def _invoke_#{name.to_s.gsub(/\W/, '_')}
klass, command = self.class.prepare_for_invocation(nil, #{name.inspect}) klass, command = self.class.prepare_for_invocation(nil, #{name.inspect})
@ -120,7 +120,7 @@ class Bundler::Thor::Group
invocations[name] = true invocations[name] = true
invocation_blocks[name] = block if block_given? invocation_blocks[name] = block if block_given?
class_eval <<-METHOD, __FILE__, __LINE__ class_eval <<-METHOD, __FILE__, __LINE__ + 1
def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')} def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')}
return unless options[#{name.inspect}] return unless options[#{name.inspect}]

View file

@ -44,6 +44,7 @@ class Bundler::Thor
@shorts = {} @shorts = {}
@switches = {} @switches = {}
@extra = [] @extra = []
@stopped_parsing_after_extra_index = nil
options.each do |option| options.each do |option|
@switches[option.switch_name] = option @switches[option.switch_name] = option
@ -66,6 +67,7 @@ class Bundler::Thor
if result == OPTS_END if result == OPTS_END
shift shift
@parsing_options = false @parsing_options = false
@stopped_parsing_after_extra_index ||= @extra.size
super super
else else
result result
@ -99,6 +101,7 @@ class Bundler::Thor
elsif @stop_on_unknown elsif @stop_on_unknown
@parsing_options = false @parsing_options = false
@extra << shifted @extra << shifted
@stopped_parsing_after_extra_index ||= @extra.size
@extra << shift while peek @extra << shift while peek
break break
elsif match elsif match
@ -120,9 +123,11 @@ class Bundler::Thor
end end
def check_unknown! def check_unknown!
to_check = @stopped_parsing_after_extra_index ? @extra[0...@stopped_parsing_after_extra_index] : @extra
# an unknown option starts with - or -- and has no more --'s afterward. # an unknown option starts with - or -- and has no more --'s afterward.
unknown = @extra.select { |str| str =~ /^--?(?:(?!--).)*$/ } unknown = to_check.select { |str| str =~ /^--?(?:(?!--).)*$/ }
raise UnknownArgumentError, "Unknown switches '#{unknown.join(', ')}'" unless unknown.empty? raise UnknownArgumentError.new(@switches.keys, unknown) unless unknown.empty?
end end
protected protected

View file

@ -3,7 +3,7 @@ require "bundler/vendor/thor/lib/thor/group"
require "bundler/vendor/thor/lib/thor/core_ext/io_binary_read" require "bundler/vendor/thor/lib/thor/core_ext/io_binary_read"
require "yaml" require "yaml"
require "digest" require "digest/md5"
require "pathname" require "pathname"
class Bundler::Thor::Runner < Bundler::Thor #:nodoc: # rubocop:disable ClassLength class Bundler::Thor::Runner < Bundler::Thor #:nodoc: # rubocop:disable ClassLength
@ -90,7 +90,7 @@ class Bundler::Thor::Runner < Bundler::Thor #:nodoc: # rubocop:disable ClassLeng
end end
thor_yaml[as] = { thor_yaml[as] = {
:filename => Digest(:MD5).hexdigest(name + as), :filename => Digest::MD5.hexdigest(name + as),
:location => location, :location => location,
:namespaces => Bundler::Thor::Util.namespaces_in_content(contents, base) :namespaces => Bundler::Thor::Util.namespaces_in_content(contents, base)
} }

View file

@ -55,7 +55,7 @@ class Bundler::Thor
# Common methods that are delegated to the shell. # Common methods that are delegated to the shell.
SHELL_DELEGATED_METHODS.each do |method| SHELL_DELEGATED_METHODS.each do |method|
module_eval <<-METHOD, __FILE__, __LINE__ module_eval <<-METHOD, __FILE__, __LINE__ + 1
def #{method}(*args,&block) def #{method}(*args,&block)
shell.#{method}(*args,&block) shell.#{method}(*args,&block)
end end

View file

@ -1,6 +1,8 @@
class Bundler::Thor class Bundler::Thor
module Shell module Shell
class Basic class Basic
DEFAULT_TERMINAL_WIDTH = 80
attr_accessor :base attr_accessor :base
attr_reader :padding attr_reader :padding
@ -45,6 +47,10 @@ class Bundler::Thor
# Asks something to the user and receives a response. # Asks something to the user and receives a response.
# #
# If a default value is specified it will be presented to the user
# and allows them to select that value with an empty response. This
# option is ignored when limited answers are supplied.
#
# If asked to limit the correct responses, you can pass in an # If asked to limit the correct responses, you can pass in an
# array of acceptable answers. If one of those is not supplied, # array of acceptable answers. If one of those is not supplied,
# they will be shown a message stating that one of those answers # they will be shown a message stating that one of those answers
@ -61,6 +67,8 @@ class Bundler::Thor
# ==== Example # ==== Example
# ask("What is your name?") # ask("What is your name?")
# #
# ask("What is the planet furthest from the sun?", :default => "Pluto")
#
# ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"]) # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"])
# #
# ask("What is your password?", :echo => false) # ask("What is your password?", :echo => false)
@ -222,8 +230,20 @@ class Bundler::Thor
paras = message.split("\n\n") paras = message.split("\n\n")
paras.map! do |unwrapped| paras.map! do |unwrapped|
unwrapped.strip.tr("\n", " ").squeeze(" ").gsub(/.{1,#{width}}(?:\s|\Z)/) { ($& + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n") } counter = 0
end unwrapped.split(" ").inject do |memo, word|
word = word.gsub(/\n\005/, "\n").gsub(/\005/, "\n")
counter = 0 if word.include? "\n"
if (counter + word.length + 1) < width
memo = "#{memo} #{word}"
counter += (word.length + 1)
else
memo = "#{memo}\n#{word}"
counter = word.length
end
memo
end
end.compact!
paras.each do |para| paras.each do |para|
para.split("\n").each do |line| para.split("\n").each do |line|
@ -239,11 +259,11 @@ class Bundler::Thor
# #
# ==== Parameters # ==== Parameters
# destination<String>:: the destination file to solve conflicts # destination<String>:: the destination file to solve conflicts
# block<Proc>:: an optional block that returns the value to be used in diff # block<Proc>:: an optional block that returns the value to be used in diff and merge
# #
def file_collision(destination) def file_collision(destination)
return true if @always_force return true if @always_force
options = block_given? ? "[Ynaqdh]" : "[Ynaqh]" options = block_given? ? "[Ynaqdhm]" : "[Ynaqh]"
loop do loop do
answer = ask( answer = ask(
@ -267,6 +287,13 @@ class Bundler::Thor
when is?(:diff) when is?(:diff)
show_diff(destination, yield) if block_given? show_diff(destination, yield) if block_given?
say "Retrying..." say "Retrying..."
when is?(:merge)
if block_given? && !merge_tool.empty?
merge(destination, yield)
return nil
end
say "Please specify merge tool to `THOR_MERGE` env."
else else
say file_collision_help say file_collision_help
end end
@ -279,11 +306,11 @@ class Bundler::Thor
result = if ENV["THOR_COLUMNS"] result = if ENV["THOR_COLUMNS"]
ENV["THOR_COLUMNS"].to_i ENV["THOR_COLUMNS"].to_i
else else
unix? ? dynamic_width : 80 unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH
end end
result < 10 ? 80 : result result < 10 ? DEFAULT_TERMINAL_WIDTH : result
rescue rescue
80 DEFAULT_TERMINAL_WIDTH
end end
# Called if something goes wrong during the execution. This is used by Bundler::Thor # Called if something goes wrong during the execution. This is used by Bundler::Thor
@ -344,6 +371,7 @@ class Bundler::Thor
q - quit, abort q - quit, abort
d - diff, show the differences between the old and the new d - diff, show the differences between the old and the new
h - help, show this help h - help, show this help
m - merge, run merge tool
HELP HELP
end end
@ -432,6 +460,23 @@ class Bundler::Thor
end end
correct_answer correct_answer
end end
def merge(destination, content) #:nodoc:
require "tempfile"
Tempfile.open([File.basename(destination), File.extname(destination)], File.dirname(destination)) do |temp|
temp.write content
temp.rewind
system %(#{merge_tool} "#{temp.path}" "#{destination}")
end
end
def merge_tool #:nodoc:
@merge_tool ||= ENV["THOR_MERGE"] || git_merge_tool
end
def git_merge_tool #:nodoc:
`git config merge.tool`.rstrip rescue ""
end
end end
end end
end end

View file

@ -27,7 +27,7 @@ class Bundler::Thor
end end
# Receives a constant and converts it to a Bundler::Thor namespace. Since Bundler::Thor # Receives a constant and converts it to a Bundler::Thor namespace. Since Bundler::Thor
# commands can be added to a sandbox, this method is also responsable for # commands can be added to a sandbox, this method is also responsible for
# removing the sandbox namespace. # removing the sandbox namespace.
# #
# This method should not be used in general because it's used to deal with # This method should not be used in general because it's used to deal with

View file

@ -1,3 +1,3 @@
class Bundler::Thor class Bundler::Thor
VERSION = "0.20.0" VERSION = "0.20.3"
end end

View file

@ -1,13 +1,10 @@
# frozen_string_literal: false # frozen_string_literal: false
# Ruby 1.9.3 and old RubyGems don't play nice with frozen version strings
# rubocop:disable MutableConstant
module Bundler module Bundler
# We're doing this because we might write tests that deal # We're doing this because we might write tests that deal
# with other versions of bundler and we are unsure how to # with other versions of bundler and we are unsure how to
# handle this better. # handle this better.
VERSION = "2.0.1" unless defined?(::Bundler::VERSION) VERSION = "2.1.0.pre.1".freeze unless defined?(::Bundler::VERSION)
def self.overwrite_loaded_gem_version def self.overwrite_loaded_gem_version
begin begin

View file

@ -5,11 +5,42 @@ module Bundler
NEq = Struct.new(:version) NEq = Struct.new(:version)
ReqR = Struct.new(:left, :right) ReqR = Struct.new(:left, :right)
class ReqR class ReqR
Endpoint = Struct.new(:version, :inclusive) Endpoint = Struct.new(:version, :inclusive) do
def <=>(other)
if version.equal?(INFINITY)
return 0 if other.version.equal?(INFINITY)
return 1
elsif other.version.equal?(INFINITY)
return -1
end
comp = version <=> other.version
return comp unless comp.zero?
if inclusive && !other.inclusive
1
elsif !inclusive && other.inclusive
-1
else
0
end
end
end
def to_s def to_s
"#{left.inclusive ? "[" : "("}#{left.version}, #{right.version}#{right.inclusive ? "]" : ")"}" "#{left.inclusive ? "[" : "("}#{left.version}, #{right.version}#{right.inclusive ? "]" : ")"}"
end end
INFINITY = Object.new.freeze INFINITY = begin
inf = Object.new
def inf.to_s
""
end
def inf.<=>(other)
return 0 if other.equal?(self)
1
end
inf.freeze
end
ZERO = Gem::Version.new("0.a") ZERO = Gem::Version.new("0.a")
def cover?(v) def cover?(v)
@ -32,6 +63,15 @@ module Bundler
left.version == right.version left.version == right.version
end end
def <=>(other)
return -1 if other.equal?(INFINITY)
comp = left <=> other.left
return comp unless comp.zero?
right <=> other.right
end
UNIVERSAL = ReqR.new(ReqR::Endpoint.new(Gem::Version.new("0.a"), true), ReqR::Endpoint.new(ReqR::INFINITY, false)).freeze UNIVERSAL = ReqR.new(ReqR::Endpoint.new(Gem::Version.new("0.a"), true), ReqR::Endpoint.new(ReqR::INFINITY, false)).freeze
end end
@ -57,7 +97,7 @@ module Bundler
end.uniq end.uniq
ranges, neqs = ranges.partition {|r| !r.is_a?(NEq) } ranges, neqs = ranges.partition {|r| !r.is_a?(NEq) }
[ranges.sort_by {|range| [range.left.version, range.left.inclusive ? 0 : 1] }, neqs.map(&:version)] [ranges.sort, neqs.map(&:version)]
end end
def self.empty?(ranges, neqs) def self.empty?(ranges, neqs)
@ -66,8 +106,14 @@ module Bundler
next false if curr_range.single? && neqs.include?(curr_range.left.version) next false if curr_range.single? && neqs.include?(curr_range.left.version)
next curr_range if last_range.right.version == ReqR::INFINITY next curr_range if last_range.right.version == ReqR::INFINITY
case last_range.right.version <=> curr_range.left.version case last_range.right.version <=> curr_range.left.version
when 1 then next curr_range # higher
when 0 then next(last_range.right.inclusive && curr_range.left.inclusive && !neqs.include?(curr_range.left.version) && curr_range) when 1 then next ReqR.new(curr_range.left, last_range.right)
# equal
when 0
if last_range.right.inclusive && curr_range.left.inclusive && !neqs.include?(curr_range.left.version)
ReqR.new(curr_range.left, [curr_range.right, last_range.right].max)
end
# lower
when -1 then next false when -1 then next false
end end
end end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "bundler/shared_helpers" require "bundler/shared_helpers"
Bundler::SharedHelpers.major_deprecation 3, Bundler::SharedHelpers.major_deprecation 2,
"The Bundler task for Vlad" "The Bundler task for Vlad"
# Vlad task for Bundler. # Vlad task for Bundler.

View file

@ -1,7 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
require "thread"
module Bundler module Bundler
class Worker class Worker
POISON = Object.new POISON = Object.new
@ -62,7 +60,7 @@ module Bundler
def apply_func(obj, i) def apply_func(obj, i)
@func.call(obj, i) @func.call(obj, i)
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
WrappedException.new(e) WrappedException.new(e)
end end

View file

@ -32,7 +32,7 @@ module Bundler
(.*) # value (.*) # value
\1 # matching closing quote \1 # matching closing quote
$ $
/xo /xo.freeze
HASH_REGEX = / HASH_REGEX = /
^ ^
@ -40,12 +40,11 @@ module Bundler
(.+) # key (.+) # key
(?::(?=(?:\s|$))) # : (without the lookahead the #key includes this when : is present in value) (?::(?=(?:\s|$))) # : (without the lookahead the #key includes this when : is present in value)
[ ]? [ ]?
(?: !\s)? # optional exclamation mark found with ruby 1.9.3
(['"]?) # optional opening quote (['"]?) # optional opening quote
(.*) # value (.*) # value
\3 # matching closing quote \3 # matching closing quote
$ $
/xo /xo.freeze
def load(str) def load(str)
res = {} res = {}

View file

@ -1,60 +0,0 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require "bundler/shared_helpers"
Bundler::SharedHelpers.major_deprecation(3, "the bundle_ruby executable has been removed in favor of `bundle platform --ruby`")
Signal.trap("INT") { exit 1 }
require "bundler/errors"
require "bundler/ruby_version"
require "bundler/ruby_dsl"
module Bundler
class Dsl
include RubyDsl
attr_accessor :ruby_version
def initialize
@ruby_version = nil
end
def eval_gemfile(gemfile, contents = nil)
contents ||= File.open(gemfile, "rb", &:read)
instance_eval(contents, gemfile.to_s, 1)
rescue SyntaxError => e
bt = e.message.split("\n")[1..-1]
raise GemfileError, ["Gemfile syntax error:", *bt].join("\n")
rescue ScriptError, RegexpError, NameError, ArgumentError => e
e.backtrace[0] = "#{e.backtrace[0]}: #{e.message} (#{e.class})"
STDERR.puts e.backtrace.join("\n ")
raise GemfileError, "There was an error in your Gemfile," \
" and Bundler cannot continue."
end
def source(source, options = {})
end
def gem(name, *args)
end
def group(*args)
end
end
end
dsl = Bundler::Dsl.new
begin
dsl.eval_gemfile(Bundler::SharedHelpers.default_gemfile)
ruby_version = dsl.ruby_version
if ruby_version
puts ruby_version
else
puts "No ruby version specified"
end
rescue Bundler::GemfileError => e
puts e.message
exit(-1)
end

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-ADD" "1" "November 2018" "" "" .TH "BUNDLE\-ADD" "1" "March 2019" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install

View file

@ -2,16 +2,16 @@ BUNDLE-ADD(1) BUNDLE-ADD(1)
1mNAME0m NAME
1mbundle-add 22m- Add gem to the Gemfile and run bundle install bundle-add - Add gem to the Gemfile and run bundle install
1mSYNOPSIS0m SYNOPSIS
1mbundle add 4m22mGEM_NAME24m [--group=GROUP] [--version=VERSION] bundle add GEM_NAME [--group=GROUP] [--version=VERSION]
[--source=SOURCE] [--skip-install] [--strict] [--optimistic] [--source=SOURCE] [--skip-install] [--strict] [--optimistic]
1mDESCRIPTION0m DESCRIPTION
Adds the named gem to the Gemfile and run 1mbundle install22m. 1mbundle in-0m Adds the named gem to the Gemfile and run bundle install. bundle
1mstall 22mcan be avoided by using the flag 1m--skip-install22m. install can be avoided by using the flag --skip-install.
Example: Example:
@ -26,27 +26,27 @@ BUNDLE-ADD(1) BUNDLE-ADD(1)
bundle add rails --group "development, test" bundle add rails --group "development, test"
1mOPTIONS0m OPTIONS
1m--version22m, 1m-v0m --version, -v
Specify version requirements(s) for the added gem. Specify version requirements(s) for the added gem.
1m--group22m, 1m-g0m --group, -g
Specify the group(s) for the added gem. Multiple groups should Specify the group(s) for the added gem. Multiple groups should
be separated by commas. be separated by commas.
1m--source22m, , 1m-s0m --source, , -s
Specify the source for the added gem. Specify the source for the added gem.
1m--skip-install0m --skip-install
Adds the gem to the Gemfile but does not install it. Adds the gem to the Gemfile but does not install it.
1m--optimistic0m --optimistic
Adds optimistic declaration of version Adds optimistic declaration of version
1m--strict0m --strict
Adds strict declaration of version Adds strict declaration of version
November 2018 BUNDLE-ADD(1) March 2019 BUNDLE-ADD(1)

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-BINSTUBS" "1" "November 2018" "" "" .TH "BUNDLE\-BINSTUBS" "1" "March 2019" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems

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