class XMigra::Program

Constants

ILLEGAL_FILENAME_CHARS
ILLEGAL_PATH_CHARS

Public Class Methods

argument_error_unless(test, message) click to toggle source
# File lib/xmigra/program.rb, line 243
def argument_error_unless(test, message)
  return if test
  raise ArgumentError, XMigra.program_message(message, :cmd=>@active_subcommand)
end
command_line(argv, use, cmdopts = {}) click to toggle source
# File lib/xmigra/program.rb, line 90
      def command_line(argv, use, cmdopts = {})
        options = OpenStruct.new
        argument_desc = cmdopts[:argument_desc]
        
        optparser = OptionParser.new do |flags|
          subcmd = @active_subcommand || "<subcmd>"
          flags.banner = [
            "Usage: #{File.basename($0)} #{subcmd} [<options>]",
            argument_desc
          ].compact.join(' ')
          flags.banner << "\n\n" + cmdopts[:help].chomp if cmdopts[:help]
          
          flags.separator ''
          flags.separator 'Subcommand options:'
          
          if use[:source_file_type]
            options.source_file_type = nil
            [
              '--migration migration',
              '--view view',
              '--procedure stored procedure',
              '--function user defined function',
              '--index index',
            ].each do |opt|
              flag, desc = opt.split(' ', 2)
              flags.on(flag, "Select #{desc} as the source file type") do
                set_source_type(options, flag[2..-1].to_sym)
              end
            end
          end
          
          if use[:target_type]
            options.target_type = :unspecified
            allowed = [:exact, :substring, :regexp]
            flags.on(
              "--by=TYPE", allowed,
              "Specify how TARGETs are matched",
              "  against subject strings",
              "  (#{allowed.collect {|i| i.to_s}.join(', ')})"
            ) do |type|
              options.target_type = type
            end
          end
          
          if use[:dev_branch]
            options.dev_branch = false
            flags.on("--dev-branch", "Favor development branch usage assumption") do
              options.dev_branch = true
            end
          end
          
          unless use[:edit].nil?
            options.edit = use[:edit] ? true : false
            flags.banner << "\n\n" << (<<END_OF_HELP).chomp
When opening an editor, the program specified by the environment variable
VISUAL is preferred, then the one specified by EDITOR.  If neither of these
environment variables is set no editor will be opened.
END_OF_HELP
            flags.on("--[no-]edit", "Open the resulting file in an editor",
                     "  (defaults to #{options.edit})") do |v|
              options.edit = %w{EDITOR VISUAL}.any? {|k| ENV.has_key?(k)} && v
            end
          end
          
          if use[:search_type]
            options.search_type = :changes
            allowed = [:changes, :sql]
            flags.on(
              "--match=SUBJECT", allowed,
              "Specify the type of subject against",
              "  which TARGETs match",
              "  (#{allowed.collect {|i| i.to_s}.join(', ')})"
            ) do |type|
              options.search_type = type
            end
          end
          
          if use[:permissions_too]
            options.include_permissions = nil
            flags.on("--[no-]grants-included",
                     "Include (or exclude) permission grants",
                     "  (overrides setting in #{SchemaManipulator::DBINFO_FILE})") do |v|
              options.include_permissions = v
            end
          end
          
          if use[:outfile]
            options.outfile = nil
            flags.on("-o", "--outfile=FILE", "Output to FILE") do |fpath|
              options.outfile = File.expand_path(fpath)
            end
          end
          
          if use[:production]
            options.production = false
            flags.on("-p", "--production", "Generate script for production databases") do 
              options.production = true
            end
          end
          
          if use[:dry_run]
            options.dry_run = false
            flags.on("--dry-run", "Generated script will test commands", 
                     "  without committing changes") do
              options.dry_run = true
            end
          end
          
          if use[:impdecl_mode]
            options.impdecl_special = {}
            flags.on("--adopt", "New declarative adopts existing object") do
              options.impdecl_special[:adopt] = true
            end
            flags.on("--renounce", "Deleted declarative releases object",
                     "  from declarative management") do
              options.impdecl_special[:renounce] = true
            end
          end
          
          options.source_dir = Dir.pwd
          flags.on("--source=DIR", "Work from/on the schema in DIR") do |dir|
            options.source_dir = File.expand_path(dir)
          end
          
          flags.on_tail("-h", "--help", "Show this message") do
            puts
            puts flags
            raise TerminatingOption.new('--help')
          end
        end
        
        argv = optparser.parse(argv)
        
        if use[:target_type] && options.target_type == :unspecified
          options.target_type = case options.search_type
          when :changes then :strict
          else :substring
          end
        end
        
        return argv, options
      end
