#!/usr/bin/env ruby require 'optparse' require 'pathname' # # add relative paths to the load path if we are not a gem and calculate what the # strip path will be if we decide to pack --self # this_path = Pathname.new( File.expand_path( __FILE__ ) ) gem_path = Pathname.new( Gem.dir ) rel_path = this_path.relative_path_from( gem_path ) if ".." == rel_path.to_s.split( File::SEPARATOR ).first then lib_path = File.join( File.dirname( __FILE__ ), "../lib" ) $:.unshift lib_path $:.unshift File.join( File.dirname( __FILE__ ), "../ext" ) end # # snapshot of what is needed for amalgalite requires, this info may only be used # when packing amalgalite itself # loaded_features_before = $LOADED_FEATURES.dup require 'amalgalite/packer' loaded_features_after = $LOADED_FEATURES.dup load_diff = loaded_features_after - loaded_features_before # # strip off any LOAD_PATH elements from the front of load_diff since that # will conflict with Amalgalite::Packer.amalgalite_require_order. Also # strip out any 'rubygems' items since those are not used by Amalgalite # and show as a side effect fo the "require 'amalgalite/packer'" # strip_paths = $LOAD_PATH.sort.reverse amalgalite_needs = [] load_diff.each do |f| next if f.split( File::SEPARATOR ).include?( "rubygems" ) appended = false strip_paths.each do |path| if 0 == f.index(path ) then rel_path = f.sub( path, '' ).sub(%r{\A#{File::SEPARATOR}},'') amalgalite_needs << rel_path appended = true break end end amalgalite_needs << f unless appended end # # Commandline parser # options = {} begin parser = OptionParser.new do |op| op.banner = "Usage: #{op.program_name} [options] " op.separator "" op.on("--dbfile DB", "The Database file in which to pack files") do |d| options[:dbfile] = d end op.on("--drop-table", "Drop the table before inserting rows") do |t| options[:drop_table] = t end op.on("-m", "--merge", "Merge these files into the existing table overwriting rows that conflict") do |m| options[:merge] = true end op.on("--require-order", "Dump Amalgalite's require order" ) do |m| puts amalgalite_needs exit 0 end op.on("--self", "pack amalgalite itself into the database") do |d| options[:self] = true end op.on("--strip-prefix PREFIX", "strip this path prefix off the front of each file") do |p| options[:strip_prefix] = File.expand_path( p ) end op.on("-t", "--table TABLE", "the table name to pack into") do |t| options[:table_name] = t end op.on("--verbose", "Be verbose about output") do |v| options[:verbose] = v end op.on("-z", "--compressed", "compress the file contents on storage") do |z| options[:compressed] = true end end parser.parse! require 'amalgalite/packer' file_list = ARGV.dup if options[:self] then options[:table_name] = Amalgalite::Requires::Bootstrap::DEFAULT_BOOTSTRAP_TABLE core_libs = (amalgalite_needs - Amalgalite::Packer.amalgalite_require_order).delete_if { |l| l.index(".rb").nil? } # # check and make sure nothing is missed # core_libs.each do |l| if l.index("amalgalite") then STDERR.puts "ERROR! require_order needs an update #{l}" exit 2 end end file_list = core_libs.concat( Amalgalite::Packer.amalgalite_require_order ) if options[:compressed] then STDERR.puts "Compressing --self is not allowed, reverting to uncompressed" options[:compressed] = false end end STDERR.puts parser if file_list.empty? packer = Amalgalite::Packer.new( options ) packer.pack( file_list ) rescue OptionParser::ParseError => pe STDERR.puts "ERROR : #{pe}" STDERR.puts parser exit 1 end __END__ puts <<-text Packing complete. To utilize the bootstrapping in #{dbfile} you must do one of the following: * statically compile the amalgalite C extension into your application * require 'amalgalite/#{RUBY_VERSION.sub(/\.\d$/,'')}/amalgalite3' Once one of those is working you can boostrap the Amalgalite library with this line in your code: Amalgalite::Requries::Boostrap.lift( 'dbfile' => '#{dbfile}' ) text