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.

Files changed (96) hide show
  1. data/ChangeLog +2335 -0
  2. data/README +54 -0
  3. data/Rakefile +293 -0
  4. data/Releases +98 -0
  5. data/TODO +7 -0
  6. data/bin/gem +11 -0
  7. data/bin/gem_server +111 -0
  8. data/bin/generate_yaml_index.rb +58 -0
  9. data/bin/update_rubygems +18 -0
  10. data/doc/doc.css +73 -0
  11. data/doc/makedoc.rb +4 -0
  12. data/examples/application/an-app.gemspec +26 -0
  13. data/examples/application/bin/myapp +3 -0
  14. data/examples/application/lib/somefunctionality.rb +3 -0
  15. data/gemspecs/README +4 -0
  16. data/gemspecs/cgikit-1.1.0.gemspec +18 -0
  17. data/gemspecs/jabber4r.gemspec +26 -0
  18. data/gemspecs/linguistics.gemspec +22 -0
  19. data/gemspecs/ook.gemspec +21 -0
  20. data/gemspecs/progressbar.gemspec +22 -0
  21. data/gemspecs/redcloth.gemspec +22 -0
  22. data/gemspecs/rublog.gemspec +23 -0
  23. data/gemspecs/ruby-doom.gemspec +21 -0
  24. data/gemspecs/rubyjdwp.gemspec +21 -0
  25. data/gemspecs/statistics.gemspec +21 -0
  26. data/lib/rubygems.rb +353 -0
  27. data/lib/rubygems/builder.rb +54 -0
  28. data/lib/rubygems/cmd_manager.rb +127 -0
  29. data/lib/rubygems/command.rb +191 -0
  30. data/lib/rubygems/config_file.rb +57 -0
  31. data/lib/rubygems/doc_manager.rb +94 -0
  32. data/lib/rubygems/format.rb +65 -0
  33. data/lib/rubygems/gem_commands.rb +925 -0
  34. data/lib/rubygems/gem_runner.rb +23 -0
  35. data/lib/rubygems/installer.rb +621 -0
  36. data/lib/rubygems/loadpath_manager.rb +108 -0
  37. data/lib/rubygems/old_format.rb +150 -0
  38. data/lib/rubygems/open-uri.rb +604 -0
  39. data/lib/rubygems/package.rb +740 -0
  40. data/lib/rubygems/remote_installer.rb +499 -0
  41. data/lib/rubygems/rubygems_version.rb +6 -0
  42. data/lib/rubygems/source_index.rb +130 -0
  43. data/lib/rubygems/specification.rb +613 -0
  44. data/lib/rubygems/user_interaction.rb +176 -0
  45. data/lib/rubygems/validator.rb +148 -0
  46. data/lib/rubygems/version.rb +279 -0
  47. data/lib/ubygems.rb +4 -0
  48. data/pkgs/sources/lib/sources.rb +6 -0
  49. data/pkgs/sources/sources.gemspec +14 -0
  50. data/post-install.rb +75 -0
  51. data/redist/session.gem +433 -0
  52. data/scripts/buildtests.rb +25 -0
  53. data/scripts/gemdoc.rb +62 -0
  54. data/scripts/runtest.rb +17 -0
  55. data/scripts/specdoc.rb +164 -0
  56. data/setup.rb +1360 -0
  57. data/test/bogussources.rb +5 -0
  58. data/test/data/legacy/keyedlist-0.4.0.ruby +11 -0
  59. data/test/data/legacy/keyedlist-0.4.0.yaml +16 -0
  60. data/test/data/lib/code.rb +1 -0
  61. data/test/data/one/README.one +1 -0
  62. data/test/data/one/lib/one.rb +3 -0
  63. data/test/data/one/one.gemspec +17 -0
  64. data/test/data/one/one.yaml +40 -0
  65. data/test/functional.rb +145 -0
  66. data/test/gemenvironment.rb +45 -0
  67. data/test/gemutilities.rb +18 -0
  68. data/test/insure_session.rb +46 -0
  69. data/test/mock/gems/gems/sources-0.0.1/lib/sources.rb +5 -0
  70. data/test/mock/gems/specifications/sources-0.0.1.gemspec +8 -0
  71. data/test/mockgemui.rb +45 -0
  72. data/test/onegem.rb +23 -0
  73. data/test/simple_gem.rb +66 -0
  74. data/test/test_builder.rb +13 -0
  75. data/test/test_cached_fetcher.rb +60 -0
  76. data/test/test_check_command.rb +28 -0
  77. data/test/test_command.rb +130 -0
  78. data/test/test_configfile.rb +36 -0
  79. data/test/test_format.rb +70 -0
  80. data/test/test_gemloadpaths.rb +45 -0
  81. data/test/test_gempaths.rb +115 -0
  82. data/test/test_loadmanager.rb +40 -0
  83. data/test/test_local_cache.rb +157 -0
  84. data/test/test_package.rb +600 -0
  85. data/test/test_parse_commands.rb +179 -0
  86. data/test/test_process_commands.rb +21 -0
  87. data/test/test_remote_fetcher.rb +162 -0
  88. data/test/test_remote_installer.rb +154 -0
  89. data/test/test_source_index.rb +58 -0
  90. data/test/test_specification.rb +286 -0
  91. data/test/test_validator.rb +53 -0
  92. data/test/test_version_comparison.rb +204 -0
  93. data/test/testgem.rc +6 -0
  94. data/test/user_capture.rb +1 -0
  95. data/test/yaml_data.rb +59 -0
  96. metadata +151 -0
