slimgems 1.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. data/ChangeLog +5811 -0
  2. data/History.txt +887 -0
  3. data/LICENSE.txt +51 -0
  4. data/README.md +87 -0
  5. data/Rakefile +120 -0
  6. data/bin/gem +25 -0
  7. data/bin/update_slimgems +35 -0
  8. data/bootstrap/Rakefile +4 -0
  9. data/hide_lib_for_update/note.txt +5 -0
  10. data/lib/gauntlet_rubygems.rb +50 -0
  11. data/lib/rbconfig/datadir.rb +20 -0
  12. data/lib/rubygems.rb +1220 -0
  13. data/lib/rubygems/builder.rb +102 -0
  14. data/lib/rubygems/command.rb +534 -0
  15. data/lib/rubygems/command_manager.rb +182 -0
  16. data/lib/rubygems/commands/build_command.rb +53 -0
  17. data/lib/rubygems/commands/cert_command.rb +86 -0
  18. data/lib/rubygems/commands/check_command.rb +80 -0
  19. data/lib/rubygems/commands/cleanup_command.rb +106 -0
  20. data/lib/rubygems/commands/contents_command.rb +98 -0
  21. data/lib/rubygems/commands/dependency_command.rb +195 -0
  22. data/lib/rubygems/commands/environment_command.rb +132 -0
  23. data/lib/rubygems/commands/fetch_command.rb +67 -0
  24. data/lib/rubygems/commands/generate_index_command.rb +133 -0
  25. data/lib/rubygems/commands/help_command.rb +172 -0
  26. data/lib/rubygems/commands/install_command.rb +178 -0
  27. data/lib/rubygems/commands/list_command.rb +35 -0
  28. data/lib/rubygems/commands/lock_command.rb +110 -0
  29. data/lib/rubygems/commands/mirror_command.rb +111 -0
  30. data/lib/rubygems/commands/outdated_command.rb +33 -0
  31. data/lib/rubygems/commands/owner_command.rb +75 -0
  32. data/lib/rubygems/commands/pristine_command.rb +93 -0
  33. data/lib/rubygems/commands/push_command.rb +56 -0
  34. data/lib/rubygems/commands/query_command.rb +280 -0
  35. data/lib/rubygems/commands/rdoc_command.rb +91 -0
  36. data/lib/rubygems/commands/search_command.rb +31 -0
  37. data/lib/rubygems/commands/server_command.rb +86 -0
  38. data/lib/rubygems/commands/setup_command.rb +387 -0
  39. data/lib/rubygems/commands/sources_command.rb +157 -0
  40. data/lib/rubygems/commands/specification_command.rb +125 -0
  41. data/lib/rubygems/commands/stale_command.rb +27 -0
  42. data/lib/rubygems/commands/uninstall_command.rb +83 -0
  43. data/lib/rubygems/commands/unpack_command.rb +121 -0
  44. data/lib/rubygems/commands/update_command.rb +212 -0
  45. data/lib/rubygems/commands/which_command.rb +86 -0
  46. data/lib/rubygems/config_file.rb +345 -0
  47. data/lib/rubygems/custom_require.rb +44 -0
  48. data/lib/rubygems/defaults.rb +101 -0
  49. data/lib/rubygems/dependency.rb +227 -0
  50. data/lib/rubygems/dependency_installer.rb +286 -0
  51. data/lib/rubygems/dependency_list.rb +208 -0
  52. data/lib/rubygems/doc_manager.rb +242 -0
  53. data/lib/rubygems/errors.rb +35 -0
  54. data/lib/rubygems/exceptions.rb +91 -0
  55. data/lib/rubygems/ext.rb +18 -0
  56. data/lib/rubygems/ext/builder.rb +56 -0
  57. data/lib/rubygems/ext/configure_builder.rb +25 -0
  58. data/lib/rubygems/ext/ext_conf_builder.rb +24 -0
  59. data/lib/rubygems/ext/rake_builder.rb +39 -0
  60. data/lib/rubygems/format.rb +81 -0
  61. data/lib/rubygems/gem_openssl.rb +92 -0
  62. data/lib/rubygems/gem_path_searcher.rb +100 -0
  63. data/lib/rubygems/gem_runner.rb +79 -0
  64. data/lib/rubygems/gemcutter_utilities.rb +49 -0
  65. data/lib/rubygems/indexer.rb +720 -0
  66. data/lib/rubygems/install_update_options.rb +125 -0
  67. data/lib/rubygems/installer.rb +604 -0
  68. data/lib/rubygems/local_remote_options.rb +135 -0
  69. data/lib/rubygems/old_format.rb +153 -0
  70. data/lib/rubygems/package.rb +97 -0
  71. data/lib/rubygems/package/f_sync_dir.rb +23 -0
  72. data/lib/rubygems/package/tar_header.rb +266 -0
  73. data/lib/rubygems/package/tar_input.rb +222 -0
  74. data/lib/rubygems/package/tar_output.rb +144 -0
  75. data/lib/rubygems/package/tar_reader.rb +106 -0
  76. data/lib/rubygems/package/tar_reader/entry.rb +141 -0
  77. data/lib/rubygems/package/tar_writer.rb +241 -0
  78. data/lib/rubygems/package_task.rb +126 -0
  79. data/lib/rubygems/platform.rb +183 -0
  80. data/lib/rubygems/remote_fetcher.rb +414 -0
  81. data/lib/rubygems/require_paths_builder.rb +18 -0
  82. data/lib/rubygems/requirement.rb +153 -0
  83. data/lib/rubygems/security.rb +814 -0
  84. data/lib/rubygems/server.rb +872 -0
  85. data/lib/rubygems/source_index.rb +597 -0
  86. data/lib/rubygems/source_info_cache.rb +395 -0
  87. data/lib/rubygems/source_info_cache_entry.rb +56 -0
  88. data/lib/rubygems/spec_fetcher.rb +337 -0
  89. data/lib/rubygems/specification.rb +1486 -0
  90. data/lib/rubygems/test_utilities.rb +147 -0
  91. data/lib/rubygems/text.rb +65 -0
  92. data/lib/rubygems/uninstaller.rb +278 -0
  93. data/lib/rubygems/user_interaction.rb +527 -0
  94. data/lib/rubygems/validator.rb +240 -0
  95. data/lib/rubygems/version.rb +316 -0
  96. data/lib/rubygems/version_option.rb +65 -0
  97. data/lib/ubygems.rb +10 -0
  98. data/setup.rb +42 -0
  99. data/test/bogussources.rb +8 -0
  100. data/test/data/gem-private_key.pem +27 -0
  101. data/test/data/gem-public_cert.pem +20 -0
  102. data/test/fake_certlib/openssl.rb +7 -0
  103. data/test/foo/discover.rb +0 -0
  104. data/test/functional.rb +92 -0
  105. data/test/gem_installer_test_case.rb +97 -0
  106. data/test/gem_package_tar_test_case.rb +132 -0
  107. data/test/gemutilities.rb +605 -0
  108. data/test/insure_session.rb +43 -0
  109. data/test/mockgemui.rb +56 -0
  110. data/test/plugin/exception/rubygems_plugin.rb +2 -0
  111. data/test/plugin/load/rubygems_plugin.rb +1 -0
  112. data/test/plugin/standarderror/rubygems_plugin.rb +2 -0
  113. data/test/private_key.pem +27 -0
  114. data/test/public_cert.pem +20 -0
  115. data/test/rubygems_plugin.rb +21 -0
  116. data/test/simple_gem.rb +66 -0
  117. data/test/test_config.rb +12 -0
  118. data/test/test_gem.rb +766 -0
  119. data/test/test_gem_builder.rb +27 -0
  120. data/test/test_gem_command.rb +178 -0
  121. data/test/test_gem_command_manager.rb +207 -0
  122. data/test/test_gem_commands_build_command.rb +74 -0
  123. data/test/test_gem_commands_cert_command.rb +124 -0
  124. data/test/test_gem_commands_check_command.rb +18 -0
  125. data/test/test_gem_commands_contents_command.rb +156 -0
  126. data/test/test_gem_commands_dependency_command.rb +216 -0
  127. data/test/test_gem_commands_environment_command.rb +144 -0
  128. data/test/test_gem_commands_fetch_command.rb +76 -0
  129. data/test/test_gem_commands_generate_index_command.rb +135 -0
  130. data/test/test_gem_commands_install_command.rb +315 -0
  131. data/test/test_gem_commands_list_command.rb +36 -0
  132. data/test/test_gem_commands_lock_command.rb +68 -0
  133. data/test/test_gem_commands_mirror_command.rb +60 -0
  134. data/test/test_gem_commands_outdated_command.rb +40 -0
  135. data/test/test_gem_commands_owner_command.rb +105 -0
  136. data/test/test_gem_commands_pristine_command.rb +108 -0
  137. data/test/test_gem_commands_push_command.rb +81 -0
  138. data/test/test_gem_commands_query_command.rb +426 -0
  139. data/test/test_gem_commands_server_command.rb +59 -0
  140. data/test/test_gem_commands_sources_command.rb +209 -0
  141. data/test/test_gem_commands_specification_command.rb +139 -0
  142. data/test/test_gem_commands_stale_command.rb +38 -0
  143. data/test/test_gem_commands_uninstall_command.rb +83 -0
  144. data/test/test_gem_commands_unpack_command.rb +199 -0
  145. data/test/test_gem_commands_update_command.rb +353 -0
  146. data/test/test_gem_commands_which_command.rb +66 -0
  147. data/test/test_gem_config_file.rb +287 -0
  148. data/test/test_gem_dependency.rb +149 -0
  149. data/test/test_gem_dependency_installer.rb +661 -0
  150. data/test/test_gem_dependency_list.rb +230 -0
  151. data/test/test_gem_doc_manager.rb +31 -0
  152. data/test/test_gem_ext_configure_builder.rb +84 -0
  153. data/test/test_gem_ext_ext_conf_builder.rb +173 -0
  154. data/test/test_gem_ext_rake_builder.rb +81 -0
  155. data/test/test_gem_format.rb +70 -0
  156. data/test/test_gem_gem_path_searcher.rb +78 -0
  157. data/test/test_gem_gem_runner.rb +45 -0
  158. data/test/test_gem_gemcutter_utilities.rb +103 -0
  159. data/test/test_gem_indexer.rb +673 -0
  160. data/test/test_gem_install_update_options.rb +68 -0
  161. data/test/test_gem_installer.rb +857 -0
  162. data/test/test_gem_local_remote_options.rb +97 -0
  163. data/test/test_gem_package_tar_header.rb +130 -0
  164. data/test/test_gem_package_tar_input.rb +112 -0
  165. data/test/test_gem_package_tar_output.rb +97 -0
  166. data/test/test_gem_package_tar_reader.rb +46 -0
  167. data/test/test_gem_package_tar_reader_entry.rb +109 -0
  168. data/test/test_gem_package_tar_writer.rb +144 -0
  169. data/test/test_gem_package_task.rb +59 -0
  170. data/test/test_gem_platform.rb +264 -0
  171. data/test/test_gem_remote_fetcher.rb +740 -0
  172. data/test/test_gem_requirement.rb +292 -0
  173. data/test/test_gem_server.rb +356 -0
  174. data/test/test_gem_silent_ui.rb +113 -0
  175. data/test/test_gem_source_index.rb +461 -0
  176. data/test/test_gem_spec_fetcher.rb +410 -0
  177. data/test/test_gem_specification.rb +1291 -0
  178. data/test/test_gem_stream_ui.rb +218 -0
  179. data/test/test_gem_text.rb +43 -0
  180. data/test/test_gem_uninstaller.rb +146 -0
  181. data/test/test_gem_validator.rb +63 -0
  182. data/test/test_gem_version.rb +181 -0
  183. data/test/test_gem_version_option.rb +89 -0
  184. data/test/test_kernel.rb +59 -0
  185. metadata +413 -0
