Support for the Ruby 2.4 series has ended. See here for reference.
![show/hide quicksearch [+]](../../images/find.png)
 
               # File rubygems/commands/unpack_command.rb, line 11
def initialize
  require 'fileutils'
  super 'unpack', 'Unpack an installed gem to the current directory',
        :version => Gem::Requirement.default,
        :target  => Dir.pwd
  add_option('--target=DIR',
             'target directory for unpacking') do |value, options|
    options[:target] = value
  end
  add_option('--spec', 'unpack the gem specification') do |value, options|
    options[:spec] = true
  end
  add_version_option
end
             
             
               # File rubygems/commands/unpack_command.rb, line 38
  def description
    <<-EOF
The unpack command allows you to examine the contents of a gem or modify
them to help diagnose a bug.
You can add the contents of the unpacked gem to the load path using the
RUBYLIB environment variable or -I:
  $ gem unpack my_gem
  Unpacked gem: '.../my_gem-1.0'
  [edit my_gem-1.0/lib/my_gem.rb]
  $ ruby -Imy_gem-1.0/lib -S other_program
You can repackage an unpacked gem using the build command.  See the build
command help for an example.
    EOF
  end
             
             
               # File rubygems/commands/unpack_command.rb, line 65
def execute
  get_all_gem_names.each do |name|
    dependency = Gem::Dependency.new name, options[:version]
    path = get_path dependency
    unless path then
      alert_error "Gem '#{name}' not installed nor fetchable."
      next
    end
    if @options[:spec] then
      spec, metadata = get_metadata path
      if metadata.nil? then
        alert_error "--spec is unsupported on '#{name}' (old format gem)"
        next
      end
      spec_file = File.basename spec.spec_file
      open spec_file, 'w' do |io|
        io.write metadata
      end
    else
      basename = File.basename path, '.gem'
      target_dir = File.expand_path basename, options[:target]
      package = Gem::Package.new path
      package.extract_files target_dir
      say "Unpacked gem: '#{target_dir}'"
    end
  end
end
             
            Find cached filename in Gem.path. Returns nil if the file cannot be found.
 
               # File rubygems/commands/unpack_command.rb, line 107
def find_in_cache(filename)
  Gem.path.each do |path|
    this_path = File.join(path, "cache", filename)
    return this_path if File.exist? this_path
  end
  return nil
end
             
            Extracts the Gem::Specification and raw metadata from the .gem file at path.
 
               # File rubygems/commands/unpack_command.rb, line 161
def get_metadata path
  format = Gem::Package.new path
  spec = format.spec
  metadata = nil
  open path, Gem.binary_mode do |io|
    tar = Gem::Package::TarReader.new io
    tar.each_entry do |entry|
      case entry.full_name
      when 'metadata' then
        metadata = entry.read
      when 'metadata.gz' then
        metadata = Gem.gunzip entry.read
      end
    end
  end
  return spec, metadata
end
             
            Return the full path to the cached gem file matching the given name and version requirement. Returns 'nil' if no match.
Example:
get_path 'rake', '> 0.4' # "/usr/lib/ruby/gems/1.8/cache/rake-0.4.2.gem" get_path 'rake', '< 0.1' # nil get_path 'rak' # nil (exact name required)
 
               # File rubygems/commands/unpack_command.rb, line 133
def get_path dependency
  return dependency.name if dependency.name =~ /\.gem$/i
  specs = dependency.matching_specs
  selected = specs.max_by { |s| s.version }
  return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless
    selected
  return unless dependency.name =~ /^#{selected.name}$/i
  # We expect to find (basename).gem in the 'cache' directory.  Furthermore,
  # the name match must be exact (ignoring case).
  path = find_in_cache File.basename selected.cache_file
  return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless path
  path
end