@@ -0,0 +1,6 @@
1
+ # DO NOT EDIT
2
+ # This file is auto-generated by build scripts.
3
+ # See: rake update_version
4
+ module Gem
5
+ RubyGemsVersion = '0.8.3'
6
+ end
@@ -0,0 +1,130 @@
1
+ require 'rubygems/user_interaction'
2
+ module Gem
3
+
4
+ # The SourceIndex object indexes all the gems available from a
5
+ # particular source (e.g. a list of gem directories, or a remote
6
+ # source). A SourceIndex maps a gem full name to a gem
7
+ # specification.
8
+ #
9
+ # NOTE:: The class used to be named Cache, but that became
10
+ # confusing when cached source fetchers where introduced.
11
+ # The constant Gem::Cache is an alias for this class to allow
12
+ # old YAMLized source index objects to load properly.
13
+ #
14
+ class SourceIndex
15
+ class << self
16
+ include Gem::UserInteraction
17
+ end
18
+
19
+ # Constructs a source index instance from the provided
20
+ # specifications
21
+ #
22
+ # specifications::
23
+ # [Hash] hash of [Gem name, Gem::Specification] pairs
24
+ #
25
+ def initialize(specifications)
26
+ @gems = specifications
27
+ end
28
+
29
+ # Factory method to construct a source index instance for a given
30
+ # path.
31
+ #
32
+ # source_dirs::
33
+ # List of gem directories to search for specifications. The
34
+ # default is the "specification" directories under each
35
+ # directory in Gem.path.
36
+ #
37
+ # return::
38
+ # SourceIndex instance
39
+ #
40
+ def self.from_installed_gems(*spec_dirs)
41
+ gems = {}
42
+ if spec_dirs.empty?
43
+ spec_dirs = Gem.path.collect {|dir| File.join(dir, "specifications")}
44
+ end
45
+ Dir.glob("{#{spec_dirs.join(',')}}/*.gemspec").each do |file_name|
46
+ gemspec = load_specification(file_name)
47
+ gems[gemspec.full_name] = gemspec if gemspec
48
+ end
49
+ self.new(gems)
50
+ end
51
+
52
+ # Load a specification from a file (eval'd Ruby code)
53
+ #
54
+ # file_name:: [String] The .gemspec file
55
+ # return:: Specification instance or nil if an error occurs
56
+ #
57
+ def self.load_specification(file_name)
58
+ begin
59
+ spec_code = File.read(file_name)
60
+ gemspec = eval(spec_code)
61
+ if gemspec.is_a?(Gem::Specification)
62
+ gemspec.loaded_from = file_name
63
+ return gemspec
64
+ end
65
+ alert_warning "File '#{file_name}' does not evaluate to a gem specification"
66
+ rescue SyntaxError => e
67
+ alert_warning e
68
+ alert_warning spec_code
69
+ rescue Exception => e
70
+ alert_warning(e.inspect.to_s + "\n" + spec_code)
71
+ alert_warning "Invalid .gemspec format in '#{file_name}'"
72
+ end
73
+ return nil
74
+ end
75
+
76
+ # Iterate over the specifications in the source index.
77
+ #
78
+ # &block:: [yields gem.long_name, Gem::Specification]
79
+ #
80
+ def each(&block)
81
+ @gems.each(&block)
82
+ end
83
+
84
+ # Search for a gem by name and optional version
85
+ #
86
+ # gem_name::
87
+ # [String] the (short) name of the gem
88
+ # version_requirement::
89
+ # [String | default=Version::Requirement.new(">= 0")] version to
90
+ # find
91
+ # return::
92
+ # [Array] list of Gem::Specification objects in sorted (version)
93
+ # order. Empty if not found.
94
+ #
95
+ def search(gem_name, version_requirement=Version::Requirement.new(">= 0"))
96
+ #FIXME - remove duplication between this and RemoteInstaller.search
97
+ gem_name = /#{ gem_name }/i if String === gem_name
98
+ version_requirement = Gem::Version::Requirement.create(version_requirement)
99
+ result = []
100
+ @gems.each do |full_spec_name, spec|
101
+ next unless spec.name =~ gem_name
102
+ result << spec if version_requirement.satisfied_by?(spec.version)
103
+ end
104
+ result = result.sort
105
+ result
106
+ end
107
+
108
+ # Refresh the source index from the local file system.
109
+ #
110
+ # return:: Returns a pointer to itself.
111
+ #
112
+ def refresh!
113
+ spec_dirs = Gem.path.collect {|dir| File.join(dir, "specifications")}
114
+ files = Dir.glob("{#{spec_dirs.join(',')}}/*.gemspec")
115
+ current_loaded_files = @gems.values.collect {|spec| spec.loaded_from}
116
+ (files - current_loaded_files).each do |spec_file|
117
+ gemspec = Gem::SourceIndex.load_specification(spec_file)
118
+
119
+ @gems[gemspec.full_name] = gemspec if gemspec
120
+ end
121
+ self
122
+ end
123
+
124
+ end
125
+
126
+ # Cache is an alias for SourceIndex to allow older YAMLized source
127
+ # index objects to load properly.
128
+ Cache = SourceIndex
129
+
130
+ end
@@ -0,0 +1,613 @@
1
+ require 'date'
2
+ require 'rubygems'
3
+ require 'rubygems/version'
4
+
5
+ module Gem
6
+
7
+ ##
8
+ # == Gem::Platform
9
+ #
10
+ # Available list of platforms for targeting Gem installations.
11
+ # Platform::RUBY is the default platform (pure Ruby Gem).
12
+ #
13
+ module Platform
14
+ RUBY = 'ruby'
15
+ WIN32 = 'mswin32'
16
+ LINUX_586 = 'i586-linux'
17
+ DARWIN = 'powerpc-darwin'
18
+ CURRENT = 'current'
19
+ end
20
+
21
+ # Potentially raised when a specification is validated.
22
+ class InvalidSpecificationException < Gem::Exception; end
23
+ class EndOfYAMLException < Gem::Exception; end
24
+
25
+ ##
26
+ # == Gem::Specification
27
+ #
28
+ # The Specification class contains the metadata for a Gem. Typically defined in a
29
+ # .gemspec file or a Rakefile, and looks like this:
30
+ #
31
+ # spec = Gem::Specification.new do |s|
32
+ # s.name = 'rfoo'
33
+ # s.version = '1.0'
34
+ # s.summary = 'Example gem specification'
35
+ # ...
36
+ # end
37
+ #
38
+ # There are many <em>gemspec attributes</em>, and the best place to learn about them in
39
+ # the "Gemspec Reference" linked from the RubyGems wiki.
40
+ #
41
+ class Specification
42
+
43
+ # ------------------------- Specification version contstants.
44
+
45
+ # The the version number of a specification that does not specify one (i.e. RubyGems 0.7
46
+ # or earlier).
47
+ NONEXISTENT_SPECIFICATION_VERSION = -1
48
+
49
+ # The specification version applied to any new Specification instances created. This
50
+ # should be bumped whenever something in the spec format changes.
51
+ CURRENT_SPECIFICATION_VERSION = 1
52
+
53
+ # An informal list of changes to the specification. The highest-valued key should be
54
+ # equal to the CURRENT_SPECIFICATION_VERSION.
55
+ SPECIFICATION_VERSION_HISTORY = {
56
+ -1 => ['(RubyGems versions up to and including 0.7 did not have versioned specifications)'],
57
+ 1 => [
58
+ 'Deprecated "test_suite_file" in favor of the new, but equivalent, "test_files"',
59
+ '"test_file=x" is a shortcut for "test_files=[x]"'
60
+ ]
61
+ }
62
+
63
+ # ------------------------- Class variables.
64
+
65
+ # List of Specification instances.
66
+ @@list = []
67
+
68
+ # Optional block used to gather newly defined instances.
69
+ @@gather = nil
70
+
71
+ # List of attribute names: [:name, :version, ...]
72
+ @@required_attributes = []
73
+
74
+ # List of _all_ attributes and default values: [[:name, nil], [:bindir, 'bin'], ...]
75
+ @@attributes = []
76
+
77
+ # Map of attribute names to default values.
78
+ @@default_value = {}
79
+
80
+ # ------------------------- Convenience class methods.
81
+
82
+ def self.attribute_names
83
+ @@attributes.map { |name, default| name }
84
+ end
85
+
86
+ def self.attribute_defaults
87
+ @@attributes.dup
88
+ end
89
+
90
+ def self.default_value(name)
91
+ @@default_value[name]
92
+ end
93
+
94
+ def self.required_attributes
95
+ @@required_attributes.dup
96
+ end
97
+
98
+ def self.required_attribute?(name)
99
+ @@required_attributes.include? name.to_sym
100
+ end
101
+
102
+ # ------------------------- Infrastructure class methods.
103
+
104
+ # A list of Specification instances that have been defined in this Ruby instance.
105
+ def self.list
106
+ @@list
107
+ end
108
+
109
+ ##
110
+ # Used to specify the name and default value of a specification attribute. The side
111
+ # effects are:
112
+ # * the name and default value are added to the @@attributes list and
113
+ # @@default_value map
114
+ # * a standard _writer_ method (<tt>attribute=</tt>) is created
115
+ # * a non-standard _reader method (<tt>attribute</tt>) is created
116
+ #
117
+ # The reader method behaves like this:
118
+ # def attribute
119
+ # @attribute ||= (copy of default value)
120
+ # end
121
+ #
122
+ # This allows lazy initialization of attributes to their default values.
123
+ #
124
+ def self.attribute(name, default=nil)
125
+ @@attributes << [name, default]
126
+ @@default_value[name] = default
127
+ attr_writer(name)
128
+ class_eval %{
129
+ def #{name}
130
+ @#{name} ||= copy_of(@@default_value[:#{name}])
131
+ end
132
+ }
133
+ end
134
+
135
+ # Same as attribute above, but also records this attribute as mandatory.
136
+ def self.required_attribute(*args)
137
+ @@required_attributes << args.first
138
+ attribute(*args)
139
+ end
140
+
141
+ # Sometimes we don't want the world to use a setter method for a particular attribute.
142
+ # +read_only+ makes it private so we can still use it internally.
143
+ def self.read_only(*names)
144
+ names.each do |name|
145
+ private "#{name}="
146
+ end
147
+ end
148
+
149
+ # Shortcut for creating several attributes at once (each with a default value of
150
+ # +nil+).
151
+ def self.attributes(*args)
152
+ args.each do |arg|
153
+ attribute(arg, nil)
154
+ end
155
+ end
156
+
157
+ # Some attributes require special behaviour when they are accessed. This allows for
158
+ # that.
159
+ def self.overwrite_accessor(name, &block)
160
+ remove_method name
161
+ define_method(name, &block)
162
+ end
163
+
164
+ ##
165
+ # Defines a _singular_ version of an existing _plural_ attribute (i.e. one whose value
166
+ # is expected to be an array). This means just creating a helper method that takes a
167
+ # single value and appends it to the array. These are created for convenience, so
168
+ # that in a spec, one can write
169
+ #
170
+ # s.require_path = 'mylib'
171
+ #
172
+ # instead of
173
+ #
174
+ # s.require_paths = ['mylib']
175
+ #
176
+ # That above convenience is available courtesy of
177
+ #
178
+ # attribute_alias_singular :require_path, :require_paths
179
+ #
180
+ def self.attribute_alias_singular(singular, plural)
181
+ define_method("#{singular}=") { |val|
182
+ send("#{plural}=", [val])
183
+ }
184
+ define_method("#{singular}") {
185
+ val = send("#{plural}")
186
+ val.nil? ? nil : val.first
187
+ }
188
+ end
189
+
190
+ def warn_deprecated(old, new)
191
+ # How (if at all) to implement this? We only want to warn when a gem is being
192
+ # built, I should think.
193
+ end
194
+
195
+ # ------------------------- REQUIRED gemspec attributes.
196
+
197
+ required_attribute :rubygems_version, RubyGemsVersion
198
+ required_attribute :specification_version, CURRENT_SPECIFICATION_VERSION
199
+ required_attribute :name
200
+ required_attribute :version
201
+ required_attribute :date
202
+ required_attribute :summary
203
+ required_attribute :require_paths, ['lib']
204
+
205
+ read_only :specification_version
206
+
207
+ # ------------------------- OPTIONAL gemspec attributes.
208
+
209
+ attributes :email, :homepage, :rubyforge_project, :description
210
+ attributes :autorequire, :default_executable
211
+ attribute :bindir, 'bin'
212
+ attribute :has_rdoc, false
213
+ attribute :required_ruby_version, Gem::Version::Requirement.default
214
+ attribute :platform, Gem::Platform::RUBY
215
+ attribute :authors, []
216
+ attribute :files, []
217
+ attribute :test_files, []
218
+ attribute :rdoc_options, []
219
+ attribute :extra_rdoc_files, []
220
+ attribute :executables, []
221
+ attribute :extensions, []
222
+ attribute :requirements, []
223
+ attribute :dependencies, []
224
+
225
+ read_only :dependencies
226
+
227
+ # ------------------------- ALIASED gemspec attributes.
228
+
229
+ attribute_alias_singular :executable, :executables
230
+ attribute_alias_singular :author, :authors
231
+ attribute_alias_singular :require_path, :require_paths
232
+ attribute_alias_singular :test_file, :test_files
233
+
234
+ # ------------------------- DEPRECATED gemspec attributes.
235
+
236
+ def test_suite_file
237
+ warn_deprecated(:test_suite_file, :test_files)
238
+ test_files.first
239
+ end
240
+
241
+ def test_suite_file=(val)
242
+ warn_deprecated(:test_suite_file, :test_files)
243
+ @test_files << val
244
+ end
245
+
246
+ # ------------------------- RUNTIME attributes (not persisted).
247
+
248
+ attr_writer :loaded
249
+ attr_accessor :loaded_from
250
+
251
+ # ------------------------- Special accessor behaviours (overwriting default).
252
+
253
+ overwrite_accessor :version= do |version|
254
+ @version = Version.create(version)
255
+ end
256
+
257
+ overwrite_accessor :platform= do |platform|
258
+ # Checks the provided platform for the special value Platform::CURRENT and
259
+ # changes it to be binary specific to the current platform (i386-mswin32, etc).
260
+ @platform = (platform == Platform::CURRENT ? RUBY_PLATFORM : platform)
261
+ end
262
+
263
+ overwrite_accessor :required_ruby_version= do |value|
264
+ @required_ruby_version = Version::Requirement.create(value)
265
+ #STDERR.puts @name, @required_ruby_version
266
+ end
267
+
268
+ overwrite_accessor :date= do |date|
269
+ # We want to end up with a Date object. If _date_ responds to :to_str, or :day,
270
+ # :month, and :year, it is duly converted. Otherwise, today's date is used.
271
+ if date.respond_to? :to_str
272
+ date = Date.parse(date.to_str)
273
+ elsif [:year, :month, :day].all? { |m| date.respond_to? m }
274
+ date = Date.new(date.year, date.month, date.day)
275
+ else
276
+ date = nil
277
+ end
278
+ @date = date || Date.today
279
+ end
280
+
281
+ overwrite_accessor :date do
282
+ # Legacy gems might have a Time object directly loaded from the YAML. We fix it here.
283
+ unless @date.is_a? Date
284
+ self.date = @date
285
+ end
286
+ @date
287
+ end
288
+
289
+ overwrite_accessor :summary= do |str|
290
+ if str
291
+ @summary = str.strip.gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').gsub(/\n[ \t]*/, " ")
292
+ end
293
+ end
294
+
295
+ overwrite_accessor :description= do |str|
296
+ if str
297
+ @description = str.strip.gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').gsub(/\n[ \t]*/, " ")
298
+ end
299
+ end
300
+
301
+ overwrite_accessor :default_executable do
302
+ return @default_executable if @default_executable
303
+ # Special case: if there is only one executable specified, then that's obviously the
304
+ # default one.
305
+ return @executables.first if @executables.size == 1
306
+ nil
307
+ end
308
+
309
+ def add_bindir(executables)
310
+ if(@executables.nil?)
311
+ return nil
312
+ end
313
+ if(@bindir)
314
+ @executables.map {|e| File.join(@bindir, e) }
315
+ else
316
+ @executables
317
+ end
318
+ end
319
+
320
+ overwrite_accessor :files do
321
+ (@files || []) | (@test_files || []) | (add_bindir(@executables) || []) |
322
+ (@extra_rdoc_files || []) | (@extensions || [])
323
+ end
324
+
325
+ overwrite_accessor :test_files do
326
+ # Handle the possibility that we have @test_suite_file but not @test_files. This will
327
+ # happen when an old gem is loaded via YAML.
328
+ if @test_suite_file
329
+ @test_files = [@test_suite_file].flatten
330
+ @test_suite_file = nil
331
+ end
332
+ @test_files ||= []
333
+ end
334
+
335
+ # ------------------------- Predicates.
336
+
337
+ def loaded?; @loaded ? true : false ; end
338
+ def has_rdoc?; has_rdoc ? true : false ; end
339
+ def has_unit_tests?; not test_files.empty?; end
340
+ alias has_test_suite? has_unit_tests? # (deprecated)
341
+
342
+ # ------------------------- Constructors.
343
+
344
+ ##
345
+ # Specification constructor. Assigns the default values to the attributes, adds this
346
+ # spec to the list of loaded specs (see Specification.list), and yields itself for
347
+ # further initialization.
348
+ #
349
+ def initialize
350
+ # Each attribute has a default value (possibly nil). Here, we initialize all
351
+ # attributes to their default value. This is done through the accessor
352
+ # methods, so special behaviours will be honored. Furthermore, we take a
353
+ # _copy_ of the default so each specification instance has its own empty
354
+ # arrays, etc.
355
+ @@attributes.each do |name, default|
356
+ self.send "#{name}=", copy_of(default)
357
+ end
358
+ @loaded = false
359
+ @@list << self
360
+ yield self if block_given?
361
+ @@gather.call(self) if @@gather
362
+ end
363
+
364
+ ##
365
+ # Special loader for YAML files. When a Specification object is loaded from a YAML file,
366
+ # it bypasses the normal Ruby object initialization routine (#initialize). This method
367
+ # makes up for that and deals with gems of different ages.
368
+ #
369
+ # 'input' can be anything that YAML.load() accepts: String or IO.
370
+ #
371
+ def Specification.from_yaml(input)
372
+ spec = YAML.load(input)
373
+ if(spec.class == FalseClass) then
374
+ raise Gem::EndOfYAMLException
375
+ end
376
+ unless Specification === spec
377
+ raise Gem::Exception, "YAML data doesn't evaluate to gem specification"
378
+ end
379
+ unless spec.instance_variable_get :@specification_version
380
+ spec.instance_variable_set :@specification_version, NONEXISTENT_SPECIFICATION_VERSION
381
+ end
382
+ spec
383
+ end
384
+
385
+ def Specification.load(filename)
386
+ gemspec = nil
387
+ fail "NESTED Specification.load calls not allowed!" if @@gather
388
+ @@gather = proc { |gs| gemspec = gs }
389
+ data = File.read(filename)
390
+ eval(data)
391
+ gemspec
392
+ ensure
393
+ @@gather = nil
394
+ end
395
+
396
+ # ------------------------- Instance methods.
397
+
398
+ ##
399
+ # Sets the rubygems_version to Gem::RubyGemsVersion.
400
+ #
401
+ def mark_version
402
+ @rubygems_version = RubyGemsVersion
403
+ end
404
+
405
+ ##
406
+ # Adds a dependency to this Gem. For example,
407
+ #
408
+ # spec.add_dependency('jabber4r', '> 0.1', '<= 0.5')
409
+ #
410
+ # gem:: [String or Gem::Dependency] The Gem name/dependency.
411
+ # requirements:: [default="> 0.0.0"] The version requirements.
412
+ #
413
+ def add_dependency(gem, *requirements)
414
+ requirements = ['> 0.0.0'] if requirements.empty?
415
+ requirements.flatten!
416
+ unless gem.respond_to?(:name) && gem.respond_to?(:version_requirements)
417
+ gem = Dependency.new(gem, requirements)
418
+ end
419
+ dependencies << gem
420
+ end
421
+
422
+ ##
423
+ # Returns the full name (name-version) of this Gem. Platform information is included
424
+ # (name-version-platform) if it is specified (and not the default Ruby platform).
425
+ #
426
+ def full_name
427
+ if platform == Gem::Platform::RUBY
428
+ "#{@name}-#{@version}"
429
+ else
430
+ "#{@name}-#{@version}-#{platform}"
431
+ end
432
+ end
433
+
434
+ ##
435
+ # The full path to the gem (install path + full name).
436
+ #
437
+ # return:: [String] the full gem path
438
+ #
439
+ def full_gem_path
440
+ File.join(installation_path, "gems", full_name)
441
+ end
442
+
443
+ ##
444
+ # The root directory that the gem was installed into.
445
+ #
446
+ # return:: [String] the installation path
447
+ #
448
+ def installation_path
449
+ (File.dirname(@loaded_from).split(File::SEPARATOR)[0..-2]).join(File::SEPARATOR)
450
+ end
451
+
452
+ ##
453
+ # Checks if this Specification meets the requirement of the supplied
454
+ # dependency.
455
+ #
456
+ # dependency:: [Gem::Dependency] the dependency to check
457
+ # return:: [Boolean] true if dependency is met, otherwise false
458
+ #
459
+ def satisfies_requirement?(dependency)
460
+ return @name == dependency.name &&
461
+ dependency.version_requirements.satisfied_by?(@version)
462
+ end
463
+
464
+ # ------------------------- Comparison methods.
465
+
466
+ ##
467
+ # Compare specs (name then version).
468
+ #
469
+ def <=>(other)
470
+ [@name, @version] <=> [other.name, other.version]
471
+ end
472
+
473
+ # Tests specs for equality (across all attributes).
474
+ def ==(other)
475
+ @@attributes.each do |name, default|
476
+ return false unless self.send(name) == other.send(name)
477
+ end
478
+ true
479
+ end
480
+
481
+ # ------------------------- Export methods (YAML and Ruby code).
482
+
483
+ # Returns an array of attribute names to be used when generating a YAML representation
484
+ # of this object. If an attribute still has its default value, it is omitted.
485
+ def to_yaml_properties
486
+ mark_version
487
+ @@attributes.map { |name, default| "@#{name}" }
488
+ end
489
+
490
+ # Returns a Ruby code representation of this specification, such that it can be
491
+ # eval'ed and reconstruct the same specification later. Attributes that still have
492
+ # their default values are omitted.
493
+ def to_ruby
494
+ mark_version
495
+ result = "Gem::Specification.new do |s|\n"
496
+ @@attributes.each do |name, default|
497
+ # TODO better implementation of next line (read_only_attribute? ... something like that)
498
+ next if name == :dependencies or name == :specification_version
499
+ current_value = self.send(name)
500
+ result << " s.#{name} = #{ruby_code(current_value)}\n" unless current_value == default
501
+ end
502
+ dependencies.each do |dep|
503
+ version_reqs_param = dep.requirements_list.inspect
504
+ result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})\n"
505
+ end
506
+ result << "end\n"
507
+ end
508
+
509
+ # ------------------------- Validation and normalization methods.
510
+
511
+ ##
512
+ # Checks that the specification contains all required fields, and
513
+ # does a very basic sanity check.
514
+ #
515
+ # Raises InvalidSpecificationException if the spec does not pass
516
+ # the checks..
517
+ def validate
518
+ normalize
519
+ if rubygems_version != RubyGemsVersion
520
+ raise InvalidSpecificationException.new(%[
521
+ Expected RubyGems Version #{RubyGemsVersion}, was #{rubygems_version}
522
+ ].strip)
523
+ end
524
+ @@required_attributes.each do |symbol|
525
+ unless self.send(symbol)
526
+ raise InvalidSpecificationException.new("Missing value for attribute #{symbol}")
527
+ end
528
+ end
529
+ if require_paths.empty?
530
+ raise InvalidSpecificationException.new("Gem spec needs to have at least one require_path")
531
+ end
532
+ end
533
+
534
+ ##
535
+ # Normalize the list of files so that:
536
+ # * All file lists have redundancies removed.
537
+ # * Files referenced in the extra_rdoc_files are included in the package file list.
538
+ #
539
+ # Also, the summary and description are converted to a normal format.
540
+ def normalize
541
+ if @extra_rdoc_files
542
+ @extra_rdoc_files.uniq!
543
+ @files ||= []
544
+ @files.concat(@extra_rdoc_files)
545
+ end
546
+ @files.uniq! if @files
547
+ end
548
+
549
+ # ------------------------- Dependency methods.
550
+
551
+ ##
552
+ # return:: [Array] [[dependent_gem, dependency, [list_of_satisfiers]]]
553
+ #
554
+ def dependent_gems
555
+ out = []
556
+ Gem.source_index.each do |name,gem|
557
+ gem.dependencies.each do |dep|
558
+ if self.satisfies_requirement?(dep) then
559
+ sats = []
560
+ find_all_satisfiers(dep) do |sat|
561
+ sats << sat
562
+ end
563
+ out << [gem, dep, sats]
564
+ end
565
+ end
566
+ end
567
+ out
568
+ end
569
+
570
+ def to_s
571
+ "#<Gem::Specification name=#{@name} version=#{@version}>"
572
+ end
573
+
574
+ private
575
+
576
+ def find_all_satisfiers(dep)
577
+ Gem.source_index.each do |name,gem|
578
+ if(gem.satisfies_requirement?(dep)) then
579
+ yield gem
580
+ end
581
+ end
582
+ end
583
+
584
+ # Duplicate an object unless it's an immediate value.
585
+ def self.copy_of(obj)
586
+ case obj
587
+ when Numeric, Symbol, true, false, nil then obj
588
+ else obj.dup
589
+ end
590
+ end
591
+
592
+ # Duplicate an object unless it's an immediate value.
593
+ def copy_of(obj)
594
+ self.class.copy_of(obj)
595
+ end
596
+
597
+ # Return a string containing a Ruby code representation of the given object.
598
+ def ruby_code(obj)
599
+ case obj
600
+ when String then '%q{' + obj + '}'
601
+ when Array then obj.inspect
602
+ when Gem::Version then obj.to_s.inspect
603
+ when Date, Time then '%q{' + obj.strftime('%Y-%m-%d') + '}'
604
+ when Numeric then obj.inspect
605
+ when true, false, nil then obj.inspect
606
+ when Gem::Version::Requirement then "Gem::Version::Requirement.new(#{obj.to_s.inspect})"
607
+ else raise Exception, "ruby_code case not handled: #{obj.class}"
608
+ end
609
+ end
610
+
611
+ end # class Specification
612
+ end # module Gem
613
+