Class: Gem::Commands::UnpackCommand

Inherits:
Gem::Command show all
Includes:
SecurityOption, 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 SecurityOption

#add_security_option

Methods included from VersionOption

#add_platform_option, #add_prerelease_option, #add_version_option, #get_platform_from_requirements

Methods inherited from Gem::Command

add_common_option, #add_extra_args, #add_option, add_specific_extra_args, #begins?, build_args, build_args=, #check_deprecated_options, common_options, #deprecate_option, #deprecated?, extra_args, extra_args=, #extract_gem_name_and_version, #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, #verbose

Methods included from DefaultUserInteraction

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

Methods included from Text

#clean_text, #format_text, #levenshtein_distance, #min3, #truncate_text

Constructor Details

#initializeUnpackCommand

Returns a new instance of UnpackCommand.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/rubygems/commands/unpack_command.rb', line 20

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_security_option
  add_version_option
end

Instance Method Details

#argumentsObject

:nodoc:



40
41
42
# File 'lib/rubygems/commands/unpack_command.rb', line 40

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

#defaults_strObject

:nodoc:



44
45
46
# File 'lib/rubygems/commands/unpack_command.rb', line 44

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

#descriptionObject



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/rubygems/commands/unpack_command.rb', line 48

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

#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.)



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/rubygems/commands/unpack_command.rb', line 75

def execute
  security_policy = options[:security_policy]

  get_all_gem_names.each do |name|
    dependency = Gem::Dependency.new name, options[:version]
    path = get_path dependency

    unless path
      alert_error "Gem '#{name}' not installed nor fetchable."
      next
    end

    if @options[:spec]
      spec,  = Gem::Package.raw_spec(path, security_policy)

      if .nil?
        alert_error "--spec is unsupported on '#{name}' (old format gem)"
        next
      end

      spec_file = File.basename spec.spec_file

      FileUtils.mkdir_p @options[:target] if @options[:target]

      destination = if @options[:target]
        File.join @options[:target], spec_file
      else
        spec_file
      end

      File.open destination, "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, security_policy
      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.



127
128
129
130
131
132
133
134
# File 'lib/rubygems/commands/unpack_command.rb', line 127

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

  nil
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?



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/rubygems/commands/unpack_command.rb', line 153

def get_path(dependency)
  return dependency.name if /\.gem$/i.match?(dependency.name)

  specs = dependency.matching_specs

  selected = specs.max_by(&:version)

  return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless
    selected

  return unless /^#{selected.name}$/i.match?(dependency.name)

  # 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:



66
67
68
# File 'lib/rubygems/commands/unpack_command.rb', line 66

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