module Sqldef

Constants

COMMANDS
ENVS
GOARCH
VERSION

Attributes

bin[RW]

Public Class Methods

apply(command:, path:, host:, port: nil, user:, password: nil, database:) click to toggle source

@param [String,Symbol] command - mysqldef, psqldef, sqllite3def @param [String] path - Schema file path

# File lib/sqldef.rb, line 69
def apply(command:, path:, host:, port: nil, user:, password: nil, database:)
  sqldef = download(command)
  execute(
    env(command), sqldef,
    "--user=#{user}", *(["--password=#{password}"] if password),
    "--host=#{host}", *(["--port=#{port}"] if port),
    database,
    in: path,
  )
end
download(command) click to toggle source

@param [String,Symbol] command - mysqldef, psqldef, sqllite3def @return String - command path

# File lib/sqldef.rb, line 82
def download(command)
  path = File.join(bin, command = command.to_s)
  return path if File.executable?(path)

  print("Downloading '#{command}' under '#{bin}'... ")
  resp = get(build_url(command), code: 302) # Latest
  resp = get(resp['location'],   code: 302) # vX.Y.Z
  resp = get(resp['location'],   code: 200) # Binary

  gzip = Zlib::GzipReader.new(StringIO.new(resp.body))
  Gem::Package::TarReader.new(gzip) do |tar|
    unless file = tar.find { |f| f.full_name == command }
      raise "'#{command}' was not found in the archive"
    end
    File.binwrite(path, file.read)
  end

  FileUtils.chmod('+x', path)
  puts 'done.'
  path
end
dry_run(command:, path:, host:, port: nil, user:, password: nil, database:) click to toggle source

@param [String,Symbol] command - mysqldef, psqldef, sqllite3def @param [String] path - Schema file path

# File lib/sqldef.rb, line 56
def dry_run(command:, path:, host:, port: nil, user:, password: nil, database:)
  sqldef = download(command)
  execute(
    env(command), sqldef,
    "--user=#{user}", *(["--password=#{password}"] if password),
    "--host=#{host}", *(["--port=#{port}"] if port),
    '--dry-run', database,
    in: path,
  )
end
export(command:, path:, host:, port: nil, user:, password: nil, database:) click to toggle source

@param [String,Symbol] command - mysqldef, psqldef, sqllite3def @param [String] path - Schema export path

# File lib/sqldef.rb, line 39
def export(command:, path:, host:, port: nil, user:, password: nil, database:)
  sqldef = download(command)
  schema = IO.popen(
    [
      env(command), sqldef,
      "--user=#{user}", *(["--password=#{password}"] if password),
      "--host=#{host}", *(["--port=#{port}"] if port),
      '--export', database,
    ],
    &:read
  )
  raise "Failed to execute '#{sqldef}'" unless $?.success?
  File.write(path, schema)
end

Private Class Methods

build_url(command) click to toggle source
# File lib/sqldef.rb, line 116
def build_url(command)
  unless COMMANDS.include?(command)
    raise "Unexpected sqldef command: #{command}" 
  end
  os = Etc.uname.fetch(:sysname).downcase
  arch = GOARCH.fetch(Etc.uname.fetch(:machine))
  "https://github.com/k0kubun/sqldef/releases/latest/download/#{command}_#{os}_#{arch}.tar.gz"
end
env(command) click to toggle source
# File lib/sqldef.rb, line 112
def env(command)
  ENVS.fetch(command.to_s, {})
end
execute(*cmd, **opts) click to toggle source
# File lib/sqldef.rb, line 106
def execute(*cmd, **opts)
  unless system(*cmd, **opts)
    raise "Failed to execute '#{cmd.first.is_a?(Hash) ? cmd[1] : cmd.first}'"
  end
end
get(url, code: nil) click to toggle source

TODO: Retry transient errors

# File lib/sqldef.rb, line 126
def get(url, code: nil)
  uri = URI.parse(url)
  Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
    http.get("#{uri.path}?#{uri.query}")
  end.tap do |resp|
    if code && resp.code != code.to_s
      raise "Expected '#{url}' to return #{code}, but got #{resp.code}: #{resp.body}"
    end
  end
end