diff options
author | hsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-22 23:08:05 +0000 |
---|---|---|
committer | hsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-22 23:08:05 +0000 |
commit | 7825e8363d4b2ccad8e2d3f5eeba9e26f6656911 (patch) | |
tree | 83cbcf419e0feeb2ab0fd063ed85e0776eb0081b /lib/bundler/vendor | |
parent | 73bed0312895322e0fd18310e840356c8e6af812 (diff) | |
download | ruby-7825e8363d4b2ccad8e2d3f5eeba9e26f6656911.tar.gz |
Postponing the Bundler merge.
I faced a big issue about Bundler with ruby core.
I have no time to resolve it issue before 2.5 final release.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61416 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/bundler/vendor')
57 files changed, 0 insertions, 10788 deletions
diff --git a/lib/bundler/vendor/fileutils/lib/fileutils.rb b/lib/bundler/vendor/fileutils/lib/fileutils.rb deleted file mode 100644 index cc69740845..0000000000 --- a/lib/bundler/vendor/fileutils/lib/fileutils.rb +++ /dev/null @@ -1,1638 +0,0 @@ -# frozen_string_literal: true -# -# = fileutils.rb -# -# Copyright (c) 2000-2007 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the same terms of ruby. -# -# == module Bundler::FileUtils -# -# Namespace for several file utility methods for copying, moving, removing, etc. -# -# === Module Functions -# -# require 'bundler/vendor/fileutils/lib/fileutils' -# -# Bundler::FileUtils.cd(dir, options) -# Bundler::FileUtils.cd(dir, options) {|dir| block } -# Bundler::FileUtils.pwd() -# Bundler::FileUtils.mkdir(dir, options) -# Bundler::FileUtils.mkdir(list, options) -# Bundler::FileUtils.mkdir_p(dir, options) -# Bundler::FileUtils.mkdir_p(list, options) -# Bundler::FileUtils.rmdir(dir, options) -# Bundler::FileUtils.rmdir(list, options) -# Bundler::FileUtils.ln(target, link, options) -# Bundler::FileUtils.ln(targets, dir, options) -# Bundler::FileUtils.ln_s(target, link, options) -# Bundler::FileUtils.ln_s(targets, dir, options) -# Bundler::FileUtils.ln_sf(target, link, options) -# Bundler::FileUtils.cp(src, dest, options) -# Bundler::FileUtils.cp(list, dir, options) -# Bundler::FileUtils.cp_r(src, dest, options) -# Bundler::FileUtils.cp_r(list, dir, options) -# Bundler::FileUtils.mv(src, dest, options) -# Bundler::FileUtils.mv(list, dir, options) -# Bundler::FileUtils.rm(list, options) -# Bundler::FileUtils.rm_r(list, options) -# Bundler::FileUtils.rm_rf(list, options) -# Bundler::FileUtils.install(src, dest, options) -# Bundler::FileUtils.chmod(mode, list, options) -# Bundler::FileUtils.chmod_R(mode, list, options) -# Bundler::FileUtils.chown(user, group, list, options) -# Bundler::FileUtils.chown_R(user, group, list, options) -# Bundler::FileUtils.touch(list, options) -# -# The <tt>options</tt> parameter is a hash of options, taken from the list -# <tt>:force</tt>, <tt>:noop</tt>, <tt>:preserve</tt>, and <tt>:verbose</tt>. -# <tt>:noop</tt> means that no changes are made. The other three are obvious. -# Each method documents the options that it honours. -# -# All methods that have the concept of a "source" file or directory can take -# either one file or a list of files in that argument. See the method -# documentation for examples. -# -# 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_file(src, dest, preserve = false, dereference = true) -# Bundler::FileUtils.copy_stream(srcstream, deststream) -# Bundler::FileUtils.remove_entry(path, force = false) -# Bundler::FileUtils.remove_entry_secure(path, force = false) -# Bundler::FileUtils.remove_file(path, force = false) -# Bundler::FileUtils.compare_file(path_a, path_b) -# Bundler::FileUtils.compare_stream(stream_a, stream_b) -# Bundler::FileUtils.uptodate?(file, cmp_list) -# -# == module Bundler::FileUtils::Verbose -# -# This module has all methods of Bundler::FileUtils module, but it outputs messages -# before acting. This equates to passing the <tt>:verbose</tt> flag to methods -# in Bundler::FileUtils. -# -# == module Bundler::FileUtils::NoWrite -# -# This module has all methods of Bundler::FileUtils module, but never changes -# files/directories. This equates to passing the <tt>:noop</tt> flag to methods -# in Bundler::FileUtils. -# -# == module Bundler::FileUtils::DryRun -# -# This module has all methods of Bundler::FileUtils module, but never changes -# 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: - module_function name - private_class_method name - end - - # - # Returns the name of the current directory. - # - def pwd - Dir.pwd - end - module_function :pwd - - alias getwd pwd - module_function :getwd - - # - # 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. - # - # Bundler::FileUtils.cd('/', :verbose => true) # chdir and report it - # - # Bundler::FileUtils.cd('/') do # chdir - # # ... # 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) - fu_output_message 'cd -' if verbose and block - end - module_function :cd - - alias chdir cd - module_function :chdir - - # - # Returns true if +new+ is newer than all +old_list+. - # Non-existent files are older than any file. - # - # Bundler::FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \ - # system 'make hello.o' - # - def uptodate?(new, old_list) - return false unless File.exist?(new) - new_time = File.mtime(new) - old_list.each do |old| - if File.exist?(old) - return false unless new_time > File.mtime(old) - end - end - true - end - module_function :uptodate? - - def remove_trailing_slash(dir) #:nodoc: - dir == '/' ? dir : dir.chomp(?/) - end - private_module_function :remove_trailing_slash - - # - # Creates one or more directories. - # - # Bundler::FileUtils.mkdir 'test' - # Bundler::FileUtils.mkdir %w( tmp data ) - # Bundler::FileUtils.mkdir 'notexist', :noop => true # Does not really create. - # Bundler::FileUtils.mkdir 'tmp', :mode => 0700 - # - def mkdir(list, mode: nil, noop: nil, verbose: nil) - list = fu_list(list) - fu_output_message "mkdir #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose - return if noop - - list.each do |dir| - fu_mkdir dir, mode - end - end - module_function :mkdir - - # - # Creates a directory and all its parent directories. - # For example, - # - # Bundler::FileUtils.mkdir_p '/usr/local/lib/ruby' - # - # causes to make following directories, if it does not exist. - # - # * /usr - # * /usr/local - # * /usr/local/lib - # * /usr/local/lib/ruby - # - # You can pass several directories at a time in a list. - # - def mkdir_p(list, mode: nil, noop: nil, verbose: nil) - list = fu_list(list) - fu_output_message "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose - return *list if noop - - list.map {|path| remove_trailing_slash(path)}.each do |path| - # optimize for the most common case - begin - fu_mkdir path, mode - next - rescue SystemCallError - next if File.directory?(path) - end - - stack = [] - until path == stack.last # dirname("/")=="/", dirname("C:/")=="C:/" - stack.push path - path = File.dirname(path) - end - stack.pop # root directory should exist - stack.reverse_each do |dir| - begin - fu_mkdir dir, mode - rescue SystemCallError - raise unless File.directory?(dir) - end - end - end - - return *list - end - module_function :mkdir_p - - alias mkpath mkdir_p - alias makedirs mkdir_p - module_function :mkpath - module_function :makedirs - - def fu_mkdir(path, mode) #:nodoc: - path = remove_trailing_slash(path) - if mode - Dir.mkdir path, mode - File.chmod mode, path - else - Dir.mkdir path - end - end - private_module_function :fu_mkdir - - # - # Removes one or more directories. - # - # Bundler::FileUtils.rmdir 'somedir' - # Bundler::FileUtils.rmdir %w(somedir anydir otherdir) - # # Does not really remove directory; outputs message. - # Bundler::FileUtils.rmdir 'somedir', :verbose => true, :noop => true - # - def rmdir(list, parents: nil, noop: nil, verbose: nil) - list = fu_list(list) - 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 - until (parent = File.dirname(dir)) == '.' or parent == dir - dir = parent - Dir.rmdir(dir) - end - end - rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT - end - end - end - module_function :rmdir - - # - # :call-seq: - # Bundler::FileUtils.ln(target, link, force: nil, noop: nil, verbose: nil) - # Bundler::FileUtils.ln(target, dir, force: nil, noop: nil, verbose: nil) - # Bundler::FileUtils.ln(targets, dir, force: nil, noop: nil, verbose: nil) - # - # In the first form, creates a hard link +link+ which points to +target+. - # If +link+ already exists, raises Errno::EEXIST. - # But if the :force option is set, overwrites +link+. - # - # Bundler::FileUtils.ln 'gcc', 'cc', verbose: true - # Bundler::FileUtils.ln '/usr/bin/emacs21', '/usr/bin/emacs' - # - # In the second form, creates a link +dir/target+ pointing to +target+. - # In the third form, creates several hard links in the directory +dir+, - # pointing to each item in +targets+. - # If +dir+ is not a directory, raises Errno::ENOTDIR. - # - # Bundler::FileUtils.cd '/sbin' - # Bundler::FileUtils.ln %w(cp mv mkdir), '/bin' # Now /sbin/cp and /bin/cp are linked. - # - def ln(src, dest, force: nil, noop: nil, verbose: nil) - fu_output_message "ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose - return if noop - fu_each_src_dest0(src, dest) do |s,d| - remove_file d, true if force - File.link s, d - end - end - module_function :ln - - alias link ln - module_function :link - - # - # :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) - # - # In the first form, creates a symbolic link +link+ which points to +target+. - # If +link+ already exists, raises Errno::EEXIST. - # But if the :force option is set, overwrites +link+. - # - # Bundler::FileUtils.ln_s '/usr/bin/ruby', '/usr/local/bin/ruby' - # Bundler::FileUtils.ln_s 'verylongsourcefilename.c', 'c', force: true - # - # In the second form, creates a link +dir/target+ pointing to +target+. - # In the third form, creates several symbolic links in the directory +dir+, - # pointing to each item in +targets+. - # If +dir+ is not a directory, raises Errno::ENOTDIR. - # - # Bundler::FileUtils.ln_s Dir.glob('/bin/*.rb'), '/home/foo/bin' - # - def ln_s(src, dest, force: nil, noop: nil, verbose: nil) - fu_output_message "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose - return if noop - fu_each_src_dest0(src, dest) do |s,d| - remove_file d, true if force - File.symlink s, d - end - end - module_function :ln_s - - alias symlink ln_s - module_function :symlink - - # - # :call-seq: - # Bundler::FileUtils.ln_sf(*args) - # - # Same as - # - # Bundler::FileUtils.ln_s(*args, force: true) - # - def ln_sf(src, dest, noop: nil, verbose: nil) - ln_s src, dest, force: true, noop: noop, verbose: verbose - end - module_function :ln_sf - - # - # Copies a file content +src+ to +dest+. If +dest+ is a directory, - # copies +src+ to +dest/src+. - # - # If +src+ is a list of files, then +dest+ must be a directory. - # - # Bundler::FileUtils.cp 'eval.c', 'eval.c.org' - # Bundler::FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6' - # Bundler::FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', :verbose => true - # Bundler::FileUtils.cp 'symlink', 'dest' # copy content, "dest" is not a symlink - # - def cp(src, dest, preserve: nil, noop: nil, verbose: nil) - fu_output_message "cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if verbose - return if noop - fu_each_src_dest(src, dest) do |s, d| - copy_file s, d, preserve - end - end - module_function :cp - - alias copy cp - module_function :copy - - # - # Copies +src+ to +dest+. If +src+ is a directory, this method copies - # all its contents recursively. If +dest+ is a directory, copies - # +src+ to +dest/src+. - # - # +src+ can be a list of files. - # - # # Installing Ruby library "mylib" under the site_ruby - # Bundler::FileUtils.rm_r site_ruby + '/mylib', :force - # Bundler::FileUtils.cp_r 'lib/', site_ruby + '/mylib' - # - # # Examples of copying several files to target directory. - # Bundler::FileUtils.cp_r %w(mail.rb field.rb debug/), site_ruby + '/tmail' - # Bundler::FileUtils.cp_r Dir.glob('*.rb'), '/home/foo/lib/ruby', :noop => true, :verbose => true - # - # # If you want to copy all contents of a directory instead of the - # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y, - # # use following code. - # Bundler::FileUtils.cp_r 'src/.', 'dest' # cp_r('src', 'dest') makes dest/src, - # # but this doesn't. - # - def cp_r(src, dest, preserve: nil, noop: nil, verbose: nil, - dereference_root: true, remove_destination: nil) - fu_output_message "cp -r#{preserve ? 'p' : ''}#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose - return if noop - fu_each_src_dest(src, dest) do |s, d| - copy_entry s, d, preserve, dereference_root, remove_destination - end - end - module_function :cp_r - - # - # Copies a file system entry +src+ to +dest+. - # If +src+ is a directory, this method copies its contents recursively. - # This method preserves file types, c.f. symlink, directory... - # (FIFO, device files and etc. are not supported yet) - # - # Both of +src+ and +dest+ must be a path name. - # +src+ must exist, +dest+ must not exist. - # - # If +preserve+ is true, this method preserves owner, group, and - # modified time. Permissions are copied regardless +preserve+. - # - # If +dereference_root+ is true, this method dereference tree root. - # - # If +remove_destination+ is true, this method removes each destination file before copy. - # - 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) - ent.copy destent.path - end, proc do |ent| - destent = Entry_.new(dest, ent.rel, false) - ent.copy_metadata destent.path if preserve - end) - end - module_function :copy_entry - - # - # Copies file contents of +src+ to +dest+. - # Both of +src+ and +dest+ must be a path name. - # - def copy_file(src, dest, preserve = false, dereference = true) - ent = Entry_.new(src, nil, dereference) - ent.copy_file dest - ent.copy_metadata dest if preserve - end - module_function :copy_file - - # - # Copies stream +src+ to +dest+. - # +src+ must respond to #read(n) and - # +dest+ must respond to #write(str). - # - def copy_stream(src, dest) - IO.copy_stream(src, dest) - end - module_function :copy_stream - - # - # Moves file(s) +src+ to +dest+. If +file+ and +dest+ exist on the different - # disk partition, the file is copied then the original file is removed. - # - # Bundler::FileUtils.mv 'badname.rb', 'goodname.rb' - # Bundler::FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', :force => true # no error - # - # Bundler::FileUtils.mv %w(junk.txt dust.txt), '/home/foo/.trash/' - # Bundler::FileUtils.mv Dir.glob('test*.rb'), 'test', :noop => true, :verbose => true - # - def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil) - fu_output_message "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose - return if noop - fu_each_src_dest(src, dest) do |s, d| - destent = Entry_.new(d, nil, true) - begin - 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 - copy_entry s, d, true - if secure - remove_entry_secure s, force - else - remove_entry s, force - end - end - rescue SystemCallError - raise unless force - end - end - end - module_function :mv - - 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. - # - # Bundler::FileUtils.rm %w( junk.txt dust.txt ) - # Bundler::FileUtils.rm Dir.glob('*.so') - # Bundler::FileUtils.rm 'NotExistFile', :force => true # never raises exception - # - def rm(list, force: nil, noop: nil, verbose: nil) - list = fu_list(list) - fu_output_message "rm#{force ? ' -f' : ''} #{list.join ' '}" if verbose - return if noop - - list.each do |path| - remove_file path, force - end - end - module_function :rm - - alias remove rm - module_function :remove - - # - # Equivalent to - # - # Bundler::FileUtils.rm(list, :force => true) - # - def rm_f(list, noop: nil, verbose: nil) - rm list, force: true, noop: noop, verbose: verbose - end - module_function :rm_f - - alias safe_unlink rm_f - module_function :safe_unlink - - # - # remove files +list+[0] +list+[1]... If +list+[n] is a directory, - # removes its all contents recursively. This method ignores - # StandardError when :force option is set. - # - # Bundler::FileUtils.rm_r Dir.glob('/tmp/*') - # Bundler::FileUtils.rm_r 'some_dir', :force => true - # - # WARNING: This method causes local vulnerability - # if one of parent directories or removing directory tree are world - # writable (including /tmp, whose permission is 1777), and the current - # process has strong privilege such as Unix super user (root), and the - # system has symbolic link. For secure removing, read the documentation - # of #remove_entry_secure carefully, and set :secure option to true. - # Default is :secure=>false. - # - # NOTE: This method calls #remove_entry_secure if :secure option is set. - # See also #remove_entry_secure. - # - def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil) - list = fu_list(list) - fu_output_message "rm -r#{force ? 'f' : ''} #{list.join ' '}" if verbose - return if noop - list.each do |path| - if secure - remove_entry_secure path, force - else - remove_entry path, force - end - end - end - module_function :rm_r - - # - # Equivalent to - # - # Bundler::FileUtils.rm_r(list, :force => true) - # - # WARNING: This method causes local vulnerability. - # Read the documentation of #rm_r first. - # - def rm_rf(list, noop: nil, verbose: nil, secure: nil) - rm_r list, force: true, noop: noop, verbose: verbose, secure: secure - end - module_function :rm_rf - - alias rmtree rm_rf - module_function :rmtree - - # - # This method removes a file system entry +path+. +path+ shall be a - # regular file, a directory, or something. If +path+ is a directory, - # remove it recursively. This method is required to avoid TOCTTOU - # (time-of-check-to-time-of-use) local security vulnerability of #rm_r. - # #rm_r causes security hole when: - # - # * Parent directory is world writable (including /tmp). - # * Removing directory tree includes world writable directory. - # * The system has symbolic link. - # - # To avoid this security hole, this method applies special preprocess. - # If +path+ is a directory, this method chown(2) and chmod(2) all - # removing directories. This requires the current process is the - # owner of the removing whole directory tree, or is the super user (root). - # - # WARNING: You must ensure that *ALL* parent directories cannot be - # moved by other untrusted users. For example, parent directories - # should not be owned by untrusted users, and should not be world - # writable except when the sticky bit set. - # - # WARNING: Only the owner of the removing directory tree, or Unix super - # user (root) should invoke this method. Otherwise this method does not - # work. - # - # 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 - # - # For fileutils.rb, this vulnerability is reported in [ruby-dev:26100]. - # - def remove_entry_secure(path, force = false) - unless fu_have_symlink? - remove_entry path, force - return - end - fullpath = File.expand_path(path) - st = File.lstat(fullpath) - unless st.directory? - File.unlink fullpath - return - end - # is a directory. - parent_st = File.stat(File.dirname(fullpath)) - unless parent_st.world_writable? - remove_entry path, force - return - end - 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 - } - # ---- tree root is frozen ---- - root = Entry_.new(path) - root.preorder_traverse do |ent| - if ent.directory? - ent.chown euid, -1 - ent.chmod 0700 - end - end - root.postorder_traverse do |ent| - begin - ent.remove - rescue - raise unless force - end - end - rescue - raise unless force - end - module_function :remove_entry_secure - - def fu_have_symlink? #:nodoc: - File.symlink nil, nil - rescue NotImplementedError - return false - rescue TypeError - return true - end - private_module_function :fu_have_symlink? - - def fu_stat_identical_entry?(a, b) #:nodoc: - a.dev == b.dev and a.ino == b.ino - end - private_module_function :fu_stat_identical_entry? - - # - # This method removes a file system entry +path+. - # +path+ might be a regular file, a directory, or something. - # If +path+ is a directory, remove it recursively. - # - # See also #remove_entry_secure. - # - def remove_entry(path, force = false) - Entry_.new(path).postorder_traverse do |ent| - begin - ent.remove - rescue - raise unless force - end - end - rescue - raise unless force - end - module_function :remove_entry - - # - # Removes a file +path+. - # This method ignores StandardError if +force+ is true. - # - def remove_file(path, force = false) - Entry_.new(path).remove_file - rescue - raise unless force - end - module_function :remove_file - - # - # Removes a directory +dir+ and its contents recursively. - # This method ignores StandardError if +force+ is true. - # - def remove_dir(path, force = false) - remove_entry path, force # FIXME?? check if it is a directory - end - module_function :remove_dir - - # - # Returns true if the contents of a file +a+ and a file +b+ are identical. - # - # Bundler::FileUtils.compare_file('somefile', 'somefile') #=> true - # Bundler::FileUtils.compare_file('/dev/null', '/dev/urandom') #=> false - # - def compare_file(a, b) - return false unless File.size(a) == File.size(b) - File.open(a, 'rb') {|fa| - File.open(b, 'rb') {|fb| - return compare_stream(fa, fb) - } - } - end - module_function :compare_file - - alias identical? compare_file - alias cmp compare_file - module_function :identical? - module_function :cmp - - # - # Returns true if the contents of a stream +a+ and +b+ are identical. - # - def compare_stream(a, b) - bsize = fu_stream_blksize(a, b) - sa = String.new(capacity: bsize) - sb = String.new(capacity: bsize) - begin - a.read(bsize, sa) - b.read(bsize, sb) - return true if sa.empty? && sb.empty? - end while sa == sb - false - end - module_function :compare_stream - - # - # If +src+ is not same as +dest+, copies it and changes the permission - # mode to +mode+. If +dest+ is a directory, destination is +dest+/+src+. - # This method removes destination before copy. - # - # Bundler::FileUtils.install 'ruby', '/usr/local/bin/ruby', :mode => 0755, :verbose => true - # Bundler::FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', :verbose => true - # - def install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil, - noop: nil, verbose: nil) - if verbose - msg = +"install -c" - msg << ' -p' if preserve - msg << ' -m ' << mode_to_s(mode) if mode - msg << " -o #{owner}" if owner - msg << " -g #{group}" if group - msg << ' ' << [src,dest].flatten.join(' ') - fu_output_message msg - end - return if noop - uid = fu_get_uid(owner) - gid = fu_get_gid(group) - fu_each_src_dest(src, dest) do |s, d| - st = File.stat(s) - unless File.exist?(d) and compare_file(s, d) - remove_file d, true - copy_file s, d - File.utime st.atime, st.mtime, d if preserve - File.chmod fu_mode(mode, st), d if mode - File.chown uid, gid, d if uid or gid - end - end - end - module_function :install - - def user_mask(target) #:nodoc: - target.each_char.inject(0) do |mask, chr| - case chr - when "u" - mask | 04700 - when "g" - mask | 02070 - when "o" - mask | 01007 - when "a" - mask | 07777 - else - raise ArgumentError, "invalid `who' symbol in file mode: #{chr}" - end - end - end - private_module_function :user_mask - - def apply_mask(mode, user_mask, op, mode_mask) #:nodoc: - case op - when '=' - (mode & ~user_mask) | (user_mask & mode_mask) - when '+' - mode | (user_mask & mode_mask) - when '-' - mode & ~(user_mask & mode_mask) - end - end - private_module_function :apply_mask - - def symbolic_modes_to_i(mode_sym, path) #:nodoc: - mode = if File::Stat === path - path.mode - else - File.stat(path).mode - end - mode_sym.split(/,/).inject(mode & 07777) do |current_mode, clause| - target, *actions = clause.split(/([=+-])/) - raise ArgumentError, "invalid file mode: #{mode_sym}" if actions.empty? - target = 'a' if target.empty? - user_mask = user_mask(target) - actions.each_slice(2) do |op, perm| - need_apply = op == '=' - mode_mask = (perm || '').each_char.inject(0) do |mask, chr| - case chr - when "r" - mask | 0444 - when "w" - mask | 0222 - when "x" - mask | 0111 - when "X" - if FileTest.directory? path - mask | 0111 - else - mask - end - when "s" - mask | 06000 - when "t" - mask | 01000 - when "u", "g", "o" - if mask.nonzero? - current_mode = apply_mask(current_mode, user_mask, op, mask) - end - need_apply = false - copy_mask = user_mask(chr) - (current_mode & copy_mask) / (copy_mask & 0111) * (user_mask & 0111) - else - raise ArgumentError, "invalid `perm' symbol in file mode: #{chr}" - end - end - - if mode_mask.nonzero? || need_apply - current_mode = apply_mask(current_mode, user_mask, op, mode_mask) - end - end - current_mode - end - end - private_module_function :symbolic_modes_to_i - - def fu_mode(mode, path) #:nodoc: - mode.is_a?(String) ? symbolic_modes_to_i(mode, path) : mode - end - private_module_function :fu_mode - - def mode_to_s(mode) #:nodoc: - mode.is_a?(String) ? mode : "%o" % mode - end - private_module_function :mode_to_s - - # - # Changes permission bits on the named files (in +list+) to the bit pattern - # represented by +mode+. - # - # +mode+ is the symbolic and absolute mode can be used. - # - # Absolute mode is - # Bundler::FileUtils.chmod 0755, 'somecommand' - # Bundler::FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb) - # Bundler::FileUtils.chmod 0755, '/usr/bin/ruby', :verbose => true - # - # Symbolic mode is - # Bundler::FileUtils.chmod "u=wrx,go=rx", 'somecommand' - # Bundler::FileUtils.chmod "u=wr,go=rr", %w(my.rb your.rb his.rb her.rb) - # Bundler::FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', :verbose => true - # - # "a" :: is user, group, other mask. - # "u" :: is user's mask. - # "g" :: is group's mask. - # "o" :: is other's mask. - # "w" :: is write permission. - # "r" :: is read permission. - # "x" :: is execute permission. - # "X" :: - # is execute permission for directories only, must be used in conjunction with "+" - # "s" :: is uid, gid. - # "t" :: is sticky bit. - # "+" :: is added to a class given the specified mode. - # "-" :: Is removed from a given class given mode. - # "=" :: Is the exact nature of the class will be given a specified mode. - - def chmod(mode, list, noop: nil, verbose: nil) - list = fu_list(list) - fu_output_message sprintf('chmod %s %s', mode_to_s(mode), list.join(' ')) if verbose - return if noop - list.each do |path| - Entry_.new(path).chmod(fu_mode(mode, path)) - end - end - module_function :chmod - - # - # Changes permission bits on the named files (in +list+) - # to the bit pattern represented by +mode+. - # - # Bundler::FileUtils.chmod_R 0700, "/tmp/app.#{$$}" - # Bundler::FileUtils.chmod_R "u=wrx", "/tmp/app.#{$$}" - # - def chmod_R(mode, list, noop: nil, verbose: nil, force: nil) - list = fu_list(list) - fu_output_message sprintf('chmod -R%s %s %s', - (force ? 'f' : ''), - mode_to_s(mode), list.join(' ')) if verbose - return if noop - list.each do |root| - Entry_.new(root).traverse do |ent| - begin - ent.chmod(fu_mode(mode, ent.path)) - rescue - raise unless force - end - end - end - end - module_function :chmod_R - - # - # Changes owner and group on the named files (in +list+) - # to the user +user+ and the group +group+. +user+ and +group+ - # may be an ID (Integer/String) or a name (String). - # If +user+ or +group+ is nil, this method does not change - # the attribute. - # - # Bundler::FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby' - # Bundler::FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), :verbose => true - # - def chown(user, group, list, noop: nil, verbose: nil) - list = fu_list(list) - fu_output_message sprintf('chown %s %s', - (group ? "#{user}:#{group}" : user || ':'), - list.join(' ')) if verbose - return if noop - uid = fu_get_uid(user) - gid = fu_get_gid(group) - list.each do |path| - Entry_.new(path).chown uid, gid - end - end - module_function :chown - - # - # Changes owner and group on the named files (in +list+) - # to the user +user+ and the group +group+ recursively. - # +user+ and +group+ may be an ID (Integer/String) or - # a name (String). If +user+ or +group+ is nil, this - # method does not change the attribute. - # - # Bundler::FileUtils.chown_R 'www', 'www', '/var/www/htdocs' - # Bundler::FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', :verbose => true - # - def chown_R(user, group, list, noop: nil, verbose: nil, force: nil) - list = fu_list(list) - fu_output_message sprintf('chown -R%s %s %s', - (force ? 'f' : ''), - (group ? "#{user}:#{group}" : user || ':'), - list.join(' ')) if verbose - return if noop - uid = fu_get_uid(user) - gid = fu_get_gid(group) - list.each do |root| - Entry_.new(root).traverse do |ent| - begin - ent.chown uid, gid - rescue - raise unless force - end - end - end - 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 - when Integer - user - when /\A\d+\z/ - user.to_i - else - Etc.getpwnam(user) ? Etc.getpwnam(user).uid : nil - end - end - private_module_function :fu_get_uid - - def fu_get_gid(group) #:nodoc: - return nil unless group - case group - when Integer - group - when /\A\d+\z/ - group.to_i - else - Etc.getgrnam(group) ? Etc.getgrnam(group).gid : nil - end - end - private_module_function :fu_get_gid - - # - # Updates modification time (mtime) and access time (atime) of file(s) in - # +list+. Files are created if they don't exist. - # - # Bundler::FileUtils.touch 'timestamp' - # Bundler::FileUtils.touch Dir.glob('*.c'); system 'make' - # - def touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil) - list = fu_list(list) - t = mtime - if verbose - fu_output_message "touch #{nocreate ? '-c ' : ''}#{t ? t.strftime('-t %Y%m%d%H%M.%S ') : ''}#{list.join ' '}" - end - return if noop - list.each do |path| - created = nocreate - begin - File.utime(t, t, path) - rescue Errno::ENOENT - raise if created - File.open(path, 'a') { - ; - } - created = true - retry if t - end - end - end - module_function :touch - - private - - module StreamUtils_ - private - - def fu_windows? - /mswin|mingw|bccwin|emx/ =~ RUBY_PLATFORM - end - - def fu_copy_stream0(src, dest, blksize = nil) #:nodoc: - IO.copy_stream(src, dest) - end - - def fu_stream_blksize(*streams) - streams.each do |s| - next unless s.respond_to?(:stat) - size = fu_blksize(s.stat) - return size if size - end - fu_default_blksize() - end - - def fu_blksize(st) - s = st.blksize - return nil unless s - return nil if s == 0 - s - end - - def fu_default_blksize - 1024 - end - end - - include StreamUtils_ - extend StreamUtils_ - - class Entry_ #:nodoc: internal use only - include StreamUtils_ - - def initialize(a, b = nil, deref = false) - @prefix = @rel = @path = nil - if b - @prefix = a - @rel = b - else - @path = a - end - @deref = deref - @stat = nil - @lstat = nil - end - - def inspect - "\#<#{self.class} #{path()}>" - end - - def path - if @path - File.path(@path) - else - join(@prefix, @rel) - end - end - - def prefix - @prefix || @path - end - - def rel - @rel - end - - def dereference? - @deref - end - - def exist? - begin - lstat - true - rescue Errno::ENOENT - false - end - end - - def file? - s = lstat! - s and s.file? - end - - def directory? - s = lstat! - s and s.directory? - end - - def symlink? - s = lstat! - s and s.symlink? - end - - def chardev? - s = lstat! - s and s.chardev? - end - - def blockdev? - s = lstat! - s and s.blockdev? - end - - def socket? - s = lstat! - s and s.socket? - end - - def pipe? - s = lstat! - s and s.pipe? - end - - S_IF_DOOR = 0xD000 - - def door? - s = lstat! - s and (s.mode & 0xF000 == S_IF_DOOR) - end - - 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)) } - end - - def stat - return @stat if @stat - if lstat() and lstat().symlink? - @stat = File.stat(path()) - else - @stat = lstat() - end - @stat - end - - def stat! - return @stat if @stat - if lstat! and lstat!.symlink? - @stat = File.stat(path()) - else - @stat = lstat! - end - @stat - rescue SystemCallError - nil - end - - def lstat - if dereference? - @lstat ||= File.stat(path()) - else - @lstat ||= File.lstat(path()) - end - end - - def lstat! - lstat() - rescue SystemCallError - nil - end - - def chmod(mode) - if symlink? - File.lchmod mode, path() if have_lchmod? - else - File.chmod mode, path() - end - end - - def chown(uid, gid) - if symlink? - File.lchown uid, gid, path() if have_lchown? - else - File.chown uid, gid, path() - end - end - - def copy(dest) - lstat - case - when file? - copy_file dest - when directory? - if !File.exist?(dest) and descendant_directory?(dest, path) - raise ArgumentError, "cannot copy directory %s to itself %s" % [path, dest] - end - begin - Dir.mkdir dest - rescue - raise unless File.directory?(dest) - end - when symlink? - File.symlink File.readlink(path()), dest - when chardev? - raise "cannot handle device file" unless File.respond_to?(:mknod) - mknod dest, ?c, 0666, lstat().rdev - when blockdev? - raise "cannot handle device file" unless File.respond_to?(:mknod) - mknod dest, ?b, 0666, lstat().rdev - when socket? - raise "cannot handle socket" unless File.respond_to?(:mknod) - mknod dest, nil, lstat().mode, 0 - when pipe? - raise "cannot handle FIFO" unless File.respond_to?(:mkfifo) - mkfifo dest, 0666 - when door? - raise "cannot handle door: #{path()}" - else - raise "unknown file type: #{path()}" - end - end - - def copy_file(dest) - File.open(path()) do |s| - File.open(dest, 'wb', s.stat.mode) do |f| - IO.copy_stream(s, f) - end - end - end - - def copy_metadata(path) - st = lstat() - if !st.symlink? - File.utime st.atime, st.mtime, path - end - mode = st.mode - begin - if st.symlink? - begin - File.lchown st.uid, st.gid, path - rescue NotImplementedError - end - else - File.chown st.uid, st.gid, path - end - rescue Errno::EPERM, Errno::EACCES - # clear setuid/setgid - mode &= 01777 - end - if st.symlink? - begin - File.lchmod mode, path - rescue NotImplementedError - end - else - File.chmod mode, path - end - end - - def remove - if directory? - remove_dir1 - else - remove_file - end - end - - def remove_dir1 - platform_support { - Dir.rmdir path().chomp(?/) - } - end - - def remove_file - platform_support { - File.unlink path - } - end - - def platform_support - return yield unless fu_windows? - first_time_p = true - begin - yield - rescue Errno::ENOENT - raise - rescue => err - if first_time_p - first_time_p = false - begin - File.chmod 0700, path() # Windows does not have symlink - retry - rescue SystemCallError - end - end - raise err - end - end - - def preorder_traverse - stack = [self] - while ent = stack.pop - yield ent - stack.concat ent.entries.reverse if ent.directory? - end - end - - alias traverse preorder_traverse - - def postorder_traverse - if directory? - entries().each do |ent| - ent.postorder_traverse do |e| - yield e - end - end - end - ensure - yield self - end - - def wrap_traverse(pre, post) - pre.call self - if directory? - entries.each do |ent| - ent.wrap_traverse pre, post - end - end - post.call self - end - - private - - $fileutils_rb_have_lchmod = nil - - def have_lchmod? - # This is not MT-safe, but it does not matter. - if $fileutils_rb_have_lchmod == nil - $fileutils_rb_have_lchmod = check_have_lchmod? - end - $fileutils_rb_have_lchmod - end - - def check_have_lchmod? - return false unless File.respond_to?(:lchmod) - File.lchmod 0 - return true - rescue NotImplementedError - return false - end - - $fileutils_rb_have_lchown = nil - - def have_lchown? - # This is not MT-safe, but it does not matter. - if $fileutils_rb_have_lchown == nil - $fileutils_rb_have_lchown = check_have_lchown? - end - $fileutils_rb_have_lchown - end - - def check_have_lchown? - return false unless File.respond_to?(:lchown) - File.lchown nil, nil - return true - rescue NotImplementedError - return false - end - - def join(dir, base) - return File.path(dir) if not base or base == '.' - return File.path(base) if not dir or dir == '.' - File.join(dir, base) - end - - if File::ALT_SEPARATOR - DIRECTORY_TERM = "(?=[/#{Regexp.quote(File::ALT_SEPARATOR)}]|\\z)" - else - DIRECTORY_TERM = "(?=/|\\z)" - end - SYSCASE = File::FNM_SYSCASE.nonzero? ? "-i" : "" - - def descendant_directory?(descendant, ascendant) - /\A(?#{SYSCASE}:#{Regexp.quote(ascendant)})#{DIRECTORY_TERM}/ =~ File.dirname(descendant) - end - end # class Entry_ - - def fu_list(arg) #:nodoc: - [arg].flatten.map {|path| File.path(path) } - end - private_module_function :fu_list - - def fu_each_src_dest(src, dest) #:nodoc: - fu_each_src_dest0(src, dest) do |s, d| - raise ArgumentError, "same file: #{s} and #{d}" if fu_same?(s, d) - yield s, d - end - end - private_module_function :fu_each_src_dest - - def fu_each_src_dest0(src, dest) #:nodoc: - if tmp = Array.try_convert(src) - tmp.each do |s| - s = File.path(s) - yield s, File.join(dest, File.basename(s)) - end - else - src = File.path(src) - if File.directory?(dest) - yield src, File.join(dest, File.basename(src)) - else - yield src, File.path(dest) - end - end - end - private_module_function :fu_each_src_dest0 - - def fu_same?(a, b) #:nodoc: - File.identical?(a, b) - end - private_module_function :fu_same? - - @fileutils_output = $stderr - @fileutils_label = '' - - def fu_output_message(msg) #:nodoc: - @fileutils_output ||= $stderr - @fileutils_label ||= '' - @fileutils_output.puts @fileutils_label + msg - end - private_module_function :fu_output_message - - # This hash table holds command options. - OPT_TABLE = {} #:nodoc: internal use only - (private_instance_methods & methods(false)).inject(OPT_TABLE) {|tbl, name| - (tbl[name.to_s] = instance_method(name).parameters).map! {|t, n| n if t == :key}.compact! - tbl - } - - # - # Returns an Array of method names which have any options. - # - # p Bundler::FileUtils.commands #=> ["chmod", "cp", "cp_r", "install", ...] - # - def self.commands - OPT_TABLE.keys - end - - # - # Returns an Array of option names. - # - # p Bundler::FileUtils.options #=> ["noop", "force", "verbose", "preserve", "mode"] - # - def self.options - OPT_TABLE.values.flatten.uniq.map {|sym| sym.to_s } - end - - # - # Returns true if the method +mid+ have an option +opt+. - # - # p Bundler::FileUtils.have_option?(:cp, :noop) #=> true - # p Bundler::FileUtils.have_option?(:rm, :force) #=> true - # p Bundler::FileUtils.have_option?(:rm, :preserve) #=> false - # - def self.have_option?(mid, opt) - li = OPT_TABLE[mid.to_s] or raise ArgumentError, "no such method: #{mid}" - li.include?(opt) - end - - # - # Returns an Array of option names of the method +mid+. - # - # p Bundler::FileUtils.options_of(:rm) #=> ["noop", "verbose", "force"] - # - def self.options_of(mid) - OPT_TABLE[mid.to_s].map {|sym| sym.to_s } - end - - # - # Returns an Array of method names which have the option +opt+. - # - # p Bundler::FileUtils.collect_method(:preserve) #=> ["cp", "cp_r", "copy", "install"] - # - def self.collect_method(opt) - OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) } - end - - LOW_METHODS = singleton_methods(false) - collect_method(:noop).map(&:intern) - module LowMethods - private - def _do_nothing(*)end - ::Bundler::FileUtils::LOW_METHODS.map {|name| alias_method name, :_do_nothing} - end - - METHODS = singleton_methods() - [:private_module_function, - :commands, :options, :have_option?, :options_of, :collect_method] - - # - # This module has all methods of Bundler::FileUtils module, but it outputs messages - # before acting. This equates to passing the <tt>:verbose</tt> flag to - # methods in Bundler::FileUtils. - # - module Verbose - include Bundler::FileUtils - @fileutils_output = $stderr - @fileutils_label = '' - names = ::Bundler::FileUtils.collect_method(:verbose) - names.each do |name| - module_eval(<<-EOS, __FILE__, __LINE__ + 1) - def #{name}(*args, **options) - super(*args, **options, verbose: true) - end - EOS - end - private(*names) - extend self - class << self - public(*::Bundler::FileUtils::METHODS) - end - end - - # - # This module has all methods of Bundler::FileUtils module, but never changes - # files/directories. This equates to passing the <tt>:noop</tt> flag - # to methods in Bundler::FileUtils. - # - module NoWrite - include Bundler::FileUtils - include LowMethods - @fileutils_output = $stderr - @fileutils_label = '' - names = ::Bundler::FileUtils.collect_method(:noop) - names.each do |name| - module_eval(<<-EOS, __FILE__, __LINE__ + 1) - def #{name}(*args, **options) - super(*args, **options, noop: true) - end - EOS - end - private(*names) - extend self - class << self - public(*::Bundler::FileUtils::METHODS) - end - end - - # - # This module has all methods of Bundler::FileUtils module, but never changes - # files/directories, with printing message before acting. - # This equates to passing the <tt>:noop</tt> and <tt>:verbose</tt> flag - # to methods in Bundler::FileUtils. - # - module DryRun - include Bundler::FileUtils - include LowMethods - @fileutils_output = $stderr - @fileutils_label = '' - names = ::Bundler::FileUtils.collect_method(:noop) - names.each do |name| - module_eval(<<-EOS, __FILE__, __LINE__ + 1) - def #{name}(*args, **options) - super(*args, **options, noop: true, verbose: true) - end - EOS - end - private(*names) - extend self - class << self - public(*::Bundler::FileUtils::METHODS) - end - end - -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo.rb b/lib/bundler/vendor/molinillo/lib/molinillo.rb deleted file mode 100644 index 9e2867144f..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -require 'bundler/vendor/molinillo/lib/molinillo/compatibility' -require 'bundler/vendor/molinillo/lib/molinillo/gem_metadata' -require 'bundler/vendor/molinillo/lib/molinillo/errors' -require 'bundler/vendor/molinillo/lib/molinillo/resolver' -require 'bundler/vendor/molinillo/lib/molinillo/modules/ui' -require 'bundler/vendor/molinillo/lib/molinillo/modules/specification_provider' - -# Bundler::Molinillo is a generic dependency resolution algorithm. -module Bundler::Molinillo -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb b/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb deleted file mode 100644 index 3eba8e4083..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - # Hacks needed for old Ruby versions. - module Compatibility - module_function - - if [].respond_to?(:flat_map) - # Flat map - # @param [Enumerable] enum an enumerable object - # @block the block to flat-map with - # @return The enum, flat-mapped - def flat_map(enum, &blk) - enum.flat_map(&blk) - end - else - # Flat map - # @param [Enumerable] enum an enumerable object - # @block the block to flat-map with - # @return The enum, flat-mapped - def flat_map(enum, &blk) - enum.map(&blk).flatten(1) - end - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb b/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb deleted file mode 100644 index bcacf35243..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - # @!visibility private - module Delegates - # Delegates all {Bundler::Molinillo::ResolutionState} methods to a `#state` property. - module ResolutionState - # (see Bundler::Molinillo::ResolutionState#name) - def name - current_state = state || Bundler::Molinillo::ResolutionState.empty - current_state.name - end - - # (see Bundler::Molinillo::ResolutionState#requirements) - def requirements - current_state = state || Bundler::Molinillo::ResolutionState.empty - current_state.requirements - end - - # (see Bundler::Molinillo::ResolutionState#activated) - def activated - current_state = state || Bundler::Molinillo::ResolutionState.empty - current_state.activated - end - - # (see Bundler::Molinillo::ResolutionState#requirement) - def requirement - current_state = state || Bundler::Molinillo::ResolutionState.empty - current_state.requirement - end - - # (see Bundler::Molinillo::ResolutionState#possibilities) - def possibilities - current_state = state || Bundler::Molinillo::ResolutionState.empty - current_state.possibilities - end - - # (see Bundler::Molinillo::ResolutionState#depth) - def depth - current_state = state || Bundler::Molinillo::ResolutionState.empty - current_state.depth - end - - # (see Bundler::Molinillo::ResolutionState#conflicts) - def conflicts - current_state = state || Bundler::Molinillo::ResolutionState.empty - current_state.conflicts - end - - # (see Bundler::Molinillo::ResolutionState#unused_unwind_options) - def unused_unwind_options - current_state = state || Bundler::Molinillo::ResolutionState.empty - current_state.unused_unwind_options - end - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb b/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb deleted file mode 100644 index ec9c770a28..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +++ /dev/null @@ -1,81 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - module Delegates - # Delegates all {Bundler::Molinillo::SpecificationProvider} methods to a - # `#specification_provider` property. - module SpecificationProvider - # (see Bundler::Molinillo::SpecificationProvider#search_for) - def search_for(dependency) - with_no_such_dependency_error_handling do - specification_provider.search_for(dependency) - end - end - - # (see Bundler::Molinillo::SpecificationProvider#dependencies_for) - def dependencies_for(specification) - with_no_such_dependency_error_handling do - specification_provider.dependencies_for(specification) - end - end - - # (see Bundler::Molinillo::SpecificationProvider#requirement_satisfied_by?) - def requirement_satisfied_by?(requirement, activated, spec) - with_no_such_dependency_error_handling do - specification_provider.requirement_satisfied_by?(requirement, activated, spec) - end - end - - # (see Bundler::Molinillo::SpecificationProvider#name_for) - def name_for(dependency) - with_no_such_dependency_error_handling do - specification_provider.name_for(dependency) - end - end - - # (see Bundler::Molinillo::SpecificationProvider#name_for_explicit_dependency_source) - def name_for_explicit_dependency_source - with_no_such_dependency_error_handling do - specification_provider.name_for_explicit_dependency_source - end - end - - # (see Bundler::Molinillo::SpecificationProvider#name_for_locking_dependency_source) - def name_for_locking_dependency_source - with_no_such_dependency_error_handling do - specification_provider.name_for_locking_dependency_source - end - end - - # (see Bundler::Molinillo::SpecificationProvider#sort_dependencies) - def sort_dependencies(dependencies, activated, conflicts) - with_no_such_dependency_error_handling do - specification_provider.sort_dependencies(dependencies, activated, conflicts) - end - end - - # (see Bundler::Molinillo::SpecificationProvider#allow_missing?) - def allow_missing?(dependency) - with_no_such_dependency_error_handling do - specification_provider.allow_missing?(dependency) - end - end - - private - - # Ensures any raised {NoSuchDependencyError} has its - # {NoSuchDependencyError#required_by} set. - # @yield - def with_no_such_dependency_error_handling - yield - rescue NoSuchDependencyError => error - if state - vertex = activated.vertex_named(name_for(error.dependency)) - error.required_by += vertex.incoming_edges.map { |e| e.origin.name } - error.required_by << name_for_explicit_dependency_source unless vertex.explicit_requirements.empty? - end - raise - end - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb deleted file mode 100644 index 677a8bd916..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +++ /dev/null @@ -1,223 +0,0 @@ -# frozen_string_literal: true - -require 'set' -require 'tsort' - -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/log' -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex' - -module Bundler::Molinillo - # A directed acyclic graph that is tuned to hold named dependencies - class DependencyGraph - include Enumerable - - # Enumerates through the vertices of the graph. - # @return [Array<Vertex>] The graph's vertices. - def each - return vertices.values.each unless block_given? - vertices.values.each { |v| yield v } - end - - include TSort - - # @!visibility private - alias tsort_each_node each - - # @!visibility private - def tsort_each_child(vertex, &block) - vertex.successors.each(&block) - end - - # Topologically sorts the given vertices. - # @param [Enumerable<Vertex>] vertices the vertices to be sorted, which must - # all belong to the same graph. - # @return [Array<Vertex>] The sorted vertices. - def self.tsort(vertices) - TSort.tsort( - lambda { |b| vertices.each(&b) }, - lambda { |v, &b| (v.successors & vertices).each(&b) } - ) - end - - # A directed edge of a {DependencyGraph} - # @attr [Vertex] origin The origin of the directed edge - # @attr [Vertex] destination The destination of the directed edge - # @attr [Object] requirement The requirement the directed edge represents - Edge = Struct.new(:origin, :destination, :requirement) - - # @return [{String => Vertex}] the vertices of the dependency graph, keyed - # by {Vertex#name} - attr_reader :vertices - - # @return [Log] the op log for this graph - attr_reader :log - - # Initializes an empty dependency graph - def initialize - @vertices = {} - @log = Log.new - end - - # Tags the current state of the dependency as the given tag - # @param [Object] tag an opaque tag for the current state of the graph - # @return [Void] - def tag(tag) - log.tag(self, tag) - end - - # Rewinds the graph to the state tagged as `tag` - # @param [Object] tag the tag to rewind to - # @return [Void] - def rewind_to(tag) - log.rewind_to(self, tag) - end - - # Initializes a copy of a {DependencyGraph}, ensuring that all {#vertices} - # are properly copied. - # @param [DependencyGraph] other the graph to copy. - def initialize_copy(other) - super - @vertices = {} - @log = other.log.dup - traverse = lambda do |new_v, old_v| - return if new_v.outgoing_edges.size == old_v.outgoing_edges.size - old_v.outgoing_edges.each do |edge| - destination = add_vertex(edge.destination.name, edge.destination.payload) - add_edge_no_circular(new_v, destination, edge.requirement) - traverse.call(destination, edge.destination) - end - end - other.vertices.each do |name, vertex| - new_vertex = add_vertex(name, vertex.payload, vertex.root?) - new_vertex.explicit_requirements.replace(vertex.explicit_requirements) - traverse.call(new_vertex, vertex) - end - end - - # @return [String] a string suitable for debugging - def inspect - "#{self.class}:#{vertices.values.inspect}" - end - - # @param [Hash] options options for dot output. - # @return [String] Returns a dot format representation of the graph - def to_dot(options = {}) - edge_label = options.delete(:edge_label) - raise ArgumentError, "Unknown options: #{options.keys}" unless options.empty? - - dot_vertices = [] - dot_edges = [] - vertices.each do |n, v| - dot_vertices << " #{n} [label=\"{#{n}|#{v.payload}}\"]" - v.outgoing_edges.each do |e| - label = edge_label ? edge_label.call(e) : e.requirement - dot_edges << " #{e.origin.name} -> #{e.destination.name} [label=#{label.to_s.dump}]" - end - end - - dot_vertices.uniq! - dot_vertices.sort! - dot_edges.uniq! - dot_edges.sort! - - dot = dot_vertices.unshift('digraph G {').push('') + dot_edges.push('}') - dot.join("\n") - end - - # @return [Boolean] whether the two dependency graphs are equal, determined - # by a recursive traversal of each {#root_vertices} and its - # {Vertex#successors} - def ==(other) - return false unless other - return true if equal?(other) - vertices.each do |name, vertex| - other_vertex = other.vertex_named(name) - return false unless other_vertex - return false unless vertex.payload == other_vertex.payload - return false unless other_vertex.successors.to_set == vertex.successors.to_set - end - end - - # @param [String] name - # @param [Object] payload - # @param [Array<String>] parent_names - # @param [Object] requirement the requirement that is requiring the child - # @return [void] - def add_child_vertex(name, payload, parent_names, requirement) - root = !parent_names.delete(nil) { true } - vertex = add_vertex(name, payload, root) - vertex.explicit_requirements << requirement if root - parent_names.each do |parent_name| - parent_vertex = vertex_named(parent_name) - add_edge(parent_vertex, vertex, requirement) - end - vertex - end - - # Adds a vertex with the given name, or updates the existing one. - # @param [String] name - # @param [Object] payload - # @return [Vertex] the vertex that was added to `self` - def add_vertex(name, payload, root = false) - log.add_vertex(self, name, payload, root) - end - - # Detaches the {#vertex_named} `name` {Vertex} from the graph, recursively - # removing any non-root vertices that were orphaned in the process - # @param [String] name - # @return [Array<Vertex>] the vertices which have been detached - def detach_vertex_named(name) - log.detach_vertex_named(self, name) - end - - # @param [String] name - # @return [Vertex,nil] the vertex with the given name - def vertex_named(name) - vertices[name] - end - - # @param [String] name - # @return [Vertex,nil] the root vertex with the given name - def root_vertex_named(name) - vertex = vertex_named(name) - vertex if vertex && vertex.root? - end - - # Adds a new {Edge} to the dependency graph - # @param [Vertex] origin - # @param [Vertex] destination - # @param [Object] requirement the requirement that this edge represents - # @return [Edge] the added edge - def add_edge(origin, destination, requirement) - if destination.path_to?(origin) - raise CircularDependencyError.new([origin, destination]) - end - add_edge_no_circular(origin, destination, requirement) - end - - # Deletes an {Edge} from the dependency graph - # @param [Edge] edge - # @return [Void] - def delete_edge(edge) - log.delete_edge(self, edge.origin.name, edge.destination.name, edge.requirement) - end - - # Sets the payload of the vertex with the given name - # @param [String] name the name of the vertex - # @param [Object] payload the payload - # @return [Void] - def set_payload(name, payload) - log.set_payload(self, name, payload) - end - - private - - # Adds a new {Edge} to the dependency graph without checking for - # circularity. - # @param (see #add_edge) - # @return (see #add_edge) - def add_edge_no_circular(origin, destination, requirement) - log.add_edge_no_circular(self, origin.name, destination.name, requirement) - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb deleted file mode 100644 index c04c7eec9c..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - class DependencyGraph - # An action that modifies a {DependencyGraph} that is reversible. - # @abstract - class Action - # rubocop:disable Lint/UnusedMethodArgument - - # @return [Symbol] The name of the action. - def self.action_name - raise 'Abstract' - end - - # Performs the action on the given graph. - # @param [DependencyGraph] graph the graph to perform the action on. - # @return [Void] - def up(graph) - raise 'Abstract' - end - - # Reverses the action on the given graph. - # @param [DependencyGraph] graph the graph to reverse the action on. - # @return [Void] - def down(graph) - raise 'Abstract' - end - - # @return [Action,Nil] The previous action - attr_accessor :previous - - # @return [Action,Nil] The next action - attr_accessor :next - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb deleted file mode 100644 index 9849aea2fe..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +++ /dev/null @@ -1,66 +0,0 @@ -# frozen_string_literal: true - -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' -module Bundler::Molinillo - class DependencyGraph - # @!visibility private - # (see DependencyGraph#add_edge_no_circular) - class AddEdgeNoCircular < Action - # @!group Action - - # (see Action.action_name) - def self.action_name - :add_vertex - end - - # (see Action#up) - def up(graph) - edge = make_edge(graph) - edge.origin.outgoing_edges << edge - edge.destination.incoming_edges << edge - edge - end - - # (see Action#down) - def down(graph) - edge = make_edge(graph) - delete_first(edge.origin.outgoing_edges, edge) - delete_first(edge.destination.incoming_edges, edge) - end - - # @!group AddEdgeNoCircular - - # @return [String] the name of the origin of the edge - attr_reader :origin - - # @return [String] the name of the destination of the edge - attr_reader :destination - - # @return [Object] the requirement that the edge represents - attr_reader :requirement - - # @param [DependencyGraph] graph the graph to find vertices from - # @return [Edge] The edge this action adds - def make_edge(graph) - Edge.new(graph.vertex_named(origin), graph.vertex_named(destination), requirement) - end - - # Initialize an action to add an edge to a dependency graph - # @param [String] origin the name of the origin of the edge - # @param [String] destination the name of the destination of the edge - # @param [Object] requirement the requirement that the edge represents - def initialize(origin, destination, requirement) - @origin = origin - @destination = destination - @requirement = requirement - end - - private - - def delete_first(array, item) - return unless index = array.index(item) - array.delete_at(index) - end - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb deleted file mode 100644 index 0a1e08255b..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: true - -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' -module Bundler::Molinillo - class DependencyGraph - # @!visibility private - # (see DependencyGraph#add_vertex) - class AddVertex < Action # :nodoc: - # @!group Action - - # (see Action.action_name) - def self.action_name - :add_vertex - end - - # (see Action#up) - def up(graph) - if existing = graph.vertices[name] - @existing_payload = existing.payload - @existing_root = existing.root - end - vertex = existing || Vertex.new(name, payload) - graph.vertices[vertex.name] = vertex - vertex.payload ||= payload - vertex.root ||= root - vertex - end - - # (see Action#down) - def down(graph) - if defined?(@existing_payload) - vertex = graph.vertices[name] - vertex.payload = @existing_payload - vertex.root = @existing_root - else - graph.vertices.delete(name) - end - end - - # @!group AddVertex - - # @return [String] the name of the vertex - attr_reader :name - - # @return [Object] the payload for the vertex - attr_reader :payload - - # @return [Boolean] whether the vertex is root or not - attr_reader :root - - # Initialize an action to add a vertex to a dependency graph - # @param [String] name the name of the vertex - # @param [Object] payload the payload for the vertex - # @param [Boolean] root whether the vertex is root or not - def initialize(name, payload, root) - @name = name - @payload = payload - @root = root - end - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb deleted file mode 100644 index 1d9f4b327d..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: true - -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' -module Bundler::Molinillo - class DependencyGraph - # @!visibility private - # (see DependencyGraph#delete_edge) - class DeleteEdge < Action - # @!group Action - - # (see Action.action_name) - def self.action_name - :delete_edge - end - - # (see Action#up) - def up(graph) - edge = make_edge(graph) - edge.origin.outgoing_edges.delete(edge) - edge.destination.incoming_edges.delete(edge) - end - - # (see Action#down) - def down(graph) - edge = make_edge(graph) - edge.origin.outgoing_edges << edge - edge.destination.incoming_edges << edge - edge - end - - # @!group DeleteEdge - - # @return [String] the name of the origin of the edge - attr_reader :origin_name - - # @return [String] the name of the destination of the edge - attr_reader :destination_name - - # @return [Object] the requirement that the edge represents - attr_reader :requirement - - # @param [DependencyGraph] graph the graph to find vertices from - # @return [Edge] The edge this action adds - def make_edge(graph) - Edge.new( - graph.vertex_named(origin_name), - graph.vertex_named(destination_name), - requirement - ) - end - - # Initialize an action to add an edge to a dependency graph - # @param [String] origin_name the name of the origin of the edge - # @param [String] destination_name the name of the destination of the edge - # @param [Object] requirement the requirement that the edge represents - def initialize(origin_name, destination_name, requirement) - @origin_name = origin_name - @destination_name = destination_name - @requirement = requirement - end - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb deleted file mode 100644 index 385dcbdd06..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +++ /dev/null @@ -1,61 +0,0 @@ -# frozen_string_literal: true - -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' -module Bundler::Molinillo - class DependencyGraph - # @!visibility private - # @see DependencyGraph#detach_vertex_named - class DetachVertexNamed < Action - # @!group Action - - # (see Action#name) - def self.action_name - :add_vertex - end - - # (see Action#up) - def up(graph) - return [] unless @vertex = graph.vertices.delete(name) - - removed_vertices = [@vertex] - @vertex.outgoing_edges.each do |e| - v = e.destination - v.incoming_edges.delete(e) - if !v.root? && v.incoming_edges.empty? - removed_vertices.concat graph.detach_vertex_named(v.name) - end - end - - @vertex.incoming_edges.each do |e| - v = e.origin - v.outgoing_edges.delete(e) - end - - removed_vertices - end - - # (see Action#down) - def down(graph) - return unless @vertex - graph.vertices[@vertex.name] = @vertex - @vertex.outgoing_edges.each do |e| - e.destination.incoming_edges << e - end - @vertex.incoming_edges.each do |e| - e.origin.outgoing_edges << e - end - end - - # @!group DetachVertexNamed - - # @return [String] the name of the vertex to detach - attr_reader :name - - # Initialize an action to detach a vertex from a dependency graph - # @param [String] name the name of the vertex to detach - def initialize(name) - @name = name - end - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb deleted file mode 100644 index 8582dd19c1..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +++ /dev/null @@ -1,126 +0,0 @@ -# frozen_string_literal: true - -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular' -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex' -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge' -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named' -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload' -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag' - -module Bundler::Molinillo - class DependencyGraph - # A log for dependency graph actions - class Log - # Initializes an empty log - def initialize - @current_action = @first_action = nil - end - - # @!macro [new] action - # {include:DependencyGraph#$0} - # @param [Graph] graph the graph to perform the action on - # @param (see DependencyGraph#$0) - # @return (see DependencyGraph#$0) - - # @macro action - def tag(graph, tag) - push_action(graph, Tag.new(tag)) - end - - # @macro action - def add_vertex(graph, name, payload, root) - push_action(graph, AddVertex.new(name, payload, root)) - end - - # @macro action - def detach_vertex_named(graph, name) - push_action(graph, DetachVertexNamed.new(name)) - end - - # @macro action - def add_edge_no_circular(graph, origin, destination, requirement) - push_action(graph, AddEdgeNoCircular.new(origin, destination, requirement)) - end - - # {include:DependencyGraph#delete_edge} - # @param [Graph] graph the graph to perform the action on - # @param [String] origin_name - # @param [String] destination_name - # @param [Object] requirement - # @return (see DependencyGraph#delete_edge) - def delete_edge(graph, origin_name, destination_name, requirement) - push_action(graph, DeleteEdge.new(origin_name, destination_name, requirement)) - end - - # @macro action - def set_payload(graph, name, payload) - push_action(graph, SetPayload.new(name, payload)) - end - - # Pops the most recent action from the log and undoes the action - # @param [DependencyGraph] graph - # @return [Action] the action that was popped off the log - def pop!(graph) - return unless action = @current_action - unless @current_action = action.previous - @first_action = nil - end - action.down(graph) - action - end - - extend Enumerable - - # @!visibility private - # Enumerates each action in the log - # @yield [Action] - def each - return enum_for unless block_given? - action = @first_action - loop do - break unless action - yield action - action = action.next - end - self - end - - # @!visibility private - # Enumerates each action in the log in reverse order - # @yield [Action] - def reverse_each - return enum_for(:reverse_each) unless block_given? - action = @current_action - loop do - break unless action - yield action - action = action.previous - end - self - end - - # @macro action - def rewind_to(graph, tag) - loop do - action = pop!(graph) - raise "No tag #{tag.inspect} found" unless action - break if action.class.action_name == :tag && action.tag == tag - end - end - - private - - # Adds the given action to the log, running the action - # @param [DependencyGraph] graph - # @param [Action] action - # @return The value returned by `action.up` - def push_action(graph, action) - action.previous = @current_action - @current_action.next = action if @current_action - @current_action = action - @first_action ||= action - action.up(graph) - end - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb deleted file mode 100644 index 37286d104a..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +++ /dev/null @@ -1,46 +0,0 @@ -# frozen_string_literal: true - -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' -module Bundler::Molinillo - class DependencyGraph - # @!visibility private - # @see DependencyGraph#set_payload - class SetPayload < Action # :nodoc: - # @!group Action - - # (see Action.action_name) - def self.action_name - :set_payload - end - - # (see Action#up) - def up(graph) - vertex = graph.vertex_named(name) - @old_payload = vertex.payload - vertex.payload = payload - end - - # (see Action#down) - def down(graph) - graph.vertex_named(name).payload = @old_payload - end - - # @!group SetPayload - - # @return [String] the name of the vertex - attr_reader :name - - # @return [Object] the payload for the vertex - attr_reader :payload - - # Initialize an action to add set the payload for a vertex in a dependency - # graph - # @param [String] name the name of the vertex - # @param [Object] payload the payload for the vertex - def initialize(name, payload) - @name = name - @payload = payload - end - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb deleted file mode 100644 index d6ad16e07a..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph/action' -module Bundler::Molinillo - class DependencyGraph - # @!visibility private - # @see DependencyGraph#tag - class Tag < Action - # @!group Action - - # (see Action.action_name) - def self.action_name - :tag - end - - # (see Action#up) - def up(_graph) - end - - # (see Action#down) - def down(_graph) - end - - # @!group Tag - - # @return [Object] An opaque tag - attr_reader :tag - - # Initialize an action to tag a state of a dependency graph - # @param [Object] tag an opaque tag - def initialize(tag) - @tag = tag - end - end - end -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 deleted file mode 100644 index e4d016de24..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +++ /dev/null @@ -1,126 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - class DependencyGraph - # A vertex in a {DependencyGraph} that encapsulates a {#name} and a - # {#payload} - class Vertex - # @return [String] the name of the vertex - attr_accessor :name - - # @return [Object] the payload the vertex holds - attr_accessor :payload - - # @return [Array<Object>] the explicit requirements that required - # this vertex - attr_reader :explicit_requirements - - # @return [Boolean] whether the vertex is considered a root vertex - attr_accessor :root - alias root? root - - # Initializes a vertex with the given name and payload. - # @param [String] name see {#name} - # @param [Object] payload see {#payload} - def initialize(name, payload) - @name = name.frozen? ? name : name.dup.freeze - @payload = payload - @explicit_requirements = [] - @outgoing_edges = [] - @incoming_edges = [] - end - - # @return [Array<Object>] all of the requirements that required - # this vertex - def requirements - (incoming_edges.map(&:requirement) + explicit_requirements).uniq - end - - # @return [Array<Edge>] the edges of {#graph} that have `self` as their - # {Edge#origin} - attr_accessor :outgoing_edges - - # @return [Array<Edge>] the edges of {#graph} that have `self` as their - # {Edge#destination} - attr_accessor :incoming_edges - - # @return [Array<Vertex>] the vertices of {#graph} that have an edge with - # `self` as their {Edge#destination} - def predecessors - incoming_edges.map(&:origin) - end - - # @return [Array<Vertex>] the vertices of {#graph} where `self` is a - # {#descendent?} - def recursive_predecessors - vertices = predecessors - vertices += Compatibility.flat_map(vertices, &:recursive_predecessors) - vertices.uniq! - vertices - end - - # @return [Array<Vertex>] the vertices of {#graph} that have an edge with - # `self` as their {Edge#origin} - def successors - outgoing_edges.map(&:destination) - end - - # @return [Array<Vertex>] the vertices of {#graph} where `self` is an - # {#ancestor?} - def recursive_successors - vertices = successors - vertices += Compatibility.flat_map(vertices, &:recursive_successors) - vertices.uniq! - vertices - end - - # @return [String] a string suitable for debugging - def inspect - "#{self.class}:#{name}(#{payload.inspect})" - end - - # @return [Boolean] whether the two vertices are equal, determined - # by a recursive traversal of each {Vertex#successors} - def ==(other) - return true if equal?(other) - shallow_eql?(other) && - successors.to_set == other.successors.to_set - end - - # @param [Vertex] other the other vertex to compare to - # @return [Boolean] whether the two vertices are equal, determined - # solely by {#name} and {#payload} equality - def shallow_eql?(other) - return true if equal?(other) - other && - name == other.name && - payload == other.payload - end - - alias eql? == - - # @return [Fixnum] a hash for the vertex based upon its {#name} - def hash - name.hash - end - - # Is there a path from `self` to `other` following edges in the - # dependency graph? - # @return true iff there is a path following edges within this {#graph} - def path_to?(other) - equal?(other) || successors.any? { |v| v.path_to?(other) } - end - - alias descendent? path_to? - - # Is there a path from `other` to `self` following edges in the - # dependency graph? - # @return true iff there is a path following edges within this {#graph} - def ancestor?(other) - other.path_to?(self) - end - - alias is_reachable_from? ancestor? - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb b/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb deleted file mode 100644 index fb343250b1..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +++ /dev/null @@ -1,138 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - # An error that occurred during the resolution process - class ResolverError < StandardError; end - - # An error caused by searching for a dependency that is completely unknown, - # i.e. has no versions available whatsoever. - class NoSuchDependencyError < ResolverError - # @return [Object] the dependency that could not be found - attr_accessor :dependency - - # @return [Array<Object>] the specifications that depended upon {#dependency} - attr_accessor :required_by - - # Initializes a new error with the given missing dependency. - # @param [Object] dependency @see {#dependency} - # @param [Array<Object>] required_by @see {#required_by} - def initialize(dependency, required_by = []) - @dependency = dependency - @required_by = required_by - super() - end - - # The error message for the missing dependency, including the specifications - # that had this dependency. - def message - sources = required_by.map { |r| "`#{r}`" }.join(' and ') - message = "Unable to find a specification for `#{dependency}`" - message += " depended upon by #{sources}" unless sources.empty? - message - end - end - - # An error caused by attempting to fulfil a dependency that was circular - # - # @note This exception will be thrown iff a {Vertex} is added to a - # {DependencyGraph} that has a {DependencyGraph::Vertex#path_to?} an - # existing {DependencyGraph::Vertex} - class CircularDependencyError < ResolverError - # [Set<Object>] the dependencies responsible for causing the error - attr_reader :dependencies - - # Initializes a new error with the given circular vertices. - # @param [Array<DependencyGraph::Vertex>] vertices the vertices in the dependency - # that caused the error - def initialize(vertices) - super "There is a circular dependency between #{vertices.map(&:name).join(' and ')}" - @dependencies = vertices.map { |vertex| vertex.payload.possibilities.last }.to_set - end - end - - # An error caused by conflicts in version - class VersionConflict < ResolverError - # @return [{String => Resolution::Conflict}] the conflicts that caused - # resolution to fail - attr_reader :conflicts - - # @return [SpecificationProvider] the specification provider used during - # resolution - attr_reader :specification_provider - - # Initializes a new error with the given version conflicts. - # @param [{String => Resolution::Conflict}] conflicts see {#conflicts} - # @param [SpecificationProvider] specification_provider see {#specification_provider} - def initialize(conflicts, specification_provider) - pairs = [] - Compatibility.flat_map(conflicts.values.flatten, &:requirements).each do |conflicting| - conflicting.each do |source, conflict_requirements| - conflict_requirements.each do |c| - pairs << [c, source] - end - end - end - - super "Unable to satisfy the following requirements:\n\n" \ - "#{pairs.map { |r, d| "- `#{r}` required by `#{d}`" }.join("\n")}" - - @conflicts = conflicts - @specification_provider = specification_provider - end - - require 'bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider' - include Delegates::SpecificationProvider - - # @return [String] An error message that includes requirement trees, - # which is much more detailed & customizable than the default message - # @param [Hash] opts the options to create a message with. - # @option opts [String] :solver_name The user-facing name of the solver - # @option opts [String] :possibility_type The generic name of a possibility - # @option opts [Proc] :reduce_trees A proc that reduced the list of requirement trees - # @option opts [Proc] :printable_requirement A proc that pretty-prints requirements - # @option opts [Proc] :additional_message_for_conflict A proc that appends additional - # messages for each conflict - # @option opts [Proc] :version_for_spec A proc that returns the version number for a - # possibility - def message_with_trees(opts = {}) - solver_name = opts.delete(:solver_name) { self.class.name.split('::').first } - possibility_type = opts.delete(:possibility_type) { 'possibility named' } - reduce_trees = opts.delete(:reduce_trees) { proc { |trees| trees.uniq.sort_by(&:to_s) } } - printable_requirement = opts.delete(:printable_requirement) { proc { |req| req.to_s } } - additional_message_for_conflict = opts.delete(:additional_message_for_conflict) { proc {} } - version_for_spec = opts.delete(:version_for_spec) { proc(&:to_s) } - - conflicts.sort.reduce(''.dup) do |o, (name, conflict)| - o << %(\n#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":\n) - if conflict.locked_requirement - o << %( In snapshot (#{name_for_locking_dependency_source}):\n) - o << %( #{printable_requirement.call(conflict.locked_requirement)}\n) - o << %(\n) - end - o << %( In #{name_for_explicit_dependency_source}:\n) - trees = reduce_trees.call(conflict.requirement_trees) - - o << trees.map do |tree| - t = ''.dup - depth = 2 - tree.each do |req| - t << ' ' * depth << req.to_s - unless tree.last == req - if spec = conflict.activated_by_name[name_for(req)] - t << %( was resolved to #{version_for_spec.call(spec)}, which) - end - t << %( depends on) - end - t << %(\n) - depth += 1 - end - t - end.join("\n") - - additional_message_for_conflict.call(o, name, conflict) - - o - end.strip - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb b/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb deleted file mode 100644 index 3feb7be9b5..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - # The version of Bundler::Molinillo. - VERSION = '0.6.4'.freeze -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb b/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb deleted file mode 100644 index fa094c1981..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +++ /dev/null @@ -1,101 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - # Provides information about specifcations and dependencies to the resolver, - # allowing the {Resolver} class to remain generic while still providing power - # and flexibility. - # - # This module contains the methods that users of Bundler::Molinillo must to implement, - # using knowledge of their own model classes. - module SpecificationProvider - # Search for the specifications that match the given dependency. - # The specifications in the returned array will be considered in reverse - # order, so the latest version ought to be last. - # @note This method should be 'pure', i.e. the return value should depend - # only on the `dependency` parameter. - # - # @param [Object] dependency - # @return [Array<Object>] the specifications that satisfy the given - # `dependency`. - def search_for(dependency) - [] - end - - # Returns the dependencies of `specification`. - # @note This method should be 'pure', i.e. the return value should depend - # only on the `specification` parameter. - # - # @param [Object] specification - # @return [Array<Object>] the dependencies that are required by the given - # `specification`. - def dependencies_for(specification) - [] - end - - # Determines whether the given `requirement` is satisfied by the given - # `spec`, in the context of the current `activated` dependency graph. - # - # @param [Object] requirement - # @param [DependencyGraph] activated the current dependency graph in the - # resolution process. - # @param [Object] spec - # @return [Boolean] whether `requirement` is satisfied by `spec` in the - # context of the current `activated` dependency graph. - def requirement_satisfied_by?(requirement, activated, spec) - true - end - - # Returns the name for the given `dependency`. - # @note This method should be 'pure', i.e. the return value should depend - # only on the `dependency` parameter. - # - # @param [Object] dependency - # @return [String] the name for the given `dependency`. - def name_for(dependency) - dependency.to_s - end - - # @return [String] the name of the source of explicit dependencies, i.e. - # those passed to {Resolver#resolve} directly. - def name_for_explicit_dependency_source - 'user-specified dependency' - end - - # @return [String] the name of the source of 'locked' dependencies, i.e. - # those passed to {Resolver#resolve} directly as the `base` - def name_for_locking_dependency_source - 'Lockfile' - end - - # Sort dependencies so that the ones that are easiest to resolve are first. - # Easiest to resolve is (usually) defined by: - # 1) Is this dependency already activated? - # 2) How relaxed are the requirements? - # 3) Are there any conflicts for this dependency? - # 4) How many possibilities are there to satisfy this dependency? - # - # @param [Array<Object>] dependencies - # @param [DependencyGraph] activated the current dependency graph in the - # resolution process. - # @param [{String => Array<Conflict>}] conflicts - # @return [Array<Object>] a sorted copy of `dependencies`. - def sort_dependencies(dependencies, activated, conflicts) - dependencies.sort_by do |dependency| - name = name_for(dependency) - [ - activated.vertex_named(name).payload ? 0 : 1, - conflicts[name] ? 0 : 1, - ] - end - end - - # Returns whether this dependency, which has no possible matching - # specifications, can safely be ignored. - # - # @param [Object] dependency - # @return [Boolean] whether this dependency can safely be skipped. - def allow_missing?(dependency) - false - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb b/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb deleted file mode 100644 index a166bc6991..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +++ /dev/null @@ -1,67 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - # Conveys information about the resolution process to a user. - module UI - # The {IO} object that should be used to print output. `STDOUT`, by default. - # - # @return [IO] - def output - STDOUT - end - - # Called roughly every {#progress_rate}, this method should convey progress - # to the user. - # - # @return [void] - def indicate_progress - output.print '.' unless debug? - end - - # How often progress should be conveyed to the user via - # {#indicate_progress}, in seconds. A third of a second, by default. - # - # @return [Float] - def progress_rate - 0.33 - end - - # Called before resolution begins. - # - # @return [void] - def before_resolution - output.print 'Resolving dependencies...' - end - - # Called after resolution ends (either successfully or with an error). - # By default, prints a newline. - # - # @return [void] - def after_resolution - output.puts - end - - # Conveys debug information to the user. - # - # @param [Integer] depth the current depth of the resolution process. - # @return [void] - def debug(depth = 0) - if debug? - debug_info = yield - debug_info = debug_info.inspect unless debug_info.is_a?(String) - debug_info = debug_info.split("\n").map { |s| ":#{depth.to_s.rjust 4}: #{s}" } - output.puts debug_info - end - end - - # Whether or not debug messages should be printed. - # By default, whether or not the `MOLINILLO_DEBUG` environment variable is - # set. - # - # @return [Boolean] - def debug? - return @debug_mode if defined?(@debug_mode) - @debug_mode = ENV['MOLINILLO_DEBUG'] - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb b/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb deleted file mode 100644 index 0eb665d17a..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +++ /dev/null @@ -1,837 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - class Resolver - # A specific resolution from a given {Resolver} - class Resolution - # A conflict that the resolution process encountered - # @attr [Object] requirement the requirement that immediately led to the conflict - # @attr [{String,Nil=>[Object]}] requirements the requirements that caused the conflict - # @attr [Object, nil] existing the existing spec that was in conflict with - # the {#possibility} - # @attr [Object] possibility_set the set of specs that was unable to be - # activated due to a conflict. - # @attr [Object] locked_requirement the relevant locking requirement. - # @attr [Array<Array<Object>>] requirement_trees the different requirement - # trees that led to every requirement for the conflicting name. - # @attr [{String=>Object}] activated_by_name the already-activated specs. - # @attr [Object] underlying_error an error that has occurred during resolution, and - # will be raised at the end of it if no resolution is found. - Conflict = Struct.new( - :requirement, - :requirements, - :existing, - :possibility_set, - :locked_requirement, - :requirement_trees, - :activated_by_name, - :underlying_error - ) - - class Conflict - # @return [Object] a spec that was unable to be activated due to a conflict - def possibility - possibility_set && possibility_set.latest_version - end - end - - # A collection of possibility states that share the same dependencies - # @attr [Array] dependencies the dependencies for this set of possibilities - # @attr [Array] possibilities the possibilities - PossibilitySet = Struct.new(:dependencies, :possibilities) - - class PossibilitySet - # String representation of the possibility set, for debugging - def to_s - "[#{possibilities.join(', ')}]" - end - - # @return [Object] most up-to-date dependency in the possibility set - def latest_version - possibilities.last - end - end - - # Details of the state to unwind to when a conflict occurs, and the cause of the unwind - # @attr [Integer] state_index the index of the state to unwind to - # @attr [Object] state_requirement the requirement of the state we're unwinding to - # @attr [Array] requirement_tree for the requirement we're relaxing - # @attr [Array] conflicting_requirements the requirements that combined to cause the conflict - # @attr [Array] requirement_trees for the conflict - # @attr [Array] requirements_unwound_to_instead array of unwind requirements that were chosen over this unwind - UnwindDetails = Struct.new( - :state_index, - :state_requirement, - :requirement_tree, - :conflicting_requirements, - :requirement_trees, - :requirements_unwound_to_instead - ) - - class UnwindDetails - include Comparable - - # We compare UnwindDetails when choosing which state to unwind to. If - # two options have the same state_index we prefer the one most - # removed from a requirement that caused the conflict. Both options - # would unwind to the same state, but a `grandparent` option will - # filter out fewer of its possibilities after doing so - where a state - # is both a `parent` and a `grandparent` to requirements that have - # caused a conflict this is the correct behaviour. - # @param [UnwindDetail] other UnwindDetail to be compared - # @return [Integer] integer specifying ordering - def <=>(other) - if state_index > other.state_index - 1 - elsif state_index == other.state_index - reversed_requirement_tree_index <=> other.reversed_requirement_tree_index - else - -1 - end - end - - # @return [Integer] index of state requirement in reversed requirement tree - # (the conflicting requirement itself will be at position 0) - def reversed_requirement_tree_index - @reversed_requirement_tree_index ||= - if state_requirement - requirement_tree.reverse.index(state_requirement) - else - 999_999 - end - end - - # @return [Boolean] where the requirement of the state we're unwinding - # to directly caused the conflict. Note: in this case, it is - # impossible for the state we're unwinding to to be a parent of - # any of the other conflicting requirements (or we would have - # circularity) - def unwinding_to_primary_requirement? - requirement_tree.last == state_requirement - end - - # @return [Array] array of sub-dependencies to avoid when choosing a - # new possibility for the state we've unwound to. Only relevant for - # non-primary unwinds - def sub_dependencies_to_avoid - @requirements_to_avoid ||= - requirement_trees.map do |tree| - index = tree.index(state_requirement) - tree[index + 1] if index - end.compact - end - - # @return [Array] array of all the requirements that led to the need for - # this unwind - def all_requirements - @all_requirements ||= requirement_trees.flatten(1) - end - end - - # @return [SpecificationProvider] the provider that knows about - # dependencies, requirements, specifications, versions, etc. - attr_reader :specification_provider - - # @return [UI] the UI that knows how to communicate feedback about the - # resolution process back to the user - attr_reader :resolver_ui - - # @return [DependencyGraph] the base dependency graph to which - # dependencies should be 'locked' - attr_reader :base - - # @return [Array] the dependencies that were explicitly required - attr_reader :original_requested - - # Initializes a new resolution. - # @param [SpecificationProvider] specification_provider - # see {#specification_provider} - # @param [UI] resolver_ui see {#resolver_ui} - # @param [Array] requested see {#original_requested} - # @param [DependencyGraph] base see {#base} - def initialize(specification_provider, resolver_ui, requested, base) - @specification_provider = specification_provider - @resolver_ui = resolver_ui - @original_requested = requested - @base = base - @states = [] - @iteration_counter = 0 - @parents_of = Hash.new { |h, k| h[k] = [] } - end - - # Resolves the {#original_requested} dependencies into a full dependency - # graph - # @raise [ResolverError] if successful resolution is impossible - # @return [DependencyGraph] the dependency graph of successfully resolved - # dependencies - def resolve - start_resolution - - while state - break if !state.requirement && state.requirements.empty? - indicate_progress - if state.respond_to?(:pop_possibility_state) # DependencyState - debug(depth) { "Creating possibility state for #{requirement} (#{possibilities.count} remaining)" } - state.pop_possibility_state.tap do |s| - if s - states.push(s) - activated.tag(s) - end - end - end - process_topmost_state - end - - resolve_activated_specs - ensure - end_resolution - end - - # @return [Integer] the number of resolver iterations in between calls to - # {#resolver_ui}'s {UI#indicate_progress} method - attr_accessor :iteration_rate - private :iteration_rate - - # @return [Time] the time at which resolution began - attr_accessor :started_at - private :started_at - - # @return [Array<ResolutionState>] the stack of states for the resolution - attr_accessor :states - private :states - - private - - # Sets up the resolution process - # @return [void] - def start_resolution - @started_at = Time.now - - handle_missing_or_push_dependency_state(initial_state) - - debug { "Starting resolution (#{@started_at})\nUser-requested dependencies: #{original_requested}" } - resolver_ui.before_resolution - end - - def resolve_activated_specs - activated.vertices.each do |_, vertex| - next unless vertex.payload - - latest_version = vertex.payload.possibilities.reverse_each.find do |possibility| - vertex.requirements.all? { |req| requirement_satisfied_by?(req, activated, possibility) } - end - - activated.set_payload(vertex.name, latest_version) - end - activated.freeze - end - - # Ends the resolution process - # @return [void] - def end_resolution - resolver_ui.after_resolution - debug do - "Finished resolution (#{@iteration_counter} steps) " \ - "(Took #{(ended_at = Time.now) - @started_at} seconds) (#{ended_at})" - end - debug { 'Unactivated: ' + Hash[activated.vertices.reject { |_n, v| v.payload }].keys.join(', ') } if state - debug { 'Activated: ' + Hash[activated.vertices.select { |_n, v| v.payload }].keys.join(', ') } if state - end - - require 'bundler/vendor/molinillo/lib/molinillo/state' - require 'bundler/vendor/molinillo/lib/molinillo/modules/specification_provider' - - require 'bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state' - require 'bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider' - - include Bundler::Molinillo::Delegates::ResolutionState - include Bundler::Molinillo::Delegates::SpecificationProvider - - # Processes the topmost available {RequirementState} on the stack - # @return [void] - def process_topmost_state - if possibility - attempt_to_activate - else - create_conflict - unwind_for_conflict - end - rescue CircularDependencyError => underlying_error - create_conflict(underlying_error) - unwind_for_conflict - end - - # @return [Object] the current possibility that the resolution is trying - # to activate - def possibility - possibilities.last - end - - # @return [RequirementState] the current state the resolution is - # operating upon - def state - states.last - end - - # Creates the initial state for the resolution, based upon the - # {#requested} dependencies - # @return [DependencyState] the initial state for the resolution - def initial_state - graph = DependencyGraph.new.tap do |dg| - original_requested.each do |requested| - vertex = dg.add_vertex(name_for(requested), nil, true) - vertex.explicit_requirements << requested - end - dg.tag(:initial_state) - end - - requirements = sort_dependencies(original_requested, graph, {}) - initial_requirement = requirements.shift - DependencyState.new( - initial_requirement && name_for(initial_requirement), - requirements, - graph, - initial_requirement, - possibilities_for_requirement(initial_requirement, graph), - 0, - {}, - [] - ) - end - - # Unwinds the states stack because a conflict has been encountered - # @return [void] - def unwind_for_conflict - details_for_unwind = build_details_for_unwind - unwind_options = unused_unwind_options - debug(depth) { "Unwinding for conflict: #{requirement} to #{details_for_unwind.state_index / 2}" } - conflicts.tap do |c| - sliced_states = states.slice!((details_for_unwind.state_index + 1)..-1) - raise_error_unless_state(c) - activated.rewind_to(sliced_states.first || :initial_state) if sliced_states - state.conflicts = c - state.unused_unwind_options = unwind_options - filter_possibilities_after_unwind(details_for_unwind) - index = states.size - 1 - @parents_of.each { |_, a| a.reject! { |i| i >= index } } - state.unused_unwind_options.reject! { |uw| uw.state_index >= index } - end - end - - # Raises a VersionConflict error, or any underlying error, if there is no - # current state - # @return [void] - def raise_error_unless_state(conflicts) - return if state - - error = conflicts.values.map(&:underlying_error).compact.first - raise error || VersionConflict.new(conflicts, specification_provider) - end - - # @return [UnwindDetails] Details of the nearest index to which we could unwind - def build_details_for_unwind - # Get the possible unwinds for the current conflict - current_conflict = conflicts[name] - binding_requirements = binding_requirements_for_conflict(current_conflict) - unwind_details = unwind_options_for_requirements(binding_requirements) - - last_detail_for_current_unwind = unwind_details.sort.last - current_detail = last_detail_for_current_unwind - - # Look for past conflicts that could be unwound to affect the - # requirement tree for the current conflict - relevant_unused_unwinds = unused_unwind_options.select do |alternative| - intersecting_requirements = - last_detail_for_current_unwind.all_requirements & - alternative.requirements_unwound_to_instead - next if intersecting_requirements.empty? - # Find the highest index unwind whilst looping through - current_detail = alternative if alternative > current_detail - alternative - end - - # Add the current unwind options to the `unused_unwind_options` array. - # The "used" option will be filtered out during `unwind_for_conflict`. - state.unused_unwind_options += unwind_details.reject { |detail| detail.state_index == -1 } - - # Update the requirements_unwound_to_instead on any relevant unused unwinds - relevant_unused_unwinds.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement } - unwind_details.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement } - - current_detail - end - - # @param [Array<Object>] array of requirements that combine to create a conflict - # @return [Array<UnwindDetails>] array of UnwindDetails that have a chance - # of resolving the passed requirements - def unwind_options_for_requirements(binding_requirements) - unwind_details = [] - - trees = [] - binding_requirements.reverse_each do |r| - partial_tree = [r] - trees << partial_tree - unwind_details << UnwindDetails.new(-1, nil, partial_tree, binding_requirements, trees, []) - - # If this requirement has alternative possibilities, check if any would - # satisfy the other requirements that created this conflict - requirement_state = find_state_for(r) - if conflict_fixing_possibilities?(requirement_state, binding_requirements) - unwind_details << UnwindDetails.new( - states.index(requirement_state), - r, - partial_tree, - binding_requirements, - trees, - [] - ) - end - - # Next, look at the parent of this requirement, and check if the requirement - # could have been avoided if an alternative PossibilitySet had been chosen - parent_r = parent_of(r) - next if parent_r.nil? - partial_tree.unshift(parent_r) - requirement_state = find_state_for(parent_r) - if requirement_state.possibilities.any? { |set| !set.dependencies.include?(r) } - unwind_details << UnwindDetails.new( - states.index(requirement_state), - parent_r, - partial_tree, - binding_requirements, - trees, - [] - ) - end - - # Finally, look at the grandparent and up of this requirement, looking - # for any possibilities that wouldn't create their parent requirement - grandparent_r = parent_of(parent_r) - until grandparent_r.nil? - partial_tree.unshift(grandparent_r) - requirement_state = find_state_for(grandparent_r) - if requirement_state.possibilities.any? { |set| !set.dependencies.include?(parent_r) } - unwind_details << UnwindDetails.new( - states.index(requirement_state), - grandparent_r, - partial_tree, - binding_requirements, - trees, - [] - ) - end - parent_r = grandparent_r - grandparent_r = parent_of(parent_r) - end - end - - unwind_details - end - - # @param [DependencyState] state - # @param [Array] array of requirements - # @return [Boolean] whether or not the given state has any possibilities - # that could satisfy the given requirements - def conflict_fixing_possibilities?(state, binding_requirements) - return false unless state - - state.possibilities.any? do |possibility_set| - possibility_set.possibilities.any? do |poss| - possibility_satisfies_requirements?(poss, binding_requirements) - end - end - end - - # Filter's a state's possibilities to remove any that would not fix the - # conflict we've just rewound from - # @param [UnwindDetails] details of the conflict just unwound from - # @return [void] - def filter_possibilities_after_unwind(unwind_details) - return unless state && !state.possibilities.empty? - - if unwind_details.unwinding_to_primary_requirement? - filter_possibilities_for_primary_unwind(unwind_details) - else - filter_possibilities_for_parent_unwind(unwind_details) - end - end - - # Filter's a state's possibilities to remove any that would not satisfy - # the requirements in the conflict we've just rewound from - # @param [UnwindDetails] details of the conflict just unwound from - # @return [void] - def filter_possibilities_for_primary_unwind(unwind_details) - unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index } - unwinds_to_state << unwind_details - unwind_requirement_sets = unwinds_to_state.map(&:conflicting_requirements) - - state.possibilities.reject! do |possibility_set| - possibility_set.possibilities.none? do |poss| - unwind_requirement_sets.any? do |requirements| - possibility_satisfies_requirements?(poss, requirements) - end - end - end - end - - # @param [Object] possibility a single possibility - # @param [Array] requirements an array of requirements - # @return [Boolean] whether the possibility satisfies all of the - # given requirements - def possibility_satisfies_requirements?(possibility, requirements) - name = name_for(possibility) - - activated.tag(:swap) - activated.set_payload(name, possibility) if activated.vertex_named(name) - satisfied = requirements.all? { |r| requirement_satisfied_by?(r, activated, possibility) } - activated.rewind_to(:swap) - - satisfied - end - - # Filter's a state's possibilities to remove any that would (eventually) - # create a requirement in the conflict we've just rewound from - # @param [UnwindDetails] details of the conflict just unwound from - # @return [void] - def filter_possibilities_for_parent_unwind(unwind_details) - unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index } - unwinds_to_state << unwind_details - - primary_unwinds = unwinds_to_state.select(&:unwinding_to_primary_requirement?).uniq - parent_unwinds = unwinds_to_state.uniq - primary_unwinds - - allowed_possibility_sets = Compatibility.flat_map(primary_unwinds) do |unwind| - states[unwind.state_index].possibilities.select do |possibility_set| - possibility_set.possibilities.any? do |poss| - possibility_satisfies_requirements?(poss, unwind.conflicting_requirements) - end - end - end - - requirements_to_avoid = Compatibility.flat_map(parent_unwinds, &:sub_dependencies_to_avoid) - - state.possibilities.reject! do |possibility_set| - !allowed_possibility_sets.include?(possibility_set) && - (requirements_to_avoid - possibility_set.dependencies).empty? - end - end - - # @param [Conflict] conflict - # @return [Array] minimal array of requirements that would cause the passed - # conflict to occur. - def binding_requirements_for_conflict(conflict) - return [conflict.requirement] if conflict.possibility.nil? - - possible_binding_requirements = conflict.requirements.values.flatten(1).uniq - - # When there’s a `CircularDependency` error the conflicting requirement - # (the one causing the circular) won’t be `conflict.requirement` - # (which won’t be for the right state, because we won’t have created it, - # because it’s circular). - # We need to make sure we have that requirement in the conflict’s list, - # otherwise we won’t be able to unwind properly, so we just return all - # the requirements for the conflict. - return possible_binding_requirements if conflict.underlying_error - - possibilities = search_for(conflict.requirement) - - # If all the requirements together don't filter out all possibilities, - # then the only two requirements we need to consider are the initial one - # (where the dependency's version was first chosen) and the last - if binding_requirement_in_set?(nil, possible_binding_requirements, possibilities) - return [conflict.requirement, requirement_for_existing_name(name_for(conflict.requirement))].compact - end - - # Loop through the possible binding requirements, removing each one - # that doesn't bind. Use a `reverse_each` as we want the earliest set of - # binding requirements, and don't use `reject!` as we wish to refine the - # array *on each iteration*. - binding_requirements = possible_binding_requirements.dup - possible_binding_requirements.reverse_each do |req| - next if req == conflict.requirement - unless binding_requirement_in_set?(req, binding_requirements, possibilities) - binding_requirements -= [req] - end - end - - binding_requirements - end - - # @param [Object] requirement we wish to check - # @param [Array] array of requirements - # @param [Array] array of possibilities the requirements will be used to filter - # @return [Boolean] whether or not the given requirement is required to filter - # out all elements of the array of possibilities. - def binding_requirement_in_set?(requirement, possible_binding_requirements, possibilities) - possibilities.any? do |poss| - possibility_satisfies_requirements?(poss, possible_binding_requirements - [requirement]) - end - end - - # @return [Object] the requirement that led to `requirement` being added - # to the list of requirements. - def parent_of(requirement) - return unless requirement - return unless index = @parents_of[requirement].last - return unless parent_state = @states[index] - parent_state.requirement - end - - # @return [Object] the requirement that led to a version of a possibility - # with the given name being activated. - def requirement_for_existing_name(name) - return nil unless vertex = activated.vertex_named(name) - return nil unless vertex.payload - states.find { |s| s.name == name }.requirement - end - - # @return [ResolutionState] the state whose `requirement` is the given - # `requirement`. - def find_state_for(requirement) - return nil unless requirement - states.find { |i| requirement == i.requirement } - end - - # @return [Conflict] a {Conflict} that reflects the failure to activate - # the {#possibility} in conjunction with the current {#state} - def create_conflict(underlying_error = nil) - vertex = activated.vertex_named(name) - locked_requirement = locked_requirement_named(name) - - requirements = {} - unless vertex.explicit_requirements.empty? - requirements[name_for_explicit_dependency_source] = vertex.explicit_requirements - end - requirements[name_for_locking_dependency_source] = [locked_requirement] if locked_requirement - vertex.incoming_edges.each do |edge| - (requirements[edge.origin.payload.latest_version] ||= []).unshift(edge.requirement) - end - - activated_by_name = {} - activated.each { |v| activated_by_name[v.name] = v.payload.latest_version if v.payload } - conflicts[name] = Conflict.new( - requirement, - requirements, - vertex.payload && vertex.payload.latest_version, - possibility, - locked_requirement, - requirement_trees, - activated_by_name, - underlying_error - ) - end - - # @return [Array<Array<Object>>] The different requirement - # trees that led to every requirement for the current spec. - def requirement_trees - vertex = activated.vertex_named(name) - vertex.requirements.map { |r| requirement_tree_for(r) } - end - - # @return [Array<Object>] the list of requirements that led to - # `requirement` being required. - def requirement_tree_for(requirement) - tree = [] - while requirement - tree.unshift(requirement) - requirement = parent_of(requirement) - end - tree - end - - # Indicates progress roughly once every second - # @return [void] - def indicate_progress - @iteration_counter += 1 - @progress_rate ||= resolver_ui.progress_rate - if iteration_rate.nil? - if Time.now - started_at >= @progress_rate - self.iteration_rate = @iteration_counter - end - end - - if iteration_rate && (@iteration_counter % iteration_rate) == 0 - resolver_ui.indicate_progress - end - end - - # Calls the {#resolver_ui}'s {UI#debug} method - # @param [Integer] depth the depth of the {#states} stack - # @param [Proc] block a block that yields a {#to_s} - # @return [void] - def debug(depth = 0, &block) - resolver_ui.debug(depth, &block) - end - - # Attempts to activate the current {#possibility} - # @return [void] - def attempt_to_activate - debug(depth) { 'Attempting to activate ' + possibility.to_s } - existing_vertex = activated.vertex_named(name) - if existing_vertex.payload - debug(depth) { "Found existing spec (#{existing_vertex.payload})" } - attempt_to_filter_existing_spec(existing_vertex) - else - latest = possibility.latest_version - # use reject!(!satisfied) for 1.8.7 compatibility - possibility.possibilities.reject! do |possibility| - !requirement_satisfied_by?(requirement, activated, possibility) - end - if possibility.latest_version.nil? - # ensure there's a possibility for better error messages - possibility.possibilities << latest if latest - create_conflict - unwind_for_conflict - else - activate_new_spec - end - end - end - - # Attempts to update the existing vertex's `PossibilitySet` with a filtered version - # @return [void] - def attempt_to_filter_existing_spec(vertex) - filtered_set = filtered_possibility_set(vertex) - if !filtered_set.possibilities.empty? - activated.set_payload(name, filtered_set) - new_requirements = requirements.dup - push_state_for_requirements(new_requirements, false) - else - create_conflict - debug(depth) { "Unsatisfied by existing spec (#{vertex.payload})" } - unwind_for_conflict - end - end - - # Generates a filtered version of the existing vertex's `PossibilitySet` using the - # current state's `requirement` - # @param [Object] existing vertex - # @return [PossibilitySet] filtered possibility set - def filtered_possibility_set(vertex) - PossibilitySet.new(vertex.payload.dependencies, vertex.payload.possibilities & possibility.possibilities) - end - - # @param [String] requirement_name the spec name to search for - # @return [Object] the locked spec named `requirement_name`, if one - # is found on {#base} - def locked_requirement_named(requirement_name) - vertex = base.vertex_named(requirement_name) - vertex && vertex.payload - end - - # Add the current {#possibility} to the dependency graph of the current - # {#state} - # @return [void] - def activate_new_spec - conflicts.delete(name) - debug(depth) { "Activated #{name} at #{possibility}" } - activated.set_payload(name, possibility) - require_nested_dependencies_for(possibility) - end - - # Requires the dependencies that the recently activated spec has - # @param [Object] activated_possibility the PossibilitySet that has just been - # activated - # @return [void] - def require_nested_dependencies_for(possibility_set) - nested_dependencies = dependencies_for(possibility_set.latest_version) - debug(depth) { "Requiring nested dependencies (#{nested_dependencies.join(', ')})" } - nested_dependencies.each do |d| - activated.add_child_vertex(name_for(d), nil, [name_for(possibility_set.latest_version)], d) - parent_index = states.size - 1 - parents = @parents_of[d] - parents << parent_index if parents.empty? - end - - push_state_for_requirements(requirements + nested_dependencies, !nested_dependencies.empty?) - end - - # Pushes a new {DependencyState} that encapsulates both existing and new - # requirements - # @param [Array] new_requirements - # @return [void] - def push_state_for_requirements(new_requirements, requires_sort = true, new_activated = activated) - new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts) if requires_sort - new_requirement = nil - loop do - new_requirement = new_requirements.shift - break if new_requirement.nil? || states.none? { |s| s.requirement == new_requirement } - end - new_name = new_requirement ? name_for(new_requirement) : ''.freeze - possibilities = possibilities_for_requirement(new_requirement) - handle_missing_or_push_dependency_state DependencyState.new( - new_name, new_requirements, new_activated, - new_requirement, possibilities, depth, conflicts.dup, unused_unwind_options.dup - ) - end - - # Checks a proposed requirement with any existing locked requirement - # before generating an array of possibilities for it. - # @param [Object] the proposed requirement - # @return [Array] possibilities - def possibilities_for_requirement(requirement, activated = self.activated) - return [] unless requirement - if locked_requirement_named(name_for(requirement)) - return locked_requirement_possibility_set(requirement, activated) - end - - group_possibilities(search_for(requirement)) - end - - # @param [Object] the proposed requirement - # @return [Array] possibility set containing only the locked requirement, if any - def locked_requirement_possibility_set(requirement, activated = self.activated) - all_possibilities = search_for(requirement) - locked_requirement = locked_requirement_named(name_for(requirement)) - - # Longwinded way to build a possibilities array with either the locked - # requirement or nothing in it. Required, since the API for - # locked_requirement isn't guaranteed. - locked_possibilities = all_possibilities.select do |possibility| - requirement_satisfied_by?(locked_requirement, activated, possibility) - end - - group_possibilities(locked_possibilities) - end - - # Build an array of PossibilitySets, with each element representing a group of - # dependency versions that all have the same sub-dependency version constraints - # and are contiguous. - # @param [Array] an array of possibilities - # @return [Array] an array of possibility sets - def group_possibilities(possibilities) - possibility_sets = [] - current_possibility_set = nil - - possibilities.reverse_each do |possibility| - dependencies = dependencies_for(possibility) - if current_possibility_set && current_possibility_set.dependencies == dependencies - current_possibility_set.possibilities.unshift(possibility) - else - possibility_sets.unshift(PossibilitySet.new(dependencies, [possibility])) - current_possibility_set = possibility_sets.first - end - end - - possibility_sets - end - - # Pushes a new {DependencyState}. - # If the {#specification_provider} says to - # {SpecificationProvider#allow_missing?} that particular requirement, and - # there are no possibilities for that requirement, then `state` is not - # pushed, and the vertex in {#activated} is removed, and we continue - # resolving the remaining requirements. - # @param [DependencyState] state - # @return [void] - def handle_missing_or_push_dependency_state(state) - if state.requirement && state.possibilities.empty? && allow_missing?(state.requirement) - state.activated.detach_vertex_named(state.name) - push_state_for_requirements(state.requirements.dup, false, state.activated) - else - states.push(state).tap { activated.tag(state) } - end - end - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb b/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb deleted file mode 100644 index 7d36858778..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +++ /dev/null @@ -1,46 +0,0 @@ -# frozen_string_literal: true - -require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph' - -module Bundler::Molinillo - # This class encapsulates a dependency resolver. - # The resolver is responsible for determining which set of dependencies to - # activate, with feedback from the {#specification_provider} - # - # - class Resolver - require 'bundler/vendor/molinillo/lib/molinillo/resolution' - - # @return [SpecificationProvider] the specification provider used - # in the resolution process - attr_reader :specification_provider - - # @return [UI] the UI module used to communicate back to the user - # during the resolution process - attr_reader :resolver_ui - - # Initializes a new resolver. - # @param [SpecificationProvider] specification_provider - # see {#specification_provider} - # @param [UI] resolver_ui - # see {#resolver_ui} - def initialize(specification_provider, resolver_ui) - @specification_provider = specification_provider - @resolver_ui = resolver_ui - end - - # Resolves the requested dependencies into a {DependencyGraph}, - # locking to the base dependency graph (if specified) - # @param [Array] requested an array of 'requested' dependencies that the - # {#specification_provider} can understand - # @param [DependencyGraph,nil] base the base dependency graph to which - # dependencies should be 'locked' - def resolve(requested, base = DependencyGraph.new) - Resolution.new(specification_provider, - resolver_ui, - requested, - base). - resolve - end - end -end diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/state.rb b/lib/bundler/vendor/molinillo/lib/molinillo/state.rb deleted file mode 100644 index 68fa1f54e3..0000000000 --- a/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +++ /dev/null @@ -1,58 +0,0 @@ -# frozen_string_literal: true - -module Bundler::Molinillo - # A state that a {Resolution} can be in - # @attr [String] name the name of the current requirement - # @attr [Array<Object>] requirements currently unsatisfied requirements - # @attr [DependencyGraph] activated the graph of activated dependencies - # @attr [Object] requirement the current requirement - # @attr [Object] possibilities the possibilities to satisfy the current requirement - # @attr [Integer] depth the depth of the resolution - # @attr [Hash] conflicts unresolved conflicts, indexed by dependency name - # @attr [Array<UnwindDetails>] unused_unwind_options unwinds for previous conflicts that weren't explored - ResolutionState = Struct.new( - :name, - :requirements, - :activated, - :requirement, - :possibilities, - :depth, - :conflicts, - :unused_unwind_options - ) - - class ResolutionState - # Returns an empty resolution state - # @return [ResolutionState] an empty state - def self.empty - new(nil, [], DependencyGraph.new, nil, nil, 0, {}, []) - end - end - - # A state that encapsulates a set of {#requirements} with an {Array} of - # possibilities - class DependencyState < ResolutionState - # Removes a possibility from `self` - # @return [PossibilityState] a state with a single possibility, - # the possibility that was removed from `self` - def pop_possibility_state - PossibilityState.new( - name, - requirements.dup, - activated, - requirement, - [possibilities.pop], - depth + 1, - conflicts.dup, - unused_unwind_options.dup - ).tap do |state| - state.activated.tag(state) - end - end - end - - # A state that encapsulates a single possibility to fulfill the given - # {#requirement} - class PossibilityState < ResolutionState - end -end diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb deleted file mode 100644 index e5e09080c2..0000000000 --- a/lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'net/protocol' - -## -# Aaron Patterson's monkeypatch (accepted into 1.9.1) to fix Net::HTTP's speed -# problems. -# -# http://gist.github.com/251244 - -class Net::BufferedIO #:nodoc: - alias :old_rbuf_fill :rbuf_fill - - def rbuf_fill - if @io.respond_to? :read_nonblock then - begin - @rbuf << @io.read_nonblock(65536) - rescue Errno::EWOULDBLOCK, Errno::EAGAIN => e - retry if IO.select [@io], nil, nil, @read_timeout - raise Timeout::Error, e.message - end - else # SSL sockets do not have read_nonblock - timeout @read_timeout do - @rbuf << @io.sysread(65536) - end - end - end -end if RUBY_VERSION < '1.9' - diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb deleted file mode 100644 index 7cbca5bc06..0000000000 --- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +++ /dev/null @@ -1,1233 +0,0 @@ -require 'net/http' -begin - require 'net/https' -rescue LoadError - # net/https or openssl -end if RUBY_VERSION < '1.9' # but only for 1.8 -require 'bundler/vendor/net-http-persistent/lib/net/http/faster' -require 'uri' -require 'cgi' # for escaping - -begin - require 'net/http/pipeline' -rescue LoadError -end - -autoload :OpenSSL, 'openssl' - -## -# Persistent connections for Net::HTTP -# -# Bundler::Persistent::Net::HTTP::Persistent maintains persistent connections across all the -# servers you wish to talk to. For each host:port you communicate with a -# single persistent connection is created. -# -# Multiple Bundler::Persistent::Net::HTTP::Persistent objects will share the same set of -# connections. -# -# For each thread you start a new connection will be created. A -# Bundler::Persistent::Net::HTTP::Persistent connection will not be shared across threads. -# -# You can shut down the HTTP connections when done by calling #shutdown. You -# should name your Bundler::Persistent::Net::HTTP::Persistent object if you intend to call this -# method. -# -# Example: -# -# require 'bundler/vendor/net-http-persistent/lib/net/http/persistent' -# -# uri = URI 'http://example.com/awesome/web/service' -# -# http = Bundler::Persistent::Net::HTTP::Persistent.new 'my_app_name' -# -# # perform a GET -# response = http.request uri -# -# # or -# -# get = Net::HTTP::Get.new uri.request_uri -# response = http.request get -# -# # create a POST -# post_uri = uri + 'create' -# post = Net::HTTP::Post.new post_uri.path -# post.set_form_data 'some' => 'cool data' -# -# # perform the POST, the URI is always required -# response http.request post_uri, post -# -# Note that for GET, HEAD and other requests that do not have a body you want -# to use URI#request_uri not URI#path. The request_uri contains the query -# params which are sent in the body for other requests. -# -# == SSL -# -# SSL connections are automatically created depending upon the scheme of the -# URI. SSL connections are automatically verified against the default -# certificate store for your computer. You can override this by changing -# verify_mode or by specifying an alternate cert_store. -# -# Here are the SSL settings, see the individual methods for documentation: -# -# #certificate :: This client's certificate -# #ca_file :: The certificate-authority -# #cert_store :: An SSL certificate store -# #private_key :: The client's SSL private key -# #reuse_ssl_sessions :: Reuse a previously opened SSL session for a new -# connection -# #ssl_version :: Which specific SSL version to use -# #verify_callback :: For server certificate verification -# #verify_mode :: How connections should be verified -# -# == Proxies -# -# A proxy can be set through #proxy= or at initialization time by providing a -# second argument to ::new. The proxy may be the URI of the proxy server or -# <code>:ENV</code> which will consult environment variables. -# -# See #proxy= and #proxy_from_env for details. -# -# == Headers -# -# Headers may be specified for use in every request. #headers are appended to -# any headers on the request. #override_headers replace existing headers on -# the request. -# -# The difference between the two can be seen in setting the User-Agent. Using -# <code>http.headers['User-Agent'] = 'MyUserAgent'</code> will send "Ruby, -# MyUserAgent" while <code>http.override_headers['User-Agent'] = -# 'MyUserAgent'</code> will send "MyUserAgent". -# -# == Tuning -# -# === Segregation -# -# By providing an application name to ::new you can separate your connections -# from the connections of other applications. -# -# === Idle Timeout -# -# If a connection hasn't been used for this number of seconds it will automatically be -# reset upon the next use to avoid attempting to send to a closed connection. -# The default value is 5 seconds. nil means no timeout. Set through #idle_timeout. -# -# Reducing this value may help avoid the "too many connection resets" error -# when sending non-idempotent requests while increasing this value will cause -# fewer round-trips. -# -# === Read Timeout -# -# The amount of time allowed between reading two chunks from the socket. Set -# through #read_timeout -# -# === Max Requests -# -# The number of requests that should be made before opening a new connection. -# Typically many keep-alive capable servers tune this to 100 or less, so the -# 101st request will fail with ECONNRESET. If unset (default), this value has no -# effect, if set, connections will be reset on the request after max_requests. -# -# === Open Timeout -# -# The amount of time to wait for a connection to be opened. Set through -# #open_timeout. -# -# === Socket Options -# -# Socket options may be set on newly-created connections. See #socket_options -# for details. -# -# === Non-Idempotent Requests -# -# By default non-idempotent requests will not be retried per RFC 2616. By -# setting retry_change_requests to true requests will automatically be retried -# once. -# -# Only do this when you know that retrying a POST or other non-idempotent -# request is safe for your application and will not create duplicate -# resources. -# -# The recommended way to handle non-idempotent requests is the following: -# -# require 'bundler/vendor/net-http-persistent/lib/net/http/persistent' -# -# uri = URI 'http://example.com/awesome/web/service' -# post_uri = uri + 'create' -# -# http = Bundler::Persistent::Net::HTTP::Persistent.new 'my_app_name' -# -# post = Net::HTTP::Post.new post_uri.path -# # ... fill in POST request -# -# begin -# response = http.request post_uri, post -# rescue Bundler::Persistent::Net::HTTP::Persistent::Error -# -# # POST failed, make a new request to verify the server did not process -# # the request -# exists_uri = uri + '...' -# response = http.get exists_uri -# -# # Retry if it failed -# retry if response.code == '404' -# end -# -# The method of determining if the resource was created or not is unique to -# the particular service you are using. Of course, you will want to add -# protection from infinite looping. -# -# === Connection Termination -# -# If you are done using the Bundler::Persistent::Net::HTTP::Persistent instance you may shut down -# all the connections in the current thread with #shutdown. This is not -# recommended for normal use, it should only be used when it will be several -# minutes before you make another HTTP request. -# -# If you are using multiple threads, call #shutdown in each thread when the -# thread is done making requests. If you don't call shutdown, that's OK. -# Ruby will automatically garbage collect and shutdown your HTTP connections -# when the thread terminates. - -class Bundler::Persistent::Net::HTTP::Persistent - - ## - # The beginning of Time - - EPOCH = Time.at 0 # :nodoc: - - ## - # Is OpenSSL available? This test works with autoload - - HAVE_OPENSSL = defined? OpenSSL::SSL # :nodoc: - - ## - # The version of Bundler::Persistent::Net::HTTP::Persistent you are using - - VERSION = '2.9.4' - - ## - # Exceptions rescued for automatic retry on ruby 2.0.0. This overlaps with - # the exception list for ruby 1.x. - - RETRIED_EXCEPTIONS = [ # :nodoc: - (Net::ReadTimeout if Net.const_defined? :ReadTimeout), - IOError, - EOFError, - Errno::ECONNRESET, - Errno::ECONNABORTED, - Errno::EPIPE, - (OpenSSL::SSL::SSLError if HAVE_OPENSSL), - Timeout::Error, - ].compact - - ## - # Error class for errors raised by Bundler::Persistent::Net::HTTP::Persistent. Various - # SystemCallErrors are re-raised with a human-readable message under this - # class. - - class Error < StandardError; end - - ## - # Use this method to detect the idle timeout of the host at +uri+. The - # value returned can be used to configure #idle_timeout. +max+ controls the - # maximum idle timeout to detect. - # - # After - # - # Idle timeout detection is performed by creating a connection then - # performing a HEAD request in a loop until the connection terminates - # waiting one additional second per loop. - # - # NOTE: This may not work on ruby > 1.9. - - def self.detect_idle_timeout uri, max = 10 - uri = URI uri unless URI::Generic === uri - uri += '/' - - req = Net::HTTP::Head.new uri.request_uri - - http = new 'net-http-persistent detect_idle_timeout' - - connection = http.connection_for uri - - sleep_time = 0 - - loop do - response = connection.request req - - $stderr.puts "HEAD #{uri} => #{response.code}" if $DEBUG - - unless Net::HTTPOK === response then - raise Error, "bad response code #{response.code} detecting idle timeout" - end - - break if sleep_time >= max - - sleep_time += 1 - - $stderr.puts "sleeping #{sleep_time}" if $DEBUG - sleep sleep_time - end - rescue - # ignore StandardErrors, we've probably found the idle timeout. - ensure - http.shutdown - - return sleep_time unless $! - end - - ## - # This client's OpenSSL::X509::Certificate - - attr_reader :certificate - - # For Net::HTTP parity - alias cert certificate - - ## - # An SSL certificate authority. Setting this will set verify_mode to - # VERIFY_PEER. - - attr_reader :ca_file - - ## - # An SSL certificate store. Setting this will override the default - # certificate store. See verify_mode for more information. - - attr_reader :cert_store - - ## - # Sends debug_output to this IO via Net::HTTP#set_debug_output. - # - # Never use this method in production code, it causes a serious security - # hole. - - attr_accessor :debug_output - - ## - # Current connection generation - - attr_reader :generation # :nodoc: - - ## - # Where this instance's connections live in the thread local variables - - attr_reader :generation_key # :nodoc: - - ## - # Headers that are added to every request using Net::HTTP#add_field - - attr_reader :headers - - ## - # Maps host:port to an HTTP version. This allows us to enable version - # specific features. - - attr_reader :http_versions - - ## - # Maximum time an unused connection can remain idle before being - # automatically closed. - - attr_accessor :idle_timeout - - ## - # Maximum number of requests on a connection before it is considered expired - # and automatically closed. - - attr_accessor :max_requests - - ## - # The value sent in the Keep-Alive header. Defaults to 30. Not needed for - # HTTP/1.1 servers. - # - # This may not work correctly for HTTP/1.0 servers - # - # This method may be removed in a future version as RFC 2616 does not - # require this header. - - attr_accessor :keep_alive - - ## - # A name for this connection. Allows you to keep your connections apart - # from everybody else's. - - attr_reader :name - - ## - # Seconds to wait until a connection is opened. See Net::HTTP#open_timeout - - attr_accessor :open_timeout - - ## - # Headers that are added to every request using Net::HTTP#[]= - - attr_reader :override_headers - - ## - # This client's SSL private key - - attr_reader :private_key - - # For Net::HTTP parity - alias key private_key - - ## - # The URL through which requests will be proxied - - attr_reader :proxy_uri - - ## - # List of host suffixes which will not be proxied - - attr_reader :no_proxy - - ## - # Seconds to wait until reading one block. See Net::HTTP#read_timeout - - attr_accessor :read_timeout - - ## - # Where this instance's request counts live in the thread local variables - - attr_reader :request_key # :nodoc: - - ## - # By default SSL sessions are reused to avoid extra SSL handshakes. Set - # this to false if you have problems communicating with an HTTPS server - # like: - # - # SSL_connect [...] read finished A: unexpected message (OpenSSL::SSL::SSLError) - - attr_accessor :reuse_ssl_sessions - - ## - # An array of options for Socket#setsockopt. - # - # By default the TCP_NODELAY option is set on sockets. - # - # To set additional options append them to this array: - # - # http.socket_options << [Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1] - - attr_reader :socket_options - - ## - # Current SSL connection generation - - attr_reader :ssl_generation # :nodoc: - - ## - # Where this instance's SSL connections live in the thread local variables - - attr_reader :ssl_generation_key # :nodoc: - - ## - # SSL version to use. - # - # By default, the version will be negotiated automatically between client - # and server. Ruby 1.9 and newer only. - - attr_reader :ssl_version if RUBY_VERSION > '1.9' - - ## - # Where this instance's last-use times live in the thread local variables - - attr_reader :timeout_key # :nodoc: - - ## - # SSL verification callback. Used when ca_file is set. - - attr_reader :verify_callback - - ## - # HTTPS verify mode. Defaults to OpenSSL::SSL::VERIFY_PEER which verifies - # the server certificate. - # - # If no ca_file or cert_store is set the default system certificate store is - # used. - # - # You can use +verify_mode+ to override any default values. - - attr_reader :verify_mode - - ## - # Enable retries of non-idempotent requests that change data (e.g. POST - # requests) when the server has disconnected. - # - # This will in the worst case lead to multiple requests with the same data, - # but it may be useful for some applications. Take care when enabling - # this option to ensure it is safe to POST or perform other non-idempotent - # requests to the server. - - attr_accessor :retry_change_requests - - ## - # Creates a new Bundler::Persistent::Net::HTTP::Persistent. - # - # Set +name+ to keep your connections apart from everybody else's. Not - # required currently, but highly recommended. Your library name should be - # good enough. This parameter will be required in a future version. - # - # +proxy+ may be set to a URI::HTTP or :ENV to pick up proxy options from - # the environment. See proxy_from_env for details. - # - # In order to use a URI for the proxy you may need to do some extra work - # beyond URI parsing if the proxy requires a password: - # - # proxy = URI 'http://proxy.example' - # proxy.user = 'AzureDiamond' - # proxy.password = 'hunter2' - - def initialize name = nil, proxy = nil - @name = name - - @debug_output = nil - @proxy_uri = nil - @no_proxy = [] - @headers = {} - @override_headers = {} - @http_versions = {} - @keep_alive = 30 - @open_timeout = nil - @read_timeout = nil - @idle_timeout = 5 - @max_requests = nil - @socket_options = [] - - @socket_options << [Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1] if - Socket.const_defined? :TCP_NODELAY - - key = ['net_http_persistent', name].compact - @generation_key = [key, 'generations' ].join('_').intern - @ssl_generation_key = [key, 'ssl_generations'].join('_').intern - @request_key = [key, 'requests' ].join('_').intern - @timeout_key = [key, 'timeouts' ].join('_').intern - - @certificate = nil - @ca_file = nil - @private_key = nil - @ssl_version = nil - @verify_callback = nil - @verify_mode = nil - @cert_store = nil - - @generation = 0 # incremented when proxy URI changes - @ssl_generation = 0 # incremented when SSL session variables change - - if HAVE_OPENSSL then - @verify_mode = OpenSSL::SSL::VERIFY_PEER - @reuse_ssl_sessions = OpenSSL::SSL.const_defined? :Session - end - - @retry_change_requests = false - - @ruby_1 = RUBY_VERSION < '2' - @retried_on_ruby_2 = !@ruby_1 - - self.proxy = proxy if proxy - end - - ## - # Sets this client's OpenSSL::X509::Certificate - - def certificate= certificate - @certificate = certificate - - reconnect_ssl - end - - # For Net::HTTP parity - alias cert= certificate= - - ## - # Sets the SSL certificate authority file. - - def ca_file= file - @ca_file = file - - reconnect_ssl - end - - ## - # Overrides the default SSL certificate store used for verifying - # connections. - - def cert_store= store - @cert_store = store - - reconnect_ssl - end - - ## - # Finishes all connections on the given +thread+ that were created before - # the given +generation+ in the threads +generation_key+ list. - # - # See #shutdown for a bunch of scary warning about misusing this method. - - def cleanup(generation, thread = Thread.current, - generation_key = @generation_key) # :nodoc: - timeouts = thread[@timeout_key] - - (0...generation).each do |old_generation| - next unless thread[generation_key] - - conns = thread[generation_key].delete old_generation - - conns.each_value do |conn| - finish conn, thread - - timeouts.delete conn.object_id if timeouts - end if conns - end - end - - ## - # Creates a new connection for +uri+ - - def connection_for uri - Thread.current[@generation_key] ||= Hash.new { |h,k| h[k] = {} } - Thread.current[@ssl_generation_key] ||= Hash.new { |h,k| h[k] = {} } - Thread.current[@request_key] ||= Hash.new 0 - Thread.current[@timeout_key] ||= Hash.new EPOCH - - use_ssl = uri.scheme.downcase == 'https' - - if use_ssl then - raise Bundler::Persistent::Net::HTTP::Persistent::Error, 'OpenSSL is not available' unless - HAVE_OPENSSL - - ssl_generation = @ssl_generation - - ssl_cleanup ssl_generation - - connections = Thread.current[@ssl_generation_key][ssl_generation] - else - generation = @generation - - cleanup generation - - connections = Thread.current[@generation_key][generation] - end - - net_http_args = [uri.host, uri.port] - connection_id = net_http_args.join ':' - - if @proxy_uri and not proxy_bypass? uri.host, uri.port then - connection_id << @proxy_connection_id - net_http_args.concat @proxy_args - else - net_http_args.concat [nil, nil, nil, nil] - end - - connection = connections[connection_id] - - unless connection = connections[connection_id] then - connections[connection_id] = http_class.new(*net_http_args) - connection = connections[connection_id] - ssl connection if use_ssl - else - reset connection if expired? connection - end - - start connection unless connection.started? - - connection.read_timeout = @read_timeout if @read_timeout - connection.keep_alive_timeout = @idle_timeout if @idle_timeout && connection.respond_to?(:keep_alive_timeout=) - - connection - rescue Errno::ECONNREFUSED - address = connection.proxy_address || connection.address - port = connection.proxy_port || connection.port - - raise Error, "connection refused: #{address}:#{port}" - rescue Errno::EHOSTDOWN - address = connection.proxy_address || connection.address - port = connection.proxy_port || connection.port - - raise Error, "host down: #{address}:#{port}" - end - - ## - # Returns an error message containing the number of requests performed on - # this connection - - def error_message connection - requests = Thread.current[@request_key][connection.object_id] - 1 # fixup - last_use = Thread.current[@timeout_key][connection.object_id] - - age = Time.now - last_use - - "after #{requests} requests on #{connection.object_id}, " \ - "last used #{age} seconds ago" - end - - ## - # URI::escape wrapper - - def escape str - CGI.escape str if str - end - - ## - # URI::unescape wrapper - - def unescape str - CGI.unescape str if str - end - - - ## - # Returns true if the connection should be reset due to an idle timeout, or - # maximum request count, false otherwise. - - def expired? connection - requests = Thread.current[@request_key][connection.object_id] - return true if @max_requests && requests >= @max_requests - return false unless @idle_timeout - return true if @idle_timeout.zero? - - last_used = Thread.current[@timeout_key][connection.object_id] - - Time.now - last_used > @idle_timeout - end - - ## - # Starts the Net::HTTP +connection+ - - def start connection - connection.set_debug_output @debug_output if @debug_output - connection.open_timeout = @open_timeout if @open_timeout - - connection.start - - socket = connection.instance_variable_get :@socket - - if socket then # for fakeweb - @socket_options.each do |option| - socket.io.setsockopt(*option) - end - end - end - - ## - # Finishes the Net::HTTP +connection+ - - def finish connection, thread = Thread.current - if requests = thread[@request_key] then - requests.delete connection.object_id - end - - connection.finish - rescue IOError - end - - def http_class # :nodoc: - if RUBY_VERSION > '2.0' then - Net::HTTP - elsif [:Artifice, :FakeWeb, :WebMock].any? { |klass| - Object.const_defined?(klass) - } or not @reuse_ssl_sessions then - Net::HTTP - else - Bundler::Persistent::Net::HTTP::Persistent::SSLReuse - end - end - - ## - # Returns the HTTP protocol version for +uri+ - - def http_version uri - @http_versions["#{uri.host}:#{uri.port}"] - end - - ## - # Is +req+ idempotent according to RFC 2616? - - def idempotent? req - case req - when Net::HTTP::Delete, Net::HTTP::Get, Net::HTTP::Head, - Net::HTTP::Options, Net::HTTP::Put, Net::HTTP::Trace then - true - end - end - - ## - # Is the request +req+ idempotent or is retry_change_requests allowed. - # - # If +retried_on_ruby_2+ is true, true will be returned if we are on ruby, - # retry_change_requests is allowed and the request is not idempotent. - - def can_retry? req, retried_on_ruby_2 = false - return @retry_change_requests && !idempotent?(req) if retried_on_ruby_2 - - @retry_change_requests || idempotent?(req) - end - - if RUBY_VERSION > '1.9' then - ## - # Workaround for missing Net::HTTPHeader#connection_close? on Ruby 1.8 - - def connection_close? header - header.connection_close? - end - - ## - # Workaround for missing Net::HTTPHeader#connection_keep_alive? on Ruby 1.8 - - def connection_keep_alive? header - header.connection_keep_alive? - end - else - ## - # Workaround for missing Net::HTTPRequest#connection_close? on Ruby 1.8 - - def connection_close? header - header['connection'] =~ /close/ or header['proxy-connection'] =~ /close/ - end - - ## - # Workaround for missing Net::HTTPRequest#connection_keep_alive? on Ruby - # 1.8 - - def connection_keep_alive? header - header['connection'] =~ /keep-alive/ or - header['proxy-connection'] =~ /keep-alive/ - end - end - - ## - # Deprecated in favor of #expired? - - def max_age # :nodoc: - return Time.now + 1 unless @idle_timeout - - Time.now - @idle_timeout - end - - ## - # Adds "http://" to the String +uri+ if it is missing. - - def normalize_uri uri - (uri =~ /^https?:/) ? uri : "http://#{uri}" - end - - ## - # Pipelines +requests+ to the HTTP server at +uri+ yielding responses if a - # block is given. Returns all responses received. - # - # See - # Net::HTTP::Pipeline[http://docs.seattlerb.org/net-http-pipeline/Net/HTTP/Pipeline.html] - # for further details. - # - # Only if <tt>net-http-pipeline</tt> was required before - # <tt>net-http-persistent</tt> #pipeline will be present. - - def pipeline uri, requests, &block # :yields: responses - connection = connection_for uri - - connection.pipeline requests, &block - end - - ## - # Sets this client's SSL private key - - def private_key= key - @private_key = key - - reconnect_ssl - end - - # For Net::HTTP parity - alias key= private_key= - - ## - # Sets the proxy server. The +proxy+ may be the URI of the proxy server, - # the symbol +:ENV+ which will read the proxy from the environment or nil to - # disable use of a proxy. See #proxy_from_env for details on setting the - # proxy from the environment. - # - # If the proxy URI is set after requests have been made, the next request - # will shut-down and re-open all connections. - # - # The +no_proxy+ query parameter can be used to specify hosts which shouldn't - # be reached via proxy; if set it should be a comma separated list of - # hostname suffixes, optionally with +:port+ appended, for example - # <tt>example.com,some.host:8080</tt>. - - def proxy= proxy - @proxy_uri = case proxy - when :ENV then proxy_from_env - when URI::HTTP then proxy - when nil then # ignore - else raise ArgumentError, 'proxy must be :ENV or a URI::HTTP' - end - - @no_proxy.clear - - if @proxy_uri then - @proxy_args = [ - @proxy_uri.host, - @proxy_uri.port, - unescape(@proxy_uri.user), - unescape(@proxy_uri.password), - ] - - @proxy_connection_id = [nil, *@proxy_args].join ':' - - if @proxy_uri.query then - @no_proxy = CGI.parse(@proxy_uri.query)['no_proxy'].join(',').downcase.split(',').map { |x| x.strip }.reject { |x| x.empty? } - end - end - - reconnect - reconnect_ssl - end - - ## - # Creates a URI for an HTTP proxy server from ENV variables. - # - # If +HTTP_PROXY+ is set a proxy will be returned. - # - # If +HTTP_PROXY_USER+ or +HTTP_PROXY_PASS+ are set the URI is given the - # indicated user and password unless HTTP_PROXY contains either of these in - # the URI. - # - # The +NO_PROXY+ ENV variable can be used to specify hosts which shouldn't - # be reached via proxy; if set it should be a comma separated list of - # hostname suffixes, optionally with +:port+ appended, for example - # <tt>example.com,some.host:8080</tt>. When set to <tt>*</tt> no proxy will - # be returned. - # - # For Windows users, lowercase ENV variables are preferred over uppercase ENV - # variables. - - def proxy_from_env - env_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY'] - - return nil if env_proxy.nil? or env_proxy.empty? - - uri = URI normalize_uri env_proxy - - env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY'] - - # '*' is special case for always bypass - return nil if env_no_proxy == '*' - - if env_no_proxy then - uri.query = "no_proxy=#{escape(env_no_proxy)}" - end - - unless uri.user or uri.password then - uri.user = escape ENV['http_proxy_user'] || ENV['HTTP_PROXY_USER'] - uri.password = escape ENV['http_proxy_pass'] || ENV['HTTP_PROXY_PASS'] - end - - uri - end - - ## - # Returns true when proxy should by bypassed for host. - - def proxy_bypass? host, port - host = host.downcase - host_port = [host, port].join ':' - - @no_proxy.each do |name| - return true if host[-name.length, name.length] == name or - host_port[-name.length, name.length] == name - end - - false - end - - ## - # Forces reconnection of HTTP connections. - - def reconnect - @generation += 1 - end - - ## - # Forces reconnection of SSL connections. - - def reconnect_ssl - @ssl_generation += 1 - end - - ## - # Finishes then restarts the Net::HTTP +connection+ - - def reset connection - Thread.current[@request_key].delete connection.object_id - Thread.current[@timeout_key].delete connection.object_id - - finish connection - - start connection - rescue Errno::ECONNREFUSED - e = Error.new "connection refused: #{connection.address}:#{connection.port}" - e.set_backtrace $@ - raise e - rescue Errno::EHOSTDOWN - e = Error.new "host down: #{connection.address}:#{connection.port}" - e.set_backtrace $@ - raise e - end - - ## - # Makes a request on +uri+. If +req+ is nil a Net::HTTP::Get is performed - # against +uri+. - # - # If a block is passed #request behaves like Net::HTTP#request (the body of - # the response will not have been read). - # - # +req+ must be a Net::HTTPRequest subclass (see Net::HTTP for a list). - # - # If there is an error and the request is idempotent according to RFC 2616 - # it will be retried automatically. - - def request uri, req = nil, &block - retried = false - bad_response = false - - req = request_setup req || uri - - connection = connection_for uri - connection_id = connection.object_id - - begin - Thread.current[@request_key][connection_id] += 1 - response = connection.request req, &block - - if connection_close?(req) or - (response.http_version <= '1.0' and - not connection_keep_alive?(response)) or - connection_close?(response) then - connection.finish - end - rescue Net::HTTPBadResponse => e - message = error_message connection - - finish connection - - raise Error, "too many bad responses #{message}" if - bad_response or not can_retry? req - - bad_response = true - retry - rescue *RETRIED_EXCEPTIONS => e # retried on ruby 2 - request_failed e, req, connection if - retried or not can_retry? req, @retried_on_ruby_2 - - reset connection - - retried = true - retry - rescue Errno::EINVAL, Errno::ETIMEDOUT => e # not retried on ruby 2 - request_failed e, req, connection if retried or not can_retry? req - - reset connection - - retried = true - retry - rescue Exception => e - finish connection - - raise - ensure - Thread.current[@timeout_key][connection_id] = Time.now - end - - @http_versions["#{uri.host}:#{uri.port}"] ||= response.http_version - - response - end - - ## - # Raises an Error for +exception+ which resulted from attempting the request - # +req+ on the +connection+. - # - # Finishes the +connection+. - - def request_failed exception, req, connection # :nodoc: - due_to = "(due to #{exception.message} - #{exception.class})" - message = "too many connection resets #{due_to} #{error_message connection}" - - finish connection - - - raise Error, message, exception.backtrace - end - - ## - # Creates a GET request if +req_or_uri+ is a URI and adds headers to the - # request. - # - # Returns the request. - - def request_setup req_or_uri # :nodoc: - req = if URI === req_or_uri then - Net::HTTP::Get.new req_or_uri.request_uri - else - req_or_uri - end - - @headers.each do |pair| - req.add_field(*pair) - end - - @override_headers.each do |name, value| - req[name] = value - end - - unless req['Connection'] then - req.add_field 'Connection', 'keep-alive' - req.add_field 'Keep-Alive', @keep_alive - end - - req - end - - ## - # Shuts down all connections for +thread+. - # - # Uses the current thread by default. - # - # If you've used Bundler::Persistent::Net::HTTP::Persistent across multiple threads you should - # call this in each thread when you're done making HTTP requests. - # - # *NOTE*: Calling shutdown for another thread can be dangerous! - # - # If the thread is still using the connection it may cause an error! It is - # best to call #shutdown in the thread at the appropriate time instead! - - def shutdown thread = Thread.current - generation = reconnect - cleanup generation, thread, @generation_key - - ssl_generation = reconnect_ssl - cleanup ssl_generation, thread, @ssl_generation_key - - thread[@request_key] = nil - thread[@timeout_key] = nil - end - - ## - # Shuts down all connections in all threads - # - # *NOTE*: THIS METHOD IS VERY DANGEROUS! - # - # Do not call this method if other threads are still using their - # connections! Call #shutdown at the appropriate time instead! - # - # Use this method only as a last resort! - - def shutdown_in_all_threads - Thread.list.each do |thread| - shutdown thread - end - - nil - end - - ## - # Enables SSL on +connection+ - - def ssl connection - connection.use_ssl = true - - connection.ssl_version = @ssl_version if @ssl_version - - connection.verify_mode = @verify_mode - - if OpenSSL::SSL::VERIFY_PEER == OpenSSL::SSL::VERIFY_NONE and - not Object.const_defined?(:I_KNOW_THAT_OPENSSL_VERIFY_PEER_EQUALS_VERIFY_NONE_IS_WRONG) then - warn <<-WARNING - !!!SECURITY WARNING!!! - -The SSL HTTP connection to: - - #{connection.address}:#{connection.port} - - !!!MAY NOT BE VERIFIED!!! - -On your platform your OpenSSL implementation is broken. - -There is no difference between the values of VERIFY_NONE and VERIFY_PEER. - -This means that attempting to verify the security of SSL connections may not -work. This exposes you to man-in-the-middle exploits, snooping on the -contents of your connection and other dangers to the security of your data. - -To disable this warning define the following constant at top-level in your -application: - - I_KNOW_THAT_OPENSSL_VERIFY_PEER_EQUALS_VERIFY_NONE_IS_WRONG = nil - - WARNING - end - - if @ca_file then - connection.ca_file = @ca_file - connection.verify_mode = OpenSSL::SSL::VERIFY_PEER - connection.verify_callback = @verify_callback if @verify_callback - end - - if @certificate and @private_key then - connection.cert = @certificate - connection.key = @private_key - end - - connection.cert_store = if @cert_store then - @cert_store - else - store = OpenSSL::X509::Store.new - store.set_default_paths - store - end - end - - ## - # Finishes all connections that existed before the given SSL parameter - # +generation+. - - def ssl_cleanup generation # :nodoc: - cleanup generation, Thread.current, @ssl_generation_key - end - - ## - # SSL version to use - - def ssl_version= ssl_version - @ssl_version = ssl_version - - reconnect_ssl - end if RUBY_VERSION > '1.9' - - ## - # Sets the HTTPS verify mode. Defaults to OpenSSL::SSL::VERIFY_PEER. - # - # Setting this to VERIFY_NONE is a VERY BAD IDEA and should NEVER be used. - # Securely transfer the correct certificate and update the default - # certificate store or set the ca file instead. - - def verify_mode= verify_mode - @verify_mode = verify_mode - - reconnect_ssl - end - - ## - # SSL verification callback. - - def verify_callback= callback - @verify_callback = callback - - reconnect_ssl - end - -end - -require 'bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse' - diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb deleted file mode 100644 index 1b6b789f6d..0000000000 --- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb +++ /dev/null @@ -1,129 +0,0 @@ -## -# This Net::HTTP subclass adds SSL session reuse and Server Name Indication -# (SNI) RFC 3546. -# -# DO NOT DEPEND UPON THIS CLASS -# -# This class is an implementation detail and is subject to change or removal -# at any time. - -class Bundler::Persistent::Net::HTTP::Persistent::SSLReuse < Net::HTTP - - @is_proxy_class = false - @proxy_addr = nil - @proxy_port = nil - @proxy_user = nil - @proxy_pass = nil - - def initialize address, port = nil # :nodoc: - super - - @ssl_session = nil - end - - ## - # From ruby trunk r33086 including http://redmine.ruby-lang.org/issues/5341 - - def connect # :nodoc: - D "opening connection to #{conn_address()}..." - s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) } - D "opened" - if use_ssl? - ssl_parameters = Hash.new - iv_list = instance_variables - SSL_ATTRIBUTES.each do |name| - ivname = "@#{name}".intern - if iv_list.include?(ivname) and - value = instance_variable_get(ivname) - ssl_parameters[name] = value - end - end - unless @ssl_context then - @ssl_context = OpenSSL::SSL::SSLContext.new - @ssl_context.set_params(ssl_parameters) - end - s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context) - s.sync_close = true - end - @socket = Net::BufferedIO.new(s) - @socket.read_timeout = @read_timeout - @socket.continue_timeout = @continue_timeout if - @socket.respond_to? :continue_timeout - @socket.debug_output = @debug_output - if use_ssl? - begin - if proxy? - @socket.writeline sprintf('CONNECT %s:%s HTTP/%s', - @address, @port, HTTPVersion) - @socket.writeline "Host: #{@address}:#{@port}" - if proxy_user - credential = ["#{proxy_user}:#{proxy_pass}"].pack('m') - credential.delete!("\r\n") - @socket.writeline "Proxy-Authorization: Basic #{credential}" - end - @socket.writeline '' - Net::HTTPResponse.read_new(@socket).value - end - s.session = @ssl_session if @ssl_session - # Server Name Indication (SNI) RFC 3546 - s.hostname = @address if s.respond_to? :hostname= - timeout(@open_timeout) { s.connect } - if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE - s.post_connection_check(@address) - end - @ssl_session = s.session - rescue => exception - D "Conn close because of connect error #{exception}" - @socket.close if @socket and not @socket.closed? - raise exception - end - end - on_connect - end if RUBY_VERSION > '1.9' - - ## - # From ruby_1_8_7 branch r29865 including a modified - # http://redmine.ruby-lang.org/issues/5341 - - def connect # :nodoc: - D "opening connection to #{conn_address()}..." - s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) } - D "opened" - if use_ssl? - unless @ssl_context.verify_mode - warn "warning: peer certificate won't be verified in this SSL session" - @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context) - s.sync_close = true - end - @socket = Net::BufferedIO.new(s) - @socket.read_timeout = @read_timeout - @socket.debug_output = @debug_output - if use_ssl? - if proxy? - @socket.writeline sprintf('CONNECT %s:%s HTTP/%s', - @address, @port, HTTPVersion) - @socket.writeline "Host: #{@address}:#{@port}" - if proxy_user - credential = ["#{proxy_user}:#{proxy_pass}"].pack('m') - credential.delete!("\r\n") - @socket.writeline "Proxy-Authorization: Basic #{credential}" - end - @socket.writeline '' - Net::HTTPResponse.read_new(@socket).value - end - s.session = @ssl_session if @ssl_session - s.connect - if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE - s.post_connection_check(@address) - end - @ssl_session = s.session - end - on_connect - end if RUBY_VERSION < '1.9' - - private :connect - -end - diff --git a/lib/bundler/vendor/thor/lib/thor.rb b/lib/bundler/vendor/thor/lib/thor.rb deleted file mode 100644 index 999e8b7e61..0000000000 --- a/lib/bundler/vendor/thor/lib/thor.rb +++ /dev/null @@ -1,509 +0,0 @@ -require "set" -require "bundler/vendor/thor/lib/thor/base" - -class Bundler::Thor - class << self - # Allows for custom "Command" package naming. - # - # === Parameters - # name<String> - # options<Hash> - # - def package_name(name, _ = {}) - @package_name = name.nil? || name == "" ? nil : name - end - - # Sets the default command when thor is executed without an explicit command to be called. - # - # ==== Parameters - # meth<Symbol>:: name of the default command - # - def default_command(meth = nil) - if meth - @default_command = meth == :none ? "help" : meth.to_s - else - @default_command ||= from_superclass(:default_command, "help") - end - end - alias_method :default_task, :default_command - - # Registers another Bundler::Thor subclass as a command. - # - # ==== Parameters - # klass<Class>:: Bundler::Thor subclass to register - # command<String>:: Subcommand name to use - # usage<String>:: Short usage for the subcommand - # description<String>:: Description for the subcommand - def register(klass, subcommand_name, usage, description, options = {}) - if klass <= Bundler::Thor::Group - desc usage, description, options - define_method(subcommand_name) { |*args| invoke(klass, args) } - else - desc usage, description, options - subcommand subcommand_name, klass - end - end - - # Defines the usage and the description of the next command. - # - # ==== Parameters - # usage<String> - # description<String> - # options<String> - # - def desc(usage, description, options = {}) - if options[:for] - command = find_and_refresh_command(options[:for]) - command.usage = usage if usage - command.description = description if description - else - @usage = usage - @desc = description - @hide = options[:hide] || false - end - end - - # Defines the long description of the next command. - # - # ==== Parameters - # long description<String> - # - def long_desc(long_description, options = {}) - if options[:for] - command = find_and_refresh_command(options[:for]) - command.long_description = long_description if long_description - else - @long_desc = long_description - end - end - - # Maps an input to a command. If you define: - # - # map "-T" => "list" - # - # Running: - # - # thor -T - # - # Will invoke the list command. - # - # ==== Parameters - # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given command. - # - def map(mappings = nil) - @map ||= from_superclass(:map, {}) - - if mappings - mappings.each do |key, value| - if key.respond_to?(:each) - key.each { |subkey| @map[subkey] = value } - else - @map[key] = value - end - end - end - - @map - end - - # Declares the options for the next command to be declared. - # - # ==== Parameters - # Hash[Symbol => Object]:: The hash key is the name of the option and the value - # is the type of the option. Can be :string, :array, :hash, :boolean, :numeric - # or :required (string). If you give a value, the type of the value is used. - # - def method_options(options = nil) - @method_options ||= {} - build_options(options, @method_options) if options - @method_options - end - - alias_method :options, :method_options - - # Adds an option to the set of method options. If :for is given as option, - # it allows you to change the options from a previous defined command. - # - # def previous_command - # # magic - # end - # - # method_option :foo => :bar, :for => :previous_command - # - # def next_command - # # magic - # end - # - # ==== Parameters - # name<Symbol>:: The name of the argument. - # options<Hash>:: Described below. - # - # ==== Options - # :desc - Description for the argument. - # :required - If the argument is required or not. - # :default - Default value for this argument. It cannot be required and have default values. - # :aliases - Aliases for this option. - # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. - # :banner - String to show on usage notes. - # :hide - If you want to hide this option from the help. - # - def method_option(name, options = {}) - scope = if options[:for] - find_and_refresh_command(options[:for]).options - else - method_options - end - - build_option(name, options, scope) - end - alias_method :option, :method_option - - # Prints help information for the given command. - # - # ==== Parameters - # shell<Bundler::Thor::Shell> - # command_name<String> - # - def command_help(shell, command_name) - meth = normalize_command_name(command_name) - command = all_commands[meth] - handle_no_command_error(meth) unless command - - shell.say "Usage:" - shell.say " #{banner(command)}" - shell.say - class_options_help(shell, nil => command.options.values) - if command.long_description - shell.say "Description:" - shell.print_wrapped(command.long_description, :indent => 2) - else - shell.say command.description - end - end - alias_method :task_help, :command_help - - # Prints help information for this class. - # - # ==== Parameters - # shell<Bundler::Thor::Shell> - # - def help(shell, subcommand = false) - list = printable_commands(true, subcommand) - Bundler::Thor::Util.thor_classes_in(self).each do |klass| - list += klass.printable_commands(false) - end - list.sort! { |a, b| a[0] <=> b[0] } - - if defined?(@package_name) && @package_name - shell.say "#{@package_name} commands:" - else - shell.say "Commands:" - end - - shell.print_table(list, :indent => 2, :truncate => true) - shell.say - class_options_help(shell) - end - - # Returns commands ready to be printed. - def printable_commands(all = true, subcommand = false) - (all ? all_commands : commands).map do |_, command| - next if command.hidden? - item = [] - item << banner(command, false, subcommand) - item << (command.description ? "# #{command.description.gsub(/\s+/m, ' ')}" : "") - item - end.compact - end - alias_method :printable_tasks, :printable_commands - - def subcommands - @subcommands ||= from_superclass(:subcommands, []) - end - alias_method :subtasks, :subcommands - - def subcommand_classes - @subcommand_classes ||= {} - end - - def subcommand(subcommand, subcommand_class) - subcommands << subcommand.to_s - subcommand_class.subcommand_help subcommand - subcommand_classes[subcommand.to_s] = subcommand_class - - define_method(subcommand) do |*args| - args, opts = Bundler::Thor::Arguments.split(args) - invoke_args = [args, opts, {:invoked_via_subcommand => true, :class_options => options}] - invoke_args.unshift "help" if opts.delete("--help") || opts.delete("-h") - invoke subcommand_class, *invoke_args - end - subcommand_class.commands.each do |_meth, command| - command.ancestor_name = subcommand - end - end - alias_method :subtask, :subcommand - - # Extend check unknown options to accept a hash of conditions. - # - # === Parameters - # options<Hash>: A hash containing :only and/or :except keys - def check_unknown_options!(options = {}) - @check_unknown_options ||= {} - options.each do |key, value| - if value - @check_unknown_options[key] = Array(value) - else - @check_unknown_options.delete(key) - end - end - @check_unknown_options - end - - # Overwrite check_unknown_options? to take subcommands and options into account. - def check_unknown_options?(config) #:nodoc: - options = check_unknown_options - return false unless options - - command = config[:current_command] - return true unless command - - name = command.name - - if subcommands.include?(name) - false - elsif options[:except] - !options[:except].include?(name.to_sym) - elsif options[:only] - options[:only].include?(name.to_sym) - else - true - end - end - - # Stop parsing of options as soon as an unknown option or a regular - # argument is encountered. All remaining arguments are passed to the command. - # This is useful if you have a command that can receive arbitrary additional - # options, and where those additional options should not be handled by - # Bundler::Thor. - # - # ==== Example - # - # To better understand how this is useful, let's consider a command that calls - # an external command. A user may want to pass arbitrary options and - # arguments to that command. The command itself also accepts some options, - # which should be handled by Bundler::Thor. - # - # class_option "verbose", :type => :boolean - # stop_on_unknown_option! :exec - # check_unknown_options! :except => :exec - # - # desc "exec", "Run a shell command" - # def exec(*args) - # puts "diagnostic output" if options[:verbose] - # Kernel.exec(*args) - # end - # - # Here +exec+ can be called with +--verbose+ to get diagnostic output, - # e.g.: - # - # $ thor exec --verbose echo foo - # diagnostic output - # foo - # - # But if +--verbose+ is given after +echo+, it is passed to +echo+ instead: - # - # $ thor exec echo --verbose foo - # --verbose foo - # - # ==== Parameters - # Symbol ...:: A list of commands that should be affected. - def stop_on_unknown_option!(*command_names) - stop_on_unknown_option.merge(command_names) - end - - def stop_on_unknown_option?(command) #:nodoc: - command && stop_on_unknown_option.include?(command.name.to_sym) - end - - # Disable the check for required options for the given commands. - # This is useful if you have a command that does not need the required options - # to work, like help. - # - # ==== Parameters - # Symbol ...:: A list of commands that should be affected. - def disable_required_check!(*command_names) - disable_required_check.merge(command_names) - end - - def disable_required_check?(command) #:nodoc: - command && disable_required_check.include?(command.name.to_sym) - end - - protected - - def stop_on_unknown_option #:nodoc: - @stop_on_unknown_option ||= Set.new - end - - # help command has the required check disabled by default. - def disable_required_check #:nodoc: - @disable_required_check ||= Set.new([:help]) - end - - # The method responsible for dispatching given the args. - def dispatch(meth, given_args, given_opts, config) #:nodoc: # rubocop:disable MethodLength - meth ||= retrieve_command_name(given_args) - command = all_commands[normalize_command_name(meth)] - - if !command && config[:invoked_via_subcommand] - # We're a subcommand and our first argument didn't match any of our - # commands. So we put it back and call our default command. - given_args.unshift(meth) - command = all_commands[normalize_command_name(default_command)] - end - - if command - args, opts = Bundler::Thor::Options.split(given_args) - if stop_on_unknown_option?(command) && !args.empty? - # given_args starts with a non-option, so we treat everything as - # ordinary arguments - args.concat opts - opts.clear - end - else - args = given_args - opts = nil - command = dynamic_command_class.new(meth) - end - - opts = given_opts || opts || [] - config[:current_command] = command - config[:command_options] = command.options - - instance = new(args, opts, config) - yield instance if block_given? - args = instance.args - trailing = args[Range.new(arguments.size, -1)] - instance.invoke_command(command, trailing || []) - end - - # The banner for this class. You can customize it if you are invoking the - # thor class by another ways which is not the Bundler::Thor::Runner. It receives - # the command that is going to be invoked and a boolean which indicates if - # the namespace should be displayed as arguments. - # - def banner(command, namespace = nil, subcommand = false) - "#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}" - end - - def baseclass #:nodoc: - Bundler::Thor - end - - def dynamic_command_class #:nodoc: - Bundler::Thor::DynamicCommand - end - - def create_command(meth) #:nodoc: - @usage ||= nil - @desc ||= nil - @long_desc ||= nil - @hide ||= nil - - if @usage && @desc - base_class = @hide ? Bundler::Thor::HiddenCommand : Bundler::Thor::Command - commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options) - @usage, @desc, @long_desc, @method_options, @hide = nil - true - elsif all_commands[meth] || meth == "method_missing" - true - else - puts "[WARNING] Attempted to create command #{meth.inspect} without usage or description. " \ - "Call desc if you want this method to be available as command or declare it inside a " \ - "no_commands{} block. Invoked from #{caller[1].inspect}." - false - end - end - alias_method :create_task, :create_command - - def initialize_added #:nodoc: - class_options.merge!(method_options) - @method_options = nil - end - - # Retrieve the command name from given args. - def retrieve_command_name(args) #:nodoc: - meth = args.first.to_s unless args.empty? - args.shift if meth && (map[meth] || meth !~ /^\-/) - end - alias_method :retrieve_task_name, :retrieve_command_name - - # receives a (possibly nil) command name and returns a name that is in - # the commands hash. In addition to normalizing aliases, this logic - # will determine if a shortened command is an unambiguous substring of - # a command or alias. - # - # +normalize_command_name+ also converts names like +animal-prison+ - # into +animal_prison+. - def normalize_command_name(meth) #:nodoc: - return default_command.to_s.tr("-", "_") unless meth - - possibilities = find_command_possibilities(meth) - raise AmbiguousTaskError, "Ambiguous command #{meth} matches [#{possibilities.join(', ')}]" if possibilities.size > 1 - - if possibilities.empty? - meth ||= default_command - elsif map[meth] - meth = map[meth] - else - meth = possibilities.first - end - - meth.to_s.tr("-", "_") # treat foo-bar as foo_bar - end - alias_method :normalize_task_name, :normalize_command_name - - # this is the logic that takes the command name passed in by the user - # and determines whether it is an unambiguous substrings of a command or - # alias name. - def find_command_possibilities(meth) - len = meth.to_s.length - possibilities = all_commands.merge(map).keys.select { |n| meth == n[0, len] }.sort - unique_possibilities = possibilities.map { |k| map[k] || k }.uniq - - if possibilities.include?(meth) - [meth] - elsif unique_possibilities.size == 1 - unique_possibilities - else - possibilities - end - end - alias_method :find_task_possibilities, :find_command_possibilities - - def subcommand_help(cmd) - desc "help [COMMAND]", "Describe subcommands or one specific subcommand" - class_eval " - def help(command = nil, subcommand = true); super; end -" - end - alias_method :subtask_help, :subcommand_help - end - - include Bundler::Thor::Base - - map HELP_MAPPINGS => :help - - desc "help [COMMAND]", "Describe available commands or one specific command" - def help(command = nil, subcommand = false) - if command - if self.class.subcommands.include? command - self.class.subcommand_classes[command].help(shell, true) - else - self.class.command_help(shell, command) - end - else - self.class.help(shell, subcommand) - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/actions.rb b/lib/bundler/vendor/thor/lib/thor/actions.rb deleted file mode 100644 index e6698572a9..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/actions.rb +++ /dev/null @@ -1,321 +0,0 @@ -require "uri" -require "bundler/vendor/thor/lib/thor/core_ext/io_binary_read" -require "bundler/vendor/thor/lib/thor/actions/create_file" -require "bundler/vendor/thor/lib/thor/actions/create_link" -require "bundler/vendor/thor/lib/thor/actions/directory" -require "bundler/vendor/thor/lib/thor/actions/empty_directory" -require "bundler/vendor/thor/lib/thor/actions/file_manipulation" -require "bundler/vendor/thor/lib/thor/actions/inject_into_file" - -class Bundler::Thor - module Actions - attr_accessor :behavior - - def self.included(base) #:nodoc: - base.extend ClassMethods - end - - module ClassMethods - # Hold source paths for one Bundler::Thor instance. source_paths_for_search is the - # method responsible to gather source_paths from this current class, - # inherited paths and the source root. - # - def source_paths - @_source_paths ||= [] - end - - # Stores and return the source root for this class - def source_root(path = nil) - @_source_root = path if path - @_source_root ||= nil - end - - # Returns the source paths in the following order: - # - # 1) This class source paths - # 2) Source root - # 3) Parents source paths - # - def source_paths_for_search - paths = [] - paths += source_paths - paths << source_root if source_root - paths += from_superclass(:source_paths, []) - paths - end - - # Add runtime options that help actions execution. - # - def add_runtime_options! - class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime, - :desc => "Overwrite files that already exist" - - class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime, - :desc => "Run but do not make any changes" - - class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime, - :desc => "Suppress status output" - - class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime, - :desc => "Skip files that already exist" - end - end - - # Extends initializer to add more configuration options. - # - # ==== Configuration - # behavior<Symbol>:: The actions default behavior. Can be :invoke or :revoke. - # It also accepts :force, :skip and :pretend to set the behavior - # and the respective option. - # - # destination_root<String>:: The root directory needed for some actions. - # - def initialize(args = [], options = {}, config = {}) - self.behavior = case config[:behavior].to_s - when "force", "skip" - _cleanup_options_and_set(options, config[:behavior]) - :invoke - when "revoke" - :revoke - else - :invoke - end - - super - self.destination_root = config[:destination_root] - end - - # Wraps an action object and call it accordingly to the thor class behavior. - # - def action(instance) #:nodoc: - if behavior == :revoke - instance.revoke! - else - instance.invoke! - end - end - - # Returns the root for this thor class (also aliased as destination root). - # - def destination_root - @destination_stack.last - end - - # Sets the root for this thor class. Relatives path are added to the - # directory where the script was invoked and expanded. - # - def destination_root=(root) - @destination_stack ||= [] - @destination_stack[0] = File.expand_path(root || "") - end - - # Returns the given path relative to the absolute root (ie, root where - # the script started). - # - def relative_to_original_destination_root(path, remove_dot = true) - path = path.dup - if path.gsub!(@destination_stack[0], ".") - remove_dot ? (path[2..-1] || "") : path - else - path - end - end - - # Holds source paths in instance so they can be manipulated. - # - def source_paths - @source_paths ||= self.class.source_paths_for_search - end - - # Receives a file or directory and search for it in the source paths. - # - def find_in_source_paths(file) - possible_files = [file, file + TEMPLATE_EXTNAME] - relative_root = relative_to_original_destination_root(destination_root, false) - - source_paths.each do |source| - possible_files.each do |f| - source_file = File.expand_path(f, File.join(source, relative_root)) - return source_file if File.exist?(source_file) - end - end - - message = "Could not find #{file.inspect} in any of your source paths. ".dup - - unless self.class.source_root - message << "Please invoke #{self.class.name}.source_root(PATH) with the PATH containing your templates. " - end - - message << if source_paths.empty? - "Currently you have no source paths." - else - "Your current source paths are: \n#{source_paths.join("\n")}" - end - - raise Error, message - end - - # Do something in the root or on a provided subfolder. If a relative path - # is given it's referenced from the current root. The full path is yielded - # to the block you provide. The path is set back to the previous path when - # the method exits. - # - # ==== Parameters - # dir<String>:: the directory to move to. - # config<Hash>:: give :verbose => true to log and use padding. - # - def inside(dir = "", config = {}, &block) - verbose = config.fetch(:verbose, false) - pretend = options[:pretend] - - say_status :inside, dir, verbose - shell.padding += 1 if verbose - @destination_stack.push File.expand_path(dir, destination_root) - - # If the directory doesnt exist and we're not pretending - if !File.exist?(destination_root) && !pretend - require "fileutils" - FileUtils.mkdir_p(destination_root) - end - - if pretend - # In pretend mode, just yield down to the block - block.arity == 1 ? yield(destination_root) : yield - else - require "fileutils" - FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield } - end - - @destination_stack.pop - shell.padding -= 1 if verbose - end - - # Goes to the root and execute the given block. - # - def in_root - inside(@destination_stack.first) { yield } - end - - # Loads an external file and execute it in the instance binding. - # - # ==== Parameters - # path<String>:: The path to the file to execute. Can be a web address or - # a relative path from the source root. - # - # ==== Examples - # - # apply "http://gist.github.com/103208" - # - # apply "recipes/jquery.rb" - # - def apply(path, config = {}) - verbose = config.fetch(:verbose, true) - is_uri = path =~ %r{^https?\://} - path = find_in_source_paths(path) unless is_uri - - say_status :apply, path, verbose - shell.padding += 1 if verbose - - contents = if is_uri - open(path, "Accept" => "application/x-thor-template", &:read) - else - open(path, &:read) - end - - instance_eval(contents, path) - shell.padding -= 1 if verbose - end - - # Executes a command returning the contents of the command. - # - # ==== Parameters - # command<String>:: the command to be executed. - # config<Hash>:: give :verbose => false to not log the status, :capture => true to hide to output. Specify :with - # to append an executable to command execution. - # - # ==== Example - # - # inside('vendor') do - # run('ln -s ~/edge rails') - # end - # - def run(command, config = {}) - return unless behavior == :invoke - - destination = relative_to_original_destination_root(destination_root, false) - desc = "#{command} from #{destination.inspect}" - - if config[:with] - desc = "#{File.basename(config[:with].to_s)} #{desc}" - command = "#{config[:with]} #{command}" - end - - say_status :run, desc, config.fetch(:verbose, true) - - unless options[:pretend] - config[:capture] ? `#{command}` : system(command.to_s) - end - end - - # Executes a ruby script (taking into account WIN32 platform quirks). - # - # ==== Parameters - # command<String>:: the command to be executed. - # config<Hash>:: give :verbose => false to not log the status. - # - def run_ruby_script(command, config = {}) - return unless behavior == :invoke - run command, config.merge(:with => Bundler::Thor::Util.ruby_command) - end - - # Run a thor command. A hash of options can be given and it's converted to - # switches. - # - # ==== Parameters - # command<String>:: the command to be invoked - # args<Array>:: arguments to the command - # config<Hash>:: give :verbose => false to not log the status, :capture => true to hide to output. - # Other options are given as parameter to Bundler::Thor. - # - # - # ==== Examples - # - # thor :install, "http://gist.github.com/103208" - # #=> thor install http://gist.github.com/103208 - # - # thor :list, :all => true, :substring => 'rails' - # #=> thor list --all --substring=rails - # - def thor(command, *args) - config = args.last.is_a?(Hash) ? args.pop : {} - verbose = config.key?(:verbose) ? config.delete(:verbose) : true - pretend = config.key?(:pretend) ? config.delete(:pretend) : false - capture = config.key?(:capture) ? config.delete(:capture) : false - - args.unshift(command) - args.push Bundler::Thor::Options.to_switches(config) - command = args.join(" ").strip - - run command, :with => :thor, :verbose => verbose, :pretend => pretend, :capture => capture - end - - protected - - # Allow current root to be shared between invocations. - # - def _shared_configuration #:nodoc: - super.merge!(:destination_root => destination_root) - end - - def _cleanup_options_and_set(options, key) #:nodoc: - case options - when Array - %w(--force -f --skip -s).each { |i| options.delete(i) } - options << "--#{key}" - when Hash - [:force, :skip, "force", "skip"].each { |i| options.delete(i) } - options.merge!(key => true) - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb b/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb deleted file mode 100644 index 97d22d9bbd..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +++ /dev/null @@ -1,104 +0,0 @@ -require "bundler/vendor/thor/lib/thor/actions/empty_directory" - -class Bundler::Thor - module Actions - # Create a new file relative to the destination root with the given data, - # which is the return value of a block or a data string. - # - # ==== Parameters - # destination<String>:: the relative path to the destination root. - # data<String|NilClass>:: the data to append to the file. - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Examples - # - # create_file "lib/fun_party.rb" do - # hostname = ask("What is the virtual hostname I should use?") - # "vhost.name = #{hostname}" - # end - # - # create_file "config/apache.conf", "your apache config" - # - def create_file(destination, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - data = args.first - action CreateFile.new(self, destination, block || data.to_s, config) - end - alias_method :add_file, :create_file - - # CreateFile is a subset of Template, which instead of rendering a file with - # ERB, it gets the content from the user. - # - class CreateFile < EmptyDirectory #:nodoc: - attr_reader :data - - def initialize(base, destination, data, config = {}) - @data = data - super(base, destination, config) - end - - # Checks if the content of the file at the destination is identical to the rendered result. - # - # ==== Returns - # Boolean:: true if it is identical, false otherwise. - # - def identical? - exists? && File.binread(destination) == render - end - - # Holds the content to be added to the file. - # - def render - @render ||= if data.is_a?(Proc) - data.call - else - data - end - end - - def invoke! - invoke_with_conflict_check do - require "fileutils" - FileUtils.mkdir_p(File.dirname(destination)) - File.open(destination, "wb") { |f| f.write render } - end - given_destination - end - - protected - - # Now on conflict we check if the file is identical or not. - # - def on_conflict_behavior(&block) - if identical? - say_status :identical, :blue - else - options = base.options.merge(config) - force_or_skip_or_conflict(options[:force], options[:skip], &block) - end - end - - # If force is true, run the action, otherwise check if it's not being - # skipped. If both are false, show the file_collision menu, if the menu - # returns true, force it, otherwise skip. - # - def force_or_skip_or_conflict(force, skip, &block) - if force - say_status :force, :yellow - yield unless pretend? - elsif skip - say_status :skip, :yellow - else - say_status :conflict, :red - force_or_skip_or_conflict(force_on_collision?, true, &block) - end - end - - # Shows the file collision menu to the user and gets the result. - # - def force_on_collision? - base.shell.file_collision(destination) { render } - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb b/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb deleted file mode 100644 index 3a664401b4..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +++ /dev/null @@ -1,60 +0,0 @@ -require "bundler/vendor/thor/lib/thor/actions/create_file" - -class Bundler::Thor - module Actions - # Create a new file relative to the destination root from the given source. - # - # ==== Parameters - # destination<String>:: the relative path to the destination root. - # source<String|NilClass>:: the relative path to the source root. - # config<Hash>:: give :verbose => false to not log the status. - # :: give :symbolic => false for hard link. - # - # ==== Examples - # - # create_link "config/apache.conf", "/etc/apache.conf" - # - def create_link(destination, *args) - config = args.last.is_a?(Hash) ? args.pop : {} - source = args.first - action CreateLink.new(self, destination, source, config) - end - alias_method :add_link, :create_link - - # CreateLink is a subset of CreateFile, which instead of taking a block of - # data, just takes a source string from the user. - # - class CreateLink < CreateFile #:nodoc: - attr_reader :data - - # Checks if the content of the file at the destination is identical to the rendered result. - # - # ==== Returns - # Boolean:: true if it is identical, false otherwise. - # - def identical? - exists? && File.identical?(render, destination) - end - - def invoke! - invoke_with_conflict_check do - require "fileutils" - FileUtils.mkdir_p(File.dirname(destination)) - # Create a symlink by default - config[:symbolic] = true if config[:symbolic].nil? - File.unlink(destination) if exists? - if config[:symbolic] - File.symlink(render, destination) - else - File.link(render, destination) - end - end - given_destination - end - - def exists? - super || File.symlink?(destination) - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/actions/directory.rb b/lib/bundler/vendor/thor/lib/thor/actions/directory.rb deleted file mode 100644 index f555f7b7e0..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +++ /dev/null @@ -1,118 +0,0 @@ -require "bundler/vendor/thor/lib/thor/actions/empty_directory" - -class Bundler::Thor - module Actions - # Copies recursively the files from source directory to root directory. - # If any of the files finishes with .tt, it's considered to be a template - # and is placed in the destination without the extension .tt. If any - # empty directory is found, it's copied and all .empty_directory files are - # ignored. If any file name is wrapped within % signs, the text within - # the % signs will be executed as a method and replaced with the returned - # value. Let's suppose a doc directory with the following files: - # - # doc/ - # components/.empty_directory - # README - # rdoc.rb.tt - # %app_name%.rb - # - # When invoked as: - # - # directory "doc" - # - # It will create a doc directory in the destination with the following - # files (assuming that the `app_name` method returns the value "blog"): - # - # doc/ - # components/ - # README - # rdoc.rb - # blog.rb - # - # <b>Encoded path note:</b> Since Bundler::Thor internals use Object#respond_to? to check if it can - # expand %something%, this `something` should be a public method in the class calling - # #directory. If a method is private, Bundler::Thor stack raises PrivateMethodEncodedError. - # - # ==== Parameters - # source<String>:: the relative path to the source root. - # destination<String>:: the relative path to the destination root. - # config<Hash>:: give :verbose => false to not log the status. - # If :recursive => false, does not look for paths recursively. - # If :mode => :preserve, preserve the file mode from the source. - # If :exclude_pattern => /regexp/, prevents copying files that match that regexp. - # - # ==== Examples - # - # directory "doc" - # directory "doc", "docs", :recursive => false - # - def directory(source, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - destination = args.first || source - action Directory.new(self, source, destination || source, config, &block) - end - - class Directory < EmptyDirectory #:nodoc: - attr_reader :source - - def initialize(base, source, destination = nil, config = {}, &block) - @source = File.expand_path(base.find_in_source_paths(source.to_s)) - @block = block - super(base, destination, {:recursive => true}.merge(config)) - end - - def invoke! - base.empty_directory given_destination, config - execute! - end - - def revoke! - execute! - end - - protected - - def execute! - lookup = Util.escape_globs(source) - lookup = config[:recursive] ? File.join(lookup, "**") : lookup - lookup = file_level_lookup(lookup) - - files(lookup).sort.each do |file_source| - next if File.directory?(file_source) - next if config[:exclude_pattern] && file_source.match(config[:exclude_pattern]) - file_destination = File.join(given_destination, file_source.gsub(source, ".")) - file_destination.gsub!("/./", "/") - - case file_source - when /\.empty_directory$/ - dirname = File.dirname(file_destination).gsub(%r{/\.$}, "") - next if dirname == given_destination - base.empty_directory(dirname, config) - when /#{TEMPLATE_EXTNAME}$/ - base.template(file_source, file_destination[0..-4], config, &@block) - else - base.copy_file(file_source, file_destination, config, &@block) - end - end - end - - if RUBY_VERSION < "2.0" - def file_level_lookup(previous_lookup) - File.join(previous_lookup, "{*,.[a-z]*}") - end - - def files(lookup) - Dir[lookup] - end - else - def file_level_lookup(previous_lookup) - File.join(previous_lookup, "*") - end - - def files(lookup) - Dir.glob(lookup, File::FNM_DOTMATCH) - end - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb b/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb deleted file mode 100644 index 284d92c19a..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +++ /dev/null @@ -1,143 +0,0 @@ -class Bundler::Thor - module Actions - # Creates an empty directory. - # - # ==== Parameters - # destination<String>:: the relative path to the destination root. - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Examples - # - # empty_directory "doc" - # - def empty_directory(destination, config = {}) - action EmptyDirectory.new(self, destination, config) - end - - # Class which holds create directory logic. This is the base class for - # other actions like create_file and directory. - # - # This implementation is based in Templater actions, created by Jonas Nicklas - # and Michael S. Klishin under MIT LICENSE. - # - class EmptyDirectory #:nodoc: - attr_reader :base, :destination, :given_destination, :relative_destination, :config - - # Initializes given the source and destination. - # - # ==== Parameters - # base<Bundler::Thor::Base>:: A Bundler::Thor::Base instance - # source<String>:: Relative path to the source of this file - # destination<String>:: Relative path to the destination of this file - # config<Hash>:: give :verbose => false to not log the status. - # - def initialize(base, destination, config = {}) - @base = base - @config = {:verbose => true}.merge(config) - self.destination = destination - end - - # Checks if the destination file already exists. - # - # ==== Returns - # Boolean:: true if the file exists, false otherwise. - # - def exists? - ::File.exist?(destination) - end - - def invoke! - invoke_with_conflict_check do - require "fileutils" - ::FileUtils.mkdir_p(destination) - end - end - - def revoke! - say_status :remove, :red - require "fileutils" - ::FileUtils.rm_rf(destination) if !pretend? && exists? - given_destination - end - - protected - - # Shortcut for pretend. - # - def pretend? - base.options[:pretend] - end - - # Sets the absolute destination value from a relative destination value. - # It also stores the given and relative destination. Let's suppose our - # script is being executed on "dest", it sets the destination root to - # "dest". The destination, given_destination and relative_destination - # are related in the following way: - # - # inside "bar" do - # empty_directory "baz" - # end - # - # destination #=> dest/bar/baz - # relative_destination #=> bar/baz - # given_destination #=> baz - # - def destination=(destination) - return unless destination - @given_destination = convert_encoded_instructions(destination.to_s) - @destination = ::File.expand_path(@given_destination, base.destination_root) - @relative_destination = base.relative_to_original_destination_root(@destination) - end - - # Filenames in the encoded form are converted. If you have a file: - # - # %file_name%.rb - # - # It calls #file_name from the base and replaces %-string with the - # return value (should be String) of #file_name: - # - # user.rb - # - # The method referenced can be either public or private. - # - def convert_encoded_instructions(filename) - filename.gsub(/%(.*?)%/) do |initial_string| - method = $1.strip - base.respond_to?(method, true) ? base.send(method) : initial_string - end - end - - # Receives a hash of options and just execute the block if some - # conditions are met. - # - def invoke_with_conflict_check(&block) - if exists? - on_conflict_behavior(&block) - else - yield unless pretend? - say_status :create, :green - end - - destination - rescue Errno::EISDIR, Errno::EEXIST - on_file_clash_behavior - end - - def on_file_clash_behavior - say_status :file_clash, :red - end - - # What to do when the destination file already exists. - # - def on_conflict_behavior - say_status :exist, :blue - end - - # Shortcut to say_status shell method. - # - def say_status(status, color) - base.shell.say_status status, relative_destination, color if config[:verbose] - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb deleted file mode 100644 index 4c83bebc86..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +++ /dev/null @@ -1,364 +0,0 @@ -require "erb" - -class Bundler::Thor - module Actions - # Copies the file from the relative source to the relative destination. If - # the destination is not given it's assumed to be equal to the source. - # - # ==== Parameters - # source<String>:: the relative path to the source root. - # destination<String>:: the relative path to the destination root. - # config<Hash>:: give :verbose => false to not log the status, and - # :mode => :preserve, to preserve the file mode from the source. - - # - # ==== Examples - # - # copy_file "README", "doc/README" - # - # copy_file "doc/README" - # - def copy_file(source, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - destination = args.first || source - source = File.expand_path(find_in_source_paths(source.to_s)) - - create_file destination, nil, config do - content = File.binread(source) - content = yield(content) if block - content - end - if config[:mode] == :preserve - mode = File.stat(source).mode - chmod(destination, mode, config) - end - end - - # Links the file from the relative source to the relative destination. If - # the destination is not given it's assumed to be equal to the source. - # - # ==== Parameters - # source<String>:: the relative path to the source root. - # destination<String>:: the relative path to the destination root. - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Examples - # - # link_file "README", "doc/README" - # - # link_file "doc/README" - # - def link_file(source, *args) - config = args.last.is_a?(Hash) ? args.pop : {} - destination = args.first || source - source = File.expand_path(find_in_source_paths(source.to_s)) - - create_link destination, source, config - end - - # Gets the content at the given address and places it at the given relative - # destination. If a block is given instead of destination, the content of - # the url is yielded and used as location. - # - # ==== Parameters - # source<String>:: the address of the given content. - # destination<String>:: the relative path to the destination root. - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Examples - # - # get "http://gist.github.com/103208", "doc/README" - # - # get "http://gist.github.com/103208" do |content| - # content.split("\n").first - # end - # - def get(source, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - destination = args.first - - if source =~ %r{^https?\://} - require "open-uri" - else - source = File.expand_path(find_in_source_paths(source.to_s)) - end - - render = open(source) { |input| input.binmode.read } - - destination ||= if block_given? - block.arity == 1 ? yield(render) : yield - else - File.basename(source) - end - - create_file destination, render, config - end - - # Gets an ERB template at the relative source, executes it and makes a copy - # at the relative destination. If the destination is not given it's assumed - # to be equal to the source removing .tt from the filename. - # - # ==== Parameters - # source<String>:: the relative path to the source root. - # destination<String>:: the relative path to the destination root. - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Examples - # - # template "README", "doc/README" - # - # template "doc/README" - # - def template(source, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - destination = args.first || source.sub(/#{TEMPLATE_EXTNAME}$/, "") - - source = File.expand_path(find_in_source_paths(source.to_s)) - 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| - erb.filename = source - end.result(context) - content = yield(content) if block - content - end - end - - # Changes the mode of the given file or directory. - # - # ==== Parameters - # mode<Integer>:: the file mode - # path<String>:: the name of the file to change mode - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Example - # - # chmod "script/server", 0755 - # - def chmod(path, mode, config = {}) - return unless behavior == :invoke - path = File.expand_path(path, destination_root) - say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true) - unless options[:pretend] - require "fileutils" - FileUtils.chmod_R(mode, path) - end - end - - # Prepend text to a file. Since it depends on insert_into_file, it's reversible. - # - # ==== Parameters - # path<String>:: path of the file to be changed - # data<String>:: the data to prepend to the file, can be also given as a block. - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Example - # - # prepend_to_file 'config/environments/test.rb', 'config.gem "rspec"' - # - # prepend_to_file 'config/environments/test.rb' do - # 'config.gem "rspec"' - # end - # - def prepend_to_file(path, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - config[:after] = /\A/ - insert_into_file(path, *(args << config), &block) - end - alias_method :prepend_file, :prepend_to_file - - # Append text to a file. Since it depends on insert_into_file, it's reversible. - # - # ==== Parameters - # path<String>:: path of the file to be changed - # data<String>:: the data to append to the file, can be also given as a block. - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Example - # - # append_to_file 'config/environments/test.rb', 'config.gem "rspec"' - # - # append_to_file 'config/environments/test.rb' do - # 'config.gem "rspec"' - # end - # - def append_to_file(path, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - config[:before] = /\z/ - insert_into_file(path, *(args << config), &block) - end - alias_method :append_file, :append_to_file - - # Injects text right after the class definition. Since it depends on - # insert_into_file, it's reversible. - # - # ==== Parameters - # path<String>:: path of the file to be changed - # klass<String|Class>:: the class to be manipulated - # data<String>:: the data to append to the class, can be also given as a block. - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Examples - # - # inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n" - # - # inject_into_class "app/controllers/application_controller.rb", ApplicationController do - # " filter_parameter :password\n" - # end - # - def inject_into_class(path, klass, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - config[:after] = /class #{klass}\n|class #{klass} .*\n/ - insert_into_file(path, *(args << config), &block) - end - - # Injects text right after the module definition. Since it depends on - # insert_into_file, it's reversible. - # - # ==== Parameters - # path<String>:: path of the file to be changed - # module_name<String|Class>:: the module to be manipulated - # data<String>:: the data to append to the class, can be also given as a block. - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Examples - # - # inject_into_module "app/helpers/application_helper.rb", ApplicationHelper, " def help; 'help'; end\n" - # - # inject_into_module "app/helpers/application_helper.rb", ApplicationHelper do - # " def help; 'help'; end\n" - # end - # - def inject_into_module(path, module_name, *args, &block) - config = args.last.is_a?(Hash) ? args.pop : {} - config[:after] = /module #{module_name}\n|module #{module_name} .*\n/ - insert_into_file(path, *(args << config), &block) - end - - # Run a regular expression replacement on a file. - # - # ==== Parameters - # path<String>:: path of the file to be changed - # flag<Regexp|String>:: the regexp or string to be replaced - # replacement<String>:: the replacement, can be also given as a block - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Example - # - # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' - # - # gsub_file 'README', /rake/, :green do |match| - # match << " no more. Use thor!" - # end - # - def gsub_file(path, flag, *args, &block) - return unless behavior == :invoke - config = args.last.is_a?(Hash) ? args.pop : {} - - path = File.expand_path(path, destination_root) - say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) - - unless options[:pretend] - content = File.binread(path) - content.gsub!(flag, *args, &block) - File.open(path, "wb") { |file| file.write(content) } - end - end - - # Uncomment all lines matching a given regex. It will leave the space - # which existed before the comment hash in tact but will remove any spacing - # between the comment hash and the beginning of the line. - # - # ==== Parameters - # path<String>:: path of the file to be changed - # flag<Regexp|String>:: the regexp or string used to decide which lines to uncomment - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Example - # - # uncomment_lines 'config/initializers/session_store.rb', /active_record/ - # - def uncomment_lines(path, flag, *args) - flag = flag.respond_to?(:source) ? flag.source : flag - - gsub_file(path, /^(\s*)#[[:blank:]]*(.*#{flag})/, '\1\2', *args) - end - - # Comment all lines matching a given regex. It will leave the space - # which existed before the beginning of the line in tact and will insert - # a single space after the comment hash. - # - # ==== Parameters - # path<String>:: path of the file to be changed - # flag<Regexp|String>:: the regexp or string used to decide which lines to comment - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Example - # - # comment_lines 'config/initializers/session_store.rb', /cookie_store/ - # - def comment_lines(path, flag, *args) - flag = flag.respond_to?(:source) ? flag.source : flag - - gsub_file(path, /^(\s*)([^#|\n]*#{flag})/, '\1# \2', *args) - end - - # Removes a file at the given location. - # - # ==== Parameters - # path<String>:: path of the file to be changed - # config<Hash>:: give :verbose => false to not log the status. - # - # ==== Example - # - # remove_file 'README' - # remove_file 'app/controllers/application_controller.rb' - # - def remove_file(path, config = {}) - return unless behavior == :invoke - path = File.expand_path(path, destination_root) - - say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true) - if !options[:pretend] && File.exist?(path) - require "fileutils" - ::FileUtils.rm_rf(path) - end - end - alias_method :remove_dir, :remove_file - - attr_accessor :output_buffer - private :output_buffer, :output_buffer= - - private - - def concat(string) - @output_buffer.concat(string) - end - - def capture(*args) - with_output_buffer { yield(*args) } - end - - def with_output_buffer(buf = "".dup) #:nodoc: - raise ArgumentError, "Buffer can not be a frozen object" if buf.frozen? - old_buffer = output_buffer - self.output_buffer = buf - yield - output_buffer - ensure - self.output_buffer = old_buffer - end - - # Bundler::Thor::Actions#capture depends on what kind of buffer is used in ERB. - # Thus CapturableERB fixes ERB to use String buffer. - class CapturableERB < ERB - def set_eoutvar(compiler, eoutvar = "_erbout") - compiler.put_cmd = "#{eoutvar}.concat" - compiler.insert_cmd = "#{eoutvar}.concat" - compiler.pre_cmd = ["#{eoutvar} = ''.dup"] - compiler.post_cmd = [eoutvar] - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb b/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb deleted file mode 100644 index 349b26ff65..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +++ /dev/null @@ -1,109 +0,0 @@ -require "bundler/vendor/thor/lib/thor/actions/empty_directory" - -class Bundler::Thor - module Actions - # Injects the given content into a file. Different from gsub_file, this - # method is reversible. - # - # ==== Parameters - # destination<String>:: Relative path to the destination root - # data<String>:: Data to add to the file. Can be given as a block. - # config<Hash>:: give :verbose => false to not log the status and the flag - # for injection (:after or :before) or :force => true for - # insert two or more times the same content. - # - # ==== Examples - # - # insert_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n" - # - # insert_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do - # gems = ask "Which gems would you like to add?" - # gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n") - # end - # - def insert_into_file(destination, *args, &block) - data = block_given? ? block : args.shift - config = args.shift - action InjectIntoFile.new(self, destination, data, config) - end - alias_method :inject_into_file, :insert_into_file - - class InjectIntoFile < EmptyDirectory #:nodoc: - attr_reader :replacement, :flag, :behavior - - def initialize(base, destination, data, config) - super(base, destination, {:verbose => true}.merge(config)) - - @behavior, @flag = if @config.key?(:after) - [:after, @config.delete(:after)] - else - [:before, @config.delete(:before)] - end - - @replacement = data.is_a?(Proc) ? data.call : data - @flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp) - end - - def invoke! - say_status :invoke - - content = if @behavior == :after - '\0' + replacement - else - replacement + '\0' - end - - if exists? - replace!(/#{flag}/, content, config[:force]) - else - unless pretend? - raise Bundler::Thor::Error, "The file #{ destination } does not appear to exist" - end - end - end - - def revoke! - say_status :revoke - - regexp = if @behavior == :after - content = '\1\2' - /(#{flag})(.*)(#{Regexp.escape(replacement)})/m - else - content = '\2\3' - /(#{Regexp.escape(replacement)})(.*)(#{flag})/m - end - - replace!(regexp, content, true) - end - - protected - - def say_status(behavior) - status = if behavior == :invoke - if flag == /\A/ - :prepend - elsif flag == /\z/ - :append - else - :insert - end - else - :subtract - end - - super(status, config[:verbose]) - end - - # Adds the content to the file. - # - def replace!(regexp, string, force) - return if pretend? - content = File.read(destination) - if force || !content.include?(replacement) - content.gsub!(regexp, string) - File.open(destination, "wb") { |file| file.write(content) } - end - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/base.rb b/lib/bundler/vendor/thor/lib/thor/base.rb deleted file mode 100644 index 9bd1077170..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/base.rb +++ /dev/null @@ -1,679 +0,0 @@ -require "bundler/vendor/thor/lib/thor/command" -require "bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access" -require "bundler/vendor/thor/lib/thor/core_ext/ordered_hash" -require "bundler/vendor/thor/lib/thor/error" -require "bundler/vendor/thor/lib/thor/invocation" -require "bundler/vendor/thor/lib/thor/parser" -require "bundler/vendor/thor/lib/thor/shell" -require "bundler/vendor/thor/lib/thor/line_editor" -require "bundler/vendor/thor/lib/thor/util" - -class Bundler::Thor - autoload :Actions, "bundler/vendor/thor/lib/thor/actions" - autoload :RakeCompat, "bundler/vendor/thor/lib/thor/rake_compat" - autoload :Group, "bundler/vendor/thor/lib/thor/group" - - # Shortcuts for help. - HELP_MAPPINGS = %w(-h -? --help -D) - - # Bundler::Thor methods that should not be overwritten by the user. - THOR_RESERVED_WORDS = %w(invoke shell options behavior root destination_root relative_root - action add_file create_file in_root inside run run_ruby_script) - - TEMPLATE_EXTNAME = ".tt" - - module Base - attr_accessor :options, :parent_options, :args - - # It receives arguments in an Array and two hashes, one for options and - # other for configuration. - # - # Notice that it does not check if all required arguments were supplied. - # It should be done by the parser. - # - # ==== Parameters - # args<Array[Object]>:: An array of objects. The objects are applied to their - # respective accessors declared with <tt>argument</tt>. - # - # options<Hash>:: An options hash that will be available as self.options. - # The hash given is converted to a hash with indifferent - # access, magic predicates (options.skip?) and then frozen. - # - # config<Hash>:: Configuration for this Bundler::Thor class. - # - def initialize(args = [], local_options = {}, config = {}) - parse_options = self.class.class_options - - # The start method splits inbound arguments at the first argument - # that looks like an option (starts with - or --). It then calls - # new, passing in the two halves of the arguments Array as the - # first two parameters. - - command_options = config.delete(:command_options) # hook for start - parse_options = parse_options.merge(command_options) if command_options - if local_options.is_a?(Array) - array_options = local_options - hash_options = {} - else - # Handle the case where the class was explicitly instantiated - # with pre-parsed options. - array_options = [] - hash_options = local_options - end - - # Let Bundler::Thor::Options parse the options first, so it can remove - # declared options from the array. This will leave us with - # a list of arguments that weren't declared. - stop_on_unknown = self.class.stop_on_unknown_option? config[:current_command] - disable_required_check = self.class.disable_required_check? config[:current_command] - opts = Bundler::Thor::Options.new(parse_options, hash_options, stop_on_unknown, disable_required_check) - self.options = opts.parse(array_options) - self.options = config[:class_options].merge(options) if config[:class_options] - - # If unknown options are disallowed, make sure that none of the - # remaining arguments looks like an option. - opts.check_unknown! if self.class.check_unknown_options?(config) - - # Add the remaining arguments from the options parser to the - # arguments passed in to initialize. Then remove any positional - # arguments declared using #argument (this is primarily used - # by Bundler::Thor::Group). Tis will leave us with the remaining - # positional arguments. - to_parse = args - to_parse += opts.remaining unless self.class.strict_args_position?(config) - - thor_args = Bundler::Thor::Arguments.new(self.class.arguments) - thor_args.parse(to_parse).each { |k, v| __send__("#{k}=", v) } - @args = thor_args.remaining - end - - class << self - def included(base) #:nodoc: - base.extend ClassMethods - base.send :include, Invocation - base.send :include, Shell - end - - # Returns the classes that inherits from Bundler::Thor or Bundler::Thor::Group. - # - # ==== Returns - # Array[Class] - # - def subclasses - @subclasses ||= [] - end - - # Returns the files where the subclasses are kept. - # - # ==== Returns - # Hash[path<String> => Class] - # - def subclass_files - @subclass_files ||= Hash.new { |h, k| h[k] = [] } - 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. - # - def register_klass_file(klass) #:nodoc: - file = caller[1].match(/(.*):\d+/)[1] - Bundler::Thor::Base.subclasses << klass unless Bundler::Thor::Base.subclasses.include?(klass) - - file_subclasses = Bundler::Thor::Base.subclass_files[File.expand_path(file)] - file_subclasses << klass unless file_subclasses.include?(klass) - end - end - - module ClassMethods - def attr_reader(*) #:nodoc: - no_commands { super } - end - - def attr_writer(*) #:nodoc: - no_commands { super } - end - - def attr_accessor(*) #:nodoc: - no_commands { super } - end - - # If you want to raise an error for unknown options, call check_unknown_options! - # This is disabled by default to allow dynamic invocations. - def check_unknown_options! - @check_unknown_options = true - end - - def check_unknown_options #:nodoc: - @check_unknown_options ||= from_superclass(:check_unknown_options, false) - end - - def check_unknown_options?(config) #:nodoc: - !!check_unknown_options - end - - # 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. - def check_default_type! - @check_default_type = true - end - - def check_default_type #:nodoc: - @check_default_type ||= from_superclass(:check_default_type, false) - end - - def check_default_type? #:nodoc: - !!check_default_type - end - - # If true, option parsing is suspended as soon as an unknown option or a - # regular argument is encountered. All remaining arguments are passed to - # the command as regular arguments. - def stop_on_unknown_option?(command_name) #:nodoc: - false - end - - # If true, option set will not suspend the execution of the command when - # a required option is not provided. - def disable_required_check?(command_name) #:nodoc: - false - end - - # If you want only strict string args (useful when cascading thor classes), - # call strict_args_position! This is disabled by default to allow dynamic - # invocations. - def strict_args_position! - @strict_args_position = true - end - - def strict_args_position #:nodoc: - @strict_args_position ||= from_superclass(:strict_args_position, false) - end - - def strict_args_position?(config) #:nodoc: - !!strict_args_position - end - - # Adds an argument to the class and creates an attr_accessor for it. - # - # Arguments are different from options in several aspects. The first one - # is how they are parsed from the command line, arguments are retrieved - # from position: - # - # thor command NAME - # - # Instead of: - # - # thor command --name=NAME - # - # Besides, arguments are used inside your code as an accessor (self.argument), - # while options are all kept in a hash (self.options). - # - # Finally, arguments cannot have type :default or :boolean but can be - # optional (supplying :optional => :true or :required => false), although - # you cannot have a required argument after a non-required argument. If you - # try it, an error is raised. - # - # ==== Parameters - # name<Symbol>:: The name of the argument. - # options<Hash>:: Described below. - # - # ==== Options - # :desc - Description for the argument. - # :required - If the argument is required or not. - # :optional - If the argument is optional or not. - # :type - The type of the argument, can be :string, :hash, :array, :numeric. - # :default - Default value for this argument. It cannot be required and have default values. - # :banner - String to show on usage notes. - # - # ==== Errors - # ArgumentError:: Raised if you supply a required argument after a non required one. - # - def argument(name, options = {}) - is_thor_reserved_word?(name, :argument) - no_commands { attr_accessor name } - - required = if options.key?(:optional) - !options[:optional] - elsif options.key?(:required) - options[:required] - else - options[:default].nil? - end - - remove_argument name - - if required - arguments.each do |argument| - next if argument.required? - raise ArgumentError, "You cannot have #{name.to_s.inspect} as required argument after " \ - "the non-required argument #{argument.human_name.inspect}." - end - end - - options[:required] = required - - arguments << Bundler::Thor::Argument.new(name, options) - end - - # Returns this class arguments, looking up in the ancestors chain. - # - # ==== Returns - # Array[Bundler::Thor::Argument] - # - def arguments - @arguments ||= from_superclass(:arguments, []) - end - - # Adds a bunch of options to the set of class options. - # - # class_options :foo => false, :bar => :required, :baz => :string - # - # If you prefer more detailed declaration, check class_option. - # - # ==== Parameters - # Hash[Symbol => Object] - # - def class_options(options = nil) - @class_options ||= from_superclass(:class_options, {}) - build_options(options, @class_options) if options - @class_options - end - - # Adds an option to the set of class options - # - # ==== Parameters - # name<Symbol>:: The name of the argument. - # options<Hash>:: Described below. - # - # ==== Options - # :desc:: -- Description for the argument. - # :required:: -- If the argument is required or not. - # :default:: -- Default value for this argument. - # :group:: -- The group for this options. Use by class options to output options in different levels. - # :aliases:: -- Aliases for this option. <b>Note:</b> Bundler::Thor follows a convention of one-dash-one-letter options. Thus aliases like "-something" wouldn't be parsed; use either "\--something" or "-s" instead. - # :type:: -- The type of the argument, can be :string, :hash, :array, :numeric or :boolean. - # :banner:: -- String to show on usage notes. - # :hide:: -- If you want to hide this option from the help. - # - def class_option(name, options = {}) - build_option(name, options, class_options) - end - - # Removes a previous defined argument. If :undefine is given, undefine - # accessors as well. - # - # ==== Parameters - # names<Array>:: Arguments to be removed - # - # ==== Examples - # - # remove_argument :foo - # remove_argument :foo, :bar, :baz, :undefine => true - # - def remove_argument(*names) - options = names.last.is_a?(Hash) ? names.pop : {} - - names.each do |name| - arguments.delete_if { |a| a.name == name.to_s } - undef_method name, "#{name}=" if options[:undefine] - end - end - - # Removes a previous defined class option. - # - # ==== Parameters - # names<Array>:: Class options to be removed - # - # ==== Examples - # - # remove_class_option :foo - # remove_class_option :foo, :bar, :baz - # - def remove_class_option(*names) - names.each do |name| - class_options.delete(name) - end - end - - # Defines the group. This is used when thor list is invoked so you can specify - # that only commands from a pre-defined group will be shown. Defaults to standard. - # - # ==== Parameters - # name<String|Symbol> - # - def group(name = nil) - if name - @group = name.to_s - else - @group ||= from_superclass(:group, "standard") - end - end - - # Returns the commands for this Bundler::Thor class. - # - # ==== Returns - # OrderedHash:: An ordered hash with commands names as keys and Bundler::Thor::Command - # objects as values. - # - def commands - @commands ||= Bundler::Thor::CoreExt::OrderedHash.new - end - alias_method :tasks, :commands - - # Returns the commands for this Bundler::Thor class and all subclasses. - # - # ==== Returns - # OrderedHash:: An ordered hash with commands names as keys and Bundler::Thor::Command - # objects as values. - # - def all_commands - @all_commands ||= from_superclass(:all_commands, Bundler::Thor::CoreExt::OrderedHash.new) - @all_commands.merge!(commands) - end - alias_method :all_tasks, :all_commands - - # Removes a given command from this Bundler::Thor class. This is usually done if you - # are inheriting from another class and don't want it to be available - # anymore. - # - # By default it only remove the mapping to the command. But you can supply - # :undefine => true to undefine the method from the class as well. - # - # ==== Parameters - # name<Symbol|String>:: The name of the command to be removed - # options<Hash>:: You can give :undefine => true if you want commands the method - # to be undefined from the class as well. - # - def remove_command(*names) - options = names.last.is_a?(Hash) ? names.pop : {} - - names.each do |name| - commands.delete(name.to_s) - all_commands.delete(name.to_s) - undef_method name if options[:undefine] - end - end - alias_method :remove_task, :remove_command - - # All methods defined inside the given block are not added as commands. - # - # So you can do: - # - # class MyScript < Bundler::Thor - # no_commands do - # def this_is_not_a_command - # end - # end - # end - # - # You can also add the method and remove it from the command list: - # - # class MyScript < Bundler::Thor - # def this_is_not_a_command - # end - # remove_command :this_is_not_a_command - # end - # - def no_commands - @no_commands = true - yield - ensure - @no_commands = false - end - alias_method :no_tasks, :no_commands - - # Sets the namespace for the Bundler::Thor or Bundler::Thor::Group class. By default the - # namespace is retrieved from the class name. If your Bundler::Thor class is named - # Scripts::MyScript, the help method, for example, will be called as: - # - # thor scripts:my_script -h - # - # If you change the namespace: - # - # namespace :my_scripts - # - # You change how your commands are invoked: - # - # thor my_scripts -h - # - # Finally, if you change your namespace to default: - # - # namespace :default - # - # Your commands can be invoked with a shortcut. Instead of: - # - # thor :my_command - # - def namespace(name = nil) - if name - @namespace = name.to_s - else - @namespace ||= Bundler::Thor::Util.namespace_from_thor_class(self) - end - end - - # Parses the command and options from the given args, instantiate the class - # and invoke the command. This method is used when the arguments must be parsed - # from an array. If you are inside Ruby and want to use a Bundler::Thor class, you - # can simply initialize it: - # - # script = MyScript.new(args, options, config) - # script.invoke(:command, first_arg, second_arg, third_arg) - # - def start(given_args = ARGV, config = {}) - config[:shell] ||= Bundler::Thor::Base.shell.new - 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? - 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) - end - - # Allows to use private methods from parent in child classes as commands. - # - # ==== Parameters - # names<Array>:: Method names to be used as commands - # - # ==== Examples - # - # public_command :foo - # public_command :foo, :bar, :baz - # - def public_command(*names) - names.each do |name| - class_eval "def #{name}(*); super end" - end - end - 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}." - end - alias_method :handle_no_task_error, :handle_no_command_error - - def handle_argument_error(command, error, args, arity) #:nodoc: - name = [command.ancestor_name, command.name].compact.join(" ") - msg = "ERROR: \"#{basename} #{name}\" was called with ".dup - msg << "no arguments" if args.empty? - msg << "arguments " << args.inspect unless args.empty? - msg << "\nUsage: #{banner(command).inspect}" - raise InvocationError, msg - end - - protected - - # Prints the class options per group. If an option does not belong to - # any group, it's printed as Class option. - # - def class_options_help(shell, groups = {}) #:nodoc: - # Group options by group - class_options.each do |_, value| - groups[value.group] ||= [] - groups[value.group] << value - end - - # Deal with default group - global_options = groups.delete(nil) || [] - print_options(shell, global_options) - - # Print all others - groups.each do |group_name, options| - print_options(shell, options, group_name) - end - end - - # Receives a set of options and print them. - def print_options(shell, options, group_name = nil) - return if options.empty? - - list = [] - padding = options.map { |o| o.aliases.size }.max.to_i * 4 - - options.each do |option| - next if option.hide - item = [option.usage(padding)] - item.push(option.description ? "# #{option.description}" : "") - - list << item - list << ["", "# Default: #{option.default}"] if option.show_default? - list << ["", "# Possible values: #{option.enum.join(', ')}"] if option.enum - end - - shell.say(group_name ? "#{group_name} options:" : "Options:") - shell.print_table(list, :indent => 2) - shell.say "" - end - - # Raises an error if the word given is a Bundler::Thor reserved word. - def is_thor_reserved_word?(word, type) #:nodoc: - return false unless THOR_RESERVED_WORDS.include?(word.to_s) - raise "#{word.inspect} is a Bundler::Thor reserved word and cannot be defined as #{type}" - end - - # Build an option and adds it to the given scope. - # - # ==== Parameters - # name<Symbol>:: The name of the argument. - # options<Hash>:: Described in both class_option and method_option. - # scope<Hash>:: 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?)) - end - - # Receives a hash of options, parse them and add to the scope. This is a - # fast way to set a bunch of options: - # - # build_options :foo => true, :bar => :required, :baz => :string - # - # ==== Parameters - # Hash[Symbol => Object] - def build_options(options, scope) #:nodoc: - options.each do |key, value| - scope[key] = Bundler::Thor::Option.parse(key, value) - end - end - - # Finds a command with the given name. If the command belongs to the current - # class, just return it, otherwise dup it and add the fresh copy to the - # current command hash. - def find_and_refresh_command(name) #:nodoc: - if commands[name.to_s] - commands[name.to_s] - elsif command = all_commands[name.to_s] # rubocop:disable AssignmentInCondition - commands[name.to_s] = command.clone - else - raise ArgumentError, "You supplied :for => #{name.inspect}, but the command #{name.inspect} could not be found." - end - end - alias_method :find_and_refresh_task, :find_and_refresh_command - - # Everytime someone inherits from a Bundler::Thor class, register the klass - # and file into baseclass. - def inherited(klass) - Bundler::Thor::Base.register_klass_file(klass) - klass.instance_variable_set(:@no_commands, false) - end - - # Fire this callback whenever a method is added. Added methods are - # tracked as commands by invoking the create_command method. - def method_added(meth) - meth = meth.to_s - - if meth == "initialize" - initialize_added - return - end - - # Return if it's not a public instance method - return unless public_method_defined?(meth.to_sym) - - @no_commands ||= false - return if @no_commands || !create_command(meth) - - is_thor_reserved_word?(meth, :command) - Bundler::Thor::Base.register_klass_file(self) - end - - # Retrieves a value from superclass. If it reaches the baseclass, - # returns default. - def from_superclass(method, default = nil) - if self == baseclass || !superclass.respond_to?(method, true) - default - else - value = superclass.send(method) - - # Ruby implements `dup` on Object, but raises a `TypeError` - # if the method is called on immediates. As a result, we - # don't have a good way to check whether dup will succeed - # without calling it and rescuing the TypeError. - begin - value.dup - rescue TypeError - value - end - - 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. - # - def basename - File.basename($PROGRAM_NAME).split(" ").first - end - - # SIGNATURE: Sets the baseclass. This is where the superclass lookup - # finishes. - def baseclass #:nodoc: - end - - # SIGNATURE: Creates a new command if valid_command? is true. This method is - # called when a new method is added to the class. - def create_command(meth) #:nodoc: - end - alias_method :create_task, :create_command - - # SIGNATURE: Defines behavior when the initialize method is added to the - # class. - def initialize_added #:nodoc: - end - - # SIGNATURE: The hook invoked by start. - def dispatch(command, given_args, given_opts, config) #:nodoc: - raise NotImplementedError - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/command.rb b/lib/bundler/vendor/thor/lib/thor/command.rb deleted file mode 100644 index c636948e5d..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/command.rb +++ /dev/null @@ -1,135 +0,0 @@ -class Bundler::Thor - class Command < Struct.new(:name, :description, :long_description, :usage, :options, :ancestor_name) - FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/ - - def initialize(name, description, long_description, usage, options = nil) - super(name.to_s, description, long_description, usage, options || {}) - end - - def initialize_copy(other) #:nodoc: - super(other) - self.options = other.options.dup if other.options - end - - def hidden? - false - end - - # By default, a command invokes a method in the thor class. You can change this - # implementation to create custom commands. - def run(instance, args = []) - arity = nil - - if private_method?(instance) - instance.class.handle_no_command_error(name) - elsif public_method?(instance) - arity = instance.method(name).arity - instance.__send__(name, *args) - elsif local_method?(instance, :method_missing) - instance.__send__(:method_missing, name.to_sym, *args) - else - instance.class.handle_no_command_error(name) - end - rescue ArgumentError => e - handle_argument_error?(instance, e, caller) ? instance.class.handle_argument_error(self, e, args, arity) : (raise e) - rescue NoMethodError => e - handle_no_method_error?(instance, e, caller) ? instance.class.handle_no_command_error(name) : (raise e) - end - - # Returns the formatted usage by injecting given required arguments - # and required options into the given usage. - def formatted_usage(klass, namespace = true, subcommand = false) - if ancestor_name - formatted = "#{ancestor_name} ".dup # add space - elsif namespace - namespace = klass.namespace - formatted = "#{namespace.gsub(/^(default)/, '')}:".dup - end - formatted ||= "#{klass.namespace.split(':').last} ".dup if subcommand - - formatted ||= "".dup - - # Add usage with required arguments - formatted << if klass && !klass.arguments.empty? - usage.to_s.gsub(/^#{name}/) do |match| - match << " " << klass.arguments.map(&:usage).compact.join(" ") - end - else - usage.to_s - end - - # Add required options - formatted << " #{required_options}" - - # Strip and go! - formatted.strip - end - - protected - - def not_debugging?(instance) - !(instance.class.respond_to?(:debugging) && instance.class.debugging) - end - - def required_options - @required_options ||= options.map { |_, o| o.usage if o.required? }.compact.sort.join(" ") - end - - # Given a target, checks if this class name is a public method. - def public_method?(instance) #:nodoc: - !(instance.public_methods & [name.to_s, name.to_sym]).empty? - end - - def private_method?(instance) - !(instance.private_methods & [name.to_s, name.to_sym]).empty? - end - - def local_method?(instance, name) - methods = instance.public_methods(false) + instance.private_methods(false) + instance.protected_methods(false) - !(methods & [name.to_s, name.to_sym]).empty? - end - - def sans_backtrace(backtrace, caller) #:nodoc: - saned = backtrace.reject { |frame| frame =~ FILE_REGEXP || (frame =~ /\.java:/ && RUBY_PLATFORM =~ /java/) || (frame =~ %r{^kernel/} && RUBY_ENGINE =~ /rbx/) } - saned - caller - end - - def handle_argument_error?(instance, error, caller) - not_debugging?(instance) && (error.message =~ /wrong number of arguments/ || error.message =~ /given \d*, expected \d*/) && begin - saned = sans_backtrace(error.backtrace, caller) - # Ruby 1.9 always include the called method in the backtrace - saned.empty? || (saned.size == 1 && RUBY_VERSION >= "1.9") - end - end - - def handle_no_method_error?(instance, error, caller) - not_debugging?(instance) && - error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/ - end - end - Task = Command - - # A command that is hidden in help messages but still invocable. - class HiddenCommand < Command - def hidden? - true - end - end - HiddenTask = HiddenCommand - - # A dynamic command that handles method missing scenarios. - class DynamicCommand < Command - def initialize(name, options = nil) - super(name.to_s, "A dynamically-generated command", name.to_s, name.to_s, options) - end - - def run(instance, args = []) - if (instance.methods & [name.to_s, name.to_sym]).empty? - super - else - instance.class.handle_no_command_error(name) - end - end - end - DynamicTask = DynamicCommand -end diff --git a/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb deleted file mode 100644 index c167aa33b8..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +++ /dev/null @@ -1,97 +0,0 @@ -class Bundler::Thor - module CoreExt #:nodoc: - # A hash with indifferent access and magic predicates. - # - # hash = Bundler::Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar', 'baz' => 'bee', 'force' => true - # - # hash[:foo] #=> 'bar' - # hash['foo'] #=> 'bar' - # hash.foo? #=> true - # - class HashWithIndifferentAccess < ::Hash #:nodoc: - def initialize(hash = {}) - super() - hash.each do |key, value| - self[convert_key(key)] = value - end - end - - def [](key) - super(convert_key(key)) - end - - def []=(key, value) - super(convert_key(key), value) - end - - def delete(key) - super(convert_key(key)) - end - - def fetch(key, *args) - super(convert_key(key), *args) - end - - def key?(key) - super(convert_key(key)) - end - - def values_at(*indices) - indices.map { |key| self[convert_key(key)] } - end - - def merge(other) - dup.merge!(other) - end - - def merge!(other) - other.each do |key, value| - self[convert_key(key)] = value - end - self - end - - def reverse_merge(other) - self.class.new(other).merge(self) - end - - def reverse_merge!(other_hash) - replace(reverse_merge(other_hash)) - end - - def replace(other_hash) - super(other_hash) - end - - # Convert to a Hash with String keys. - def to_hash - Hash.new(default).merge!(self) - end - - protected - - def convert_key(key) - key.is_a?(Symbol) ? key.to_s : key - end - - # Magic predicates. For instance: - # - # options.force? # => !!options['force'] - # options.shebang # => "/usr/lib/local/ruby" - # options.test_framework?(:rspec) # => options[:test_framework] == :rspec - # - def method_missing(method, *args) - method = method.to_s - if method =~ /^(\w+)\?$/ - if args.empty? - !!self[$1] - else - self[$1] == args.first - end - else - self[method] - end - end - end - end -end 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 0f6e2e0af2..0000000000 --- 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/core_ext/ordered_hash.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb deleted file mode 100644 index 76f1e43c65..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +++ /dev/null @@ -1,129 +0,0 @@ -class Bundler::Thor - module CoreExt - class OrderedHash < ::Hash - if RUBY_VERSION < "1.9" - def initialize(*args, &block) - super - @keys = [] - end - - def initialize_copy(other) - super - # make a deep copy of keys - @keys = other.keys - end - - def []=(key, value) - @keys << key unless key?(key) - super - end - - def delete(key) - if key? key - index = @keys.index(key) - @keys.delete_at index - end - super - end - - def delete_if - super - sync_keys! - self - end - - alias_method :reject!, :delete_if - - def reject(&block) - dup.reject!(&block) - end - - def keys - @keys.dup - end - - def values - @keys.map { |key| self[key] } - end - - def to_hash - self - end - - def to_a - @keys.map { |key| [key, self[key]] } - end - - def each_key - return to_enum(:each_key) unless block_given? - @keys.each { |key| yield(key) } - self - end - - def each_value - return to_enum(:each_value) unless block_given? - @keys.each { |key| yield(self[key]) } - self - end - - def each - return to_enum(:each) unless block_given? - @keys.each { |key| yield([key, self[key]]) } - self - end - - def each_pair - return to_enum(:each_pair) unless block_given? - @keys.each { |key| yield(key, self[key]) } - self - end - - alias_method :select, :find_all - - def clear - super - @keys.clear - self - end - - def shift - k = @keys.first - v = delete(k) - [k, v] - end - - def merge!(other_hash) - if block_given? - other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v } - else - other_hash.each { |k, v| self[k] = v } - end - self - end - - alias_method :update, :merge! - - def merge(other_hash, &block) - dup.merge!(other_hash, &block) - end - - # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not. - def replace(other) - super - @keys = other.keys - self - end - - def inspect - "#<#{self.class} #{super}>" - end - - private - - def sync_keys! - @keys.delete_if { |k| !key?(k) } - end - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/error.rb b/lib/bundler/vendor/thor/lib/thor/error.rb deleted file mode 100644 index 2f816081f3..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/error.rb +++ /dev/null @@ -1,32 +0,0 @@ -class Bundler::Thor - # 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 that are caused by the developer, like declaring a method which - # overwrites a thor keyword, SHOULD NOT raise a Bundler::Thor::Error. This way, we - # ensure that developer errors are shown with full backtrace. - class Error < StandardError - end - - # Raised when a command was not found. - class UndefinedCommandError < Error - end - UndefinedTaskError = UndefinedCommandError - - class AmbiguousCommandError < Error - end - AmbiguousTaskError = AmbiguousCommandError - - # Raised when a command was found, but not invoked properly. - class InvocationError < Error - end - - class UnknownArgumentError < Error - end - - class RequiredArgumentMissingError < InvocationError - end - - class MalformattedArgumentError < InvocationError - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/group.rb b/lib/bundler/vendor/thor/lib/thor/group.rb deleted file mode 100644 index 05ddc10cd3..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/group.rb +++ /dev/null @@ -1,281 +0,0 @@ -require "bundler/vendor/thor/lib/thor/base" - -# Bundler::Thor has a special class called Bundler::Thor::Group. The main difference to Bundler::Thor class -# is that it invokes all commands at once. It also include some methods that allows -# invocations to be done at the class method, which are not available to Bundler::Thor -# commands. -class Bundler::Thor::Group - class << self - # The description for this Bundler::Thor::Group. If none is provided, but a source root - # exists, tries to find the USAGE one folder above it, otherwise searches - # in the superclass. - # - # ==== Parameters - # description<String>:: The description for this Bundler::Thor::Group. - # - def desc(description = nil) - if description - @desc = description - else - @desc ||= from_superclass(:desc, nil) - end - end - - # Prints help information. - # - # ==== Options - # short:: When true, shows only usage. - # - def help(shell) - shell.say "Usage:" - shell.say " #{banner}\n" - shell.say - class_options_help(shell) - shell.say desc if desc - end - - # Stores invocations for this class merging with superclass values. - # - def invocations #:nodoc: - @invocations ||= from_superclass(:invocations, {}) - end - - # Stores invocation blocks used on invoke_from_option. - # - def invocation_blocks #:nodoc: - @invocation_blocks ||= from_superclass(:invocation_blocks, {}) - end - - # Invoke the given namespace or class given. It adds an instance - # method that will invoke the klass and command. You can give a block to - # configure how it will be invoked. - # - # The namespace/class given will have its options showed on the help - # usage. Check invoke_from_option for more information. - # - def invoke(*names, &block) - options = names.last.is_a?(Hash) ? names.pop : {} - verbose = options.fetch(:verbose, true) - - names.each do |name| - invocations[name] = false - invocation_blocks[name] = block if block_given? - - class_eval <<-METHOD, __FILE__, __LINE__ - def _invoke_#{name.to_s.gsub(/\W/, '_')} - klass, command = self.class.prepare_for_invocation(nil, #{name.inspect}) - - if klass - say_status :invoke, #{name.inspect}, #{verbose.inspect} - block = self.class.invocation_blocks[#{name.inspect}] - _invoke_for_class_method klass, command, &block - else - say_status :error, %(#{name.inspect} [not found]), :red - end - end - METHOD - end - end - - # Invoke a thor class based on the value supplied by the user to the - # given option named "name". A class option must be created before this - # method is invoked for each name given. - # - # ==== Examples - # - # class GemGenerator < Bundler::Thor::Group - # class_option :test_framework, :type => :string - # invoke_from_option :test_framework - # end - # - # ==== Boolean options - # - # In some cases, you want to invoke a thor class if some option is true or - # false. This is automatically handled by invoke_from_option. Then the - # option name is used to invoke the generator. - # - # ==== Preparing for invocation - # - # In some cases you want to customize how a specified hook is going to be - # invoked. You can do that by overwriting the class method - # prepare_for_invocation. The class method must necessarily return a klass - # and an optional command. - # - # ==== Custom invocations - # - # You can also supply a block to customize how the option is going to be - # invoked. The block receives two parameters, an instance of the current - # class and the klass to be invoked. - # - def invoke_from_option(*names, &block) - options = names.last.is_a?(Hash) ? names.pop : {} - verbose = options.fetch(:verbose, :white) - - names.each do |name| - unless class_options.key?(name) - raise ArgumentError, "You have to define the option #{name.inspect} " \ - "before setting invoke_from_option." - end - - invocations[name] = true - invocation_blocks[name] = block if block_given? - - class_eval <<-METHOD, __FILE__, __LINE__ - def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')} - return unless options[#{name.inspect}] - - value = options[#{name.inspect}] - value = #{name.inspect} if TrueClass === value - klass, command = self.class.prepare_for_invocation(#{name.inspect}, value) - - if klass - say_status :invoke, value, #{verbose.inspect} - block = self.class.invocation_blocks[#{name.inspect}] - _invoke_for_class_method klass, command, &block - else - say_status :error, %(\#{value} [not found]), :red - end - end - METHOD - end - end - - # Remove a previously added invocation. - # - # ==== Examples - # - # remove_invocation :test_framework - # - def remove_invocation(*names) - names.each do |name| - remove_command(name) - remove_class_option(name) - invocations.delete(name) - invocation_blocks.delete(name) - end - end - - # Overwrite class options help to allow invoked generators options to be - # shown recursively when invoking a generator. - # - def class_options_help(shell, groups = {}) #:nodoc: - get_options_from_invocations(groups, class_options) do |klass| - klass.send(:get_options_from_invocations, groups, class_options) - end - super(shell, groups) - end - - # Get invocations array and merge options from invocations. Those - # options are added to group_options hash. Options that already exists - # in base_options are not added twice. - # - def get_options_from_invocations(group_options, base_options) #:nodoc: # rubocop:disable MethodLength - invocations.each do |name, from_option| - value = if from_option - option = class_options[name] - option.type == :boolean ? name : option.default - else - name - end - next unless value - - klass, _ = prepare_for_invocation(name, value) - next unless klass && klass.respond_to?(:class_options) - - value = value.to_s - human_name = value.respond_to?(:classify) ? value.classify : value - - group_options[human_name] ||= [] - group_options[human_name] += klass.class_options.values.select do |class_option| - base_options[class_option.name.to_sym].nil? && class_option.group.nil? && - !group_options.values.flatten.any? { |i| i.name == class_option.name } - end - - yield klass if block_given? - end - end - - # Returns commands ready to be printed. - def printable_commands(*) - item = [] - item << banner - item << (desc ? "# #{desc.gsub(/\s+/m, ' ')}" : "") - [item] - end - alias_method :printable_tasks, :printable_commands - - def handle_argument_error(command, error, _args, arity) #:nodoc: - msg = "#{basename} #{command.name} takes #{arity} argument".dup - msg << "s" if arity > 1 - msg << ", but it should not." - raise error, msg - end - - protected - - # The method responsible for dispatching given the args. - def dispatch(command, given_args, given_opts, config) #:nodoc: - if Bundler::Thor::HELP_MAPPINGS.include?(given_args.first) - help(config[:shell]) - return - end - - args, opts = Bundler::Thor::Options.split(given_args) - opts = given_opts || opts - - instance = new(args, opts, config) - yield instance if block_given? - - if command - instance.invoke_command(all_commands[command]) - else - instance.invoke_all - end - end - - # The banner for this class. You can customize it if you are invoking the - # thor class by another ways which is not the Bundler::Thor::Runner. - def banner - "#{basename} #{self_command.formatted_usage(self, false)}" - end - - # Represents the whole class as a command. - def self_command #:nodoc: - Bundler::Thor::DynamicCommand.new(namespace, class_options) - end - alias_method :self_task, :self_command - - def baseclass #:nodoc: - Bundler::Thor::Group - end - - def create_command(meth) #:nodoc: - commands[meth.to_s] = Bundler::Thor::Command.new(meth, nil, nil, nil, nil) - true - end - alias_method :create_task, :create_command - end - - include Bundler::Thor::Base - -protected - - # Shortcut to invoke with padding and block handling. Use internally by - # invoke and invoke_from_option class methods. - def _invoke_for_class_method(klass, command = nil, *args, &block) #:nodoc: - with_padding do - if block - case block.arity - when 3 - yield(self, klass, command) - when 2 - yield(self, klass) - when 1 - instance_exec(klass, &block) - end - else - invoke klass, command, *args - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/invocation.rb b/lib/bundler/vendor/thor/lib/thor/invocation.rb deleted file mode 100644 index 866d2212a7..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/invocation.rb +++ /dev/null @@ -1,177 +0,0 @@ -class Bundler::Thor - module Invocation - def self.included(base) #:nodoc: - base.extend ClassMethods - end - - module ClassMethods - # This method is responsible for receiving a name and find the proper - # class and command for it. The key is an optional parameter which is - # available only in class methods invocations (i.e. in Bundler::Thor::Group). - def prepare_for_invocation(key, name) #:nodoc: - case name - when Symbol, String - Bundler::Thor::Util.find_class_and_command_by_namespace(name.to_s, !key) - else - name - end - end - end - - # Make initializer aware of invocations and the initialization args. - def initialize(args = [], options = {}, config = {}, &block) #:nodoc: - @_invocations = config[:invocations] || Hash.new { |h, k| h[k] = [] } - @_initializer = [args, options, config] - super - end - - # Make the current command chain accessible with in a Bundler::Thor-(sub)command - def current_command_chain - @_invocations.values.flatten.map(&:to_sym) - end - - # Receives a name and invokes it. The name can be a string (either "command" or - # "namespace:command"), a Bundler::Thor::Command, a Class or a Bundler::Thor instance. If the - # command cannot be guessed by name, it can also be supplied as second argument. - # - # You can also supply the arguments, options and configuration values for - # the command to be invoked, if none is given, the same values used to - # initialize the invoker are used to initialize the invoked. - # - # When no name is given, it will invoke the default command of the current class. - # - # ==== Examples - # - # class A < Bundler::Thor - # def foo - # invoke :bar - # invoke "b:hello", ["Erik"] - # end - # - # def bar - # invoke "b:hello", ["Erik"] - # end - # end - # - # class B < Bundler::Thor - # def hello(name) - # puts "hello #{name}" - # end - # end - # - # You can notice that the method "foo" above invokes two commands: "bar", - # which belongs to the same class and "hello" which belongs to the class B. - # - # By using an invocation system you ensure that a command is invoked only once. - # In the example above, invoking "foo" will invoke "b:hello" just once, even - # if it's invoked later by "bar" method. - # - # When class A invokes class B, all arguments used on A initialization are - # supplied to B. This allows lazy parse of options. Let's suppose you have - # some rspec commands: - # - # class Rspec < Bundler::Thor::Group - # class_option :mock_framework, :type => :string, :default => :rr - # - # def invoke_mock_framework - # invoke "rspec:#{options[:mock_framework]}" - # end - # end - # - # As you noticed, it invokes the given mock framework, which might have its - # own options: - # - # class Rspec::RR < Bundler::Thor::Group - # class_option :style, :type => :string, :default => :mock - # end - # - # Since it's not rspec concern to parse mock framework options, when RR - # is invoked all options are parsed again, so RR can extract only the options - # that it's going to use. - # - # If you want Rspec::RR to be initialized with its own set of options, you - # have to do that explicitly: - # - # invoke "rspec:rr", [], :style => :foo - # - # Besides giving an instance, you can also give a class to invoke: - # - # invoke Rspec::RR, [], :style => :foo - # - def invoke(name = nil, *args) - if name.nil? - warn "[Bundler::Thor] Calling invoke() without argument is deprecated. Please use invoke_all instead.\n#{caller.join("\n")}" - return invoke_all - end - - args.unshift(nil) if args.first.is_a?(Array) || args.first.nil? - command, args, opts, config = args - - klass, command = _retrieve_class_and_command(name, command) - raise "Missing Bundler::Thor class for invoke #{name}" unless klass - raise "Expected Bundler::Thor class, got #{klass}" unless klass <= Bundler::Thor::Base - - args, opts, config = _parse_initialization_options(args, opts, config) - klass.send(:dispatch, command, args, opts, config) do |instance| - instance.parent_options = options - end - end - - # Invoke the given command if the given args. - def invoke_command(command, *args) #:nodoc: - current = @_invocations[self.class] - - unless current.include?(command.name) - current << command.name - command.run(self, *args) - end - end - alias_method :invoke_task, :invoke_command - - # Invoke all commands for the current instance. - def invoke_all #:nodoc: - self.class.all_commands.map { |_, command| invoke_command(command) } - end - - # Invokes using shell padding. - def invoke_with_padding(*args) - with_padding { invoke(*args) } - end - - protected - - # Configuration values that are shared between invocations. - def _shared_configuration #:nodoc: - {:invocations => @_invocations} - end - - # This method simply retrieves the class and command to be invoked. - # If the name is nil or the given name is a command in the current class, - # use the given name and return self as class. Otherwise, call - # prepare_for_invocation in the current class. - def _retrieve_class_and_command(name, sent_command = nil) #:nodoc: - if name.nil? - [self.class, nil] - elsif self.class.all_commands[name.to_s] - [self.class, name.to_s] - else - klass, command = self.class.prepare_for_invocation(nil, name) - [klass, command || sent_command] - end - end - alias_method :_retrieve_class_and_task, :_retrieve_class_and_command - - # Initialize klass using values stored in the @_initializer. - def _parse_initialization_options(args, opts, config) #:nodoc: - stored_args, stored_opts, stored_config = @_initializer - - args ||= stored_args.dup - opts ||= stored_opts.dup - - config ||= {} - config = stored_config.merge(_shared_configuration).merge!(config) - - [args, opts, config] - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/line_editor.rb b/lib/bundler/vendor/thor/lib/thor/line_editor.rb deleted file mode 100644 index ce81a17484..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/line_editor.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "bundler/vendor/thor/lib/thor/line_editor/basic" -require "bundler/vendor/thor/lib/thor/line_editor/readline" - -class Bundler::Thor - module LineEditor - def self.readline(prompt, options = {}) - best_available.new(prompt, options).readline - end - - def self.best_available - [ - Bundler::Thor::LineEditor::Readline, - Bundler::Thor::LineEditor::Basic - ].detect(&:available?) - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb b/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb deleted file mode 100644 index 0adb2b3137..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +++ /dev/null @@ -1,37 +0,0 @@ -class Bundler::Thor - module LineEditor - class Basic - attr_reader :prompt, :options - - def self.available? - true - end - - def initialize(prompt, options) - @prompt = prompt - @options = options - end - - def readline - $stdout.print(prompt) - get_input - end - - private - - def get_input - if echo? - $stdin.gets - else - # Lazy-load io/console since it is gem-ified as of 2.3 - require "io/console" if RUBY_VERSION > "1.9.2" - $stdin.noecho(&:gets) - end - end - - def echo? - options.fetch(:echo, true) - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb b/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb deleted file mode 100644 index dd39cff35d..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +++ /dev/null @@ -1,88 +0,0 @@ -begin - require "readline" -rescue LoadError -end - -class Bundler::Thor - module LineEditor - class Readline < Basic - def self.available? - Object.const_defined?(:Readline) - end - - def readline - if echo? - ::Readline.completion_append_character = nil - # Ruby 1.8.7 does not allow Readline.completion_proc= to receive nil. - if complete = completion_proc - ::Readline.completion_proc = complete - end - ::Readline.readline(prompt, add_to_history?) - else - super - end - end - - private - - def add_to_history? - options.fetch(:add_to_history, true) - end - - def completion_proc - if use_path_completion? - proc { |text| PathCompletion.new(text).matches } - elsif completion_options.any? - proc do |text| - completion_options.select { |option| option.start_with?(text) } - end - end - end - - def completion_options - options.fetch(:limited_to, []) - end - - def use_path_completion? - options.fetch(:path, false) - end - - class PathCompletion - attr_reader :text - private :text - - def initialize(text) - @text = text - end - - def matches - relative_matches - end - - private - - def relative_matches - absolute_matches.map { |path| path.sub(base_path, "") } - end - - def absolute_matches - Dir[glob_pattern].map do |path| - if File.directory?(path) - "#{path}/" - else - path - end - end - end - - def glob_pattern - "#{base_path}#{text}*" - end - - def base_path - "#{Dir.pwd}/" - end - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/parser.rb b/lib/bundler/vendor/thor/lib/thor/parser.rb deleted file mode 100644 index 08f80e565d..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/parser.rb +++ /dev/null @@ -1,4 +0,0 @@ -require "bundler/vendor/thor/lib/thor/parser/argument" -require "bundler/vendor/thor/lib/thor/parser/arguments" -require "bundler/vendor/thor/lib/thor/parser/option" -require "bundler/vendor/thor/lib/thor/parser/options" diff --git a/lib/bundler/vendor/thor/lib/thor/parser/argument.rb b/lib/bundler/vendor/thor/lib/thor/parser/argument.rb deleted file mode 100644 index dfe7398583..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +++ /dev/null @@ -1,70 +0,0 @@ -class Bundler::Thor - class Argument #:nodoc: - VALID_TYPES = [:numeric, :hash, :array, :string] - - attr_reader :name, :description, :enum, :required, :type, :default, :banner - alias_method :human_name, :name - - def initialize(name, options = {}) - class_name = self.class.name.split("::").last - - type = options[:type] - - raise ArgumentError, "#{class_name} name can't be nil." if name.nil? - raise ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type) - - @name = name.to_s - @description = options[:desc] - @required = options.key?(:required) ? options[:required] : true - @type = (type || :string).to_sym - @default = options[:default] - @banner = options[:banner] || default_banner - @enum = options[:enum] - - validate! # Trigger specific validations - end - - def usage - required? ? banner : "[#{banner}]" - end - - def required? - required - end - - def show_default? - case default - when Array, String, Hash - !default.empty? - else - default - end - end - - protected - - def validate! - raise ArgumentError, "An argument cannot be required and have default value." if required? && !default.nil? - raise ArgumentError, "An argument cannot have an enum other than an array." if @enum && !@enum.is_a?(Array) - end - - def valid_type?(type) - self.class::VALID_TYPES.include?(type.to_sym) - end - - def default_banner - case type - when :boolean - nil - when :string, :default - human_name.upcase - when :numeric - "N" - when :hash - "key:value" - when :array - "one two three" - 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 deleted file mode 100644 index 1fd790f4b7..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +++ /dev/null @@ -1,175 +0,0 @@ -class Bundler::Thor - class Arguments #:nodoc: # rubocop:disable ClassLength - NUMERIC = /[-+]?(\d*\.\d+|\d+)/ - - # Receives an array of args and returns two arrays, one with arguments - # and one with switches. - # - def self.split(args) - arguments = [] - - args.each do |item| - break if item =~ /^-/ - arguments << item - end - - [arguments, args[Range.new(arguments.size, -1)]] - end - - def self.parse(*args) - to_parse = args.pop - new(*args).parse(to_parse) - end - - # Takes an array of Bundler::Thor::Argument objects. - # - def initialize(arguments = []) - @assigns = {} - @non_assigned_required = [] - @switches = arguments - - arguments.each do |argument| - if !argument.default.nil? - @assigns[argument.human_name] = argument.default - elsif argument.required? - @non_assigned_required << argument - end - end - end - - def parse(args) - @pile = args.dup - - @switches.each do |argument| - break unless peek - @non_assigned_required.delete(argument) - @assigns[argument.human_name] = send(:"parse_#{argument.type}", argument.human_name) - end - - check_requirement! - @assigns - end - - def remaining - @pile - end - - private - - def no_or_skip?(arg) - arg =~ /^--(no|skip)-([-\w]+)$/ - $2 - end - - def last? - @pile.empty? - end - - def peek - @pile.first - end - - def shift - @pile.shift - end - - def unshift(arg) - if arg.is_a?(Array) - @pile = arg + @pile - else - @pile.unshift(arg) - end - end - - def current_is_value? - peek && peek.to_s !~ /^-/ - end - - # Runs through the argument array getting strings that contains ":" and - # mark it as a hash: - # - # [ "name:string", "age:integer" ] - # - # Becomes: - # - # { "name" => "string", "age" => "integer" } - # - def parse_hash(name) - return shift if peek.is_a?(Hash) - hash = {} - - while current_is_value? && peek.include?(":") - key, value = shift.split(":", 2) - raise MalformattedArgumentError, "You can't specify '#{key}' more than once in option '#{name}'; got #{key}:#{hash[key]} and #{key}:#{value}" if hash.include? key - hash[key] = value - end - hash - end - - # Runs through the argument array getting all strings until no string is - # found or a switch is found. - # - # ["a", "b", "c"] - # - # And returns it as an array: - # - # ["a", "b", "c"] - # - def parse_array(name) - return shift if peek.is_a?(Array) - array = [] - array << shift while current_is_value? - array - end - - # Check if the peek is numeric format and return a Float or Integer. - # Check if the peek is included in enum if enum is provided. - # Otherwise raises an error. - # - def parse_numeric(name) - return shift if peek.is_a?(Numeric) - - unless peek =~ NUMERIC && $& == peek - raise MalformattedArgumentError, "Expected numeric value for '#{name}'; got #{peek.inspect}" - end - - value = $&.index(".") ? shift.to_f : shift.to_i - if @switches.is_a?(Hash) && switch = @switches[name] - if switch.enum && !switch.enum.include?(value) - raise MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}" - end - end - value - end - - # Parse string: - # for --string-arg, just return the current value in the pile - # for --no-string-arg, nil - # Check if the peek is included in enum if enum is provided. Otherwise raises an error. - # - def parse_string(name) - if no_or_skip?(name) - nil - else - value = shift - if @switches.is_a?(Hash) && switch = @switches[name] - if switch.enum && !switch.enum.include?(value) - raise MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}" - end - end - value - end - end - - # Raises an error if @non_assigned_required array is not empty. - # - def check_requirement! - return if @non_assigned_required.empty? - names = @non_assigned_required.map do |o| - o.respond_to?(:switch_name) ? o.switch_name : o.human_name - end.join("', '") - class_name = self.class.name.split("::").last.downcase - raise RequiredArgumentMissingError, "No value provided for required #{class_name} '#{names}'" - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/parser/option.rb b/lib/bundler/vendor/thor/lib/thor/parser/option.rb deleted file mode 100644 index 85169b56c8..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/parser/option.rb +++ /dev/null @@ -1,146 +0,0 @@ -class Bundler::Thor - class Option < Argument #:nodoc: - attr_reader :aliases, :group, :lazy_default, :hide - - VALID_TYPES = [:boolean, :numeric, :hash, :array, :string] - - def initialize(name, options = {}) - @check_default_type = options[:check_default_type] - options[:required] = false unless options.key?(:required) - super - @lazy_default = options[:lazy_default] - @group = options[:group].to_s.capitalize if options[:group] - @aliases = Array(options[:aliases]) - @hide = options[:hide] - end - - # This parse quick options given as method_options. It makes several - # assumptions, but you can be more specific using the option method. - # - # parse :foo => "bar" - # #=> Option foo with default value bar - # - # parse [:foo, :baz] => "bar" - # #=> Option foo with default value bar and alias :baz - # - # parse :foo => :required - # #=> Required option foo without default value - # - # parse :foo => 2 - # #=> Option foo with default value 2 and type numeric - # - # parse :foo => :numeric - # #=> Option foo without default value and type numeric - # - # parse :foo => true - # #=> Option foo with default value true and type boolean - # - # The valid types are :boolean, :numeric, :hash, :array and :string. If none - # is given a default type is assumed. This default type accepts arguments as - # string (--foo=value) or booleans (just --foo). - # - # By default all options are optional, unless :required is given. - # - def self.parse(key, value) - if key.is_a?(Array) - name, *aliases = key - else - name = key - aliases = [] - end - - name = name.to_s - default = value - - type = case value - when Symbol - default = nil - if VALID_TYPES.include?(value) - value - elsif required = (value == :required) # rubocop:disable AssignmentInCondition - :string - end - when TrueClass, FalseClass - :boolean - when Numeric - :numeric - when Hash, Array, String - value.class.name.downcase.to_sym - end - - new(name.to_s, :required => required, :type => type, :default => default, :aliases => aliases) - end - - def switch_name - @switch_name ||= dasherized? ? name : dasherize(name) - end - - def human_name - @human_name ||= dasherized? ? undasherize(name) : name - end - - def usage(padding = 0) - sample = if banner && !banner.to_s.empty? - "#{switch_name}=#{banner}".dup - else - switch_name - end - - sample = "[#{sample}]".dup unless required? - - if boolean? - sample << ", [#{dasherize('no-' + human_name)}]" unless (name == "force") || name.start_with?("no-") - end - - if aliases.empty? - (" " * padding) << sample - else - "#{aliases.join(', ')}, #{sample}" - end - end - - VALID_TYPES.each do |type| - class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def #{type}? - self.type == #{type.inspect} - end - RUBY - end - - protected - - def validate! - raise ArgumentError, "An option cannot be boolean and required." if boolean? && required? - validate_default_type! if @check_default_type - end - - def validate_default_type! - default_type = case @default - when nil - return - when TrueClass, FalseClass - required? ? :string : :boolean - when Numeric - :numeric - when Symbol - :string - when Hash, Array, String - @default.class.name.downcase.to_sym - end - - raise ArgumentError, "Expected #{@type} default value for '#{switch_name}'; got #{@default.inspect} (#{default_type})" unless default_type == @type - end - - def dasherized? - name.index("-") == 0 - end - - def undasherize(str) - str.sub(/^-{1,2}/, "") - end - - def dasherize(str) - (str.length > 1 ? "--" : "-") + str.tr("_", "-") - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/parser/options.rb b/lib/bundler/vendor/thor/lib/thor/parser/options.rb deleted file mode 100644 index 70f6366842..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/parser/options.rb +++ /dev/null @@ -1,221 +0,0 @@ -class Bundler::Thor - class Options < Arguments #:nodoc: # rubocop:disable ClassLength - LONG_RE = /^(--\w+(?:-\w+)*)$/ - SHORT_RE = /^(-[a-z])$/i - EQ_RE = /^(--\w+(?:-\w+)*|-[a-z])=(.*)$/i - SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args - SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i - OPTS_END = "--".freeze - - # Receives a hash and makes it switches. - def self.to_switches(options) - options.map do |key, value| - case value - when true - "--#{key}" - when Array - "--#{key} #{value.map(&:inspect).join(' ')}" - when Hash - "--#{key} #{value.map { |k, v| "#{k}:#{v}" }.join(' ')}" - when nil, false - nil - else - "--#{key} #{value.inspect}" - end - end.compact.join(" ") - end - - # Takes a hash of Bundler::Thor::Option and a hash with defaults. - # - # If +stop_on_unknown+ is true, #parse will stop as soon as it encounters - # an unknown option or a regular argument. - def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false, disable_required_check = false) - @stop_on_unknown = stop_on_unknown - @disable_required_check = disable_required_check - options = hash_options.values - super(options) - - # Add defaults - defaults.each do |key, value| - @assigns[key.to_s] = value - @non_assigned_required.delete(hash_options[key]) - end - - @shorts = {} - @switches = {} - @extra = [] - - options.each do |option| - @switches[option.switch_name] = option - - option.aliases.each do |short| - name = short.to_s.sub(/^(?!\-)/, "-") - @shorts[name] ||= option.switch_name - end - end - end - - def remaining - @extra - end - - def peek - return super unless @parsing_options - - result = super - if result == OPTS_END - shift - @parsing_options = false - super - else - result - end - end - - def parse(args) # rubocop:disable MethodLength - @pile = args.dup - @parsing_options = true - - while peek - if parsing_options? - match, is_switch = current_is_switch? - shifted = shift - - if is_switch - case shifted - when SHORT_SQ_RE - unshift($1.split("").map { |f| "-#{f}" }) - next - when EQ_RE, SHORT_NUM - unshift($2) - switch = $1 - when LONG_RE, SHORT_RE - switch = $1 - end - - switch = normalize_switch(switch) - option = switch_option(switch) - @assigns[option.human_name] = parse_peek(switch, option) - elsif @stop_on_unknown - @parsing_options = false - @extra << shifted - @extra << shift while peek - break - elsif match - @extra << shifted - @extra << shift while peek && peek !~ /^-/ - else - @extra << shifted - end - else - @extra << shift - end - end - - check_requirement! unless @disable_required_check - - assigns = Bundler::Thor::CoreExt::HashWithIndifferentAccess.new(@assigns) - assigns.freeze - assigns - end - - def check_unknown! - # 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? - end - - protected - - # Check if the current value in peek is a registered switch. - # - # Two booleans are returned. The first is true if the current value - # starts with a hyphen; the second is true if it is a registered switch. - def current_is_switch? - case peek - when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM - [true, switch?($1)] - when SHORT_SQ_RE - [true, $1.split("").any? { |f| switch?("-#{f}") }] - else - [false, false] - end - end - - def current_is_switch_formatted? - case peek - when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE - true - else - false - end - end - - def current_is_value? - peek && (!parsing_options? || super) - end - - def switch?(arg) - switch_option(normalize_switch(arg)) - end - - def switch_option(arg) - if match = no_or_skip?(arg) # rubocop:disable AssignmentInCondition - @switches[arg] || @switches["--#{match}"] - else - @switches[arg] - end - end - - # Check if the given argument is actually a shortcut. - # - def normalize_switch(arg) - (@shorts[arg] || arg).tr("_", "-") - end - - def parsing_options? - peek - @parsing_options - end - - # Parse boolean values which can be given as --foo=true, --foo or --no-foo. - # - def parse_boolean(switch) - if current_is_value? - if ["true", "TRUE", "t", "T", true].include?(peek) - shift - true - elsif ["false", "FALSE", "f", "F", false].include?(peek) - shift - false - else - !no_or_skip?(switch) - end - else - @switches.key?(switch) || !no_or_skip?(switch) - end - end - - # Parse the value at the peek analyzing if it requires an input or not. - # - def parse_peek(switch, option) - if parsing_options? && (current_is_switch_formatted? || last?) - if option.boolean? - # No problem for boolean types - elsif no_or_skip?(switch) - return nil # User set value to nil - elsif option.string? && !option.required? - # Return the default if there is one, else the human name - return option.lazy_default || option.default || option.human_name - elsif option.lazy_default - return option.lazy_default - else - raise MalformattedArgumentError, "No value provided for option '#{switch}'" - end - end - - @non_assigned_required.delete(option) - send(:"parse_#{option.type}", switch) - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/rake_compat.rb b/lib/bundler/vendor/thor/lib/thor/rake_compat.rb deleted file mode 100644 index 60282e2991..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +++ /dev/null @@ -1,71 +0,0 @@ -require "rake" -require "rake/dsl_definition" - -class Bundler::Thor - # Adds a compatibility layer to your Bundler::Thor classes which allows you to use - # rake package tasks. For example, to use rspec rake tasks, one can do: - # - # require 'bundler/vendor/thor/lib/thor/rake_compat' - # require 'rspec/core/rake_task' - # - # class Default < Bundler::Thor - # include Bundler::Thor::RakeCompat - # - # RSpec::Core::RakeTask.new(:spec) do |t| - # t.spec_opts = ['--options', './.rspec'] - # t.spec_files = FileList['spec/**/*_spec.rb'] - # end - # end - # - module RakeCompat - include Rake::DSL if defined?(Rake::DSL) - - def self.rake_classes - @rake_classes ||= [] - end - - def self.included(base) - # Hack. Make rakefile point to invoker, so rdoc task is generated properly. - rakefile = File.basename(caller[0].match(/(.*):\d+/)[1]) - Rake.application.instance_variable_set(:@rakefile, rakefile) - rake_classes << base - end - end -end - -# override task on (main), for compatibility with Rake 0.9 -instance_eval do - alias rake_namespace namespace - - def task(*) - task = super - - if klass = Bundler::Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition - non_namespaced_name = task.name.split(":").last - - description = non_namespaced_name - description << task.arg_names.map { |n| n.to_s.upcase }.join(" ") - description.strip! - - klass.desc description, Rake.application.last_description || non_namespaced_name - Rake.application.last_description = nil - klass.send :define_method, non_namespaced_name do |*args| - Rake::Task[task.name.to_sym].invoke(*args) - end - end - - task - end - - def namespace(name) - if klass = Bundler::Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition - const_name = Bundler::Thor::Util.camel_case(name.to_s).to_sym - klass.const_set(const_name, Class.new(Bundler::Thor)) - new_klass = klass.const_get(const_name) - Bundler::Thor::RakeCompat.rake_classes << new_klass - end - - super - Bundler::Thor::RakeCompat.rake_classes.pop - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/runner.rb b/lib/bundler/vendor/thor/lib/thor/runner.rb deleted file mode 100644 index b110b8d478..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/runner.rb +++ /dev/null @@ -1,324 +0,0 @@ -require "bundler/vendor/thor/lib/thor" -require "bundler/vendor/thor/lib/thor/group" -require "bundler/vendor/thor/lib/thor/core_ext/io_binary_read" - -require "yaml" -require "digest" -require "pathname" - -class Bundler::Thor::Runner < Bundler::Thor #:nodoc: # rubocop:disable ClassLength - map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version - - def self.banner(command, all = false, subcommand = false) - "thor " + command.formatted_usage(self, all, subcommand) - end - - def self.exit_on_failure? - true - end - - # Override Bundler::Thor#help so it can give information about any class and any method. - # - def help(meth = nil) - if meth && !respond_to?(meth) - initialize_thorfiles(meth) - klass, command = Bundler::Thor::Util.find_class_and_command_by_namespace(meth) - self.class.handle_no_command_error(command, false) if klass.nil? - klass.start(["-h", command].compact, :shell => shell) - else - super - end - end - - # If a command is not found on Bundler::Thor::Runner, method missing is invoked and - # Bundler::Thor::Runner is then responsible for finding the command in all classes. - # - def method_missing(meth, *args) - meth = meth.to_s - initialize_thorfiles(meth) - klass, command = Bundler::Thor::Util.find_class_and_command_by_namespace(meth) - self.class.handle_no_command_error(command, false) if klass.nil? - args.unshift(command) if command - klass.start(args, :shell => shell) - end - - desc "install NAME", "Install an optionally named Bundler::Thor file into your system commands" - method_options :as => :string, :relative => :boolean, :force => :boolean - def install(name) # rubocop:disable MethodLength - initialize_thorfiles - - # If a directory name is provided as the argument, look for a 'main.thor' - # command in said directory. - begin - if File.directory?(File.expand_path(name)) - base = File.join(name, "main.thor") - package = :directory - contents = open(base, &:read) - else - base = name - package = :file - contents = open(name, &:read) - end - rescue OpenURI::HTTPError - raise Error, "Error opening URI '#{name}'" - rescue Errno::ENOENT - raise Error, "Error opening file '#{name}'" - end - - say "Your Bundler::Thorfile contains:" - say contents - - unless options["force"] - return false if no?("Do you wish to continue [y/N]?") - end - - as = options["as"] || begin - first_line = contents.split("\n")[0] - (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil - end - - unless as - basename = File.basename(name) - as = ask("Please specify a name for #{name} in the system repository [#{basename}]:") - as = basename if as.empty? - end - - location = if options[:relative] || name =~ %r{^https?://} - name - else - File.expand_path(name) - end - - thor_yaml[as] = { - :filename => Digest(:MD5).hexdigest(name + as), - :location => location, - :namespaces => Bundler::Thor::Util.namespaces_in_content(contents, base) - } - - save_yaml(thor_yaml) - say "Storing thor file in your system repository" - destination = File.join(thor_root, thor_yaml[as][:filename]) - - if package == :file - File.open(destination, "w") { |f| f.puts contents } - else - require "fileutils" - FileUtils.cp_r(name, destination) - end - - thor_yaml[as][:filename] # Indicate success - end - - desc "version", "Show Bundler::Thor version" - def version - require "bundler/vendor/thor/lib/thor/version" - say "Bundler::Thor #{Bundler::Thor::VERSION}" - end - - desc "uninstall NAME", "Uninstall a named Bundler::Thor module" - def uninstall(name) - raise Error, "Can't find module '#{name}'" unless thor_yaml[name] - say "Uninstalling #{name}." - require "fileutils" - FileUtils.rm_rf(File.join(thor_root, (thor_yaml[name][:filename]).to_s)) - - thor_yaml.delete(name) - save_yaml(thor_yaml) - - puts "Done." - end - - desc "update NAME", "Update a Bundler::Thor file from its original location" - def update(name) - raise Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location] - - say "Updating '#{name}' from #{thor_yaml[name][:location]}" - - old_filename = thor_yaml[name][:filename] - self.options = options.merge("as" => name) - - if File.directory? File.expand_path(name) - require "fileutils" - FileUtils.rm_rf(File.join(thor_root, old_filename)) - - thor_yaml.delete(old_filename) - save_yaml(thor_yaml) - - filename = install(name) - else - filename = install(thor_yaml[name][:location]) - end - - File.delete(File.join(thor_root, old_filename)) unless filename == old_filename - end - - desc "installed", "List the installed Bundler::Thor modules and commands" - method_options :internal => :boolean - def installed - initialize_thorfiles(nil, true) - display_klasses(true, options["internal"]) - end - - desc "list [SEARCH]", "List the available thor commands (--substring means .*SEARCH)" - method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean - def list(search = "") - initialize_thorfiles - - search = ".*#{search}" if options["substring"] - search = /^#{search}.*/i - group = options[:group] || "standard" - - klasses = Bundler::Thor::Base.subclasses.select do |k| - (options[:all] || k.group == group) && k.namespace =~ search - end - - display_klasses(false, false, klasses) - end - -private - - def thor_root - Bundler::Thor::Util.thor_root - end - - def thor_yaml - @thor_yaml ||= begin - yaml_file = File.join(thor_root, "thor.yml") - yaml = YAML.load_file(yaml_file) if File.exist?(yaml_file) - yaml || {} - end - end - - # Save the yaml file. If none exists in thor root, creates one. - # - def save_yaml(yaml) - yaml_file = File.join(thor_root, "thor.yml") - - unless File.exist?(yaml_file) - require "fileutils" - FileUtils.mkdir_p(thor_root) - yaml_file = File.join(thor_root, "thor.yml") - FileUtils.touch(yaml_file) - end - - 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 - # in the thor_root instead of loading them all. - # - # By default, it also traverses the current path until find Bundler::Thor files, as - # described in thorfiles. This look up can be skipped by supplying - # skip_lookup true. - # - def initialize_thorfiles(relevant_to = nil, skip_lookup = false) - thorfiles(relevant_to, skip_lookup).each do |f| - Bundler::Thor::Util.load_thorfile(f, nil, options[:debug]) unless Bundler::Thor::Base.subclass_files.keys.include?(File.expand_path(f)) - end - end - - # Finds Bundler::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. - # - # ==== Example - # - # If we start at /Users/wycats/dev/thor ... - # - # 1. /Users/wycats/dev/thor - # 2. /Users/wycats/dev - # 3. /Users/wycats <-- we find a Bundler::Thorfile here, so we stop - # - # Suppose we start at c:\Documents and Settings\james\dev\thor ... - # - # 1. c:\Documents and Settings\james\dev\thor - # 2. c:\Documents and Settings\james\dev - # 3. c:\Documents and Settings\james - # 4. c:\Documents and Settings - # 5. c:\ <-- no Bundler::Thorfiles found! - # - def thorfiles(relevant_to = nil, skip_lookup = false) - thorfiles = [] - - unless skip_lookup - Pathname.pwd.ascend do |path| - thorfiles = Bundler::Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten - break unless thorfiles.empty? - end - end - - files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Bundler::Thor::Util.thor_root_glob) - files += thorfiles - files -= ["#{thor_root}/thor.yml"] - - files.map! do |file| - File.directory?(file) ? File.join(file, "main.thor") : file - end - end - - # Load Bundler::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. - # - def thorfiles_relevant_to(meth) - lookup = [meth, meth.split(":")[0...-1].join(":")] - - files = thor_yaml.select do |_, v| - v[:namespaces] && !(v[:namespaces] & lookup).empty? - end - - files.map { |_, v| File.join(thor_root, (v[:filename]).to_s) } - end - - # Display information about the given klasses. If with_module is given, - # it shows a table with information extracted from the yaml file. - # - def display_klasses(with_modules = false, show_internal = false, klasses = Bundler::Thor::Base.subclasses) - klasses -= [Bundler::Thor, Bundler::Thor::Runner, Bundler::Thor::Group] unless show_internal - - raise Error, "No Bundler::Thor commands available" if klasses.empty? - show_modules if with_modules && !thor_yaml.empty? - - list = Hash.new { |h, k| h[k] = [] } - groups = klasses.select { |k| k.ancestors.include?(Bundler::Thor::Group) } - - # Get classes which inherit from Bundler::Thor - (klasses - groups).each { |k| list[k.namespace.split(":").first] += k.printable_commands(false) } - - # Get classes which inherit from Bundler::Thor::Base - groups.map! { |k| k.printable_commands(false).first } - list["root"] = groups - - # Order namespaces with default coming first - list = list.sort { |a, b| a[0].sub(/^default/, "") <=> b[0].sub(/^default/, "") } - list.each { |n, commands| display_commands(n, commands) unless commands.empty? } - end - - def display_commands(namespace, list) #:nodoc: - list.sort! { |a, b| a[0] <=> b[0] } - - say shell.set_color(namespace, :blue, true) - say "-" * namespace.size - - print_table(list, :truncate => true) - say - end - alias_method :display_tasks, :display_commands - - def show_modules #:nodoc: - info = [] - labels = %w(Modules Namespaces) - - info << labels - info << ["-" * labels[0].size, "-" * labels[1].size] - - thor_yaml.each do |name, hash| - info << [name, hash[:namespaces].join(", ")] - end - - print_table info - say "" - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/shell.rb b/lib/bundler/vendor/thor/lib/thor/shell.rb deleted file mode 100644 index e945549324..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/shell.rb +++ /dev/null @@ -1,81 +0,0 @@ -require "rbconfig" - -class Bundler::Thor - module Base - class << self - attr_writer :shell - - # Returns the shell used in all Bundler::Thor classes. If you are in a Unix platform - # it will use a colored log, otherwise it will use a basic one without color. - # - def shell - @shell ||= if ENV["THOR_SHELL"] && !ENV["THOR_SHELL"].empty? - Bundler::Thor::Shell.const_get(ENV["THOR_SHELL"]) - elsif RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ && !ENV["ANSICON"] - Bundler::Thor::Shell::Basic - else - Bundler::Thor::Shell::Color - end - end - end - end - - module Shell - SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width] - attr_writer :shell - - autoload :Basic, "bundler/vendor/thor/lib/thor/shell/basic" - autoload :Color, "bundler/vendor/thor/lib/thor/shell/color" - autoload :HTML, "bundler/vendor/thor/lib/thor/shell/html" - - # Add shell to initialize config values. - # - # ==== Configuration - # shell<Object>:: An instance of the shell to be used. - # - # ==== Examples - # - # class MyScript < Bundler::Thor - # argument :first, :type => :numeric - # end - # - # MyScript.new [1.0], { :foo => :bar }, :shell => Bundler::Thor::Shell::Basic.new - # - def initialize(args = [], options = {}, config = {}) - super - self.shell = config[:shell] - shell.base ||= self if shell.respond_to?(:base) - end - - # Holds the shell for the given Bundler::Thor instance. If no shell is given, - # it gets a default shell from Bundler::Thor::Base.shell. - def shell - @shell ||= Bundler::Thor::Base.shell.new - end - - # Common methods that are delegated to the shell. - SHELL_DELEGATED_METHODS.each do |method| - module_eval <<-METHOD, __FILE__, __LINE__ - def #{method}(*args,&block) - shell.#{method}(*args,&block) - end - METHOD - end - - # Yields the given block with padding. - def with_padding - shell.padding += 1 - yield - ensure - shell.padding -= 1 - end - - protected - - # Allow shell to be shared between invocations. - # - def _shared_configuration #:nodoc: - super.merge!(:shell => shell) - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb deleted file mode 100644 index 5162390efd..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +++ /dev/null @@ -1,437 +0,0 @@ -class Bundler::Thor - module Shell - class Basic - attr_accessor :base - attr_reader :padding - - # Initialize base, mute and padding to nil. - # - def initialize #:nodoc: - @base = nil - @mute = false - @padding = 0 - @always_force = false - end - - # Mute everything that's inside given block - # - def mute - @mute = true - yield - ensure - @mute = false - end - - # Check if base is muted - # - def mute? - @mute - end - - # Sets the output padding, not allowing less than zero values. - # - def padding=(value) - @padding = [0, value].max - end - - # Sets the output padding while executing a block and resets it. - # - def indent(count = 1) - orig_padding = padding - self.padding = padding + count - yield - self.padding = orig_padding - end - - # Asks something to the user and receives a response. - # - # 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 - # must be given and re-asked the question. - # - # If asking for sensitive information, the :echo option can be set - # to false to mask user input from $stdin. - # - # If the required input is a path, then set the path option to - # true. This will enable tab completion for file paths relative - # to the current working directory on systems that support - # Readline. - # - # ==== Example - # ask("What is your name?") - # - # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"]) - # - # ask("What is your password?", :echo => false) - # - # ask("Where should the file be saved?", :path => true) - # - def ask(statement, *args) - options = args.last.is_a?(Hash) ? args.pop : {} - color = args.first - - if options[:limited_to] - ask_filtered(statement, color, options) - else - ask_simply(statement, color, options) - end - end - - # Say (print) something to the user. If the sentence ends with a whitespace - # or tab character, a new line is not appended (print + flush). Otherwise - # are passed straight to puts (behavior got from Highline). - # - # ==== Example - # say("I know you knew that.") - # - def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/)) - buffer = prepare_message(message, *color) - buffer << "\n" if force_new_line && !message.to_s.end_with?("\n") - - stdout.print(buffer) - stdout.flush - end - - # Say a status with the given color and appends the message. Since this - # method is used frequently by actions, it allows nil or false to be given - # in log_status, avoiding the message from being shown. If a Symbol is - # given in log_status, it's used as the color. - # - def say_status(status, message, log_status = true) - return if quiet? || log_status == false - spaces = " " * (padding + 1) - color = log_status.is_a?(Symbol) ? log_status : :green - - status = status.to_s.rjust(12) - status = set_color status, color, true if color - - buffer = "#{status}#{spaces}#{message}" - buffer = "#{buffer}\n" unless buffer.end_with?("\n") - - stdout.print(buffer) - stdout.flush - end - - # Make a question the to user and returns true if the user replies "y" or - # "yes". - # - def yes?(statement, color = nil) - !!(ask(statement, color, :add_to_history => false) =~ is?(:yes)) - end - - # Make a question the to user and returns true if the user replies "n" or - # "no". - # - def no?(statement, color = nil) - !!(ask(statement, color, :add_to_history => false) =~ is?(:no)) - end - - # Prints values in columns - # - # ==== Parameters - # Array[String, String, ...] - # - def print_in_columns(array) - return if array.empty? - colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2 - array.each_with_index do |value, index| - # Don't output trailing spaces when printing the last column - if ((((index + 1) % (terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length - stdout.puts value - else - stdout.printf("%-#{colwidth}s", value) - end - end - end - - # Prints a table. - # - # ==== Parameters - # Array[Array[String, String, ...]] - # - # ==== Options - # indent<Integer>:: Indent the first column by indent value. - # colwidth<Integer>:: Force the first column to colwidth spaces wide. - # - def print_table(array, options = {}) # rubocop:disable MethodLength - return if array.empty? - - formats = [] - indent = options[:indent].to_i - colwidth = options[:colwidth] - options[:truncate] = terminal_width if options[:truncate] == true - - formats << "%-#{colwidth + 2}s".dup if colwidth - start = colwidth ? 1 : 0 - - colcount = array.max { |a, b| a.size <=> b.size }.size - - maximas = [] - - start.upto(colcount - 1) do |index| - maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max - maximas << maxima - formats << if index == colcount - 1 - # Don't output 2 trailing spaces when printing the last column - "%-s".dup - else - "%-#{maxima + 2}s".dup - end - end - - formats[0] = formats[0].insert(0, " " * indent) - formats << "%s" - - array.each do |row| - sentence = "".dup - - row.each_with_index do |column, index| - maxima = maximas[index] - - f = if column.is_a?(Numeric) - if index == row.size - 1 - # Don't output 2 trailing spaces when printing the last column - "%#{maxima}s" - else - "%#{maxima}s " - end - else - formats[index] - end - sentence << f % column.to_s - end - - sentence = truncate(sentence, options[:truncate]) if options[:truncate] - stdout.puts sentence - end - end - - # Prints a long string, word-wrapping the text to the current width of the - # terminal display. Ideal for printing heredocs. - # - # ==== Parameters - # String - # - # ==== Options - # indent<Integer>:: Indent each line of the printed paragraph by indent value. - # - def print_wrapped(message, options = {}) - indent = options[:indent] || 0 - width = terminal_width - indent - 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 - - paras.each do |para| - para.split("\n").each do |line| - stdout.puts line.insert(0, " " * indent) - end - stdout.puts unless para == paras.last - end - end - - # Deals with file collision and returns true if the file should be - # overwritten and false otherwise. If a block is given, it uses the block - # response as the content for the diff. - # - # ==== Parameters - # destination<String>:: the destination file to solve conflicts - # block<Proc>:: an optional block that returns the value to be used in diff - # - def file_collision(destination) - return true if @always_force - options = block_given? ? "[Ynaqdh]" : "[Ynaqh]" - - loop do - answer = ask( - %[Overwrite #{destination}? (enter "h" for help) #{options}], - :add_to_history => false - ) - - case answer - when nil - say "" - return true - when is?(:yes), is?(:force), "" - return true - when is?(:no), is?(:skip) - return false - when is?(:always) - return @always_force = true - when is?(:quit) - say "Aborting..." - raise SystemExit - when is?(:diff) - show_diff(destination, yield) if block_given? - say "Retrying..." - else - say file_collision_help - end - end - end - - # This code was copied from Rake, available under MIT-LICENSE - # Copyright (c) 2003, 2004 Jim Weirich - def terminal_width - result = if ENV["THOR_COLUMNS"] - ENV["THOR_COLUMNS"].to_i - else - unix? ? dynamic_width : 80 - end - result < 10 ? 80 : result - rescue - 80 - end - - # Called if something goes wrong during the execution. This is used by Bundler::Thor - # internally and should not be used inside your scripts. If something went - # wrong, you can always raise an exception. If you raise a Bundler::Thor::Error, it - # will be rescued and wrapped in the method below. - # - def error(statement) - stderr.puts statement - end - - # Apply color to the given string with optional bold. Disabled in the - # Bundler::Thor::Shell::Basic class. - # - def set_color(string, *) #:nodoc: - string - end - - protected - - def prepare_message(message, *color) - spaces = " " * padding - spaces + set_color(message.to_s, *color) - end - - def can_display_colors? - false - end - - def lookup_color(color) - return color unless color.is_a?(Symbol) - self.class.const_get(color.to_s.upcase) - end - - def stdout - $stdout - end - - def stderr - $stderr - end - - def is?(value) #:nodoc: - value = value.to_s - - if value.size == 1 - /\A#{value}\z/i - else - /\A(#{value}|#{value[0, 1]})\z/i - end - end - - def file_collision_help #:nodoc: - <<-HELP - Y - yes, overwrite - n - no, do not overwrite - a - all, overwrite this and all others - q - quit, abort - d - diff, show the differences between the old and the new - h - help, show this help - HELP - end - - def show_diff(destination, content) #:nodoc: - diff_cmd = ENV["THOR_DIFF"] || ENV["RAILS_DIFF"] || "diff -u" - - require "tempfile" - Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp| - temp.write content - temp.rewind - system %(#{diff_cmd} "#{destination}" "#{temp.path}") - end - end - - def quiet? #:nodoc: - mute? || (base && base.options[:quiet]) - end - - # Calculate the dynamic width of the terminal - def dynamic_width - @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) - end - - def dynamic_width_stty - `stty size 2>/dev/null`.split[1].to_i - end - - def dynamic_width_tput - `tput cols 2>/dev/null`.to_i - end - - def unix? - RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i - end - - def truncate(string, width) - as_unicode do - chars = string.chars.to_a - if chars.length <= width - chars.join - else - chars[0, width - 3].join + "..." - end - end - end - - if "".respond_to?(:encode) - def as_unicode - yield - end - else - def as_unicode - old = $KCODE - $KCODE = "U" - yield - ensure - $KCODE = old - end - end - - def ask_simply(statement, color, options) - default = options[:default] - message = [statement, ("(#{default})" if default), nil].uniq.join(" ") - message = prepare_message(message, *color) - result = Bundler::Thor::LineEditor.readline(message, options) - - return unless result - - result = result.strip - - if default && result == "" - default - else - result - end - end - - def ask_filtered(statement, color, options) - answer_set = options[:limited_to] - 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 - say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer - end - correct_answer - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/shell/color.rb b/lib/bundler/vendor/thor/lib/thor/shell/color.rb deleted file mode 100644 index da289cb50c..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/shell/color.rb +++ /dev/null @@ -1,149 +0,0 @@ -require "bundler/vendor/thor/lib/thor/shell/basic" - -class Bundler::Thor - module Shell - # Inherit from Bundler::Thor::Shell::Basic and add set_color behavior. Check - # Bundler::Thor::Shell::Basic to see all available methods. - # - class Color < Basic - # Embed in a String to clear all previous ANSI sequences. - CLEAR = "\e[0m" - # The start of an ANSI bold sequence. - BOLD = "\e[1m" - - # Set the terminal's foreground ANSI color to black. - BLACK = "\e[30m" - # Set the terminal's foreground ANSI color to red. - RED = "\e[31m" - # Set the terminal's foreground ANSI color to green. - GREEN = "\e[32m" - # Set the terminal's foreground ANSI color to yellow. - YELLOW = "\e[33m" - # Set the terminal's foreground ANSI color to blue. - BLUE = "\e[34m" - # Set the terminal's foreground ANSI color to magenta. - MAGENTA = "\e[35m" - # Set the terminal's foreground ANSI color to cyan. - CYAN = "\e[36m" - # Set the terminal's foreground ANSI color to white. - WHITE = "\e[37m" - - # Set the terminal's background ANSI color to black. - ON_BLACK = "\e[40m" - # Set the terminal's background ANSI color to red. - ON_RED = "\e[41m" - # Set the terminal's background ANSI color to green. - ON_GREEN = "\e[42m" - # Set the terminal's background ANSI color to yellow. - ON_YELLOW = "\e[43m" - # Set the terminal's background ANSI color to blue. - ON_BLUE = "\e[44m" - # Set the terminal's background ANSI color to magenta. - ON_MAGENTA = "\e[45m" - # Set the terminal's background ANSI color to cyan. - ON_CYAN = "\e[46m" - # Set the terminal's background ANSI color to white. - ON_WHITE = "\e[47m" - - # Set color by using a string or one of the defined constants. If a third - # option is set to true, it also adds bold to the string. This is based - # on Highline implementation and it automatically appends CLEAR to the end - # of the returned String. - # - # Pass foreground, background and bold options to this method as - # symbols. - # - # Example: - # - # set_color "Hi!", :red, :on_white, :bold - # - # The available colors are: - # - # :bold - # :black - # :red - # :green - # :yellow - # :blue - # :magenta - # :cyan - # :white - # :on_black - # :on_red - # :on_green - # :on_yellow - # :on_blue - # :on_magenta - # :on_cyan - # :on_white - def set_color(string, *colors) - if colors.compact.empty? || !can_display_colors? - string - elsif colors.all? { |color| color.is_a?(Symbol) || color.is_a?(String) } - ansi_colors = colors.map { |color| lookup_color(color) } - "#{ansi_colors.join}#{string}#{CLEAR}" - else - # The old API was `set_color(color, bold=boolean)`. We - # continue to support the old API because you should never - # break old APIs unnecessarily :P - foreground, bold = colors - foreground = self.class.const_get(foreground.to_s.upcase) if foreground.is_a?(Symbol) - - bold = bold ? BOLD : "" - "#{bold}#{foreground}#{string}#{CLEAR}" - end - end - - protected - - def can_display_colors? - stdout.tty? - end - - # Overwrite show_diff to show diff with colors if Diff::LCS is - # available. - # - def show_diff(destination, content) #:nodoc: - if diff_lcs_loaded? && ENV["THOR_DIFF"].nil? && ENV["RAILS_DIFF"].nil? - actual = File.binread(destination).to_s.split("\n") - content = content.to_s.split("\n") - - Diff::LCS.sdiff(actual, content).each do |diff| - output_diff_line(diff) - end - else - super - end - end - - def output_diff_line(diff) #:nodoc: - case diff.action - when "-" - say "- #{diff.old_element.chomp}", :red, true - when "+" - say "+ #{diff.new_element.chomp}", :green, true - when "!" - say "- #{diff.old_element.chomp}", :red, true - say "+ #{diff.new_element.chomp}", :green, true - else - say " #{diff.old_element.chomp}", nil, true - end - end - - # Check if Diff::LCS is loaded. If it is, use it to create pretty output - # for diff. - # - def diff_lcs_loaded? #:nodoc: - return true if defined?(Diff::LCS) - return @diff_lcs_loaded unless @diff_lcs_loaded.nil? - - @diff_lcs_loaded = begin - require "diff/lcs" - true - rescue LoadError - false - end - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/shell/html.rb b/lib/bundler/vendor/thor/lib/thor/shell/html.rb deleted file mode 100644 index 83d2054988..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/shell/html.rb +++ /dev/null @@ -1,126 +0,0 @@ -require "bundler/vendor/thor/lib/thor/shell/basic" - -class Bundler::Thor - module Shell - # Inherit from Bundler::Thor::Shell::Basic and add set_color behavior. Check - # Bundler::Thor::Shell::Basic to see all available methods. - # - class HTML < Basic - # The start of an HTML bold sequence. - BOLD = "font-weight: bold" - - # Set the terminal's foreground HTML color to black. - BLACK = "color: black" - # Set the terminal's foreground HTML color to red. - RED = "color: red" - # Set the terminal's foreground HTML color to green. - GREEN = "color: green" - # Set the terminal's foreground HTML color to yellow. - YELLOW = "color: yellow" - # Set the terminal's foreground HTML color to blue. - BLUE = "color: blue" - # Set the terminal's foreground HTML color to magenta. - MAGENTA = "color: magenta" - # Set the terminal's foreground HTML color to cyan. - CYAN = "color: cyan" - # Set the terminal's foreground HTML color to white. - WHITE = "color: white" - - # Set the terminal's background HTML color to black. - ON_BLACK = "background-color: black" - # Set the terminal's background HTML color to red. - ON_RED = "background-color: red" - # Set the terminal's background HTML color to green. - ON_GREEN = "background-color: green" - # Set the terminal's background HTML color to yellow. - ON_YELLOW = "background-color: yellow" - # Set the terminal's background HTML color to blue. - ON_BLUE = "background-color: blue" - # Set the terminal's background HTML color to magenta. - ON_MAGENTA = "background-color: magenta" - # Set the terminal's background HTML color to cyan. - ON_CYAN = "background-color: cyan" - # Set the terminal's background HTML color to white. - ON_WHITE = "background-color: white" - - # Set color by using a string or one of the defined constants. If a third - # option is set to true, it also adds bold to the string. This is based - # on Highline implementation and it automatically appends CLEAR to the end - # of the returned String. - # - 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) } - "<span style=\"#{html_colors.join('; ')};\">#{string}</span>" - 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 - "<span style=\"#{styles.join('; ')};\">#{string}</span>" - end - end - - # Ask something to the user and receives a response. - # - # ==== Example - # ask("What is your name?") - # - # TODO: Implement #ask for Bundler::Thor::Shell::HTML - def ask(statement, color = nil) - raise NotImplementedError, "Implement #ask for Bundler::Thor::Shell::HTML" - end - - protected - - def can_display_colors? - true - end - - # Overwrite show_diff to show diff with colors if Diff::LCS is - # available. - # - def show_diff(destination, content) #:nodoc: - if diff_lcs_loaded? && ENV["THOR_DIFF"].nil? && ENV["RAILS_DIFF"].nil? - actual = File.binread(destination).to_s.split("\n") - content = content.to_s.split("\n") - - Diff::LCS.sdiff(actual, content).each do |diff| - output_diff_line(diff) - end - else - super - end - end - - def output_diff_line(diff) #:nodoc: - case diff.action - when "-" - say "- #{diff.old_element.chomp}", :red, true - when "+" - say "+ #{diff.new_element.chomp}", :green, true - when "!" - say "- #{diff.old_element.chomp}", :red, true - say "+ #{diff.new_element.chomp}", :green, true - else - say " #{diff.old_element.chomp}", nil, true - end - end - - # Check if Diff::LCS is loaded. If it is, use it to create pretty output - # for diff. - # - def diff_lcs_loaded? #:nodoc: - return true if defined?(Diff::LCS) - return @diff_lcs_loaded unless @diff_lcs_loaded.nil? - - @diff_lcs_loaded = begin - require "diff/lcs" - true - rescue LoadError - false - end - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/util.rb b/lib/bundler/vendor/thor/lib/thor/util.rb deleted file mode 100644 index 5d03177a28..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/util.rb +++ /dev/null @@ -1,268 +0,0 @@ -require "rbconfig" - -class Bundler::Thor - module Sandbox #:nodoc: - end - - # This module holds several utilities: - # - # 1) Methods to convert thor namespaces to constants and vice-versa. - # - # Bundler::Thor::Util.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz" - # - # 2) Loading thor files and sandboxing: - # - # Bundler::Thor::Util.load_thorfile("~/.thor/foo") - # - module Util - class << self - # Receives a namespace and search for it in the Bundler::Thor::Base subclasses. - # - # ==== Parameters - # namespace<String>:: The namespace to search for. - # - def find_by_namespace(namespace) - namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/ - Bundler::Thor::Base.subclasses.detect { |klass| klass.namespace == namespace } - 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 - # removing the sandbox namespace. - # - # This method should not be used in general because it's used to deal with - # older versions of Bundler::Thor. On current versions, if you need to get the - # namespace from a class, just call namespace on it. - # - # ==== Parameters - # constant<Object>:: The constant to be converted to the thor path. - # - # ==== Returns - # String:: If we receive Foo::Bar::Baz it returns "foo:bar:baz" - # - def namespace_from_thor_class(constant) - constant = constant.to_s.gsub(/^Bundler::Thor::Sandbox::/, "") - constant = snake_case(constant).squeeze(":") - constant - end - - # Given the contents, evaluate it inside the sandbox and returns the - # namespaces defined in the sandbox. - # - # ==== Parameters - # contents<String> - # - # ==== Returns - # Array[Object] - # - def namespaces_in_content(contents, file = __FILE__) - old_constants = Bundler::Thor::Base.subclasses.dup - Bundler::Thor::Base.subclasses.clear - - load_thorfile(file, contents) - - new_constants = Bundler::Thor::Base.subclasses.dup - Bundler::Thor::Base.subclasses.replace(old_constants) - - new_constants.map!(&:namespace) - new_constants.compact! - new_constants - end - - # Returns the thor classes declared inside the given class. - # - def thor_classes_in(klass) - stringfied_constants = klass.constants.map(&:to_s) - Bundler::Thor::Base.subclasses.select do |subclass| - next unless subclass.name - stringfied_constants.include?(subclass.name.gsub("#{klass.name}::", "")) - end - end - - # Receives a string and convert it to snake case. SnakeCase returns snake_case. - # - # ==== Parameters - # String - # - # ==== Returns - # String - # - def snake_case(str) - return str.downcase if str =~ /^[A-Z_]+$/ - str.gsub(/\B[A-Z]/, '_\&').squeeze("_") =~ /_*(.*)/ - $+.downcase - end - - # Receives a string and convert it to camel case. camel_case returns CamelCase. - # - # ==== Parameters - # String - # - # ==== Returns - # String - # - def camel_case(str) - return str if str !~ /_/ && str =~ /[A-Z]+.*/ - str.split("_").map(&:capitalize).join - end - - # Receives a namespace and tries to retrieve a Bundler::Thor or Bundler::Thor::Group class - # from it. It first searches for a class using the all the given namespace, - # if it's not found, removes the highest entry and searches for the class - # again. If found, returns the highest entry as the class name. - # - # ==== Examples - # - # class Foo::Bar < Bundler::Thor - # def baz - # end - # end - # - # class Baz::Foo < Bundler::Thor::Group - # end - # - # Bundler::Thor::Util.namespace_to_thor_class("foo:bar") #=> Foo::Bar, nil # will invoke default command - # Bundler::Thor::Util.namespace_to_thor_class("baz:foo") #=> Baz::Foo, nil - # Bundler::Thor::Util.namespace_to_thor_class("foo:bar:baz") #=> Foo::Bar, "baz" - # - # ==== Parameters - # namespace<String> - # - def find_class_and_command_by_namespace(namespace, fallback = true) - if namespace.include?(":") # look for a namespaced command - pieces = namespace.split(":") - command = pieces.pop - klass = Bundler::Thor::Util.find_by_namespace(pieces.join(":")) - end - unless klass # look for a Bundler::Thor::Group with the right name - klass = Bundler::Thor::Util.find_by_namespace(namespace) - command = nil - end - if !klass && fallback # try a command in the default namespace - command = namespace - klass = Bundler::Thor::Util.find_by_namespace("") - end - [klass, command] - end - alias_method :find_class_and_task_by_namespace, :find_class_and_command_by_namespace - - # Receives a path and load the thor file in the path. The file is evaluated - # inside the sandbox to avoid namespacing conflicts. - # - def load_thorfile(path, content = nil, debug = false) - content ||= File.binread(path) - - begin - Bundler::Thor::Sandbox.class_eval(content, path) - rescue StandardError => e - $stderr.puts("WARNING: unable to load thorfile #{path.inspect}: #{e.message}") - if debug - $stderr.puts(*e.backtrace) - else - $stderr.puts(e.backtrace.first) - end - end - end - - def user_home - @@user_home ||= if ENV["HOME"] - ENV["HOME"] - elsif ENV["USERPROFILE"] - ENV["USERPROFILE"] - elsif ENV["HOMEDRIVE"] && ENV["HOMEPATH"] - File.join(ENV["HOMEDRIVE"], ENV["HOMEPATH"]) - elsif ENV["APPDATA"] - ENV["APPDATA"] - else - begin - File.expand_path("~") - rescue - if File::ALT_SEPARATOR - "C:/" - else - "/" - end - end - end - end - - # Returns the root where thor files are located, depending on the OS. - # - def thor_root - File.join(user_home, ".thor").tr('\\', "/") - end - - # Returns the files in the thor root. On Windows thor_root will be something - # like this: - # - # C:\Documents and Settings\james\.thor - # - # If we don't #gsub the \ character, Dir.glob will fail. - # - def thor_root_glob - files = Dir["#{escape_globs(thor_root)}/*"] - - files.map! do |file| - File.directory?(file) ? File.join(file, "main.thor") : file - end - end - - # Where to look for Bundler::Thor files. - # - def globs_for(path) - path = escape_globs(path) - ["#{path}/Bundler::Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"] - end - - # Return the path to the ruby interpreter taking into account multiple - # installations and windows extensions. - # - def ruby_command - @ruby_command ||= begin - ruby_name = RbConfig::CONFIG["ruby_install_name"] - ruby = File.join(RbConfig::CONFIG["bindir"], ruby_name) - ruby << RbConfig::CONFIG["EXEEXT"] - - # avoid using different name than ruby (on platforms supporting links) - if ruby_name != "ruby" && File.respond_to?(:readlink) - begin - alternate_ruby = File.join(RbConfig::CONFIG["bindir"], "ruby") - alternate_ruby << RbConfig::CONFIG["EXEEXT"] - - # ruby is a symlink - if File.symlink? alternate_ruby - linked_ruby = File.readlink alternate_ruby - - # symlink points to 'ruby_install_name' - ruby = alternate_ruby if linked_ruby == ruby_name || linked_ruby == ruby - end - rescue NotImplementedError # rubocop:disable HandleExceptions - # just ignore on windows - end - end - - # escape string in case path to ruby executable contain spaces. - ruby.sub!(/.*\s.*/m, '"\&"') - ruby - end - end - - # Returns a string that has had any glob characters escaped. - # The glob characters are `* ? { } [ ]`. - # - # ==== Examples - # - # Bundler::Thor::Util.escape_globs('[apps]') # => '\[apps\]' - # - # ==== Parameters - # String - # - # ==== Returns - # String - # - def escape_globs(path) - path.to_s.gsub(/[*?{}\[\]]/, '\\\\\\&') - end - end - end -end diff --git a/lib/bundler/vendor/thor/lib/thor/version.rb b/lib/bundler/vendor/thor/lib/thor/version.rb deleted file mode 100644 index df8f18821a..0000000000 --- a/lib/bundler/vendor/thor/lib/thor/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Bundler::Thor - VERSION = "0.20.0" -end |