edit(fpath) click to toggle source
# File lib/xmigra/program.rb, line 248
def edit(fpath)
  case
  when (editor = ENV['VISUAL']) && PLATFORM == :mswin
    system(%Q{start #{editor} "#{fpath}"})
  when editor = ENV['VISUAL']
    system(%Q{#{editor} "#{fpath}" &})
  when editor = ENV['EDITOR']
    system(%Q{#{editor} "#{fpath}"})
  end
end
help(argv) click to toggle source
# File lib/xmigra/program.rb, line 54
def help(argv)
  if (argv.length != 1) || (argv[0] == '--help')
    show_subcommands
    return
  end
  
  argv << "--help"
  run(argv)
end
output_to(fpath_or_nil) { |$stdout| ... } click to toggle source
# File lib/xmigra/program.rb, line 233
def output_to(fpath_or_nil)
  if fpath_or_nil.nil?
    yield($stdout)
  else
    File.open(fpath_or_nil, "w") do |stream|
      yield(stream)
    end
  end
end
run(*argv) click to toggle source

Run the given command line.

An array of command line arguments may be given as the only argument or arguments may be given as call parameters. Returns nil if the command completed or a TerminatingOption object if a terminating option (typically “–help”) was passed.

# File lib/xmigra/program.rb, line 24
def run(*argv)
  options = (Hash === argv.last) ? argv.pop : {}
  argv = argv[0] if argv.length == 1 && Array === argv[0]
  prev_subcommand = @active_subcommand
  begin
    @active_subcommand = subcmd = argv.shift
    
    begin
      if subcmd == "help" || subcmd.nil?
        help(argv)
        return
      end
      
      begin
        (@subcommands[subcmd] || method(:show_subcommands_as_help)).call(argv)
      rescue StandardError => error
        raise unless options[:error]
        options[:error].call(error)
      end
    rescue TerminatingOption => stop
      return stop
    rescue Plugin::LoadingError => error
      $stderr.puts error.message
      exit 1
    end
  ensure
    @active_subcommand = prev_subcommand
  end
end
set_source_type(options, type) click to toggle source
# File lib/xmigra/program.rb, line 259
def set_source_type(options, type)
  argument_error_unless(
    [nil, type].include?(options.source_file_type),
    "Source type cannot be #{options.source_file_type} and #{type}"
  )
  options.source_file_type = type
end
show_subcommands(_1=nil) click to toggle source
# File lib/xmigra/program.rb, line 64
def show_subcommands(_1=nil)
  puts
  puts "Use '#{File.basename($0)} help <subcommand>' for help on one of these subcommands:"
  puts
  
  descs = @subcommand_descriptions
  cmd_width = descs.enum_for(:each_key).max_by {|i| i.length}.length + 2
  descs.each_pair do |cmd, description|
    printf("%*s - ", cmd_width, cmd)
    description.lines.each_with_index do |line, i|
      indent = if (i > 0)..(i == description.lines.count - 1)
        cmd_width + 3
      else
        0
      end
      puts(" " * indent + line.chomp)
    end
  end
  puts
end
show_subcommands_as_help(_1=nil) click to toggle source
# File lib/xmigra/program.rb, line 85
def show_subcommands_as_help(_1=nil)
  show_subcommands
  raise ArgumentError.new("Invalid subcommand").extend(QuietError)
end
subcommand(name, description, &block) click to toggle source
# File lib/xmigra/program.rb, line 13
def subcommand(name, description, &block)
  (@subcommands ||= {})[name] = block
  (@subcommand_descriptions ||= {})[name] = description
end