summaryrefslogtreecommitdiff
path: root/trunk/lib/rubygems/indexer
diff options
context:
space:
mode:
authoryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-08-25 15:02:05 +0000
committeryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-08-25 15:02:05 +0000
commit0dc342de848a642ecce8db697b8fecd83a63e117 (patch)
tree2b7ed4724aff1f86073e4740134bda9c4aac1a39 /trunk/lib/rubygems/indexer
parentef70cf7138ab8034b5b806f466e4b484b24f0f88 (diff)
added tag v1_9_0_4
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_9_0_4@18845 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'trunk/lib/rubygems/indexer')
-rw-r--r--trunk/lib/rubygems/indexer/abstract_index_builder.rb88
-rw-r--r--trunk/lib/rubygems/indexer/latest_index_builder.rb35
-rw-r--r--trunk/lib/rubygems/indexer/marshal_index_builder.rb17
-rw-r--r--trunk/lib/rubygems/indexer/master_index_builder.rb54
-rw-r--r--trunk/lib/rubygems/indexer/quick_index_builder.rb50
5 files changed, 244 insertions, 0 deletions
diff --git a/trunk/lib/rubygems/indexer/abstract_index_builder.rb b/trunk/lib/rubygems/indexer/abstract_index_builder.rb
new file mode 100644
index 0000000000..5815dcda87
--- /dev/null
+++ b/trunk/lib/rubygems/indexer/abstract_index_builder.rb
@@ -0,0 +1,88 @@
+require 'zlib'
+
+require 'rubygems/indexer'
+
+# Abstract base class for building gem indicies. Uses the template pattern
+# with subclass specialization in the +begin_index+, +end_index+ and +cleanup+
+# methods.
+class Gem::Indexer::AbstractIndexBuilder
+
+ # Directory to put index files in
+ attr_reader :directory
+
+ # File name of the generated index
+ attr_reader :filename
+
+ # List of written files/directories to move into production
+ attr_reader :files
+
+ def initialize(filename, directory)
+ @filename = filename
+ @directory = directory
+ @files = []
+ end
+
+ ##
+ # Build a Gem index. Yields to block to handle the details of the
+ # actual building. Calls +begin_index+, +end_index+ and +cleanup+ at
+ # appropriate times to customize basic operations.
+
+ def build
+ FileUtils.mkdir_p @directory unless File.exist? @directory
+ raise "not a directory: #{@directory}" unless File.directory? @directory
+
+ file_path = File.join @directory, @filename
+
+ @files << @filename
+
+ File.open file_path, "wb" do |file|
+ @file = file
+ start_index
+ yield
+ end_index
+ end
+
+ cleanup
+ ensure
+ @file = nil
+ end
+
+ ##
+ # Compress the given file.
+
+ def compress(filename, ext="rz")
+ data = open filename, 'rb' do |fp| fp.read end
+
+ zipped = zip data
+
+ File.open "#{filename}.#{ext}", "wb" do |file|
+ file.write zipped
+ end
+ end
+
+ # Called immediately before the yield in build. The index file is open and
+ # available as @file.
+ def start_index
+ end
+
+ # Called immediately after the yield in build. The index file is still open
+ # and available as @file.
+ def end_index
+ end
+
+ # Called from within builder after the index file has been closed.
+ def cleanup
+ end
+
+ # Return an uncompressed version of a compressed string.
+ def unzip(string)
+ Zlib::Inflate.inflate(string)
+ end
+
+ # Return a compressed version of the given string.
+ def zip(string)
+ Zlib::Deflate.deflate(string)
+ end
+
+end
+
diff --git a/trunk/lib/rubygems/indexer/latest_index_builder.rb b/trunk/lib/rubygems/indexer/latest_index_builder.rb
new file mode 100644
index 0000000000..a5798580a6
--- /dev/null
+++ b/trunk/lib/rubygems/indexer/latest_index_builder.rb
@@ -0,0 +1,35 @@
+require 'rubygems/indexer'
+
+##
+# Construct the latest Gem index file.
+
+class Gem::Indexer::LatestIndexBuilder < Gem::Indexer::AbstractIndexBuilder
+
+ def start_index
+ super
+
+ @index = Gem::SourceIndex.new
+ end
+
+ def end_index
+ super
+
+ latest = @index.latest_specs.sort.map { |spec| spec.original_name }
+
+ @file.write latest.join("\n")
+ end
+
+ def cleanup
+ super
+
+ compress @file.path
+
+ @files.delete 'latest_index' # HACK installed via QuickIndexBuilder :/
+ end
+
+ def add(spec)
+ @index.add_spec(spec)
+ end
+
+end
+
diff --git a/trunk/lib/rubygems/indexer/marshal_index_builder.rb b/trunk/lib/rubygems/indexer/marshal_index_builder.rb
new file mode 100644
index 0000000000..e1a4d9f9b8
--- /dev/null
+++ b/trunk/lib/rubygems/indexer/marshal_index_builder.rb
@@ -0,0 +1,17 @@
+require 'rubygems/indexer'
+
+# Construct the master Gem index file.
+class Gem::Indexer::MarshalIndexBuilder < Gem::Indexer::MasterIndexBuilder
+ def end_index
+ gems = {}
+ index = Gem::SourceIndex.new
+
+ @index.each do |name, gemspec|
+ gems[gemspec.original_name] = gemspec
+ end
+
+ index.instance_variable_get(:@gems).replace gems
+
+ @file.write index.dump
+ end
+end
diff --git a/trunk/lib/rubygems/indexer/master_index_builder.rb b/trunk/lib/rubygems/indexer/master_index_builder.rb
new file mode 100644
index 0000000000..669ea5a1df
--- /dev/null
+++ b/trunk/lib/rubygems/indexer/master_index_builder.rb
@@ -0,0 +1,54 @@
+require 'rubygems/indexer'
+
+##
+# Construct the master Gem index file.
+
+class Gem::Indexer::MasterIndexBuilder < Gem::Indexer::AbstractIndexBuilder
+
+ def start_index
+ super
+ @index = Gem::SourceIndex.new
+ end
+
+ def end_index
+ super
+
+ @file.puts "--- !ruby/object:#{@index.class}"
+ @file.puts "gems:"
+
+ gems = @index.sort_by { |name, gemspec| gemspec.sort_obj }
+ gems.each do |name, gemspec|
+ yaml = gemspec.to_yaml.gsub(/^/, ' ')
+ yaml = yaml.sub(/\A ---/, '') # there's a needed extra ' ' here
+ @file.print " #{gemspec.original_name}:"
+ @file.puts yaml
+ end
+ end
+
+ def cleanup
+ super
+
+ index_file_name = File.join @directory, @filename
+
+ compress index_file_name, "Z"
+ paranoid index_file_name, "#{index_file_name}.Z"
+
+ @files << "#{@filename}.Z"
+ end
+
+ def add(spec)
+ @index.add_spec(spec)
+ end
+
+ private
+
+ def paranoid(path, compressed_path)
+ data = Gem.read_binary path
+ compressed_data = Gem.read_binary compressed_path
+
+ if data != unzip(compressed_data) then
+ raise "Compressed file #{compressed_path} does not match uncompressed file #{path}"
+ end
+ end
+
+end
diff --git a/trunk/lib/rubygems/indexer/quick_index_builder.rb b/trunk/lib/rubygems/indexer/quick_index_builder.rb
new file mode 100644
index 0000000000..dc36179dc5
--- /dev/null
+++ b/trunk/lib/rubygems/indexer/quick_index_builder.rb
@@ -0,0 +1,50 @@
+require 'rubygems/indexer'
+
+##
+# Construct a quick index file and all of the individual specs to support
+# incremental loading.
+
+class Gem::Indexer::QuickIndexBuilder < Gem::Indexer::AbstractIndexBuilder
+
+ def initialize(filename, directory)
+ directory = File.join directory, 'quick'
+
+ super filename, directory
+ end
+
+ def cleanup
+ super
+
+ quick_index_file = File.join @directory, @filename
+ compress quick_index_file
+
+ # the complete quick index is in a directory, so move it as a whole
+ @files.delete 'index'
+ @files << 'quick'
+ end
+
+ def add(spec)
+ @file.puts spec.original_name
+ add_yaml(spec)
+ add_marshal(spec)
+ end
+
+ def add_yaml(spec)
+ fn = File.join @directory, "#{spec.original_name}.gemspec.rz"
+ zipped = zip spec.to_yaml
+ File.open fn, "wb" do |gsfile| gsfile.write zipped end
+ end
+
+ def add_marshal(spec)
+ # HACK why does this not work in #initialize?
+ FileUtils.mkdir_p File.join(@directory, "Marshal.#{Gem.marshal_version}")
+
+ fn = File.join @directory, "Marshal.#{Gem.marshal_version}",
+ "#{spec.original_name}.gemspec.rz"
+
+ zipped = zip Marshal.dump(spec)
+ File.open fn, "wb" do |gsfile| gsfile.write zipped end
+ end
+
+end
+