#!/usr/bin/env ruby $: << File.expand_path('../../lib', __FILE__) require 'rubygems' require 'yaml' require 'optparse' require 'fileutils' require 'ridgepole' $stdout.sync = true $stderr.sync = true Version = Ridgepole::VERSION DEFAULT_FILENAME = 'Schemafile' config = nil mode = nil file = DEFAULT_FILENAME output_file = '-' split = false options = { :dry_run => false, :debug => false, } set_mode = proc do |m| raise 'More than one mode is specified' if mode mode = m end ARGV.options do |opt| begin opt.on('-c', '--config CONF_OR_FILE') {|v| config = v } opt.on('-a', '--apply') { set_mode[:apply] } opt.on('-m', '--merge') { set_mode[:apply]; options[:merge] = true } opt.on('-f', '--file FILE') {|v| file = v } opt.on('', '--dry-run') { options[:dry_run] = true } opt.on('-e', '--export') { set_mode[:export] } opt.on('', '--split') {|v| split = true } opt.on('', '--split-with-dir') {|v| split = :with_dir } opt.on('-o', '--output FILE') {|v| output_file = v } opt.on('-t', '--tables TABLES', Array) {|v| options[:tables] = v } opt.on('', '--ignore-tables TABLES', Array) {|v| options[:ignore_tables] = v.map {|i| Regexp.new(i) } } opt.on('', '--disable-mysql-unsigned') { options[:disable_mysql_unsigned] = true } opt.on('' , '--verbose') { Ridgepole::Logger.verbose = true } opt.on('' , '--debug') { options[:debug] = true } opt.parse! unless config and mode puts opt.help exit 1 end rescue => e $stderr.puts("[ERROR] #{e.message}") exit 1 end end begin logger = Ridgepole::Logger.instance logger.set_debug(options[:debug]) config = open(config) {|f| f.read } if File.exist?(config) config = YAML.load(config) client = Ridgepole::Client.new(config, options) case mode when :export if split logger.info('Export Schema') output_file = DEFAULT_FILENAME if output_file == '-' requires = [] client.dump do |name, definition| schema_dir = File.dirname(output_file) schema_dir = File.join(schema_dir, name) if split == :with_dir schema_file = File.join(schema_dir, "#{name}.schema") require_path = File.basename(schema_file) require_path = File.join(name, require_path) if split == :with_dir requires << require_path logger.info(" write `#{schema_file}`") FileUtils.mkdir_p(schema_dir) open(schema_file, 'wb') do |f| f.puts definition end end logger.info(" write `#{output_file}`") open(output_file, 'wb') do |f| requires.each do |require_path| f.puts "require '#{require_path}'" end end else if output_file == '-' logger.info('# Export Schema') puts client.dump else logger.info("Export Schema to `#{output_file}`") open(output_file, 'wb') {|f| f.puts client.dump } end end when :apply unless File.exist?(file) raise "No Schemafile found (looking for: #{file})" end msg = (options[:merge] ? 'Merge' : 'Apply') + " `#{file}`" msg << ' (dry-run)' if options[:dry_run] logger.info(msg) dsl = open(file) {|f| f.read } delta = client.diff(dsl, :path => file) if options[:dry_run] puts delta.script if delta.differ? else logger.verbose_info('# Update schema') delta.migrate end unless delta.differ? logger.info('No change') end end rescue => e if options[:debug] raise e else $stderr.puts("[ERROR] #{e.message}") exit 1 end end