@@ -0,0 +1,157 @@
1
+ require 'fileutils'
2
+ require 'rubygems/command'
3
+ require 'rubygems/remote_fetcher'
4
+ require 'rubygems/source_info_cache'
5
+ require 'rubygems/spec_fetcher'
6
+ require 'rubygems/local_remote_options'
7
+
8
+ class Gem::Commands::SourcesCommand < Gem::Command
9
+
10
+ include Gem::LocalRemoteOptions
11
+
12
+ def initialize
13
+ super 'sources',
14
+ "Manage the sources and cache file #{Gem::NAME} uses to search for gems"
15
+
16
+ add_option '-a', '--add SOURCE_URI', 'Add source' do |value, options|
17
+ options[:add] = value
18
+ end
19
+
20
+ add_option '-l', '--list', 'List sources' do |value, options|
21
+ options[:list] = value
22
+ end
23
+
24
+ add_option '-r', '--remove SOURCE_URI', 'Remove source' do |value, options|
25
+ options[:remove] = value
26
+ end
27
+
28
+ add_option '-c', '--clear-all',
29
+ 'Remove all sources (clear the cache)' do |value, options|
30
+ options[:clear_all] = value
31
+ end
32
+
33
+ add_option '-u', '--update', 'Update source cache' do |value, options|
34
+ options[:update] = value
35
+ end
36
+
37
+ add_proxy_option
38
+ end
39
+
40
+ def defaults_str
41
+ '--list'
42
+ end
43
+
44
+ def execute
45
+ options[:list] = !(options[:add] ||
46
+ options[:clear_all] ||
47
+ options[:remove] ||
48
+ options[:update])
49
+
50
+ if options[:clear_all] then
51
+ path = Gem::SpecFetcher.fetcher.dir
52
+ FileUtils.rm_rf path
53
+
54
+ if not File.exist?(path) then
55
+ say "*** Removed specs cache ***"
56
+ elsif not File.writable?(path) then
57
+ say "*** Unable to remove source cache (write protected) ***"
58
+ else
59
+ say "*** Unable to remove source cache ***"
60
+ end
61
+
62
+ sic = Gem::SourceInfoCache
63
+ remove_cache_file 'user', sic.user_cache_file
64
+ remove_cache_file 'latest user', sic.latest_user_cache_file
65
+ remove_cache_file 'system', sic.system_cache_file
66
+ remove_cache_file 'latest system', sic.latest_system_cache_file
67
+ end
68
+
69
+ if options[:add] then
70
+ source_uri = options[:add]
71
+ uri = URI.parse source_uri
72
+
73
+ begin
74
+ Gem::SpecFetcher.fetcher.load_specs uri, 'specs'
75
+ Gem.sources << source_uri
76
+ Gem.configuration.write
77
+
78
+ say "#{source_uri} added to sources"
79
+ rescue URI::Error, ArgumentError
80
+ say "#{source_uri} is not a URI"
81
+ rescue Gem::RemoteFetcher::FetchError => e
82
+ yaml_uri = uri + 'yaml'
83
+ gem_repo = Gem::RemoteFetcher.fetcher.fetch_size yaml_uri rescue false
84
+
85
+ if e.uri =~ /specs\.#{Regexp.escape Gem.marshal_version}\.gz$/ and
86
+ gem_repo then
87
+
88
+ alert_warning <<-EOF
89
+ #{Gem::NAME} 1.2+ index not found for:
90
+ \t#{source_uri}
91
+
92
+ Will cause #{Gem::NAME} to revert to legacy indexes, degrading performance.
93
+ EOF
94
+
95
+ say "#{source_uri} added to sources"
96
+ else
97
+ say "Error fetching #{source_uri}:\n\t#{e.message}"
98
+ end
99
+ end
100
+ end
101
+
102
+ if options[:remove] then
103
+ source_uri = options[:remove]
104
+
105
+ unless Gem.sources.include? source_uri then
106
+ say "source #{source_uri} not present in cache"
107
+ else
108
+ Gem.sources.delete source_uri
109
+ Gem.configuration.write
110
+
111
+ say "#{source_uri} removed from sources"
112
+ end
113
+ end
114
+
115
+ if options[:update] then
116
+ fetcher = Gem::SpecFetcher.fetcher
117
+
118
+ if fetcher.legacy_repos.empty? then
119
+ Gem.sources.each do |update_uri|
120
+ update_uri = URI.parse update_uri
121
+ fetcher.load_specs update_uri, 'specs'
122
+ fetcher.load_specs update_uri, 'latest_specs'
123
+ end
124
+ else
125
+ Gem::SourceInfoCache.cache true
126
+ Gem::SourceInfoCache.cache.flush
127
+ end
128
+
129
+ say "source cache successfully updated"
130
+ end
131
+
132
+ if options[:list] then
133
+ say "*** CURRENT SOURCES ***"
134
+ say
135
+
136
+ Gem.sources.each do |source|
137
+ say source
138
+ end
139
+ end
140
+ end
141
+
142
+ private
143
+
144
+ def remove_cache_file(desc, path)
145
+ FileUtils.rm_rf path
146
+
147
+ if not File.exist?(path) then
148
+ say "*** Removed #{desc} source cache ***"
149
+ elsif not File.writable?(path) then
150
+ say "*** Unable to remove #{desc} source cache (write protected) ***"
151
+ else
152
+ say "*** Unable to remove #{desc} source cache ***"
153
+ end
154
+ end
155
+
156
+ end
157
+
@@ -0,0 +1,125 @@
1
+ require 'rubygems/command'
2
+ require 'rubygems/local_remote_options'
3
+ require 'rubygems/version_option'
4
+ require 'rubygems/source_info_cache'
5
+ require 'rubygems/format'
6
+
7
+ class Gem::Commands::SpecificationCommand < Gem::Command
8
+
9
+ include Gem::LocalRemoteOptions
10
+ include Gem::VersionOption
11
+
12
+ def initialize
13
+ Gem.load_yaml
14
+
15
+ super 'specification', 'Display gem specification (in yaml)',
16
+ :domain => :local, :version => Gem::Requirement.default,
17
+ :format => :yaml
18
+
19
+ add_version_option('examine')
20
+ add_platform_option
21
+
22
+ add_option('--all', 'Output specifications for all versions of',
23
+ 'the gem') do |value, options|
24
+ options[:all] = true
25
+ end
26
+
27
+ add_option('--ruby', 'Output ruby format') do |value, options|
28
+ options[:format] = :ruby
29
+ end
30
+
31
+ add_option('--yaml', 'Output RUBY format') do |value, options|
32
+ options[:format] = :yaml
33
+ end
34
+
35
+ add_option('--marshal', 'Output Marshal format') do |value, options|
36
+ options[:format] = :marshal
37
+ end
38
+
39
+ add_local_remote_options
40
+ end
41
+
42
+ def arguments # :nodoc:
43
+ <<-ARGS
44
+ GEMFILE name of gem to show the gemspec for
45
+ FIELD name of gemspec field to show
46
+ ARGS
47
+ end
48
+
49
+ def defaults_str # :nodoc:
50
+ "--local --version '#{Gem::Requirement.default}' --yaml"
51
+ end
52
+
53
+ def usage # :nodoc:
54
+ "#{program_name} [GEMFILE] [FIELD]"
55
+ end
56
+
57
+ def execute
58
+ specs = []
59
+ gem = options[:args].shift
60
+
61
+ unless gem then
62
+ raise Gem::CommandLineError,
63
+ "Please specify a gem name or file on the command line"
64
+ end
65
+
66
+ dep = Gem::Dependency.new gem, options[:version]
67
+
68
+ field = get_one_optional_argument
69
+
70
+ if field then
71
+ field = field.intern
72
+
73
+ if options[:format] == :ruby then
74
+ raise Gem::CommandLineError, "--ruby and FIELD are mutually exclusive"
75
+ end
76
+
77
+ unless Gem::Specification.attribute_names.include? field then
78
+ raise Gem::CommandLineError,
79
+ "no field %p on Gem::Specification" % field.to_s
80
+ end
81
+ end
82
+
83
+ if local? then
84
+ if File.exist? gem then
85
+ specs << Gem::Format.from_file_by_path(gem).spec rescue nil
86
+ end
87
+
88
+ if specs.empty? then
89
+ specs.push(*Gem.source_index.search(dep))
90
+ end
91
+ end
92
+
93
+ if remote? then
94
+ found = Gem::SpecFetcher.fetcher.fetch dep
95
+
96
+ specs.push(*found.map { |spec,| spec })
97
+ end
98
+
99
+ if specs.empty? then
100
+ alert_error "Unknown gem '#{gem}'"
101
+ terminate_interaction 1
102
+ end
103
+
104
+ output = lambda do |s|
105
+ s = s.send field if field
106
+
107
+ say case options[:format]
108
+ when :ruby then s.to_ruby
109
+ when :marshal then Marshal.dump s
110
+ else s.to_yaml
111
+ end
112
+
113
+ say "\n"
114
+ end
115
+
116
+ if options[:all] then
117
+ specs.each(&output)
118
+ else
119
+ spec = specs.sort_by { |s| s.version }.last
120
+ output[spec]
121
+ end
122
+ end
123
+
124
+ end
125
+
@@ -0,0 +1,27 @@
1
+ require 'rubygems/command'
2
+
3
+ class Gem::Commands::StaleCommand < Gem::Command
4
+ def initialize
5
+ super('stale', 'List gems along with access times')
6
+ end
7
+
8
+ def usage # :nodoc:
9
+ "#{program_name}"
10
+ end
11
+
12
+ def execute
13
+ gem_to_atime = {}
14
+ Gem.source_index.each do |name, spec|
15
+ Dir["#{spec.full_gem_path}/**/*.*"].each do |file|
16
+ next if File.directory?(file)
17
+ stat = File.stat(file)
18
+ gem_to_atime[name] ||= stat.atime
19
+ gem_to_atime[name] = stat.atime if gem_to_atime[name] < stat.atime
20
+ end
21
+ end
22
+
23
+ gem_to_atime.sort_by { |_, atime| atime }.each do |name, atime|
24
+ say "#{name} at #{atime.strftime '%c'}"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,83 @@
1
+ require 'rubygems/command'
2
+ require 'rubygems/version_option'
3
+ require 'rubygems/uninstaller'
4
+
5
+ ##
6
+ # Gem uninstaller command line tool
7
+ #
8
+ # See `gem help uninstall`
9
+
10
+ class Gem::Commands::UninstallCommand < Gem::Command
11
+
12
+ include Gem::VersionOption
13
+
14
+ def initialize
15
+ super 'uninstall', 'Uninstall gems from the local repository',
16
+ :version => Gem::Requirement.default, :user_install => true
17
+
18
+ add_option('-a', '--[no-]all',
19
+ 'Uninstall all matching versions'
20
+ ) do |value, options|
21
+ options[:all] = value
22
+ end
23
+
24
+ add_option('-I', '--[no-]ignore-dependencies',
25
+ 'Ignore dependency requirements while',
26
+ 'uninstalling') do |value, options|
27
+ options[:ignore] = value
28
+ end
29
+
30
+ add_option('-x', '--[no-]executables',
31
+ 'Uninstall applicable executables without',
32
+ 'confirmation') do |value, options|
33
+ options[:executables] = value
34
+ end
35
+
36
+ add_option('-i', '--install-dir DIR',
37
+ 'Directory to uninstall gem from') do |value, options|
38
+ options[:install_dir] = File.expand_path(value)
39
+ end
40
+
41
+ add_option('-n', '--bindir DIR',
42
+ 'Directory to remove binaries from') do |value, options|
43
+ options[:bin_dir] = File.expand_path(value)
44
+ end
45
+
46
+ add_option('--[no-]user-install',
47
+ 'Uninstall from user\'s home directory',
48
+ 'in addition to GEM_HOME.') do |value, options|
49
+ options[:user_install] = value
50
+ end
51
+
52
+ add_version_option
53
+ add_platform_option
54
+ end
55
+
56
+ def arguments # :nodoc:
57
+ "GEMNAME name of gem to uninstall"
58
+ end
59
+
60
+ def defaults_str # :nodoc:
61
+ "--version '#{Gem::Requirement.default}' --no-force " \
62
+ "--install-dir #{Gem.dir}\n" \
63
+ "--user-install"
64
+ end
65
+
66
+ def usage # :nodoc:
67
+ "#{program_name} GEMNAME [GEMNAME ...]"
68
+ end
69
+
70
+ def execute
71
+ get_all_gem_names.each do |gem_name|
72
+ begin
73
+ Gem::Uninstaller.new(gem_name, options).uninstall
74
+ rescue Gem::GemNotInHomeException => e
75
+ spec = e.spec
76
+ alert("In order to remove #{spec.name}, please execute:\n" \
77
+ "\tgem uninstall #{spec.name} --install-dir=#{spec.installation_path}")
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+
@@ -0,0 +1,121 @@
1
+ require 'fileutils'
2
+ require 'rubygems/command'
3
+ require 'rubygems/installer'
4
+ require 'rubygems/version_option'
5
+
6
+ class Gem::Commands::UnpackCommand < Gem::Command
7
+
8
+ include Gem::VersionOption
9
+
10
+ def initialize
11
+ super 'unpack', 'Unpack an installed gem to the current directory',
12
+ :version => Gem::Requirement.default,
13
+ :target => Dir.pwd
14
+
15
+ add_option('--target=DIR',
16
+ 'target directory for unpacking') do |value, options|
17
+ options[:target] = value
18
+ end
19
+
20
+ add_version_option
21
+ end
22
+
23
+ def arguments # :nodoc:
24
+ "GEMNAME name of gem to unpack"
25
+ end
26
+
27
+ def defaults_str # :nodoc:
28
+ "--version '#{Gem::Requirement.default}'"
29
+ end
30
+
31
+ def usage # :nodoc:
32
+ "#{program_name} GEMNAME"
33
+ end
34
+
35
+ def download dependency
36
+ found = Gem::SpecFetcher.fetcher.fetch dependency
37
+
38
+ return if found.empty?
39
+
40
+ spec, source_uri = found.first
41
+
42
+ Gem::RemoteFetcher.fetcher.download spec, source_uri
43
+ end
44
+
45
+ #--
46
+ # TODO: allow, e.g., 'gem unpack rake-0.3.1'. Find a general solution for
47
+ # this, so that it works for uninstall as well. (And check other commands
48
+ # at the same time.)
49
+
50
+ def execute
51
+ get_all_gem_names.each do |name|
52
+ dependency = Gem::Dependency.new name, options[:version]
53
+ path = get_path dependency
54
+
55
+ if path then
56
+ basename = File.basename path, '.gem'
57
+ target_dir = File.expand_path basename, options[:target]
58
+ FileUtils.mkdir_p target_dir
59
+ Gem::Installer.new(path, :unpack => true).unpack target_dir
60
+ say "Unpacked gem: '#{target_dir}'"
61
+ else
62
+ alert_error "Gem '#{name}' not installed."
63
+ end
64
+ end
65
+ end
66
+
67
+ ##
68
+ #
69
+ # Find cached filename in Gem.path. Returns nil if the file cannot be found.
70
+ #
71
+ #--
72
+ # TODO: see comments in get_path() about general service.
73
+
74
+ def find_in_cache(filename)
75
+ Gem.path.each do |gem_dir|
76
+ this_path = File.join gem_dir, 'cache', filename
77
+ return this_path if File.exist? this_path
78
+ end
79
+
80
+ return nil
81
+ end
82
+
83
+ ##
84
+ # Return the full path to the cached gem file matching the given
85
+ # name and version requirement. Returns 'nil' if no match.
86
+ #
87
+ # Example:
88
+ #
89
+ # get_path 'rake', '> 0.4' # "/usr/lib/ruby/gems/1.8/cache/rake-0.4.2.gem"
90
+ # get_path 'rake', '< 0.1' # nil
91
+ # get_path 'rak' # nil (exact name required)
92
+ #--
93
+ # TODO: This should be refactored so that it's a general service. I don't
94
+ # think any of our existing classes are the right place though. Just maybe
95
+ # 'Cache'?
96
+ #
97
+ # TODO: It just uses Gem.dir for now. What's an easy way to get the list of
98
+ # source directories?
99
+
100
+ def get_path dependency
101
+ return dependency.name if dependency.name =~ /\.gem$/i
102
+
103
+ specs = Gem.source_index.search dependency
104
+
105
+ selected = specs.sort_by { |s| s.version }.last
106
+
107
+ return download(dependency) if selected.nil?
108
+
109
+ return unless dependency.name =~ /^#{selected.name}$/i
110
+
111
+ # We expect to find (basename).gem in the 'cache' directory. Furthermore,
112
+ # the name match must be exact (ignoring case).
113
+
114
+ path = find_in_cache(selected.file_name)
115
+ return download(dependency) unless path
116
+
117
+ path
118
+ end
119
+
120
+ end
121
+