# class Gem::Commands::SetupCommand

Installs RubyGems itself. This command is ordinarily only available from a RubyGems checkout or tarball.

### Constants

HISTORY_HEADER
VERSION_MATCHER

### Public Class Methods

new() click to toggle source
Calls superclass method `Gem::Command::new`

    # File lib/rubygems/commands/setup_command.rb, line 12
    def initialize
      require 'tmpdir'

      super 'setup', 'Install RubyGems',
            :format_executable => true, :document => %w[ri],
            :site_or_vendor => 'sitelibdir',
            :destdir => '', :prefix => '', :previous_version => ''

      add_option '--previous-version=VERSION',
                 'Previous version of rubygems',
                 'Used for changelog processing' do |version, options|
        options[:previous_version] = version
      end

      add_option '--prefix=PREFIX',
                 'Prefix path for installing RubyGems',
                 'Will not affect gem repository location' do |prefix, options|
        options[:prefix] = File.expand_path prefix
      end

      add_option '--destdir=DESTDIR',
                 'Root directory to install RubyGems into',
                 'Mainly used for packaging RubyGems' do |destdir, options|
        options[:destdir] = File.expand_path destdir
      end

      add_option '--[no-]vendor',
                 'Install into vendorlibdir not sitelibdir' do |vendor, options|
        options[:site_or_vendor] = vendor ? 'vendorlibdir' : 'sitelibdir'
      end

      add_option '--[no-]format-executable',
                 'Makes `gem` match ruby',
                 'If ruby is ruby18, gem will be gem18' do |value, options|
        options[:format_executable] = value
      end

      add_option '--[no-]document [TYPES]', Array,
                 'Generate documentation for RubyGems',
                 'List the documentation types you wish to',
                 'generate.  For example: rdoc,ri' do |value, options|
        options[:document] = case value
                             when nil   then %w[rdoc ri]
                             when false then []
                             else            value
                             end
      end

      add_option '--[no-]rdoc',
                 'Generate RDoc documentation for RubyGems' do |value, options|
        if value then
          options[:document] << 'rdoc'
        else
          options[:document].delete 'rdoc'
        end

        options[:document].uniq!
      end

      add_option '--[no-]ri',
                 'Generate RI documentation for RubyGems' do |value, options|
        if value then
          options[:document] << 'ri'
        else
          options[:document].delete 'ri'
        end

        options[:document].uniq!
      end

      @verbose = nil
    end

### Public Instance Methods

check_ruby_version() click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 85
    def check_ruby_version
      required_version = Gem::Requirement.new '>= 1.8.7'

      unless required_version.satisfied_by? Gem.ruby_version then
        alert_error "Expected Ruby version #{required_version}, is #{Gem.ruby_version}"
        terminate_interaction 1
      end
    end

