summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBundlerbot <bot@bundler.io>2019-03-26 00:37:48 +0000
committerBundlerbot <bot@bundler.io>2019-03-26 00:37:48 +0000
commit6f39ea5b15d61e5bdf7915bc94d66c31b1242d15 (patch)
tree9fe72e6e4588331a3e5e8e8381aafc837089b94b
parentaaa0b0ce6a447aa0f01301799f3163832da6566d (diff)
parent16223dcfbc0176ba6a1e855890fa36172ec8b9de (diff)
downloadbundler-6f39ea5b15d61e5bdf7915bc94d66c31b1242d15.tar.gz
Merge #7067
7067: Tweaking vendoring r=hsbt a=deivid-rodriguez ### What was the end-user problem that led to this PR? The problem was that we were not using the latest versions of some of our vendored dependencies. ### What was your diagnosis of the problem? My diagnosis was that we should upgrade them. ### What is your fix for the problem, implemented in this PR? My fix is to upgrade them using `automatiek`, and add a few tweaks to our vendoring setup. ### Why did you choose this fix out of the possible options? I chose this fix because.... I didn't really considered other options. Co-authored-by: David Rodríguez <deivid.rodriguez@riseup.net>
-rw-r--r--Rakefile41
-rw-r--r--lib/bundler/vendor/fileutils/lib/fileutils.rb149
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions.rb18
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb13
-rw-r--r--lib/bundler/vendor/thor/lib/thor/base.rb7
-rw-r--r--lib/bundler/vendor/thor/lib/thor/error.rb82
-rw-r--r--lib/bundler/vendor/thor/lib/thor/group.rb4
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/options.rb9
-rw-r--r--lib/bundler/vendor/thor/lib/thor/runner.rb4
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/basic.rb59
-rw-r--r--lib/bundler/vendor/thor/lib/thor/version.rb2
12 files changed, 328 insertions, 62 deletions
diff --git a/Rakefile b/Rakefile
index 597564736e..d64e9cc789 100644
--- a/Rakefile
+++ b/Rakefile
@@ -10,8 +10,8 @@ else
File.expand_path("tmp/rubygems")
end
-def bundler_spec
- @bundler_spec ||= Gem::Specification.load("bundler.gemspec")
+def development_dependencies
+ @development_dependencies ||= Gem::Specification.load("bundler.gemspec").development_dependencies
end
# Benchmark task execution
@@ -43,7 +43,7 @@ namespace :spec do
desc "Ensure spec dependencies are installed"
task :deps do
- deps = Hash[bundler_spec.development_dependencies.map do |d|
+ deps = Hash[development_dependencies.map do |d|
[d.name, d.requirement.to_s]
end]
@@ -228,7 +228,7 @@ task :rubocop do
end
namespace :man do
- ronn_dep = bundler_spec.development_dependencies.find do |dep|
+ ronn_dep = development_dependencies.find do |dep|
dep.name == "ronn"
end
@@ -297,9 +297,32 @@ namespace :man do
end
end
+automatiek_dep = development_dependencies.find do |dep|
+ dep.name == "automatiek"
+end
+
+automatiek_requirement = automatiek_dep.requirement.to_s
+
begin
+ gem "automatiek", automatiek_requirement
+
require "automatiek"
+rescue LoadError
+ namespace :vendor do
+ desc "Vendor a specific version of molinillo"
+ task(:molinillo) { abort "We couldn't activate automatiek (#{automatiek_requirement}). Try `gem install automatiek:'#{automatiek_requirement}'` to be able to vendor gems" }
+
+ desc "Vendor a specific version of fileutils"
+ task(:fileutils) { abort "We couldn't activate automatiek (#{automatiek_requirement}). Try `gem install automatiek:'#{automatiek_requirement}'` to be able to vendor gems" }
+ desc "Vendor a specific version of thor"
+ task(:thor) { abort "We couldn't activate automatiek (#{automatiek_requirement}). Try `gem install automatiek:'#{automatiek_requirement}'` to be able to vendor gems" }
+
+ desc "Vendor a specific version of net-http-persistent"
+ task(:"net-http-persistent") { abort "We couldn't activate automatiek (#{automatiek_requirement}). Try `gem install automatiek:'#{automatiek_requirement}'` to be able to vendor gems" }
+ end
+else
+ desc "Vendor a specific version of molinillo"
Automatiek::RakeTask.new("molinillo") do |lib|
lib.download = { :github => "https://github.com/CocoaPods/Molinillo" }
lib.namespace = "Molinillo"
@@ -307,6 +330,7 @@ begin
lib.vendor_lib = "lib/bundler/vendor/molinillo"
end
+ desc "Vendor a specific version of thor"
Automatiek::RakeTask.new("thor") do |lib|
lib.download = { :github => "https://github.com/erikhuda/thor" }
lib.namespace = "Thor"
@@ -314,6 +338,7 @@ begin
lib.vendor_lib = "lib/bundler/vendor/thor"
end
+ desc "Vendor a specific version of fileutils"
Automatiek::RakeTask.new("fileutils") do |lib|
lib.download = { :github => "https://github.com/ruby/fileutils" }
lib.namespace = "FileUtils"
@@ -321,6 +346,7 @@ begin
lib.vendor_lib = "lib/bundler/vendor/fileutils"
end
+ desc "Vendor a specific version of net-http-persistent"
Automatiek::RakeTask.new("net-http-persistent") do |lib|
lib.download = { :github => "https://github.com/drbrain/net-http-persistent" }
lib.namespace = "Net::HTTP::Persistent"
@@ -337,13 +363,6 @@ begin
end
lib.send(:extend, mixin)
end
-rescue LoadError
- namespace :vendor do
- task(:fileutils) { abort "Install the automatiek gem to be able to vendor gems." }
- task(:molinillo) { abort "Install the automatiek gem to be able to vendor gems." }
- task(:thor) { abort "Install the automatiek gem to be able to vendor gems." }
- task("net-http-persistent") { abort "Install the automatiek gem to be able to vendor gems." }
- end
end
task :override_version do
diff --git a/lib/bundler/vendor/fileutils/lib/fileutils.rb b/lib/bundler/vendor/fileutils/lib/fileutils.rb
index cc69740845..77b3bade52 100644
--- a/lib/bundler/vendor/fileutils/lib/fileutils.rb
+++ b/lib/bundler/vendor/fileutils/lib/fileutils.rb
@@ -85,8 +85,12 @@
# <tt>:verbose</tt> flags to methods in Bundler::FileUtils.
#
+require 'rbconfig'
+
module Bundler::FileUtils
+ VERSION = "1.1.0"
+
def self.private_module_function(name) #:nodoc:
module_function name
private_class_method name
@@ -117,8 +121,9 @@ module Bundler::FileUtils
#
def cd(dir, verbose: nil, &block) # :yield: dir
fu_output_message "cd #{dir}" if verbose
- Dir.chdir(dir, &block)
+ result = Dir.chdir(dir, &block)
fu_output_message 'cd -' if verbose and block
+ result
end
module_function :cd
@@ -245,15 +250,15 @@ module Bundler::FileUtils
fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if verbose
return if noop
list.each do |dir|
- begin
- Dir.rmdir(dir = remove_trailing_slash(dir))
- if parents
+ Dir.rmdir(dir = remove_trailing_slash(dir))
+ if parents
+ begin
until (parent = File.dirname(dir)) == '.' or parent == dir
dir = parent
Dir.rmdir(dir)
end
+ rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
end
- rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
end
end
end
@@ -295,6 +300,39 @@ module Bundler::FileUtils
#
# :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:
# Bundler::FileUtils.ln_s(target, link, force: nil, noop: nil, verbose: nil)
# Bundler::FileUtils.ln_s(target, dir, force: nil, noop: nil, verbose: nil)
# Bundler::FileUtils.ln_s(targets, dir, force: nil, noop: nil, verbose: nil)
@@ -340,6 +378,26 @@ module Bundler::FileUtils
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 +src+ to +dest/src+.
#
@@ -412,7 +470,7 @@ module Bundler::FileUtils
def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
Entry_.new(src, nil, dereference_root).wrap_traverse(proc do |ent|
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
end, proc do |ent|
destent = Entry_.new(dest, ent.rel, false)
@@ -486,7 +544,7 @@ module Bundler::FileUtils
module_function :move
def rename_cannot_overwrite_file? #:nodoc:
- /emx/ =~ RUBY_PLATFORM
+ /emx/ =~ RbConfig::CONFIG['host_os']
end
private_module_function :rename_cannot_overwrite_file?
@@ -601,8 +659,8 @@ module Bundler::FileUtils
#
# For details of this security vulnerability, see Perl's case:
#
- # * http://www.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-2005-0448
+ # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452
#
# For fileutils.rb, this vulnerability is reported in [ruby-dev:26100].
#
@@ -626,22 +684,38 @@ module Bundler::FileUtils
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})"
end
+
# freeze tree root
euid = Process.euid
- File.open(fullpath + '/.') {|f|
- unless fu_stat_identical_entry?(st, f.stat)
- # symlink (TOC-to-TOU attack?)
- File.unlink fullpath
- return
- end
- f.chown euid, -1
- f.chmod 0700
- unless fu_stat_identical_entry?(st, File.lstat(fullpath))
- # TOC-to-TOU attack?
- File.unlink fullpath
- return
- end
- }
+ dot_file = fullpath + "/."
+ begin
+ File.open(dot_file) {|f|
+ unless fu_stat_identical_entry?(st, f.stat)
+ # symlink (TOC-to-TOU attack?)
+ File.unlink fullpath
+ return
+ end
+ f.chown euid, -1
+ f.chmod 0700
+ }
+ rescue EISDIR # JRuby in non-native mode can't open files as dirs
+ 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 ----
root = Entry_.new(path)
root.preorder_traverse do |ent|
@@ -742,8 +816,15 @@ module Bundler::FileUtils
#
def compare_stream(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
a.read(bsize, sa)
b.read(bsize, sb)
@@ -1068,7 +1149,7 @@ module Bundler::FileUtils
private
def fu_windows?
- /mswin|mingw|bccwin|emx/ =~ RUBY_PLATFORM
+ /mswin|mingw|bccwin|emx/ =~ RbConfig::CONFIG['host_os']
end
def fu_copy_stream0(src, dest, blksize = nil) #:nodoc:
@@ -1250,6 +1331,22 @@ module Bundler::FileUtils
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)
lstat
case
diff --git a/lib/bundler/vendor/thor/lib/thor/actions.rb b/lib/bundler/vendor/thor/lib/thor/actions.rb
index e6698572a9..b06feac2a0 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions.rb
@@ -113,8 +113,10 @@ class Bundler::Thor
# the script started).
#
def relative_to_original_destination_root(path, remove_dot = true)
- path = path.dup
- if path.gsub!(@destination_stack[0], ".")
+ root = @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
else
path
@@ -217,6 +219,7 @@ class Bundler::Thor
shell.padding += 1 if verbose
contents = if is_uri
+ require "open-uri"
open(path, "Accept" => "application/x-thor-template", &:read)
else
open(path, &:read)
@@ -252,9 +255,16 @@ class Bundler::Thor
say_status :run, desc, config.fetch(:verbose, true)
- unless options[:pretend]
- config[:capture] ? `#{command}` : system(command.to_s)
+ return if options[:pretend]
+
+ result = config[:capture] ? `#{command}` : system(command.to_s)
+
+ if config[:abort_on_failure]
+ success = config[:capture] ? $?.success? : result
+ abort unless success
end
+
+ result
end
# Executes a ruby script (taking into account WIN32 platform quirks).
diff --git a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
index 4c83bebc86..cc29db05a8 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
@@ -60,6 +60,9 @@ class Bundler::Thor
# destination. If a block is given instead of destination, the content of
# 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
# source<String>:: the address of the given content.
# destination<String>:: the relative path to the destination root.
@@ -117,7 +120,13 @@ class Bundler::Thor
context = config.delete(:context) || instance_eval("binding")
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
end.result(context)
content = yield(content) if block
@@ -301,7 +310,7 @@ class Bundler::Thor
def comment_lines(path, flag, *args)
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
# Removes a file at the given location.
diff --git a/lib/bundler/vendor/thor/lib/thor/base.rb b/lib/bundler/vendor/thor/lib/thor/base.rb
index 7e41dc226b..e79d03d087 100644
--- a/lib/bundler/vendor/thor/lib/thor/base.rb
+++ b/lib/bundler/vendor/thor/lib/thor/base.rb
@@ -466,13 +466,13 @@ class Bundler::Thor
dispatch(nil, given_args.dup, nil, config)
rescue Bundler::Thor::Error => e
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
# This happens if a thor command is piped to something like `head`,
# which closes the pipe when it's done reading. This will also
# mean that if the pipe is closed, further unnecessary
# computation will not occur.
- exit(0)
+ exit(true)
end
# 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
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, "Could not find command #{command.inspect}."
+ raise UndefinedCommandError.new(command, all_commands.keys, (namespace if has_namespace))
end
alias_method :handle_no_task_error, :handle_no_command_error
diff --git a/lib/bundler/vendor/thor/lib/thor/error.rb b/lib/bundler/vendor/thor/lib/thor/error.rb
index 2f816081f3..16c68294e4 100644
--- a/lib/bundler/vendor/thor/lib/thor/error.rb
+++ b/lib/bundler/vendor/thor/lib/thor/error.rb
@@ -1,4 +1,23 @@
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
# 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.
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
UndefinedTaskError = UndefinedCommandError
@@ -22,6 +70,33 @@ class Bundler::Thor
end
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
class RequiredArgumentMissingError < InvocationError
@@ -29,4 +104,11 @@ class Bundler::Thor
class MalformattedArgumentError < InvocationError
end
+
+ if Correctable
+ DidYouMean::SPELL_CHECKERS.merge!(
+ 'Bundler::Thor::UndefinedCommandError' => UndefinedCommandError::SpellChecker,
+ 'Bundler::Thor::UnknownArgumentError' => UnknownArgumentError::SpellChecker
+ )
+ end
end
diff --git a/lib/bundler/vendor/thor/lib/thor/group.rb b/lib/bundler/vendor/thor/lib/thor/group.rb
index 05ddc10cd3..30db46529e 100644
--- a/lib/bundler/vendor/thor/lib/thor/group.rb
+++ b/lib/bundler/vendor/thor/lib/thor/group.rb
@@ -61,7 +61,7 @@ class Bundler::Thor::Group
invocations[name] = false
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/, '_')}
klass, command = self.class.prepare_for_invocation(nil, #{name.inspect})
@@ -120,7 +120,7 @@ class Bundler::Thor::Group
invocations[name] = true
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/, '_')}
return unless options[#{name.inspect}]
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/options.rb b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
index 70f6366842..179f4fa015 100644
--- a/lib/bundler/vendor/thor/lib/thor/parser/options.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
@@ -44,6 +44,7 @@ class Bundler::Thor
@shorts = {}
@switches = {}
@extra = []
+ @stopped_parsing_after_extra_index = nil
options.each do |option|
@switches[option.switch_name] = option
@@ -66,6 +67,7 @@ class Bundler::Thor
if result == OPTS_END
shift
@parsing_options = false
+ @stopped_parsing_after_extra_index ||= @extra.size
super
else
result
@@ -99,6 +101,7 @@ class Bundler::Thor
elsif @stop_on_unknown
@parsing_options = false
@extra << shifted
+ @stopped_parsing_after_extra_index ||= @extra.size
@extra << shift while peek
break
elsif match
@@ -120,9 +123,11 @@ class Bundler::Thor
end
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.
- unknown = @extra.select { |str| str =~ /^--?(?:(?!--).)*$/ }
- raise UnknownArgumentError, "Unknown switches '#{unknown.join(', ')}'" unless unknown.empty?
+ unknown = to_check.select { |str| str =~ /^--?(?:(?!--).)*$/ }
+ raise UnknownArgumentError.new(@switches.keys, unknown) unless unknown.empty?
end
protected
diff --git a/lib/bundler/vendor/thor/lib/thor/runner.rb b/lib/bundler/vendor/thor/lib/thor/runner.rb
index b110b8d478..65ae422d7f 100644
--- a/lib/bundler/vendor/thor/lib/thor/runner.rb
+++ b/lib/bundler/vendor/thor/lib/thor/runner.rb
@@ -3,7 +3,7 @@ require "bundler/vendor/thor/lib/thor/group"
require "bundler/vendor/thor/lib/thor/core_ext/io_binary_read"
require "yaml"
-require "digest"
+require "digest/md5"
require "pathname"
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
thor_yaml[as] = {
- :filename => Digest(:MD5).hexdigest(name + as),
+ :filename => Digest::MD5.hexdigest(name + as),
:location => location,
:namespaces => Bundler::Thor::Util.namespaces_in_content(contents, base)
}
diff --git a/lib/bundler/vendor/thor/lib/thor/shell.rb b/lib/bundler/vendor/thor/lib/thor/shell.rb
index e945549324..a68cdf8a98 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell.rb
@@ -55,7 +55,7 @@ class Bundler::Thor
# Common methods that are delegated to the shell.
SHELL_DELEGATED_METHODS.each do |method|
- module_eval <<-METHOD, __FILE__, __LINE__
+ module_eval <<-METHOD, __FILE__, __LINE__ + 1
def #{method}(*args,&block)
shell.#{method}(*args,&block)
end
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
index 5162390efd..52648fee8f 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
@@ -1,6 +1,8 @@
class Bundler::Thor
module Shell
class Basic
+ DEFAULT_TERMINAL_WIDTH = 80
+
attr_accessor :base
attr_reader :padding
@@ -45,6 +47,10 @@ class Bundler::Thor
# 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
# array of acceptable answers. If one of those is not supplied,
# they will be shown a message stating that one of those answers
@@ -61,6 +67,8 @@ class Bundler::Thor
# ==== Example
# 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 password?", :echo => false)
@@ -222,8 +230,20 @@ class Bundler::Thor
paras = message.split("\n\n")
paras.map! do |unwrapped|
- unwrapped.strip.tr("\n", " ").squeeze(" ").gsub(/.{1,#{width}}(?:\s|\Z)/) { ($& + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n") }
- end
+ counter = 0
+ 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|
para.split("\n").each do |line|
@@ -239,11 +259,11 @@ class Bundler::Thor
#
# ==== Parameters
# 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)
return true if @always_force
- options = block_given? ? "[Ynaqdh]" : "[Ynaqh]"
+ options = block_given? ? "[Ynaqdhm]" : "[Ynaqh]"
loop do
answer = ask(
@@ -267,6 +287,13 @@ class Bundler::Thor
when is?(:diff)
show_diff(destination, yield) if block_given?
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
say file_collision_help
end
@@ -279,11 +306,11 @@ class Bundler::Thor
result = if ENV["THOR_COLUMNS"]
ENV["THOR_COLUMNS"].to_i
else
- unix? ? dynamic_width : 80
+ unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH
end
- result < 10 ? 80 : result
+ result < 10 ? DEFAULT_TERMINAL_WIDTH : result
rescue
- 80
+ DEFAULT_TERMINAL_WIDTH
end
# Called if something goes wrong during the execution. This is used by Bundler::Thor
@@ -344,6 +371,7 @@ class Bundler::Thor
q - quit, abort
d - diff, show the differences between the old and the new
h - help, show this help
+ m - merge, run merge tool
HELP
end
@@ -432,6 +460,23 @@ class Bundler::Thor
end
correct_answer
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
diff --git a/lib/bundler/vendor/thor/lib/thor/version.rb b/lib/bundler/vendor/thor/lib/thor/version.rb
index df8f18821a..98f2b79081 100644
--- a/lib/bundler/vendor/thor/lib/thor/version.rb
+++ b/lib/bundler/vendor/thor/lib/thor/version.rb
@@ -1,3 +1,3 @@
class Bundler::Thor
- VERSION = "0.20.0"
+ VERSION = "0.20.3"
end