diff --git a/lib/bundler/vendor/thor/lib/thor.rb b/lib/bundler/vendor/thor/lib/thor.rb index f2a03388cc3..01c0b2f83c8 100644 --- a/lib/bundler/vendor/thor/lib/thor.rb +++ b/lib/bundler/vendor/thor/lib/thor.rb @@ -344,6 +344,13 @@ def disable_required_check?(command) #:nodoc: command && disable_required_check.include?(command.name.to_sym) end + def deprecation_warning(message) #:nodoc: + unless ENV['THOR_SILENCE_DEPRECATION'] + warn "Deprecation warning: #{message}\n" + + 'You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.' + end + end + protected def stop_on_unknown_option #:nodoc: diff --git a/lib/bundler/vendor/thor/lib/thor/actions.rb b/lib/bundler/vendor/thor/lib/thor/actions.rb index 39ce67e1420..a5368d07f30 100644 --- a/lib/bundler/vendor/thor/lib/thor/actions.rb +++ b/lib/bundler/vendor/thor/lib/thor/actions.rb @@ -1,5 +1,3 @@ -require "uri" -require_relative "core_ext/io_binary_read" require_relative "actions/create_file" require_relative "actions/create_link" require_relative "actions/directory" @@ -258,13 +256,19 @@ def run(command, config = {}) return if options[:pretend] - result = config[:capture] ? `#{command}` : system(command.to_s) + env_splat = [config[:env]] if config[:env] - if config[:abort_on_failure] - success = config[:capture] ? $?.success? : result - abort unless success + if config[:capture] + require "open3" + result, status = Open3.capture2e(*env_splat, command.to_s) + success = status.success? + else + result = system(*env_splat, command.to_s) + success = result end + abort if !success && config.fetch(:abort_on_failure, self.class.exit_on_failure?) + result end diff --git a/lib/bundler/vendor/thor/lib/thor/base.rb b/lib/bundler/vendor/thor/lib/thor/base.rb index 6089fd3dc4f..bd2ebb61565 100644 --- a/lib/bundler/vendor/thor/lib/thor/base.rb +++ b/lib/bundler/vendor/thor/lib/thor/base.rb @@ -153,17 +153,20 @@ def check_unknown_options?(config) #:nodoc: # If you want to raise an error when the default value of an option does not match # the type call check_default_type! - # This is disabled by default for compatibility. + # This will be the default; for compatibility a deprecation warning is issued if necessary. def check_default_type! @check_default_type = true end - def check_default_type #:nodoc: - @check_default_type ||= from_superclass(:check_default_type, false) + # If you want to use defaults that don't match the type of an option, + # either specify `check_default_type: false` or call `allow_incompatible_default_type!` + def allow_incompatible_default_type! + @check_default_type = false end - def check_default_type? #:nodoc: - !!check_default_type + def check_default_type #:nodoc: + @check_default_type = from_superclass(:check_default_type, nil) unless defined?(@check_default_type) + @check_default_type end # If true, option parsing is suspended as soon as an unknown option or a @@ -506,6 +509,12 @@ def handle_argument_error(command, error, args, arity) #:nodoc: raise InvocationError, msg end + # A flag that makes the process exit with status 1 if any error happens. + def exit_on_failure? + Bundler::Thor.deprecation_warning "Bundler::Thor exit with status 0 on errors. To keep this behavior, you must define `exit_on_failure?` in `#{self.name}`" + false + end + protected # Prints the class options per group. If an option does not belong to @@ -563,7 +572,7 @@ def is_thor_reserved_word?(word, type) #:nodoc: # options:: Described in both class_option and method_option. # scope:: Options hash that is being built up def build_option(name, options, scope) #:nodoc: - scope[name] = Bundler::Thor::Option.new(name, options.merge(:check_default_type => check_default_type?)) + scope[name] = Bundler::Thor::Option.new(name, {:check_default_type => check_default_type}.merge!(options)) end # Receives a hash of options, parse them and add to the scope. This is a @@ -643,11 +652,6 @@ def from_superclass(method, default = nil) end end - # A flag that makes the process exit with status 1 if any error happens. - def exit_on_failure? - false - end - # # The basename of the program invoking the thor class. # diff --git a/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb deleted file mode 100644 index 0f6e2e0af2f..00000000000 --- a/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +++ /dev/null @@ -1,12 +0,0 @@ -class IO #:nodoc: - class << self - unless method_defined? :binread - def binread(file, *args) - raise ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3 - File.open(file, "rb") do |f| - f.read(*args) - end - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb b/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb index a17a3fcf22a..d0f43e2d971 100644 --- a/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +++ b/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb @@ -82,7 +82,7 @@ def unshift(arg) end def current_is_value? - peek && peek.to_s !~ /^-/ + peek && peek.to_s !~ /^-{1,2}\S+/ end # Runs through the argument array getting strings that contains ":" and diff --git a/lib/bundler/vendor/thor/lib/thor/parser/option.rb b/lib/bundler/vendor/thor/lib/thor/parser/option.rb index 0ddd472b432..5a5af6f8888 100644 --- a/lib/bundler/vendor/thor/lib/thor/parser/option.rb +++ b/lib/bundler/vendor/thor/lib/thor/parser/option.rb @@ -112,7 +112,7 @@ def #{type}? def validate! raise ArgumentError, "An option cannot be boolean and required." if boolean? && required? - validate_default_type! if @check_default_type + validate_default_type! end def validate_default_type! @@ -130,7 +130,18 @@ def validate_default_type! end expected_type = (@repeatable && @type != :hash) ? :array : @type - raise ArgumentError, "Expected #{expected_type} default value for '#{switch_name}'; got #{@default.inspect} (#{default_type})" unless default_type == expected_type + + if default_type != expected_type + err = "Expected #{expected_type} default value for '#{switch_name}'; got #{@default.inspect} (#{default_type})" + + if @check_default_type + raise ArgumentError, err + elsif @check_default_type == nil + Bundler::Thor.deprecation_warning "#{err}.\n" + + 'This will be rejected in the future unless you explicitly pass the options `check_default_type: false`' + + ' or call `allow_incompatible_default_type!` in your code' + end + end end def dasherized? diff --git a/lib/bundler/vendor/thor/lib/thor/runner.rb b/lib/bundler/vendor/thor/lib/thor/runner.rb index 48d33d7ac34..54c55250937 100644 --- a/lib/bundler/vendor/thor/lib/thor/runner.rb +++ b/lib/bundler/vendor/thor/lib/thor/runner.rb @@ -1,6 +1,5 @@ require_relative "../thor" require_relative "group" -require_relative "core_ext/io_binary_read" require "yaml" require "digest/md5" @@ -67,7 +66,7 @@ def install(name) # rubocop:disable MethodLength raise Error, "Error opening file '#{name}'" end - say "Your Bundler::Thorfile contains:" + say "Your Thorfile contains:" say contents unless options["force"] @@ -206,7 +205,7 @@ def save_yaml(yaml) File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml } end - # Load the Bundler::Thorfiles. If relevant_to is supplied, looks for specific files + # Load the Thorfiles. If relevant_to is supplied, looks for specific files # in the thor_root instead of loading them all. # # By default, it also traverses the current path until find Bundler::Thor files, as @@ -219,11 +218,11 @@ def initialize_thorfiles(relevant_to = nil, skip_lookup = false) end end - # Finds Bundler::Thorfiles by traversing from your current directory down to the root + # Finds Thorfiles by traversing from your current directory down to the root # directory of your system. If at any time we find a Bundler::Thor file, we stop. # - # We also ensure that system-wide Bundler::Thorfiles are loaded first, so local - # Bundler::Thorfiles can override them. + # We also ensure that system-wide Thorfiles are loaded first, so local + # Thorfiles can override them. # # ==== Example # @@ -231,7 +230,7 @@ def initialize_thorfiles(relevant_to = nil, skip_lookup = false) # # 1. /Users/wycats/dev/thor # 2. /Users/wycats/dev - # 3. /Users/wycats <-- we find a Bundler::Thorfile here, so we stop + # 3. /Users/wycats <-- we find a Thorfile here, so we stop # # Suppose we start at c:\Documents and Settings\james\dev\thor ... # @@ -239,7 +238,7 @@ def initialize_thorfiles(relevant_to = nil, skip_lookup = false) # 2. c:\Documents and Settings\james\dev # 3. c:\Documents and Settings\james # 4. c:\Documents and Settings - # 5. c:\ <-- no Bundler::Thorfiles found! + # 5. c:\ <-- no Thorfiles found! # def thorfiles(relevant_to = nil, skip_lookup = false) thorfiles = [] @@ -260,7 +259,7 @@ def thorfiles(relevant_to = nil, skip_lookup = false) end end - # Load Bundler::Thorfiles relevant to the given method. If you provide "foo:bar" it + # Load Thorfiles relevant to the given method. If you provide "foo:bar" it # will load all thor files in the thor.yaml that has "foo" e "foo:bar" # namespaces registered. # diff --git a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb index 52648fee8fe..be48358cb11 100644 --- a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +++ b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb @@ -451,16 +451,25 @@ def ask_simply(statement, color, options) def ask_filtered(statement, color, options) answer_set = options[:limited_to] + case_insensitive = options.fetch(:case_insensitive, false) correct_answer = nil until correct_answer answers = answer_set.join(", ") answer = ask_simply("#{statement} [#{answers}]", color, options) - correct_answer = answer_set.include?(answer) ? answer : nil + correct_answer = answer_match(answer_set, answer, case_insensitive) say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer end correct_answer end + def answer_match(possibilities, answer, case_insensitive) + if case_insensitive + possibilities.detect{ |possibility| possibility.downcase == answer.downcase } + else + possibilities.detect{ |possibility| possibility == answer } + end + end + def merge(destination, content) #:nodoc: require "tempfile" Tempfile.open([File.basename(destination), File.extname(destination)], File.dirname(destination)) do |temp| diff --git a/lib/bundler/vendor/thor/lib/thor/shell/html.rb b/lib/bundler/vendor/thor/lib/thor/shell/html.rb index 55262f19cc5..77a6d13a233 100644 --- a/lib/bundler/vendor/thor/lib/thor/shell/html.rb +++ b/lib/bundler/vendor/thor/lib/thor/shell/html.rb @@ -51,13 +51,13 @@ class HTML < Basic def set_color(string, *colors) if colors.all? { |color| color.is_a?(Symbol) || color.is_a?(String) } html_colors = colors.map { |color| lookup_color(color) } - "#{string}" + "#{Bundler::Thor::Util.escape_html(string)}" else color, bold = colors html_color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol) styles = [html_color] styles << BOLD if bold - "#{string}" + "#{Bundler::Thor::Util.escape_html(string)}" end end diff --git a/lib/bundler/vendor/thor/lib/thor/util.rb b/lib/bundler/vendor/thor/lib/thor/util.rb index 0fe7d4d8599..ddf4d21b90b 100644 --- a/lib/bundler/vendor/thor/lib/thor/util.rb +++ b/lib/bundler/vendor/thor/lib/thor/util.rb @@ -211,7 +211,7 @@ def thor_root_glob # def globs_for(path) path = escape_globs(path) - ["#{path}/Bundler::Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"] + ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"] end # Return the path to the ruby interpreter taking into account multiple @@ -263,6 +263,22 @@ def ruby_command def escape_globs(path) path.to_s.gsub(/[*?{}\[\]]/, '\\\\\\&') end + + # Returns a string that has had any HTML characters escaped. + # + # ==== Examples + # + # Bundler::Thor::Util.escape_html('
') # => "<div>" + # + # ==== Parameters + # String + # + # ==== Returns + # String + # + def escape_html(string) + CGI.escapeHTML(string) + end end end end