class Gem::Commands::UnpackCommand

Public Class Methods

new() click to toggle source
Calls superclass method Gem::Command.new
# File lib/rubygems/commands/unpack_command.rb, line 10
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

Public Instance Methods

description() click to toggle source
# File lib/rubygems/commands/unpack_command.rb, line 37
 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
execute() click to toggle source
# File lib/rubygems/commands/unpack_command.rb, line 64
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_in_cache(filename) click to toggle source

Find cached filename in Gem.path. Returns nil if the file cannot be found.

# File lib/rubygems/commands/unpack_command.rb, line 106
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
get_metadata(path) click to toggle source

Extracts the Gem::Specification and raw metadata from the .gem file at path.

# File lib/rubygems/commands/unpack_command.rb, line 160
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
get_path(dependency) click to toggle source

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 lib/rubygems/commands/unpack_command.rb, line 132
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