1require 'English'
2require 'rubygems/command'
3require 'rubygems/version_option'
4
5class Gem::Commands::ContentsCommand < Gem::Command
6
7  include Gem::VersionOption
8
9  def initialize
10    super 'contents', 'Display the contents of the installed gems',
11          :specdirs => [], :lib_only => false, :prefix => true
12
13    add_version_option
14
15    add_option(      '--all',
16               "Contents for all gems") do |all, options|
17      options[:all] = all
18    end
19
20    add_option('-s', '--spec-dir a,b,c', Array,
21               "Search for gems under specific paths") do |spec_dirs, options|
22      options[:specdirs] = spec_dirs
23    end
24
25    add_option('-l', '--[no-]lib-only',
26               "Only return files in the Gem's lib_dirs") do |lib_only, options|
27      options[:lib_only] = lib_only
28    end
29
30    add_option(      '--[no-]prefix',
31               "Don't include installed path prefix") do |prefix, options|
32      options[:prefix] = prefix
33    end
34  end
35
36  def arguments # :nodoc:
37    "GEMNAME       name of gem to list contents for"
38  end
39
40  def defaults_str # :nodoc:
41    "--no-lib-only --prefix"
42  end
43
44  def usage # :nodoc:
45    "#{program_name} GEMNAME [GEMNAME ...]"
46  end
47
48  def execute
49    version = options[:version] || Gem::Requirement.default
50
51    spec_dirs = options[:specdirs].map do |i|
52      [i, File.join(i, "specifications")]
53    end.flatten
54
55    path_kind = if spec_dirs.empty? then
56                  spec_dirs = Gem::Specification.dirs
57                  "default gem paths"
58                else
59                  "specified path"
60                end
61
62    gem_names = if options[:all] then
63                  Gem::Specification.map(&:name)
64                else
65                  get_all_gem_names
66                end
67
68    gem_names.each do |name|
69      # HACK: find_by_name fails for some reason... ARGH
70      # How many places must we embed our resolve logic?
71      spec = Gem::Specification.find_all_by_name(name, version).last
72
73      unless spec then
74        say "Unable to find gem '#{name}' in #{path_kind}"
75
76        if Gem.configuration.verbose then
77          say "\nDirectories searched:"
78          spec_dirs.sort.each { |dir| say dir }
79        end
80
81        terminate_interaction 1 if gem_names.length == 1
82      end
83
84      if spec.default_gem?
85        files = spec.files.sort.map do |file|
86          case file
87          when /\A#{spec.bindir}\//
88            [Gem::ConfigMap[:bindir], $POSTMATCH]
89          when /\.so\z/
90            [Gem::ConfigMap[:archdir], file]
91          else
92            [Gem::ConfigMap[:rubylibdir], file]
93          end
94        end
95      else
96        gem_path  = spec.full_gem_path
97        extra     = "/{#{spec.require_paths.join ','}}" if options[:lib_only]
98        glob      = "#{gem_path}#{extra}/**/*"
99        prefix_re = /#{Regexp.escape(gem_path)}\//
100        files     = Dir[glob].map do |file|
101          [gem_path, file.sub(prefix_re, "")]
102        end
103      end
104
105      files.sort.each do |prefix, basename|
106        absolute_path = File.join(prefix, basename)
107        next if File.directory? absolute_path
108
109        if options[:prefix]
110          say absolute_path
111        else
112          say basename
113        end
114      end
115    end
116  end
117
118end
119
120