rubygems-update 0.8.3
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.
Potentially problematic release.
This version of rubygems-update might be problematic. Click here for more details.
- data/ChangeLog +2335 -0
- data/README +54 -0
- data/Rakefile +293 -0
- data/Releases +98 -0
- data/TODO +7 -0
- data/bin/gem +11 -0
- data/bin/gem_server +111 -0
- data/bin/generate_yaml_index.rb +58 -0
- data/bin/update_rubygems +18 -0
- data/doc/doc.css +73 -0
- data/doc/makedoc.rb +4 -0
- data/examples/application/an-app.gemspec +26 -0
- data/examples/application/bin/myapp +3 -0
- data/examples/application/lib/somefunctionality.rb +3 -0
- data/gemspecs/README +4 -0
- data/gemspecs/cgikit-1.1.0.gemspec +18 -0
- data/gemspecs/jabber4r.gemspec +26 -0
- data/gemspecs/linguistics.gemspec +22 -0
- data/gemspecs/ook.gemspec +21 -0
- data/gemspecs/progressbar.gemspec +22 -0
- data/gemspecs/redcloth.gemspec +22 -0
- data/gemspecs/rublog.gemspec +23 -0
- data/gemspecs/ruby-doom.gemspec +21 -0
- data/gemspecs/rubyjdwp.gemspec +21 -0
- data/gemspecs/statistics.gemspec +21 -0
- data/lib/rubygems.rb +353 -0
- data/lib/rubygems/builder.rb +54 -0
- data/lib/rubygems/cmd_manager.rb +127 -0
- data/lib/rubygems/command.rb +191 -0
- data/lib/rubygems/config_file.rb +57 -0
- data/lib/rubygems/doc_manager.rb +94 -0
- data/lib/rubygems/format.rb +65 -0
- data/lib/rubygems/gem_commands.rb +925 -0
- data/lib/rubygems/gem_runner.rb +23 -0
- data/lib/rubygems/installer.rb +621 -0
- data/lib/rubygems/loadpath_manager.rb +108 -0
- data/lib/rubygems/old_format.rb +150 -0
- data/lib/rubygems/open-uri.rb +604 -0
- data/lib/rubygems/package.rb +740 -0
- data/lib/rubygems/remote_installer.rb +499 -0
- data/lib/rubygems/rubygems_version.rb +6 -0
- data/lib/rubygems/source_index.rb +130 -0
- data/lib/rubygems/specification.rb +613 -0
- data/lib/rubygems/user_interaction.rb +176 -0
- data/lib/rubygems/validator.rb +148 -0
- data/lib/rubygems/version.rb +279 -0
- data/lib/ubygems.rb +4 -0
- data/pkgs/sources/lib/sources.rb +6 -0
- data/pkgs/sources/sources.gemspec +14 -0
- data/post-install.rb +75 -0
- data/redist/session.gem +433 -0
- data/scripts/buildtests.rb +25 -0
- data/scripts/gemdoc.rb +62 -0
- data/scripts/runtest.rb +17 -0
- data/scripts/specdoc.rb +164 -0
- data/setup.rb +1360 -0
- data/test/bogussources.rb +5 -0
- data/test/data/legacy/keyedlist-0.4.0.ruby +11 -0
- data/test/data/legacy/keyedlist-0.4.0.yaml +16 -0
- data/test/data/lib/code.rb +1 -0
- data/test/data/one/README.one +1 -0
- data/test/data/one/lib/one.rb +3 -0
- data/test/data/one/one.gemspec +17 -0
- data/test/data/one/one.yaml +40 -0
- data/test/functional.rb +145 -0
- data/test/gemenvironment.rb +45 -0
- data/test/gemutilities.rb +18 -0
- data/test/insure_session.rb +46 -0
- data/test/mock/gems/gems/sources-0.0.1/lib/sources.rb +5 -0
- data/test/mock/gems/specifications/sources-0.0.1.gemspec +8 -0
- data/test/mockgemui.rb +45 -0
- data/test/onegem.rb +23 -0
- data/test/simple_gem.rb +66 -0
- data/test/test_builder.rb +13 -0
- data/test/test_cached_fetcher.rb +60 -0
- data/test/test_check_command.rb +28 -0
- data/test/test_command.rb +130 -0
- data/test/test_configfile.rb +36 -0
- data/test/test_format.rb +70 -0
- data/test/test_gemloadpaths.rb +45 -0
- data/test/test_gempaths.rb +115 -0
- data/test/test_loadmanager.rb +40 -0
- data/test/test_local_cache.rb +157 -0
- data/test/test_package.rb +600 -0
- data/test/test_parse_commands.rb +179 -0
- data/test/test_process_commands.rb +21 -0
- data/test/test_remote_fetcher.rb +162 -0
- data/test/test_remote_installer.rb +154 -0
- data/test/test_source_index.rb +58 -0
- data/test/test_specification.rb +286 -0
- data/test/test_validator.rb +53 -0
- data/test/test_version_comparison.rb +204 -0
- data/test/testgem.rc +6 -0
- data/test/user_capture.rb +1 -0
- data/test/yaml_data.rb +59 -0
- metadata +151 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'rubygems/package'
|
2
|
+
|
3
|
+
module Gem
|
4
|
+
|
5
|
+
##
|
6
|
+
# The format class knows the guts of the RubyGem .gem file format
|
7
|
+
# and provides the capability to read gem files
|
8
|
+
#
|
9
|
+
class Format
|
10
|
+
attr_accessor :spec, :file_entries, :gem_path
|
11
|
+
extend Gem::UserInteraction
|
12
|
+
|
13
|
+
##
|
14
|
+
# Constructs an instance of a Format object, representing the gem's
|
15
|
+
# data structure.
|
16
|
+
#
|
17
|
+
# gem:: [String] The file name of the gem
|
18
|
+
#
|
19
|
+
def initialize(gem_path)
|
20
|
+
@gem_path = gem_path
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Reads the named gem file and returns a Format object, representing
|
25
|
+
# the data from the gem file
|
26
|
+
#
|
27
|
+
# file_path:: [String] Path to the gem file
|
28
|
+
#
|
29
|
+
def self.from_file_by_path(file_path)
|
30
|
+
unless File.exist?(file_path)
|
31
|
+
raise Gem::Exception, "Cannot load gem at [#{file_path}]"
|
32
|
+
end
|
33
|
+
require 'fileutils'
|
34
|
+
# check for old version gem
|
35
|
+
if File.read(file_path, 20).include?("MD5SUM =")
|
36
|
+
#alert_warning "Gem #{file_path} is in old format."
|
37
|
+
require 'rubygems/old_format'
|
38
|
+
return OldFormat.from_file_by_path(file_path)
|
39
|
+
else
|
40
|
+
f = File.open(file_path, 'rb')
|
41
|
+
return from_io(f, file_path)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Reads a gem from an io stream and returns a Format object, representing
|
47
|
+
# the data from the gem file
|
48
|
+
#
|
49
|
+
# io:: [IO] Stream from which to read the gem
|
50
|
+
#
|
51
|
+
def self.from_io(io, gem_path="(io)")
|
52
|
+
format = self.new(gem_path)
|
53
|
+
Package.open_from_io(io) do |pkg|
|
54
|
+
format.spec = pkg.metadata
|
55
|
+
format.file_entries = []
|
56
|
+
pkg.each do |entry|
|
57
|
+
format.file_entries << [{"size", entry.size, "mode", entry.mode,
|
58
|
+
"path", entry.full_name}, entry.read]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
format
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,925 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module Gem
|
4
|
+
|
5
|
+
class CommandLineError < Gem::Exception; end
|
6
|
+
|
7
|
+
module CommandAids
|
8
|
+
def get_one_gem_name
|
9
|
+
args = options[:args]
|
10
|
+
if args.nil? or args.empty?
|
11
|
+
fail Gem::CommandLineError,
|
12
|
+
"Please specify a gem name on the command line (e.g. gem build GEMNAME)"
|
13
|
+
end
|
14
|
+
if args.size > 1
|
15
|
+
fail Gem::CommandLineError,
|
16
|
+
"Too many gem names (#{args.join(', ')}); please specify only one"
|
17
|
+
end
|
18
|
+
args.first
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_one_optional_argument
|
22
|
+
args = options[:args] || []
|
23
|
+
args.first
|
24
|
+
end
|
25
|
+
|
26
|
+
def begins?(long, short)
|
27
|
+
return false if short.nil?
|
28
|
+
long[0, short.length] == short
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module LocalRemoteOptions
|
33
|
+
def add_local_remote_options
|
34
|
+
add_option('-l', '--local', 'Restrict operations to the LOCAL domain (default)') do |value, options|
|
35
|
+
options[:domain] = :local
|
36
|
+
end
|
37
|
+
add_option('-r', '--remote', 'Restrict operations to the REMOTE domain') do |value, options|
|
38
|
+
options[:domain] = :remote
|
39
|
+
end
|
40
|
+
add_option('-b', '--both', 'Allow LOCAL and REMOTE operations') do |value, options|
|
41
|
+
options[:domain] = :both
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def local?
|
46
|
+
options[:domain] == :local || options[:domain] == :both
|
47
|
+
end
|
48
|
+
|
49
|
+
def remote?
|
50
|
+
options[:domain] == :remote || options[:domain] == :both
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
module InstallUpdateOptions
|
55
|
+
def add_install_update_options
|
56
|
+
add_option('-i', '--install-dir DIR', '') do |value, options|
|
57
|
+
options[:install_dir] = value
|
58
|
+
end
|
59
|
+
add_option('-d', '--[no-]rdoc', 'Generate RDoc documentation for the gem on install') do |value, options|
|
60
|
+
options[:generate_rdoc] = value
|
61
|
+
end
|
62
|
+
add_option('-f', '--[no-]force', 'Force gem to install, bypassing dependency checks') do |value, options|
|
63
|
+
options[:force] = value
|
64
|
+
end
|
65
|
+
add_option('-t', '--[no-]test', 'Run unit tests prior to installation') do |value, options|
|
66
|
+
options[:test] = value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def install_update_defaults_str
|
71
|
+
'--rdoc --no-force --no-test'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
module VersionOption
|
76
|
+
def add_version_option(taskname)
|
77
|
+
add_option('-v', '--version VERSION', "Specify version of gem to #{taskname}") do |value, options|
|
78
|
+
options[:version] = value
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
####################################################################
|
84
|
+
class InstallCommand < Command
|
85
|
+
include CommandAids
|
86
|
+
include VersionOption
|
87
|
+
include LocalRemoteOptions
|
88
|
+
include InstallUpdateOptions
|
89
|
+
|
90
|
+
def initialize
|
91
|
+
super(
|
92
|
+
'install',
|
93
|
+
'Install a gem into the local repository',
|
94
|
+
{
|
95
|
+
:domain => :both,
|
96
|
+
:generate_rdoc => true,
|
97
|
+
:force => false,
|
98
|
+
:test => false,
|
99
|
+
:version => "> 0",
|
100
|
+
:install_dir => Gem.dir
|
101
|
+
})
|
102
|
+
add_version_option('install')
|
103
|
+
add_local_remote_options
|
104
|
+
add_install_update_options
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def usage
|
109
|
+
"#{program_name} GEMNAME"
|
110
|
+
end
|
111
|
+
|
112
|
+
def arguments
|
113
|
+
"GEMNAME name of gem to install"
|
114
|
+
end
|
115
|
+
|
116
|
+
def defaults_str
|
117
|
+
"--both --version '> 0' --rdoc --no-force --no-test\n" +
|
118
|
+
"--install-dir #{Gem.dir}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def execute
|
122
|
+
ENV['GEM_PATH'] = options[:install_dir]
|
123
|
+
# TODO: If a dependency isn't met, first check to see if it's in
|
124
|
+
# the install list
|
125
|
+
if(options[:args].empty?)
|
126
|
+
fail Gem::CommandLineError,
|
127
|
+
"Please specify a gem name on the command line (e.g. gem build GEMNAME)"
|
128
|
+
end
|
129
|
+
options[:args].each do |gem_name|
|
130
|
+
if local?
|
131
|
+
begin
|
132
|
+
say "Attempting local installation of '#{gem_name}'"
|
133
|
+
entries = []
|
134
|
+
if(File.exist?(gem_name) && !File.directory?(gem_name))
|
135
|
+
entries << gem_name
|
136
|
+
else
|
137
|
+
filepattern = gem_name + "*.gem"
|
138
|
+
entries = Dir[filepattern]
|
139
|
+
end
|
140
|
+
unless entries.size > 0
|
141
|
+
if options[:domain] == :both
|
142
|
+
say "Local gem file not found: #{filepattern}"
|
143
|
+
else
|
144
|
+
alert_error "Local gem file not found: #{filepattern}"
|
145
|
+
end
|
146
|
+
else
|
147
|
+
result = Gem::Installer.new(entries.last).install(options[:force], options[:install_dir])
|
148
|
+
installed_gems = [result].flatten
|
149
|
+
say "Successfully installed #{installed_gems[0].name}, version #{installed_gems[0].version}" if installed_gems
|
150
|
+
end
|
151
|
+
rescue LocalInstallationError => e
|
152
|
+
say " -> Local installation can't proceed: #{e.message}"
|
153
|
+
rescue Gem::LoadError => e
|
154
|
+
say " -> Local installation can't proceed due to LoadError: #{e.message}"
|
155
|
+
rescue => e
|
156
|
+
alert_error "Error installing gem #{gem_name}[.gem]: #{e.message}"
|
157
|
+
return
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
if remote? && installed_gems.nil?
|
162
|
+
say "Attempting remote installation of '#{gem_name}'"
|
163
|
+
installer = Gem::RemoteInstaller.new(options[:http_proxy])
|
164
|
+
installed_gems = installer.install(gem_name, options[:version], options[:force], options[:install_dir])
|
165
|
+
say "Successfully installed #{installed_gems[0].name}, version #{installed_gems[0].version}" if installed_gems
|
166
|
+
end
|
167
|
+
|
168
|
+
unless installed_gems
|
169
|
+
alert_error "Could not install a local or remote copy of the gem: #{gem_name}"
|
170
|
+
terminate_interaction(1)
|
171
|
+
end
|
172
|
+
|
173
|
+
if options[:generate_rdoc]
|
174
|
+
installed_gems.each do |gem|
|
175
|
+
Gem::DocManager.new(gem, options[:rdoc_args]).generate_rdoc
|
176
|
+
end
|
177
|
+
# TODO: catch exceptions and inform user that doc generation was not successful.
|
178
|
+
end
|
179
|
+
if options[:test]
|
180
|
+
installed_gems.each do |spec|
|
181
|
+
gem_spec = Gem::SourceIndex.from_installed_gems.search(spec.name, spec.version.version).first
|
182
|
+
result = Gem::Validator.new.unit_test(gem_spec)
|
183
|
+
unless result.passed?
|
184
|
+
unless ask_yes_no("...keep Gem?", true) then
|
185
|
+
Gem::Uninstaller.new(spec.name, spec.version.version).uninstall
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
####################################################################
|
196
|
+
class UninstallCommand < Command
|
197
|
+
include VersionOption
|
198
|
+
include CommandAids
|
199
|
+
|
200
|
+
def initialize
|
201
|
+
super('uninstall', 'Uninstall a gem from the local repository', {:version=>"> 0"})
|
202
|
+
add_version_option('uninstall')
|
203
|
+
end
|
204
|
+
|
205
|
+
def defaults_str
|
206
|
+
"--version '> 0'"
|
207
|
+
end
|
208
|
+
|
209
|
+
def usage
|
210
|
+
"#{program_name} GEMNAME"
|
211
|
+
end
|
212
|
+
|
213
|
+
def arguments
|
214
|
+
"GEMNAME name of gem to uninstall"
|
215
|
+
end
|
216
|
+
|
217
|
+
def execute
|
218
|
+
gem_name = get_one_gem_name
|
219
|
+
say "Attempting to uninstall gem '#{gem_name}'"
|
220
|
+
Gem::Uninstaller.new(gem_name, options[:version]).uninstall
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
####################################################################
|
225
|
+
class CheckCommand < Command
|
226
|
+
include CommandAids
|
227
|
+
|
228
|
+
def initialize
|
229
|
+
super('check', 'Check installed gems', {:verify => false, :alien => false})
|
230
|
+
add_option('-v', '--verify FILE', 'Verify gem file against its internal checksum') do |value, options|
|
231
|
+
options[:verify] = value
|
232
|
+
end
|
233
|
+
add_option('-a', '--alien', "Report 'unmanaged' or rogue files in the gem repository") do |value, options|
|
234
|
+
options[:alien] = true
|
235
|
+
end
|
236
|
+
add_option('-t', '--test', "Run unit tests for gem") do |value, options|
|
237
|
+
options[:test] = true
|
238
|
+
end
|
239
|
+
add_option('-V', '--version', "Specify version for which to run unit tests") do |value, options|
|
240
|
+
options[:version] = value
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def execute
|
245
|
+
if options[:test]
|
246
|
+
version = options[:version] || "> 0.0.0"
|
247
|
+
gem_spec = Gem::SourceIndex.from_installed_gems.search(get_one_gem_name, version).first
|
248
|
+
Gem::Validator.new.unit_test(gem_spec)
|
249
|
+
end
|
250
|
+
if options[:alien]
|
251
|
+
say "Performing the 'alien' operation"
|
252
|
+
Gem::Validator.new.alien.each do |key, val|
|
253
|
+
if(val.size > 0)
|
254
|
+
say "#{key} has #{val.size} problems"
|
255
|
+
val.each do |error_entry|
|
256
|
+
say "\t#{error_entry.path}:"
|
257
|
+
say "\t#{error_entry.problem}"
|
258
|
+
say
|
259
|
+
end
|
260
|
+
else
|
261
|
+
say "#{key} is error-free"
|
262
|
+
end
|
263
|
+
say
|
264
|
+
end
|
265
|
+
end
|
266
|
+
if options[:verify]
|
267
|
+
gem_name = options[:verify]
|
268
|
+
unless gem_name
|
269
|
+
alert_error "Must specifiy a .gem file with --verify NAME"
|
270
|
+
return
|
271
|
+
end
|
272
|
+
unless File.exist?(gem_name)
|
273
|
+
alert_error "Unknown file: #{gem_name}."
|
274
|
+
return
|
275
|
+
end
|
276
|
+
say "Verifying gem: '#{gem_name}'"
|
277
|
+
begin
|
278
|
+
Gem::Validator.new.verify_gem_file(gem_name)
|
279
|
+
rescue Exception => e
|
280
|
+
alert_error "#{gem_name} is invalid."
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
end # class
|
286
|
+
|
287
|
+
####################################################################
|
288
|
+
class BuildCommand < Command
|
289
|
+
include CommandAids
|
290
|
+
|
291
|
+
def initialize
|
292
|
+
super('build', 'Build a gem from a gemspec')
|
293
|
+
end
|
294
|
+
|
295
|
+
def usage
|
296
|
+
"#{program_name} GEMSPEC_FILE"
|
297
|
+
end
|
298
|
+
|
299
|
+
def arguments
|
300
|
+
"GEMSPEC_FILE name of gemspec file used to build the gem"
|
301
|
+
end
|
302
|
+
|
303
|
+
def execute
|
304
|
+
gemspec = get_one_gem_name
|
305
|
+
if File.exist?(gemspec)
|
306
|
+
say "Attempting to build gem spec '#{gemspec}'"
|
307
|
+
specs = load_gemspecs(gemspec)
|
308
|
+
specs.each do |spec|
|
309
|
+
Gem::Builder.new(spec).build
|
310
|
+
end
|
311
|
+
return
|
312
|
+
else
|
313
|
+
alert_error "Gemspec file not found: #{gemspec}"
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def load_gemspecs(filename)
|
318
|
+
if yaml?(filename)
|
319
|
+
require 'yaml'
|
320
|
+
result = []
|
321
|
+
open(filename) do |f|
|
322
|
+
begin
|
323
|
+
while spec = Gem::Specification.from_yaml(f)
|
324
|
+
result << spec
|
325
|
+
end
|
326
|
+
rescue EndOfYAMLException => e
|
327
|
+
# OK
|
328
|
+
end
|
329
|
+
end
|
330
|
+
else
|
331
|
+
result = [Gem::Specification.load(filename)]
|
332
|
+
end
|
333
|
+
result
|
334
|
+
end
|
335
|
+
|
336
|
+
def yaml?(filename)
|
337
|
+
line = open(filename) { |f| line = f.gets }
|
338
|
+
result = line =~ %r{^--- *!ruby/object:Gem::Specification}
|
339
|
+
result
|
340
|
+
end
|
341
|
+
|
342
|
+
end
|
343
|
+
|
344
|
+
####################################################################
|
345
|
+
class QueryCommand < Command
|
346
|
+
include LocalRemoteOptions
|
347
|
+
|
348
|
+
def initialize(name='query', summary='Query gem information in local or remote repositories')
|
349
|
+
super(name,
|
350
|
+
summary,
|
351
|
+
{:name=>/.*/, :domain=>:local, :details=>false}
|
352
|
+
)
|
353
|
+
add_option('-n', '--name-matches REGEXP', 'Name of gem(s) to query on maches the provided REGEXP') do |value, options|
|
354
|
+
options[:name] = /#{value}/i
|
355
|
+
end
|
356
|
+
add_option('-d', '--[no-]details', 'Display detailed information of gem(s)') do |value, options|
|
357
|
+
options[:details] = value
|
358
|
+
end
|
359
|
+
add_local_remote_options
|
360
|
+
end
|
361
|
+
|
362
|
+
def defaults_str
|
363
|
+
"--local --name-matches '.*' --no-details"
|
364
|
+
end
|
365
|
+
|
366
|
+
def execute
|
367
|
+
if local?
|
368
|
+
say
|
369
|
+
say "*** LOCAL GEMS ***"
|
370
|
+
output_query_results(Gem::cache.search(options[:name]))
|
371
|
+
end
|
372
|
+
if remote?
|
373
|
+
say
|
374
|
+
say "*** REMOTE GEMS ***"
|
375
|
+
begin
|
376
|
+
output_query_results(Gem::RemoteInstaller.new(options[:http_proxy]).search(options[:name]))
|
377
|
+
rescue Gem::RemoteSourceException => e
|
378
|
+
alert_error e.to_s
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
private
|
384
|
+
|
385
|
+
def output_query_results(gemspecs)
|
386
|
+
gem_list_with_version = {}
|
387
|
+
gemspecs.flatten.each do |gemspec|
|
388
|
+
gem_list_with_version[gemspec.name] ||= []
|
389
|
+
gem_list_with_version[gemspec.name] << gemspec
|
390
|
+
end
|
391
|
+
|
392
|
+
gem_list_with_version = gem_list_with_version.sort do |first, second|
|
393
|
+
first[0].downcase <=> second[0].downcase
|
394
|
+
end
|
395
|
+
gem_list_with_version.each do |gem_name, list_of_matching|
|
396
|
+
say
|
397
|
+
list_of_matching = list_of_matching.sort_by { |x| x.version }.reverse
|
398
|
+
seen_versions = []
|
399
|
+
list_of_matching.delete_if do |item|
|
400
|
+
if(seen_versions.member?(item.version))
|
401
|
+
true
|
402
|
+
else
|
403
|
+
seen_versions << item.version
|
404
|
+
false
|
405
|
+
end
|
406
|
+
end
|
407
|
+
say "#{gem_name} (#{list_of_matching.map{|gem| gem.version.to_s}.join(", ")})"
|
408
|
+
say format_text(list_of_matching[0].summary, 68, 4)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
##
|
413
|
+
# Used for wrapping and indenting text
|
414
|
+
#
|
415
|
+
def format_text(text, wrap, indent=0)
|
416
|
+
result = []
|
417
|
+
pattern = Regexp.new("^(.{0,#{wrap}})[ \n]")
|
418
|
+
work = text.dup
|
419
|
+
while work.length > wrap
|
420
|
+
if work =~ pattern
|
421
|
+
result << $1
|
422
|
+
work.slice!(0, $&.length)
|
423
|
+
else
|
424
|
+
result << work.slice!(0, wrap)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
result << work if work.length.nonzero?
|
428
|
+
result.join("\n").gsub(/^/, " " * indent)
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
####################################################################
|
433
|
+
class ListCommand < QueryCommand
|
434
|
+
include CommandAids
|
435
|
+
|
436
|
+
def initialize
|
437
|
+
super(
|
438
|
+
'list',
|
439
|
+
'Display all gems whose name starts with STRING'
|
440
|
+
)
|
441
|
+
remove_option('--name-matches')
|
442
|
+
end
|
443
|
+
|
444
|
+
def defaults_str
|
445
|
+
"--local --no-details"
|
446
|
+
end
|
447
|
+
|
448
|
+
def usage
|
449
|
+
"#{program_name} [STRING]"
|
450
|
+
end
|
451
|
+
|
452
|
+
def arguments
|
453
|
+
"STRING start of gem name to look for"
|
454
|
+
end
|
455
|
+
|
456
|
+
def execute
|
457
|
+
string = get_one_optional_argument || ''
|
458
|
+
options[:name] = /^#{string}/i
|
459
|
+
super
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
####################################################################
|
464
|
+
class SearchCommand < QueryCommand
|
465
|
+
include CommandAids
|
466
|
+
|
467
|
+
def initialize
|
468
|
+
super(
|
469
|
+
'search',
|
470
|
+
'Display all gems whose name contains STRING'
|
471
|
+
)
|
472
|
+
remove_option('--name-matches')
|
473
|
+
end
|
474
|
+
|
475
|
+
def defaults_str
|
476
|
+
"--local --no-details"
|
477
|
+
end
|
478
|
+
|
479
|
+
def usage
|
480
|
+
"#{program_name} [STRING]"
|
481
|
+
end
|
482
|
+
|
483
|
+
def arguments
|
484
|
+
"STRING fragment of gem name to look for"
|
485
|
+
end
|
486
|
+
|
487
|
+
def execute
|
488
|
+
string = get_one_optional_argument
|
489
|
+
options[:name] = /#{string}/i
|
490
|
+
super
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
####################################################################
|
495
|
+
class UpdateCommand < Command
|
496
|
+
include InstallUpdateOptions
|
497
|
+
|
498
|
+
def initialize
|
499
|
+
super(
|
500
|
+
'update',
|
501
|
+
'Upgrade all currently installed gems in the local repository',
|
502
|
+
{
|
503
|
+
:generate_rdoc => true,
|
504
|
+
:force => false,
|
505
|
+
:test => false,
|
506
|
+
:install_dir => Gem.dir
|
507
|
+
})
|
508
|
+
add_install_update_options
|
509
|
+
end
|
510
|
+
|
511
|
+
def defaults_str
|
512
|
+
"--rdoc --no-force --no-test\n" +
|
513
|
+
"--install-dir #{Gem.dir}"
|
514
|
+
end
|
515
|
+
|
516
|
+
def execute
|
517
|
+
say "Upgrading installed gems..."
|
518
|
+
hig = highest_installed_gems = {}
|
519
|
+
Gem::SourceIndex.from_installed_gems.each do |name, spec|
|
520
|
+
if hig[spec.name].nil? or hig[spec.name].version < spec.version
|
521
|
+
hig[spec.name] = spec
|
522
|
+
end
|
523
|
+
end
|
524
|
+
remote_gemspecs = Gem::RemoteInstaller.new(options[:http_proxy]).search(//)
|
525
|
+
# For some reason, this is an array of arrays. The actual list of specifications is
|
526
|
+
# the first and only element. If there were more remote sources, perhaps there would be
|
527
|
+
# more.
|
528
|
+
remote_gemspecs = remote_gemspecs.flatten
|
529
|
+
gems_to_update = []
|
530
|
+
highest_installed_gems.each do |l_name, l_spec|
|
531
|
+
hrg = highest_remote_gem =
|
532
|
+
remote_gemspecs.select { |spec| spec.name == l_name }.
|
533
|
+
sort_by { |spec| spec.version }.
|
534
|
+
last
|
535
|
+
if hrg and l_spec.version < hrg.version
|
536
|
+
gems_to_update << l_name
|
537
|
+
end
|
538
|
+
end
|
539
|
+
options[:domain] = :remote # install from remote source
|
540
|
+
install_command = command_manager['install']
|
541
|
+
gems_to_update.uniq.sort.each do |name|
|
542
|
+
say "Attempting remote upgrade of #{name}"
|
543
|
+
options[:args] = [name]
|
544
|
+
install_command.merge_options(options)
|
545
|
+
install_command.execute
|
546
|
+
end
|
547
|
+
say "All gems up to date"
|
548
|
+
end
|
549
|
+
|
550
|
+
def command_manager
|
551
|
+
Gem::CommandManager.instance
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
####################################################################
|
556
|
+
class RDocCommand < Command
|
557
|
+
include VersionOption
|
558
|
+
include CommandAids
|
559
|
+
|
560
|
+
def initialize
|
561
|
+
super('rdoc', 'Generates RDoc for pre-installed gems', {:version=>"> 0.0.0"})
|
562
|
+
add_option('--all', 'Generate RDoc documentation for all installed gems') do |value, options|
|
563
|
+
options[:all] = value
|
564
|
+
end
|
565
|
+
add_version_option('rdoc')
|
566
|
+
end
|
567
|
+
|
568
|
+
def defaults_str
|
569
|
+
"--version '> 0.0.0'"
|
570
|
+
end
|
571
|
+
|
572
|
+
def usage
|
573
|
+
"#{program_name} [args]"
|
574
|
+
end
|
575
|
+
|
576
|
+
def arguments
|
577
|
+
"GEMNAME The gem to generate RDoc for (unless --all)"
|
578
|
+
end
|
579
|
+
|
580
|
+
def execute
|
581
|
+
if options[:all]
|
582
|
+
Gem::SourceIndex.from_installed_gems.each do |name, spec|
|
583
|
+
say "Doing gem #{spec.name}"
|
584
|
+
Gem::DocManager.new(spec).generate_rdoc
|
585
|
+
end
|
586
|
+
else
|
587
|
+
gem_name = get_one_gem_name
|
588
|
+
specs = Gem::SourceIndex.from_installed_gems.search(gem_name, options[:version])
|
589
|
+
if specs.empty?
|
590
|
+
#version = options[:version] || "> 0.0.0"
|
591
|
+
fail "Failed to find gem #{gem_name} to generate RDoc for #{options[:version]}"
|
592
|
+
end
|
593
|
+
specs.each do |spec|
|
594
|
+
Gem::DocManager.new(spec).generate_rdoc
|
595
|
+
end
|
596
|
+
end
|
597
|
+
true
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
####################################################################
|
602
|
+
class EnvironmentCommand < Command
|
603
|
+
include CommandAids
|
604
|
+
|
605
|
+
def initialize
|
606
|
+
super('environment', 'Display RubyGems environmental information')
|
607
|
+
end
|
608
|
+
|
609
|
+
def usage
|
610
|
+
"#{program_name} [args]"
|
611
|
+
end
|
612
|
+
|
613
|
+
def arguments
|
614
|
+
args = <<-EOF
|
615
|
+
packageversion display the package version
|
616
|
+
gemdir display the path where gems are installed
|
617
|
+
gempath display path used to search for gems
|
618
|
+
version display the gem format version
|
619
|
+
remotesources display the remote gem servers
|
620
|
+
<omitted> display everything
|
621
|
+
EOF
|
622
|
+
return args.gsub(/^\s+/, '')
|
623
|
+
end
|
624
|
+
|
625
|
+
def execute
|
626
|
+
out = ''
|
627
|
+
arg = options[:args][0]
|
628
|
+
if begins?("packageversion", arg)
|
629
|
+
out = Gem::RubyGemsPackageVersion.to_s
|
630
|
+
elsif begins?("version", arg)
|
631
|
+
out = Gem::RubyGemsVersion.to_s
|
632
|
+
elsif begins?("gemdir", arg)
|
633
|
+
out = Gem.dir
|
634
|
+
elsif begins?("gempath", arg)
|
635
|
+
Gem.path.collect { |p| out << "#{p}\n" }
|
636
|
+
elsif begins?("remotesources", arg)
|
637
|
+
Gem::RemoteInstaller.new.sources.collect do |s|
|
638
|
+
out << "#{s}\n"
|
639
|
+
end
|
640
|
+
elsif arg
|
641
|
+
fail Gem::CommandLineError, "Unknown enviroment option [#{arg}]"
|
642
|
+
else
|
643
|
+
out = "Rubygems Environment:\n"
|
644
|
+
out << " - VERSION: #{Gem::RubyGemsVersion} (#{Gem::RubyGemsPackageVersion})\n"
|
645
|
+
out << " - INSTALLATION DIRECTORY: #{Gem.dir}\n"
|
646
|
+
out << " - GEM PATH:\n"
|
647
|
+
Gem.path.collect { |p| out << " - #{p}\n" }
|
648
|
+
out << " - REMOTE SOURCES:\n"
|
649
|
+
Gem::RemoteInstaller.new.sources.collect do |s|
|
650
|
+
out << " - #{s}\n"
|
651
|
+
end
|
652
|
+
end
|
653
|
+
say out
|
654
|
+
true
|
655
|
+
end
|
656
|
+
end
|
657
|
+
|
658
|
+
####################################################################
|
659
|
+
class SpecificationCommand < Command
|
660
|
+
include VersionOption
|
661
|
+
include LocalRemoteOptions
|
662
|
+
include CommandAids
|
663
|
+
|
664
|
+
def initialize
|
665
|
+
super('specification', 'Display gem specification (in yaml)', {:domain=>:local, :version=>"> 0.0.0"})
|
666
|
+
add_version_option('examine')
|
667
|
+
add_local_remote_options
|
668
|
+
add_option('--all', 'Output specifications for all versions of the gem') do
|
669
|
+
options[:all] = true
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
def defaults_str
|
674
|
+
"--local --version '(latest)'"
|
675
|
+
end
|
676
|
+
|
677
|
+
def usage
|
678
|
+
"#{program_name} GEMFILE"
|
679
|
+
end
|
680
|
+
|
681
|
+
def arguments
|
682
|
+
"GEMFILE Name of a .gem file to examine"
|
683
|
+
end
|
684
|
+
|
685
|
+
def execute
|
686
|
+
if local?
|
687
|
+
gem = get_one_gem_name
|
688
|
+
gem_specs = Gem::SourceIndex.from_installed_gems.search(gem, options[:version])
|
689
|
+
unless gem_specs.empty?
|
690
|
+
require 'yaml'
|
691
|
+
output = lambda { |spec| say spec.to_yaml; say "\n" }
|
692
|
+
if options[:all]
|
693
|
+
gem_specs.each(&output)
|
694
|
+
else
|
695
|
+
spec = gem_specs.sort_by { |spec| spec.version }.last
|
696
|
+
output[spec]
|
697
|
+
end
|
698
|
+
else
|
699
|
+
alert_error "Unknown gem #{gem}"
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
703
|
+
if remote?
|
704
|
+
say "(Remote 'info' operation is not yet implemented.)"
|
705
|
+
# NOTE: when we do implement remote info, make sure we don't duplicate huge swabs of
|
706
|
+
# local data. If it's the same, just say it's the same.
|
707
|
+
end
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
711
|
+
####################################################################
|
712
|
+
class UnpackCommand < Command
|
713
|
+
include VersionOption
|
714
|
+
include CommandAids
|
715
|
+
|
716
|
+
def initialize
|
717
|
+
super(
|
718
|
+
'unpack',
|
719
|
+
'Unpack an installed gem to the current directory',
|
720
|
+
{ :version => '> 0' }
|
721
|
+
)
|
722
|
+
add_version_option('unpack')
|
723
|
+
end
|
724
|
+
|
725
|
+
def defaults_str
|
726
|
+
"--version '> 0'"
|
727
|
+
end
|
728
|
+
|
729
|
+
def usage
|
730
|
+
"#{program_name} GEMNAME"
|
731
|
+
end
|
732
|
+
|
733
|
+
def arguments
|
734
|
+
"GEMNAME Name of the gem to unpack"
|
735
|
+
end
|
736
|
+
|
737
|
+
# TODO: allow, e.g., 'gem unpack rake-0.3.1'. Find a general solution for this, so that it
|
738
|
+
# works for uninstall as well. (And check other commands at the same time.)
|
739
|
+
def execute
|
740
|
+
gemname = get_one_gem_name
|
741
|
+
path = get_path(gemname, options[:version])
|
742
|
+
if path
|
743
|
+
require 'fileutils'
|
744
|
+
target_dir = File.basename(path).sub(/\.gem$/, '')
|
745
|
+
FileUtils.mkdir_p target_dir
|
746
|
+
Installer.new(path).unpack(target_dir)
|
747
|
+
say "Unpacked gem: '#{target_dir}'"
|
748
|
+
else
|
749
|
+
alert_error "Gem '#{gemname}' not installed."
|
750
|
+
end
|
751
|
+
end
|
752
|
+
|
753
|
+
# Return the full path to the cached gem file matching the given name and version
|
754
|
+
# requirement. Returns 'nil' if no match. Example:
|
755
|
+
#
|
756
|
+
# get_path('rake', '> 0.4') # -> '/usr/lib/ruby/gems/1.8/cache/rake-0.4.2.gem'
|
757
|
+
# get_path('rake', '< 0.1') # -> nil
|
758
|
+
# get_path('rak') # -> nil (exact name required)
|
759
|
+
#
|
760
|
+
# XXX: This should be refactored so that it's a general service. I don't think any of our
|
761
|
+
# existing classes are the right place though. Just maybe 'Cache'?
|
762
|
+
#
|
763
|
+
# XXX: It just uses Gem.dir for now. What's an easy way to get the list of source directories?
|
764
|
+
#
|
765
|
+
def get_path(gemname, version_req)
|
766
|
+
specs = SourceIndex.from_installed_gems.search(gemname, version_req)
|
767
|
+
selected = specs.sort_by { |s| s.full_name }.last
|
768
|
+
return nil if selected.nil?
|
769
|
+
# We expect to find (basename).gem in the 'cache' directory. Furthermore, the name match
|
770
|
+
# must be exact.
|
771
|
+
if gemname == selected.name
|
772
|
+
filename = selected.full_name + '.gem'
|
773
|
+
return File.join(Gem.dir, 'cache', filename)
|
774
|
+
else
|
775
|
+
return nil
|
776
|
+
end
|
777
|
+
end
|
778
|
+
end
|
779
|
+
|
780
|
+
####################################################################
|
781
|
+
class HelpCommand < Command
|
782
|
+
include CommandAids
|
783
|
+
|
784
|
+
def initialize
|
785
|
+
super('help', "Provide help on the 'gem' command")
|
786
|
+
end
|
787
|
+
|
788
|
+
def usage
|
789
|
+
"#{program_name} ARGUMENT"
|
790
|
+
end
|
791
|
+
|
792
|
+
def arguments
|
793
|
+
args = <<-EOF
|
794
|
+
commands List all 'gem' commands
|
795
|
+
examples Show examples of 'gem' usage
|
796
|
+
<command> Show specific help for <command>
|
797
|
+
EOF
|
798
|
+
return args.gsub(/^\s+/, '')
|
799
|
+
end
|
800
|
+
|
801
|
+
def execute
|
802
|
+
arg = options[:args][0]
|
803
|
+
if begins?("commands", arg)
|
804
|
+
require 'stringio'
|
805
|
+
out = StringIO.new
|
806
|
+
out.puts "\nGEM commands are:\n\n"
|
807
|
+
desc_indent = command_manager.command_names.collect {|n| n.size}.max + 4
|
808
|
+
format = " %-#{desc_indent}s %s\n"
|
809
|
+
command_manager.command_names.each do |cmd_name|
|
810
|
+
out.printf format, "#{cmd_name}", command_manager[cmd_name].summary
|
811
|
+
end
|
812
|
+
out.puts "\nFor help on a particular command, use 'gem help COMMAND'."
|
813
|
+
out.puts "\nCommands may be abbreviated, so long as they are unambiguous."
|
814
|
+
out.puts "e.g. 'gem i rake' is short for 'gem install rake'."
|
815
|
+
say out.string
|
816
|
+
elsif begins?("options", arg)
|
817
|
+
say Gem::HELP
|
818
|
+
elsif begins?("examples", arg)
|
819
|
+
say Gem::EXAMPLES
|
820
|
+
elsif options[:help]
|
821
|
+
command = command_manager[options[:help]]
|
822
|
+
if command
|
823
|
+
# help with provided command
|
824
|
+
command.invoke("--help")
|
825
|
+
else
|
826
|
+
alert_error "Unknown command #{options[:help]}. Try 'gem help commands'"
|
827
|
+
end
|
828
|
+
elsif arg
|
829
|
+
possibilities = command_manager.find_command_possibilities(arg.downcase)
|
830
|
+
if possibilities.size == 1
|
831
|
+
command = command_manager[possibilities.first]
|
832
|
+
command.invoke("--help")
|
833
|
+
elsif possibilities.size > 1
|
834
|
+
alert_warning "Ambiguous command #{arg} (#{possibilities.join(', ')})"
|
835
|
+
else
|
836
|
+
alert_warning "Unknown command #{arg}. Try gem help commands"
|
837
|
+
end
|
838
|
+
else
|
839
|
+
say Gem::HELP
|
840
|
+
end
|
841
|
+
end
|
842
|
+
|
843
|
+
def command_manager
|
844
|
+
Gem::CommandManager.instance
|
845
|
+
end
|
846
|
+
end
|
847
|
+
|
848
|
+
end # module
|
849
|
+
|
850
|
+
## Documentation Constants
|
851
|
+
|
852
|
+
module Gem
|
853
|
+
|
854
|
+
HELP = %{
|
855
|
+
RubyGems is a sophisticated package manager for Ruby. This is a
|
856
|
+
basic help message containing pointers to more information.
|
857
|
+
|
858
|
+
Usage:
|
859
|
+
gem -h/--help
|
860
|
+
gem -v/--version
|
861
|
+
gem command [arguments...] [options...]
|
862
|
+
|
863
|
+
Examples:
|
864
|
+
gem install rake
|
865
|
+
gem list --local
|
866
|
+
gem build package.gemspec
|
867
|
+
gem help install
|
868
|
+
|
869
|
+
Further help:
|
870
|
+
gem help commands list all 'gem' commands
|
871
|
+
gem help examples show some examples of usage
|
872
|
+
gem help <COMMAND> show help on COMMAND
|
873
|
+
(e.g. 'gem help install')
|
874
|
+
Further information:
|
875
|
+
http://rubygems.rubyforge.org
|
876
|
+
}.gsub(/^ /, "")
|
877
|
+
|
878
|
+
EXAMPLES = %{
|
879
|
+
Some examples of 'gem' usage.
|
880
|
+
|
881
|
+
* Install 'rake', either from local directory or remote server:
|
882
|
+
|
883
|
+
gem install rake
|
884
|
+
|
885
|
+
* Install 'rake', only from remote server:
|
886
|
+
|
887
|
+
gem install rake --remote
|
888
|
+
|
889
|
+
* Install 'rake' from remote server, and run unit tests,
|
890
|
+
and generate RDocs:
|
891
|
+
|
892
|
+
gem install --remote rake --test --rdoc
|
893
|
+
|
894
|
+
* Install 'rake', but only version 0.3.1, even if dependencies
|
895
|
+
are not met, and into a specific directory:
|
896
|
+
|
897
|
+
gem install rake --version 0.3.1 --force --install-dir $HOME/.gems
|
898
|
+
|
899
|
+
* List local gems whose name begins with 'D':
|
900
|
+
|
901
|
+
gem list D
|
902
|
+
|
903
|
+
* List local and remote gems whose name contains 'log':
|
904
|
+
|
905
|
+
gem search log --both
|
906
|
+
|
907
|
+
* List only remote gems whose name contains 'log':
|
908
|
+
|
909
|
+
gem search log --remote
|
910
|
+
|
911
|
+
* Uninstall 'rake':
|
912
|
+
|
913
|
+
gem uninstall rake
|
914
|
+
|
915
|
+
* Create a gem:
|
916
|
+
|
917
|
+
See http://rubygems.rubyforge.org/wiki/wiki.pl?CreateAGemInTenMinutes
|
918
|
+
|
919
|
+
* See information about RubyGems:
|
920
|
+
|
921
|
+
gem environment
|
922
|
+
|
923
|
+
}.gsub(/^ /, "")
|
924
|
+
|
925
|
+
end
|