#!/usr/bin/env jruby
# -*- coding: utf-8 -*-

# This script is for use with JRuby, to copy the (patched) stdlib and external test files from
# various locations in MRI's layout to JRuby's layout. It should be used
# against the jruby-specific fork of MRI's repository at
# github.com/jruby/ruby. 
#
# This script selects the branch to use against with the version number, i.e: jruby-ruby_1_8_7 or jruby-ruby_1_9_3.
#
# usage: sync_ruby <tests|stdlib|all> <version(1_8_7|1_9_3|2_0_0)> <jruby ruby fork clone> <jruby dir>
#
# Example:
# 
# The JRuby ruby fork is in ../jruby-ruby, and jruby is in the current directory.
# We want to sync both 1.8.7 standard libraries.
# 
# $ jruby tool/sync_ruby stdlib 1_8_7 ../jruby-ruby .
# ~/projects/jruby ➔ jruby tool/sync_ruby stdlib 1_8_7 ../jruby-ruby .
# Already on 'jruby-ruby_1_8_7'
# cp -r ../jruby-ruby/lib/English.rb ./lib/ruby/1.8
# cp -r ../jruby-ruby/lib/Env.rb ./lib/ruby/1.8
# ...

require 'fileutils'

class Sync
  include FileUtils

  def initialize(type, version, source, target)
    @type = type
    @named_version = version
    @version = format_version(version)
    @source = source
    @target = target

    checkout
  end

  def sync_tests
    Dir.glob("#{@source}/test/*") do |file|
      cp_r file, "#{@target}/test/externals/ruby#{@version}", :verbose => true
    end
  end

  def sync_stdlib
    load File.dirname(__FILE__) + "/globals_#{@named_version}.rb"

    for file in STDLIB_FILES
      cp_r "#{@source}/lib/#{file}", "#{@target}/lib/ruby/#{@version}", :verbose => true
    end

    for file, target in EXT_FILES
      if File.directory? "#{@source}/#{file}"
        cp_r "#{@source}/#{file}", "#{@target}/lib/ruby/#{@version}/", :verbose => true
      else
        cp_r "#{@source}/#{file}", "#{@target}/lib/ruby/#{@version}/#{target}", :verbose => true
      end
    end
  end

  def sync_rubygems
    if Dir.pwd != File.expand_path('../..', __FILE__) || @target != '.'
      $stderr.puts "Rubygems is sync'd into the jruby where this script was launched."
      $stderr.puts "To acknowledge this, run in the top level of that jruby tree and use a target of `.'."
      raise ArgumentError, "Sync Rubygems target mismatch"
    end
    (Dir["#@target/lib/ruby/site_ruby/1.8/*ubygems"] + ["#@target/lib/ruby/site_ruby/1.8/rbconfig"]).each do |f|
      rm_rf f
    end
    cd(@source) do
      system "ruby setup.rb --no-format-executable --no-ri --no-rdoc"
    end
    gem_script = File.join(@target, "bin", "gem")

    # Fix up shebang so it doesn't have abs path
    lines = IO.readlines gem_script
    lines[0] = "#!/usr/bin/env jruby\n"
    File.open(gem_script, "wb") {|f| lines.each {|l| f << l } }
    cp File.join(@target, "bin", "gem"), File.join(@target, "bin", "jgem")
  end

  private
  def format_version(version)
    version.gsub(/_\d+$/, '').gsub(/_/, '.')
  end

  def checkout
    cd(@source) do
      branch = "jruby-ruby#{@type == 'rubygems' ? 'gems' : ''}_#{@named_version}"

      if (branches = `git branch | sed 's/[\*\s]*//'`).split("\n").include? branch
        `git checkout #{branch}`
      else
        `git checkout -t origin/#{branch}`
      end
    end
  end
end

if $0 == __FILE__
  if ARGV.size != 4
    puts "usage: sync_ruby <tests|stdlib|rubygems|all> <version(1_8_7|1_9_3)> <jruby ruby(gems) fork clone> <jruby dir>"
    exit 1
  end

  if !%w{tests stdlib rubygems all}.include? ARGV[0]
    puts "invalid source to sync: #{ARGV[0]}"
    exit 1
  end

  if !(ARGV[1] =~ /\d+_\d+_\d+/)
    puts "invalid version number: #{ARGV[1]}"
    exit 1
  end

  if !File.exist?(ARGV[2]) || !File.directory?(ARGV[2])
    puts "invalid source dir: #{ARGV[2]}"
    exit 1
  end

  if !File.exist?(ARGV[3]) || !File.directory?(ARGV[2])
    puts "invalid target dir: #{ARGV[2]}"
    exit 1
  end

  sync = Sync.new(*ARGV)
  if ARGV[0] == 'all'
    sync.sync_tests
    sync.sync_stdlib
  else
    sync.send(:"sync_#{ARGV[0]}")
  end
end
