#!/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] <files>"
    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
