Class: Gem::Commands::UnpackCommand

Inherits:
Gem::Command show all
Includes:
VersionOption
Defined in:
lib/rubygems/commands/unpack_command.rb

Instance Attribute Summary

Attributes inherited from Gem::Command

#command, #defaults, #options, #program_name, #summary

Instance Method Summary collapse

Methods included from VersionOption

#add_platform_option, #add_prerelease_option, #add_version_option

Methods inherited from Gem::Command

add_common_option, #add_extra_args, #add_option, add_specific_extra_args, #begins?, build_args, build_args=, common_options, #description, extra_args, extra_args=, #get_all_gem_names, #get_all_gem_names_and_versions, #get_one_gem_name, #get_one_optional_argument, #handle_options, #handles?, #invoke, #invoke_with_build_args, #merge_options, #remove_option, #show_help, #show_lookup_failure, specific_extra_args, specific_extra_args_hash, #when_invoked

Methods included from UserInteraction

#alert, #alert_error, #alert_warning, #ask, #ask_for_password, #ask_yes_no, #choose_from_list, #say, #terminate_interaction

Methods included from DefaultUserInteraction

ui, #ui, ui=, #ui=, use_ui, #use_ui

Constructor Details

#initializeUnpackCommand

Returns a new instance of UnpackCommand.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 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

Instance Method Details

#argumentsObject

:nodoc:



29
30
31
# File 'lib/rubygems/commands/unpack_command.rb', line 29

def arguments # :nodoc:
  "GEMNAME       name of gem to unpack"
end

#defaults_strObject

:nodoc:



33
34
35
# File 'lib/rubygems/commands/unpack_command.rb', line 33

def defaults_str # :nodoc:
  "--version '#{Gem::Requirement.default}'"
end

#executeObject

– TODO: allow, e.g., ‘gem unpack rake-0.3.1’. Find a general solution for this, so that it works for uninstall as well. (And check other commands at the same time.)



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rubygems/commands/unpack_command.rb', line 46

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,  =  path

      if .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 
      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) ⇒ Object

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

– TODO: see comments in get_path() about general service.



88
89
90
91
92
93
94
95
# File 'lib/rubygems/commands/unpack_command.rb', line 88

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) ⇒ Object

Extracts the Gem::Specification and raw metadata from the .gem file at path. – TODO move to Gem::Package as #raw_spec or something



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/rubygems/commands/unpack_command.rb', line 142

def  path
  format = Gem::Package.new path
  spec = format.spec

   = 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
         = entry.read
      when 'metadata.gz' then
         = Gem.gunzip entry.read
      end
    end
  end

  return spec, 
end

#get_path(dependency) ⇒ Object

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)

– TODO: This should be refactored so that it’s a general service. I don’t think any of our existing classes are the right place though. Just maybe ‘Cache’?

TODO: It just uses Gem.dir for now. What’s an easy way to get the list of source directories?



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/rubygems/commands/unpack_command.rb', line 114

def get_path dependency
  return dependency.name if dependency.name =~ /\.gem$/i

  specs = dependency.matching_specs

  selected = specs.sort_by { |s| s.version }.last # HACK: hunt last down

  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

#usageObject

:nodoc:



37
38
39
# File 'lib/rubygems/commands/unpack_command.rb', line 37

def usage # :nodoc:
  "#{program_name} GEMNAME"
end