diff options
author | hsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-04-14 06:01:35 +0000 |
---|---|---|
committer | hsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-04-14 06:01:35 +0000 |
commit | 68ddd4d300e9a88737c4f37af74e1a0312949b2f (patch) | |
tree | 787e1e83d76934ce039eb336995a8d5bb53a89e6 /lib/bundler/vendor | |
parent | d636809c057432e8d42abe30c6c6785eb0721d77 (diff) | |
download | ruby-68ddd4d300e9a88737c4f37af74e1a0312949b2f.tar.gz |
Merge Bundler 2.1.0.pre.1 as developed version from upstream.
https://github.com/bundler/bundler/commit/a53709556b95a914e874b22ed2116a46b0528852
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67539 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/bundler/vendor')
-rw-r--r-- | lib/bundler/vendor/fileutils/lib/fileutils.rb | 199 | ||||
-rw-r--r-- | lib/bundler/vendor/fileutils/lib/fileutils/version.rb | 5 | ||||
-rw-r--r-- | lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb | 38 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/actions.rb | 18 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb | 13 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/base.rb | 9 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/error.rb | 82 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/group.rb | 4 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/parser/options.rb | 9 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/runner.rb | 4 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/shell.rb | 2 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/shell/basic.rb | 59 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/util.rb | 2 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/version.rb | 2 |
14 files changed, 363 insertions, 83 deletions
diff --git a/lib/bundler/vendor/fileutils/lib/fileutils.rb b/lib/bundler/vendor/fileutils/lib/fileutils.rb index cc69740845..fb7777eb49 100644 --- a/lib/bundler/vendor/fileutils/lib/fileutils.rb +++ b/lib/bundler/vendor/fileutils/lib/fileutils.rb @@ -1,4 +1,13 @@ # frozen_string_literal: true + +begin + require 'rbconfig' +rescue LoadError + # for make mjit-headers +end + +require "bundler/vendor/fileutils/lib/fileutils/version" + # # = fileutils.rb # @@ -56,7 +65,7 @@ # # 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_stream(srcstream, deststream) # Bundler::FileUtils.remove_entry(path, force = false) @@ -84,7 +93,6 @@ # files/directories. This equates to passing the <tt>:noop</tt> and # <tt>:verbose</tt> flags to methods in Bundler::FileUtils. # - module Bundler::FileUtils def self.private_module_function(name) #:nodoc: @@ -106,19 +114,22 @@ module Bundler::FileUtils # # Changes the current directory to the directory +dir+. # - # If this method is called with block, resumes to the old - # working directory after the block execution finished. + # If this method is called with block, resumes to the previous + # 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 # end # return to original directory # 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 +256,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 +306,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 +384,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 +476,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) @@ -461,13 +525,12 @@ module Bundler::FileUtils if destent.exist? if destent.directory? raise Errno::EEXIST, d - else - destent.remove_file if rename_cannot_overwrite_file? end end begin File.rename s, d - rescue Errno::EXDEV + rescue Errno::EXDEV, + Errno::EPERM # move from unencrypted to encrypted dir (ext4) copy_entry s, d, true if secure remove_entry_secure s, force @@ -485,11 +548,6 @@ module Bundler::FileUtils alias move mv 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. # 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: # - # * 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 Errno::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) @@ -1001,11 +1082,6 @@ module Bundler::FileUtils end module_function :chown_R - begin - require 'etc' - rescue LoadError # rescue LoadError for miniruby - end - def fu_get_uid(user) #:nodoc: return nil unless user case user @@ -1014,6 +1090,7 @@ module Bundler::FileUtils when /\A\d+\z/ user.to_i else + require 'etc' Etc.getpwnam(user) ? Etc.getpwnam(user).uid : nil end end @@ -1027,6 +1104,7 @@ module Bundler::FileUtils when /\A\d+\z/ group.to_i else + require 'etc' Etc.getgrnam(group) ? Etc.getgrnam(group).gid : nil end end @@ -1067,8 +1145,11 @@ module Bundler::FileUtils module StreamUtils_ private - def fu_windows? - /mswin|mingw|bccwin|emx/ =~ RUBY_PLATFORM + case (defined?(::RbConfig) ? ::RbConfig::CONFIG['host_os'] : ::RUBY_PLATFORM) + when /mswin|mingw/ + def fu_windows?; true end + else + def fu_windows?; false end end def fu_copy_stream0(src, dest, blksize = nil) #:nodoc: @@ -1193,9 +1274,15 @@ module Bundler::FileUtils def entries opts = {} opts[:encoding] = ::Encoding::UTF_8 if fu_windows? - Dir.entries(path(), opts)\ - .reject {|n| n == '.' or n == '..' }\ - .map {|n| Entry_.new(prefix(), join(rel(), n.untaint)) } + + files = if Dir.respond_to?(:children) + 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 def stat @@ -1250,6 +1337,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/fileutils/lib/fileutils/version.rb b/lib/bundler/vendor/fileutils/lib/fileutils/version.rb new file mode 100644 index 0000000000..6d8504ccd5 --- /dev/null +++ b/lib/bundler/vendor/fileutils/lib/fileutils/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module Bundler::FileUtils + VERSION = "1.2.0" +end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb index 7ecdc4b65a..41bc013143 100644 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +++ b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb @@ -50,14 +50,25 @@ module Bundler::Molinillo incoming_edges.map(&:origin) end - # @return [Array<Vertex>] the vertices of {#graph} where `self` is a + # @return [Set<Vertex>] the vertices of {#graph} where `self` is a # {#descendent?} def recursive_predecessors - vertices = predecessors - vertices += Compatibility.flat_map(vertices, &:recursive_predecessors) - vertices.uniq! + _recursive_predecessors + end + + # @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 end + protected :_recursive_predecessors # @return [Array<Vertex>] the vertices of {#graph} that have an edge with # `self` as their {Edge#origin} @@ -65,14 +76,25 @@ module Bundler::Molinillo outgoing_edges.map(&:destination) end - # @return [Array<Vertex>] the vertices of {#graph} where `self` is an + # @return [Set<Vertex>] the vertices of {#graph} where `self` is an # {#ancestor?} def recursive_successors - vertices = successors - vertices += Compatibility.flat_map(vertices, &:recursive_successors) - vertices.uniq! + _recursive_successors + end + + # @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 end + protected :_recursive_successors # @return [String] a string suitable for debugging def inspect 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 9bd1077170..e79d03d087 100644 --- a/lib/bundler/vendor/thor/lib/thor/base.rb +++ b/lib/bundler/vendor/thor/lib/thor/base.rb @@ -113,7 +113,7 @@ class Bundler::Thor end # 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: file = caller[1].match(/(.*):\d+/)[1] @@ -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/util.rb b/lib/bundler/vendor/thor/lib/thor/util.rb index 5d03177a28..0fe7d4d859 100644 --- a/lib/bundler/vendor/thor/lib/thor/util.rb +++ b/lib/bundler/vendor/thor/lib/thor/util.rb @@ -27,7 +27,7 @@ class Bundler::Thor end # 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. # # This method should not be used in general because it's used to deal with 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 |