execute() click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 116
    def execute
      @verbose = Gem.configuration.really_verbose

      install_destdir = options[:destdir]

      unless install_destdir.empty? then
        ENV['GEM_HOME'] ||= File.join(install_destdir,
                                      Gem.default_dir.gsub(/^[a-zA-Z]:/, ''))
      end

      check_ruby_version

      require 'fileutils'
      if Gem.configuration.really_verbose then
        extend FileUtils::Verbose
      else
        extend FileUtils
      end

      lib_dir, bin_dir = make_destination_dirs install_destdir

      install_lib lib_dir

      install_executables bin_dir

      remove_old_bin_files bin_dir

      remove_old_lib_files lib_dir

      say "RubyGems #{Gem::VERSION} installed"

      uninstall_old_gemcutter

      documentation_success = install_rdoc

      say
      if @verbose then
        say "-" * 78
        say
      end

      if options[:previous_version].empty?
        options[:previous_version] = Gem::VERSION.sub(/[0-9]+$/, '0')
      end

      options[:previous_version] = Gem::Version.new(options[:previous_version])

      show_release_notes

      say
      say "-" * 78
      say

      say "RubyGems installed the following executables:"
      say @bin_file_names.map { |name| "\t#{name}\n" }
      say

      unless @bin_file_names.grep(/#{File::SEPARATOR}gem$/) then
        say "If `gem` was installed by a previous RubyGems installation, you may need"
        say "to remove it by hand."
        say
      end

      if documentation_success
        if options[:document].include? 'rdoc' then
          say "Rdoc documentation was installed. You may now invoke:"
          say "  gem server"
          say "and then peruse beautifully formatted documentation for your gems"
          say "with your web browser."
          say "If you do not wish to install this documentation in the future, use the"
          say "--no-document flag, or set it as the default in your ~/.gemrc file. See"
          say "'gem help env' for details."
          say
        end

        if options[:document].include? 'ri' then
          say "Ruby Interactive (ri) documentation was installed. ri is kind of like man "
          say "pages for ruby libraries. You may access it like this:"
          say "  ri Classname"
          say "  ri Classname.class_method"
          say "  ri Classname#instance_method"
          say "If you do not wish to install this documentation in the future, use the"
          say "--no-document flag, or set it as the default in your ~/.gemrc file. See"
          say "'gem help env' for details."
          say
        end
      end
    end

generate_default_dirs(install_destdir) click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 342
    def generate_default_dirs(install_destdir)
      prefix = options[:prefix]
      site_or_vendor = options[:site_or_vendor]

      if prefix.empty? then
        lib_dir = RbConfig::CONFIG[site_or_vendor]
        bin_dir = RbConfig::CONFIG['bindir']
      else
        # Apple installed RubyGems into libdir, and RubyGems <= 1.1.0 gets
        # confused about installation location, so switch back to
        # sitelibdir/vendorlibdir.
        if defined?(APPLE_GEM_HOME) and
          # just in case Apple and RubyGems don't get this patched up proper.
          (prefix == RbConfig::CONFIG['libdir'] or
           # this one is important
           prefix == File.join(RbConfig::CONFIG['libdir'], 'ruby')) then
           lib_dir = RbConfig::CONFIG[site_or_vendor]
           bin_dir = RbConfig::CONFIG['bindir']
        else
          lib_dir = File.join prefix, 'lib'
          bin_dir = File.join prefix, 'bin'
        end
      end

      unless install_destdir.empty? then
        lib_dir = File.join install_destdir, lib_dir.gsub(/^[a-zA-Z]:/, '')
        bin_dir = File.join install_destdir, bin_dir.gsub(/^[a-zA-Z]:/, '')
      end

      [lib_dir, bin_dir]
    end

install_executables(bin_dir) click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 205
      def install_executables(bin_dir)
        say "Installing gem executable" if @verbose

        @bin_file_names = []

        Dir.chdir 'bin' do
          bin_files = Dir['*']

          bin_files.delete 'update_rubygems'

          bin_files.each do |bin_file|
            bin_file_formatted = if options[:format_executable] then
                                   Gem.default_exec_format % bin_file
                                 else
                                   bin_file
                                 end

            dest_file = File.join bin_dir, bin_file_formatted
            bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}"

            begin
              bin = File.readlines bin_file
              bin[0] = "#!#{Gem.ruby}\n"

              File.open bin_tmp_file, 'w' do |fp|
                fp.puts bin.join
              end

              install bin_tmp_file, dest_file, :mode => 0755
              @bin_file_names << dest_file
            ensure
              rm bin_tmp_file
            end

            next unless Gem.win_platform?

            begin
              bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat"

              File.open bin_cmd_file, 'w' do |file|
                file.puts <<-TEXT
    @ECHO OFF
    IF NOT "%~f0" == "~f0" GOTO :WinNT
    @"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9
    GOTO :EOF
    :WinNT
    @"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
    TEXT
              end

              install bin_cmd_file, "#{dest_file}.bat", :mode => 0755
            ensure
              rm bin_cmd_file
            end
          end
        end
      end

install_file(file, dest_dir) click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 263
    def install_file file, dest_dir
      dest_file = File.join dest_dir, file
      dest_dir = File.dirname dest_file
      mkdir_p dest_dir unless File.directory? dest_dir

      install file, dest_file, :mode => 0644
    end

install_lib(lib_dir) click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 271
    def install_lib(lib_dir)
      say "Installing RubyGems" if @verbose

      lib_files = rb_files_in 'lib'
      pem_files = pem_files_in 'lib'

      Dir.chdir 'lib' do
        lib_files.each do |lib_file|
          install_file lib_file, lib_dir
        end

        pem_files.each do |pem_file|
          install_file pem_file, lib_dir
        end
      end
    end

