libgems 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) 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 +113 -0
  6. data/lib/gauntlet_libgems.rb +50 -0
  7. data/lib/libgems.rb +1246 -0
  8. data/lib/libgems/builder.rb +102 -0
  9. data/lib/libgems/command.rb +534 -0
  10. data/lib/libgems/command_manager.rb +182 -0
  11. data/lib/libgems/commands/build_command.rb +53 -0
  12. data/lib/libgems/commands/cert_command.rb +86 -0
  13. data/lib/libgems/commands/check_command.rb +80 -0
  14. data/lib/libgems/commands/cleanup_command.rb +106 -0
  15. data/lib/libgems/commands/contents_command.rb +98 -0
  16. data/lib/libgems/commands/dependency_command.rb +195 -0
  17. data/lib/libgems/commands/environment_command.rb +133 -0
  18. data/lib/libgems/commands/fetch_command.rb +67 -0
  19. data/lib/libgems/commands/generate_index_command.rb +133 -0
  20. data/lib/libgems/commands/help_command.rb +172 -0
  21. data/lib/libgems/commands/install_command.rb +178 -0
  22. data/lib/libgems/commands/list_command.rb +35 -0
  23. data/lib/libgems/commands/lock_command.rb +110 -0
  24. data/lib/libgems/commands/mirror_command.rb +111 -0
  25. data/lib/libgems/commands/outdated_command.rb +33 -0
  26. data/lib/libgems/commands/owner_command.rb +75 -0
  27. data/lib/libgems/commands/pristine_command.rb +93 -0
  28. data/lib/libgems/commands/push_command.rb +56 -0
  29. data/lib/libgems/commands/query_command.rb +280 -0
  30. data/lib/libgems/commands/rdoc_command.rb +91 -0
  31. data/lib/libgems/commands/search_command.rb +31 -0
  32. data/lib/libgems/commands/server_command.rb +86 -0
  33. data/lib/libgems/commands/sources_command.rb +157 -0
  34. data/lib/libgems/commands/specification_command.rb +125 -0
  35. data/lib/libgems/commands/stale_command.rb +27 -0
  36. data/lib/libgems/commands/uninstall_command.rb +83 -0
  37. data/lib/libgems/commands/unpack_command.rb +121 -0
  38. data/lib/libgems/commands/update_command.rb +160 -0
  39. data/lib/libgems/commands/which_command.rb +86 -0
  40. data/lib/libgems/config_file.rb +345 -0
  41. data/lib/libgems/custom_require.rb +44 -0
  42. data/lib/libgems/defaults.rb +101 -0
  43. data/lib/libgems/dependency.rb +227 -0
  44. data/lib/libgems/dependency_installer.rb +286 -0
  45. data/lib/libgems/dependency_list.rb +208 -0
  46. data/lib/libgems/doc_manager.rb +242 -0
  47. data/lib/libgems/errors.rb +35 -0
  48. data/lib/libgems/exceptions.rb +91 -0
  49. data/lib/libgems/ext.rb +18 -0
  50. data/lib/libgems/ext/builder.rb +56 -0
  51. data/lib/libgems/ext/configure_builder.rb +25 -0
  52. data/lib/libgems/ext/ext_conf_builder.rb +24 -0
  53. data/lib/libgems/ext/rake_builder.rb +39 -0
  54. data/lib/libgems/format.rb +81 -0
  55. data/lib/libgems/gem_openssl.rb +92 -0
  56. data/lib/libgems/gem_path_searcher.rb +100 -0
  57. data/lib/libgems/gem_runner.rb +79 -0
  58. data/lib/libgems/gemcutter_utilities.rb +49 -0
  59. data/lib/libgems/indexer.rb +720 -0
  60. data/lib/libgems/install_update_options.rb +125 -0
  61. data/lib/libgems/installer.rb +604 -0
  62. data/lib/libgems/local_remote_options.rb +135 -0
  63. data/lib/libgems/old_format.rb +153 -0
  64. data/lib/libgems/package.rb +97 -0
  65. data/lib/libgems/package/f_sync_dir.rb +23 -0
  66. data/lib/libgems/package/tar_header.rb +266 -0
  67. data/lib/libgems/package/tar_input.rb +222 -0
  68. data/lib/libgems/package/tar_output.rb +144 -0
  69. data/lib/libgems/package/tar_reader.rb +106 -0
  70. data/lib/libgems/package/tar_reader/entry.rb +141 -0
  71. data/lib/libgems/package/tar_writer.rb +241 -0
  72. data/lib/libgems/package_task.rb +126 -0
  73. data/lib/libgems/platform.rb +183 -0
  74. data/lib/libgems/remote_fetcher.rb +414 -0
  75. data/lib/libgems/require_paths_builder.rb +18 -0
  76. data/lib/libgems/requirement.rb +153 -0
  77. data/lib/libgems/security.rb +814 -0
  78. data/lib/libgems/server.rb +872 -0
  79. data/lib/libgems/source_index.rb +597 -0
  80. data/lib/libgems/source_info_cache.rb +395 -0
  81. data/lib/libgems/source_info_cache_entry.rb +56 -0
  82. data/lib/libgems/spec_fetcher.rb +337 -0
  83. data/lib/libgems/specification.rb +1487 -0
  84. data/lib/libgems/test_utilities.rb +147 -0
  85. data/lib/libgems/text.rb +65 -0
  86. data/lib/libgems/uninstaller.rb +278 -0
  87. data/lib/libgems/user_interaction.rb +527 -0
  88. data/lib/libgems/validator.rb +240 -0
  89. data/lib/libgems/version.rb +316 -0
  90. data/lib/libgems/version_option.rb +65 -0
  91. data/lib/rbconfig/datadir.rb +20 -0
  92. data/test/bogussources.rb +8 -0
  93. data/test/data/gem-private_key.pem +27 -0
  94. data/test/data/gem-public_cert.pem +20 -0
  95. data/test/fake_certlib/openssl.rb +7 -0
  96. data/test/foo/discover.rb +0 -0
  97. data/test/gem_installer_test_case.rb +97 -0
  98. data/test/gem_package_tar_test_case.rb +132 -0
  99. data/test/gemutilities.rb +605 -0
  100. data/test/insure_session.rb +43 -0
  101. data/test/mockgemui.rb +56 -0
  102. data/test/plugin/exception/libgems_plugin.rb +2 -0
  103. data/test/plugin/load/libgems_plugin.rb +1 -0
  104. data/test/plugin/standarderror/libgems_plugin.rb +2 -0
  105. data/test/private_key.pem +27 -0
  106. data/test/public_cert.pem +20 -0
  107. data/test/rubygems_plugin.rb +21 -0
  108. data/test/simple_gem.rb +66 -0
  109. data/test/test_config.rb +12 -0
  110. data/test/test_gem.rb +780 -0
  111. data/test/test_gem_builder.rb +27 -0
  112. data/test/test_gem_command.rb +178 -0
  113. data/test/test_gem_command_manager.rb +207 -0
  114. data/test/test_gem_commands_build_command.rb +74 -0
  115. data/test/test_gem_commands_cert_command.rb +124 -0
  116. data/test/test_gem_commands_check_command.rb +18 -0
  117. data/test/test_gem_commands_contents_command.rb +156 -0
  118. data/test/test_gem_commands_dependency_command.rb +216 -0
  119. data/test/test_gem_commands_environment_command.rb +144 -0
  120. data/test/test_gem_commands_fetch_command.rb +76 -0
  121. data/test/test_gem_commands_generate_index_command.rb +135 -0
  122. data/test/test_gem_commands_install_command.rb +315 -0
  123. data/test/test_gem_commands_list_command.rb +36 -0
  124. data/test/test_gem_commands_lock_command.rb +68 -0
  125. data/test/test_gem_commands_mirror_command.rb +60 -0
  126. data/test/test_gem_commands_outdated_command.rb +40 -0
  127. data/test/test_gem_commands_owner_command.rb +105 -0
  128. data/test/test_gem_commands_pristine_command.rb +108 -0
  129. data/test/test_gem_commands_push_command.rb +81 -0
  130. data/test/test_gem_commands_query_command.rb +426 -0
  131. data/test/test_gem_commands_server_command.rb +59 -0
  132. data/test/test_gem_commands_sources_command.rb +209 -0
  133. data/test/test_gem_commands_specification_command.rb +139 -0
  134. data/test/test_gem_commands_stale_command.rb +38 -0
  135. data/test/test_gem_commands_uninstall_command.rb +83 -0
  136. data/test/test_gem_commands_unpack_command.rb +199 -0
  137. data/test/test_gem_commands_update_command.rb +207 -0
  138. data/test/test_gem_commands_which_command.rb +66 -0
  139. data/test/test_gem_config_file.rb +287 -0
  140. data/test/test_gem_dependency.rb +149 -0
  141. data/test/test_gem_dependency_installer.rb +661 -0
  142. data/test/test_gem_dependency_list.rb +230 -0
  143. data/test/test_gem_doc_manager.rb +31 -0
  144. data/test/test_gem_ext_configure_builder.rb +84 -0
  145. data/test/test_gem_ext_ext_conf_builder.rb +173 -0
  146. data/test/test_gem_ext_rake_builder.rb +81 -0
  147. data/test/test_gem_format.rb +70 -0
  148. data/test/test_gem_gem_path_searcher.rb +78 -0
  149. data/test/test_gem_gem_runner.rb +45 -0
  150. data/test/test_gem_gemcutter_utilities.rb +103 -0
  151. data/test/test_gem_indexer.rb +673 -0
  152. data/test/test_gem_install_update_options.rb +68 -0
  153. data/test/test_gem_installer.rb +857 -0
  154. data/test/test_gem_local_remote_options.rb +97 -0
  155. data/test/test_gem_package_tar_header.rb +130 -0
  156. data/test/test_gem_package_tar_input.rb +112 -0
  157. data/test/test_gem_package_tar_output.rb +97 -0
  158. data/test/test_gem_package_tar_reader.rb +46 -0
  159. data/test/test_gem_package_tar_reader_entry.rb +109 -0
  160. data/test/test_gem_package_tar_writer.rb +144 -0
  161. data/test/test_gem_package_task.rb +59 -0
  162. data/test/test_gem_platform.rb +264 -0
  163. data/test/test_gem_remote_fetcher.rb +740 -0
  164. data/test/test_gem_requirement.rb +292 -0
  165. data/test/test_gem_server.rb +356 -0
  166. data/test/test_gem_silent_ui.rb +113 -0
  167. data/test/test_gem_source_index.rb +461 -0
  168. data/test/test_gem_spec_fetcher.rb +410 -0
  169. data/test/test_gem_specification.rb +1334 -0
  170. data/test/test_gem_stream_ui.rb +218 -0
  171. data/test/test_gem_text.rb +43 -0
  172. data/test/test_gem_uninstaller.rb +146 -0
  173. data/test/test_gem_validator.rb +63 -0
  174. data/test/test_gem_version.rb +181 -0
  175. data/test/test_gem_version_option.rb +89 -0
  176. data/test/test_kernel.rb +59 -0
  177. metadata +402 -0
