Class Gem::Indexer
In: lib/rubygems/indexer.rb
Parent: Object

Top level class for building the gem repository index.

Methods

Included Modules

Gem::UserInteraction

Attributes

dest_directory  [R]  Index install location
directory  [R]  Index build directory

Public Class methods

Create an indexer that will index the gems in directory.

[Source]

    # File lib/rubygems/indexer.rb, line 32
32:   def initialize(directory)
33:     unless ''.respond_to? :to_xs then
34:       fail "Gem::Indexer requires that the XML Builder library be installed:" \
35:            "\n\tgem install builder"
36:     end
37: 
38:     @dest_directory = directory
39:     @directory = File.join Dir.tmpdir, "gem_generate_index_#{$$}"
40: 
41:     marshal_name = "Marshal.#{Gem.marshal_version}"
42: 
43:     @master_index = Gem::Indexer::MasterIndexBuilder.new "yaml", @directory
44:     @marshal_index = Gem::Indexer::MarshalIndexBuilder.new marshal_name, @directory
45:     @quick_index = Gem::Indexer::QuickIndexBuilder.new 'index', @directory
46: 
47:     quick_dir = File.join @directory, 'quick'
48:     @latest_index = Gem::Indexer::LatestIndexBuilder.new 'latest_index', quick_dir
49:   end

Public Instance methods

Abbreviate the spec for downloading. Abbreviated specs are only used for searching, downloading and related activities and do not need deployment specific information (e.g. list of files). So we abbreviate the spec, making it much smaller for quicker downloads.

[Source]

     # File lib/rubygems/indexer.rb, line 141
141:   def abbreviate(spec)
142:     spec.files = []
143:     spec.test_files = []
144:     spec.rdoc_options = []
145:     spec.extra_rdoc_files = []
146:     spec.cert_chain = []
147:     spec
148:   end

Build the index.

[Source]

     # File lib/rubygems/indexer.rb, line 54
 54:   def build_index
 55:     @master_index.build do
 56:       @quick_index.build do
 57:         @marshal_index.build do
 58:           @latest_index.build do
 59:             progress = ui.progress_reporter gem_file_list.size,
 60:                                           "Generating index for #{gem_file_list.size} gems in #{@dest_directory}",
 61:                                           "Loaded all gems"
 62: 
 63:                                           gem_file_list.each do |gemfile|
 64:               if File.size(gemfile.to_s) == 0 then
 65:                 alert_warning "Skipping zero-length gem: #{gemfile}"
 66:                 next
 67:               end
 68: 
 69:               begin
 70:                 spec = Gem::Format.from_file_by_path(gemfile).spec
 71: 
 72:                 unless gemfile =~ /\/#{Regexp.escape spec.original_name}.*\.gem\z/i then
 73:                   alert_warning "Skipping misnamed gem: #{gemfile} => #{spec.full_name} (#{spec.original_name})"
 74:                   next
 75:                 end
 76: 
 77:                 abbreviate spec
 78:                 sanitize spec
 79: 
 80:                 @master_index.add spec
 81:                 @quick_index.add spec
 82:                 @marshal_index.add spec
 83:                 @latest_index.add spec
 84: 
 85:                 progress.updated spec.original_name
 86: 
 87:               rescue SignalException => e
 88:                 alert_error "Received signal, exiting"
 89:                 raise
 90:               rescue Exception => e
 91:                 alert_error "Unable to process #{gemfile}\n#{e.message} (#{e.class})\n\t#{e.backtrace.join "\n\t"}"
 92:               end
 93:                                           end
 94: 
 95:             progress.done
 96: 
 97:             say "Generating master indexes (this may take a while)"
 98:           end
 99:         end
100:       end
101:     end
102:   end

List of gem file names to index.

[Source]

     # File lib/rubygems/indexer.rb, line 133
133:   def gem_file_list
134:     Dir.glob(File.join(@dest_directory, "gems", "*.gem"))
135:   end

[Source]

     # File lib/rubygems/indexer.rb, line 121
121:   def generate_index
122:     FileUtils.rm_rf @directory
123:     FileUtils.mkdir_p @directory, :mode => 0700
124: 
125:     build_index
126:     install_index
127:   rescue SignalException
128:   ensure
129:     FileUtils.rm_rf @directory
130:   end

[Source]

     # File lib/rubygems/indexer.rb, line 104
104:   def install_index
105:     verbose = Gem.configuration.really_verbose
106: 
107:     say "Moving index into production dir #{@dest_directory}" if verbose
108: 
109:     files = @master_index.files + @quick_index.files + @marshal_index.files +
110:             @latest_index.files
111: 
112:     files.each do |file|
113:       src_name = File.join @directory, file
114:       dst_name = File.join @dest_directory, file
115: 
116:       FileUtils.rm_rf dst_name, :verbose => verbose
117:       FileUtils.mv src_name, @dest_directory, :verbose => verbose
118:     end
119:   end

Sanitize the descriptive fields in the spec. Sometimes non-ASCII characters will garble the site index. Non-ASCII characters will be replaced by their XML entity equivalent.

[Source]

     # File lib/rubygems/indexer.rb, line 153
153:   def sanitize(spec)
154:     spec.summary = sanitize_string(spec.summary)
155:     spec.description = sanitize_string(spec.description)
156:     spec.post_install_message = sanitize_string(spec.post_install_message)
157:     spec.authors = spec.authors.collect { |a| sanitize_string(a) }
158:     spec
159:   end

Sanitize a single string.

[Source]

     # File lib/rubygems/indexer.rb, line 162
162:   def sanitize_string(string)
163:     # HACK the #to_s is in here because RSpec has an Array of Arrays of
164:     # Strings for authors.  Need a way to disallow bad values on gempsec
165:     # generation.  (Probably won't happen.)
166:     string ? string.to_s.to_xs : string
167:   end

[Validate]