install_rdoc() click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 288
    def install_rdoc
      gem_doc_dir = File.join Gem.dir, 'doc'
      rubygems_name = "rubygems-#{Gem::VERSION}"
      rubygems_doc_dir = File.join gem_doc_dir, rubygems_name

      begin
        Gem.ensure_gem_subdirectories Gem.dir
      rescue SystemCallError
        # ignore
      end

      if File.writable? gem_doc_dir and
         (not File.exist? rubygems_doc_dir or
          File.writable? rubygems_doc_dir) then
        say "Removing old RubyGems RDoc and ri" if @verbose
        Dir[File.join(Gem.dir, 'doc', 'rubygems-[0-9]*')].each do |dir|
          rm_rf dir
        end

        require 'rubygems/rdoc'

        fake_spec = Gem::Specification.new 'rubygems', Gem::VERSION
        def fake_spec.full_gem_path
          File.expand_path '../../../..', __FILE__
        end

        generate_ri   = options[:document].include? 'ri'
        generate_rdoc = options[:document].include? 'rdoc'

        rdoc = Gem::RDoc.new fake_spec, generate_rdoc, generate_ri
        rdoc.generate

        return true
      elsif @verbose then
        say "Skipping RDoc generation, #{gem_doc_dir} not writable"
        say "Set the GEM_HOME environment variable if you want RDoc generated"
      end

      return false
    end

make_destination_dirs(install_destdir) click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 329
    def make_destination_dirs(install_destdir)
      lib_dir, bin_dir = Gem.default_rubygems_dirs

      unless lib_dir
        lib_dir, bin_dir = generate_default_dirs(install_destdir)
      end

      mkdir_p lib_dir
      mkdir_p bin_dir

      return lib_dir, bin_dir
    end

pem_files_in(dir) click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 374
    def pem_files_in dir
      Dir.chdir dir do
        Dir[File.join('**', '*pem')]
      end
    end

rb_files_in(dir) click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 380
    def rb_files_in dir
      Dir.chdir dir do
        Dir[File.join('**', '*rb')]
      end
    end

remove_old_bin_files(bin_dir) click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 386
      def remove_old_bin_files(bin_dir)
        old_bin_files = {
          'gem_mirror' => 'gem mirror',
          'gem_server' => 'gem server',
          'gemlock' => 'gem lock',
          'gemri' => 'ri',
          'gemwhich' => 'gem which',
          'index_gem_repository.rb' => 'gem generate_index',
        }

        old_bin_files.each do |old_bin_file, new_name|
          old_bin_path = File.join bin_dir, old_bin_file
          next unless File.exist? old_bin_path

          deprecation_message = "`#{old_bin_file}` has been deprecated.  Use `#{new_name}` instead."

          File.open old_bin_path, 'w' do |fp|
            fp.write <<-EOF
    #!#{Gem.ruby}

    abort "#{deprecation_message}"
        EOF
          end

          next unless Gem.win_platform?

          File.open "#{old_bin_path}.bat", 'w' do |fp|
            fp.puts %{@ECHO.#{deprecation_message}}
          end
        end
      end

remove_old_lib_files(lib_dir) click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 418
    def remove_old_lib_files lib_dir
      rubygems_dir = File.join lib_dir, 'rubygems'
      lib_files = rb_files_in 'lib/rubygems'

      old_lib_files = rb_files_in rubygems_dir

      to_remove = old_lib_files - lib_files

      to_remove.delete_if do |file|
        file.start_with? 'defaults'
      end

      Dir.chdir rubygems_dir do
        to_remove.each do |file|
          FileUtils.rm_f file

          warn "unable to remove old file #{file} please remove it by hand" if
            File.exist? file
        end
      end
    end

show_release_notes() click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 440
      def show_release_notes
        release_notes = File.join Dir.pwd, 'History.txt'

        release_notes =
          if File.exist? release_notes then
            history = File.read release_notes

            history.force_encoding Encoding::UTF_8 if
              Object.const_defined? :Encoding

            history = history.sub(/^# coding:.*?(?=^=)/m, '')

            text = history.split(HISTORY_HEADER)
            text.shift # correct an off-by-one generated by split
            version_lines = history.scan(HISTORY_HEADER)
            versions = history.scan(VERSION_MATCHER).flatten.map do |x|
              Gem::Version.new(x)
            end

            history_string = ""

            until versions.length == 0 or
                  versions.shift < options[:previous_version] do
              history_string += version_lines.shift + text.shift
            end

            history_string
          else
            "Oh-no! Unable to find release notes!"
          end

        say release_notes
      end

      def uninstall_old_gemcutter
        require 'rubygems/uninstaller'

        ui = Gem::Uninstaller.new('gemcutter', :all => true, :ignore => true,
                                  :version => '< 0.4')
        ui.uninstall
      rescue Gem::InstallError
      end

    end

uninstall_old_gemcutter() click to toggle source

    # File lib/rubygems/commands/setup_command.rb, line 474
    def uninstall_old_gemcutter
      require 'rubygems/uninstaller'

      ui = Gem::Uninstaller.new('gemcutter', :all => true, :ignore => true,
                                :version => '< 0.4')
      ui.uninstall
    rescue Gem::InstallError
    end