@@ -0,0 +1,182 @@
1
+ #--
2
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+ require 'timeout'
8
+ require 'libgems/command'
9
+ require 'libgems/user_interaction'
10
+
11
+ ##
12
+ # The command manager registers and installs all the individual sub-commands
13
+ # supported by the gem command.
14
+ #
15
+ # Extra commands can be provided by writing a rubygems_plugin.rb
16
+ # file in an installed gem. You should register your command against the
17
+ # LibGems::CommandManager instance, like this:
18
+ #
19
+ # # file rubygems_plugin.rb
20
+ # require 'libgems/command_manager'
21
+ #
22
+ # class LibGems::Commands::EditCommand < LibGems::Command
23
+ # # ...
24
+ # end
25
+ #
26
+ # LibGems::CommandManager.instance.register_command :edit
27
+ #
28
+ # See LibGems::Command for instructions on writing gem commands.
29
+
30
+ class LibGems::CommandManager
31
+
32
+ include LibGems::UserInteraction
33
+
34
+ ##
35
+ # Return the authoritative instance of the command manager.
36
+
37
+ def self.instance
38
+ @command_manager ||= new
39
+ end
40
+
41
+ ##
42
+ # Register all the subcommands supported by the gem command.
43
+
44
+ def initialize
45
+ @commands = {}
46
+ register_command :build
47
+ register_command :cert
48
+ register_command :check
49
+ register_command :cleanup
50
+ register_command :contents
51
+ register_command :dependency
52
+ register_command :environment
53
+ register_command :fetch
54
+ register_command :generate_index
55
+ register_command :help
56
+ register_command :install
57
+ register_command :list
58
+ register_command :lock
59
+ register_command :mirror
60
+ register_command :outdated
61
+ register_command :owner
62
+ register_command :pristine
63
+ register_command :push
64
+ register_command :query
65
+ register_command :rdoc
66
+ register_command :search
67
+ register_command :server
68
+ register_command :sources
69
+ register_command :specification
70
+ register_command :stale
71
+ register_command :uninstall
72
+ register_command :unpack
73
+ register_command :update
74
+ register_command :which
75
+ end
76
+
77
+ ##
78
+ # Register the Symbol +command+ as a gem command.
79
+
80
+ def register_command(command)
81
+ @commands[command] = false
82
+ end
83
+
84
+ ##
85
+ # Return the registered command from the command name.
86
+
87
+ def [](command_name)
88
+ command_name = command_name.intern
89
+ return nil if @commands[command_name].nil?
90
+ @commands[command_name] ||= load_and_instantiate(command_name)
91
+ end
92
+
93
+ ##
94
+ # Return a sorted list of all command names (as strings).
95
+
96
+ def command_names
97
+ @commands.keys.collect {|key| key.to_s}.sort
98
+ end
99
+
100
+ ##
101
+ # Run the config specified by +args+.
102
+
103
+ def run(args)
104
+ process_args(args)
105
+ rescue StandardError, Timeout::Error => ex
106
+ alert_error "While executing gem ... (#{ex.class})\n #{ex.to_s}"
107
+ ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if
108
+ LibGems.configuration.backtrace
109
+ terminate_interaction(1)
110
+ rescue Interrupt
111
+ alert_error "Interrupted"
112
+ terminate_interaction(1)
113
+ end
114
+
115
+ def process_args(args)
116
+ args = args.to_str.split(/\s+/) if args.respond_to?(:to_str)
117
+ if args.size == 0
118
+ say LibGems::Command::HELP
119
+ terminate_interaction(1)
120
+ end
121
+ case args[0]
122
+ when '-h', '--help'
123
+ say LibGems::Command::HELP
124
+ terminate_interaction(0)
125
+ when '-v', '--version'
126
+ say "#{LibGems::NAME} #{LibGems::VERSION} (RubyGems #{LibGems::GEM_VERSION})"
127
+ terminate_interaction(0)
128
+ when /^-/
129
+ alert_error "Invalid option: #{args[0]}. See 'gem --help'."
130
+ terminate_interaction(1)
131
+ else
132
+ cmd_name = args.shift.downcase
133
+ cmd = find_command(cmd_name)
134
+ cmd.invoke(*args)
135
+ end
136
+ end
137
+
138
+ def find_command(cmd_name)
139
+ possibilities = find_command_possibilities cmd_name
140
+ if possibilities.size > 1 then
141
+ raise "Ambiguous command #{cmd_name} matches [#{possibilities.join(', ')}]"
142
+ elsif possibilities.size < 1 then
143
+ raise "Unknown command #{cmd_name}"
144
+ end
145
+
146
+ self[possibilities.first]
147
+ end
148
+
149
+ def find_command_possibilities(cmd_name)
150
+ len = cmd_name.length
151
+
152
+ command_names.select { |n| cmd_name == n[0, len] }
153
+ end
154
+
155
+ private
156
+
157
+ def load_and_instantiate(command_name)
158
+ command_name = command_name.to_s
159
+ const_name = command_name.capitalize.gsub(/_(.)/) { $1.upcase } << "Command"
160
+ commands = LibGems::Commands
161
+ retried = false
162
+
163
+ begin
164
+ commands.const_get const_name
165
+ rescue NameError
166
+ raise if retried
167
+
168
+ retried = true
169
+ begin
170
+ require "libgems/commands/#{command_name}_command"
171
+ rescue Exception => e
172
+ alert_error "Loading command: #{command_name} (#{e.class})\n #{e}"
173
+ ui.errs.puts "\t#{e.backtrace.join "\n\t"}" if
174
+ LibGems.configuration.backtrace
175
+ raise RuntimeError
176
+ end
177
+ retry
178
+ end.new
179
+ end
180
+
181
+ end
182
+
@@ -0,0 +1,53 @@
1
+ require 'libgems/command'
2
+ require 'libgems/builder'
3
+
4
+ class LibGems::Commands::BuildCommand < LibGems::Command
5
+
6
+ def initialize
7
+ super('build', 'Build a gem from a gemspec')
8
+ end
9
+
10
+ def arguments # :nodoc:
11
+ "GEMSPEC_FILE gemspec file name to build a gem for"
12
+ end
13
+
14
+ def usage # :nodoc:
15
+ "#{program_name} GEMSPEC_FILE"
16
+ end
17
+
18
+ def execute
19
+ gemspec = get_one_gem_name
20
+ if File.exist?(gemspec)
21
+ specs = load_gemspecs(gemspec)
22
+ specs.each do |spec|
23
+ LibGems::Builder.new(spec).build
24
+ end
25
+ else
26
+ alert_error "Gemspec file not found: #{gemspec}"
27
+ end
28
+ end
29
+
30
+ def load_gemspecs(filename)
31
+ if yaml?(filename)
32
+ result = []
33
+ open(filename) do |f|
34
+ begin
35
+ while not f.eof? and spec = LibGems::Specification.from_yaml(f)
36
+ result << spec
37
+ end
38
+ rescue LibGems::EndOfYAMLException
39
+ # OK
40
+ end
41
+ end
42
+ else
43
+ result = [LibGems::Specification.load(filename)]
44
+ end
45
+ result
46
+ end
47
+
48
+ def yaml?(filename)
49
+ line = open(filename) { |f| line = f.gets }
50
+ result = line =~ %r{!ruby/object:LibGems::Specification}
51
+ result
52
+ end
53
+ end
@@ -0,0 +1,86 @@
1
+ require 'libgems/command'
2
+ require 'libgems/security'
3
+
4
+ class LibGems::Commands::CertCommand < LibGems::Command
5
+
6
+ def initialize
7
+ super 'cert', "Manage #{LibGems::NAME} certificates and signing settings"
8
+
9
+ add_option('-a', '--add CERT',
10
+ 'Add a trusted certificate.') do |value, options|
11
+ cert = OpenSSL::X509::Certificate.new(File.read(value))
12
+ LibGems::Security.add_trusted_cert(cert)
13
+ say "Added '#{cert.subject.to_s}'"
14
+ end
15
+
16
+ add_option('-l', '--list',
17
+ 'List trusted certificates.') do |value, options|
18
+ glob_str = File::join(LibGems::Security::OPT[:trust_dir], '*.pem')
19
+ Dir::glob(glob_str) do |path|
20
+ begin
21
+ cert = OpenSSL::X509::Certificate.new(File.read(path))
22
+ # this could probably be formatted more gracefully
23
+ say cert.subject.to_s
24
+ rescue OpenSSL::X509::CertificateError
25
+ next
26
+ end
27
+ end
28
+ end
29
+
30
+ add_option('-r', '--remove STRING',
31
+ 'Remove trusted certificates containing',
32
+ 'STRING.') do |value, options|
33
+ trust_dir = LibGems::Security::OPT[:trust_dir]
34
+ glob_str = File::join(trust_dir, '*.pem')
35
+
36
+ Dir::glob(glob_str) do |path|
37
+ begin
38
+ cert = OpenSSL::X509::Certificate.new(File.read(path))
39
+ if cert.subject.to_s.downcase.index(value)
40
+ say "Removed '#{cert.subject.to_s}'"
41
+ File.unlink(path)
42
+ end
43
+ rescue OpenSSL::X509::CertificateError
44
+ next
45
+ end
46
+ end
47
+ end
48
+
49
+ add_option('-b', '--build EMAIL_ADDR',
50
+ 'Build private key and self-signed',
51
+ 'certificate for EMAIL_ADDR.') do |value, options|
52
+ vals = LibGems::Security.build_self_signed_cert(value)
53
+ File.chmod 0600, vals[:key_path]
54
+ say "Public Cert: #{vals[:cert_path]}"
55
+ say "Private Key: #{vals[:key_path]}"
56
+ say "Don't forget to move the key file to somewhere private..."
57
+ end
58
+
59
+ add_option('-C', '--certificate CERT',
60
+ 'Certificate for --sign command.') do |value, options|
61
+ cert = OpenSSL::X509::Certificate.new(File.read(value))
62
+ LibGems::Security::OPT[:issuer_cert] = cert
63
+ end
64
+
65
+ add_option('-K', '--private-key KEY',
66
+ 'Private key for --sign command.') do |value, options|
67
+ key = OpenSSL::PKey::RSA.new(File.read(value))
68
+ LibGems::Security::OPT[:issuer_key] = key
69
+ end
70
+
71
+ add_option('-s', '--sign NEWCERT',
72
+ 'Sign a certificate with my key and',
73
+ 'certificate.') do |value, options|
74
+ cert = OpenSSL::X509::Certificate.new(File.read(value))
75
+ my_cert = LibGems::Security::OPT[:issuer_cert]
76
+ my_key = LibGems::Security::OPT[:issuer_key]
77
+ cert = LibGems::Security.sign_cert(cert, my_key, my_cert)
78
+ File.open(value, 'wb') { |file| file.write(cert.to_pem) }
79
+ end
80
+ end
81
+
82
+ def execute
83
+ end
84
+
85
+ end
86
+
@@ -0,0 +1,80 @@
1
+ require 'libgems/command'
2
+ require 'libgems/version_option'
3
+ require 'libgems/validator'
4
+
5
+ class LibGems::Commands::CheckCommand < LibGems::Command
6
+
7
+ include LibGems::VersionOption
8
+
9
+ def initialize
10
+ super 'check', 'Check installed gems',
11
+ :verify => false, :alien => false
12
+
13
+ add_option( '--verify FILE',
14
+ 'Verify gem file against its internal',
15
+ 'checksum') do |value, options|
16
+ options[:verify] = value
17
+ end
18
+
19
+ add_option('-a', '--alien', "Report 'unmanaged' or rogue files in the",
20
+ "gem repository") do |value, options|
21
+ options[:alien] = true
22
+ end
23
+
24
+ add_option('-v', '--verbose', "Spew more words") do |value, options|
25
+ options[:verbose] = true
26
+ end
27
+
28
+ add_option('-t', '--test', "Run unit tests for gem") do |value, options|
29
+ options[:test] = true
30
+ end
31
+
32
+ add_version_option 'run tests for'
33
+ end
34
+
35
+ def execute
36
+ if options[:test]
37
+ version = options[:version] || LibGems::Requirement.default
38
+ dep = LibGems::Dependency.new get_one_gem_name, version
39
+ gem_spec = LibGems::SourceIndex.from_installed_gems.search(dep).first
40
+ LibGems::Validator.new.unit_test(gem_spec)
41
+ end
42
+
43
+ if options[:alien]
44
+ say "Performing the 'alien' operation"
45
+ say
46
+ gems = get_all_gem_names rescue []
47
+ LibGems::Validator.new.alien(gems).sort.each do |key, val|
48
+ unless val.empty? then
49
+ say "#{key} has #{val.size} problems"
50
+ val.each do |error_entry|
51
+ say " #{error_entry.path}:"
52
+ say " #{error_entry.problem}"
53
+ end
54
+ else
55
+ say "#{key} is error-free" if options[:verbose]
56
+ end
57
+ say
58
+ end
59
+ end
60
+
61
+ if options[:verify]
62
+ gem_name = options[:verify]
63
+ unless gem_name
64
+ alert_error "Must specify a .gem file with --verify NAME"
65
+ return
66
+ end
67
+ unless File.exist?(gem_name)
68
+ alert_error "Unknown file: #{gem_name}."
69
+ return
70
+ end
71
+ say "Verifying gem: '#{gem_name}'"
72
+ begin
73
+ LibGems::Validator.new.verify_gem_file(gem_name)
74
+ rescue Exception
75
+ alert_error "#{gem_name} is invalid."
76
+ end
77
+ end
78
+ end
79
+
80
+ end
@@ -0,0 +1,106 @@
1
+ require 'libgems/command'
2
+ require 'libgems/source_index'
3
+ require 'libgems/dependency_list'
4
+ require 'libgems/uninstaller'
5
+
6
+ class LibGems::Commands::CleanupCommand < LibGems::Command
7
+
8
+ def initialize
9
+ super 'cleanup',
10
+ 'Clean up old versions of installed gems in the local repository',
11
+ :force => false, :test => false, :install_dir => LibGems.dir
12
+
13
+ add_option('-d', '--dryrun', "") do |value, options|
14
+ options[:dryrun] = true
15
+ end
16
+ end
17
+
18
+ def arguments # :nodoc:
19
+ "GEMNAME name of gem to cleanup"
20
+ end
21
+
22
+ def defaults_str # :nodoc:
23
+ "--no-dryrun"
24
+ end
25
+
26
+ def description # :nodoc:
27
+ <<-EOF
28
+ The cleanup command removes old gems from GEM_HOME. If an older version is
29
+ installed elsewhere in GEM_PATH the cleanup command won't touch it.
30
+ EOF
31
+ end
32
+
33
+ def usage # :nodoc:
34
+ "#{program_name} [GEMNAME ...]"
35
+ end
36
+
37
+ def execute
38
+ say "Cleaning up installed gems..."
39
+ primary_gems = {}
40
+
41
+ LibGems.source_index.each do |name, spec|
42
+ if primary_gems[spec.name].nil? or
43
+ primary_gems[spec.name].version < spec.version then
44
+ primary_gems[spec.name] = spec
45
+ end
46
+ end
47
+
48
+ gems_to_cleanup = []
49
+
50
+ unless options[:args].empty? then
51
+ options[:args].each do |gem_name|
52
+ dep = LibGems::Dependency.new gem_name, LibGems::Requirement.default
53
+ specs = LibGems.source_index.search dep
54
+ specs.each do |spec|
55
+ gems_to_cleanup << spec
56
+ end
57
+ end
58
+ else
59
+ LibGems.source_index.each do |name, spec|
60
+ gems_to_cleanup << spec
61
+ end
62
+ end
63
+
64
+ gems_to_cleanup = gems_to_cleanup.select { |spec|
65
+ primary_gems[spec.name].version != spec.version
66
+ }
67
+
68
+ deplist = LibGems::DependencyList.new
69
+ gems_to_cleanup.uniq.each do |spec| deplist.add spec end
70
+
71
+ deps = deplist.strongly_connected_components.flatten.reverse
72
+
73
+ deps.each do |spec|
74
+ if options[:dryrun] then
75
+ say "Dry Run Mode: Would uninstall #{spec.full_name}"
76
+ else
77
+ say "Attempting to uninstall #{spec.full_name}"
78
+
79
+ options[:args] = [spec.name]
80
+
81
+ uninstall_options = {
82
+ :executables => false,
83
+ :version => "= #{spec.version}",
84
+ }
85
+
86
+ if LibGems.user_dir == spec.installation_path then
87
+ uninstall_options[:install_dir] = spec.installation_path
88
+ end
89
+
90
+ uninstaller = LibGems::Uninstaller.new spec.name, uninstall_options
91
+
92
+ begin
93
+ uninstaller.uninstall
94
+ rescue LibGems::DependencyRemovalException, LibGems::InstallError,
95
+ LibGems::GemNotInHomeException => e
96
+ say "Unable to uninstall #{spec.full_name}:"
97
+ say "\t#{e.class}: #{e.message}"
98
+ end
99
+ end
100
+ end
101
+
102
+ say "Clean Up Complete"
103
+ end
104
+
105
+ end
106
+