Skip to content

Commit c9a94d1

Browse files
committed
Implement Sqldef
1 parent 7766be0 commit c9a94d1

File tree

2 files changed

+124
-4
lines changed

2 files changed

+124
-4
lines changed

lib/sqldef.rb

Lines changed: 123 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,128 @@
11
# frozen_string_literal: true
22

3-
require_relative "sqldef/version"
3+
require 'etc'
4+
require 'fileutils'
5+
require 'net/http'
6+
require 'rubygems/package'
7+
require 'stringio'
8+
require 'uri'
9+
require 'zlib'
10+
require_relative 'sqldef/version'
411

512
module Sqldef
6-
class Error < StandardError; end
7-
# Your code goes here...
13+
GOARCH = {
14+
'x86_64' => 'amd64',
15+
'aarch64' => 'arm64',
16+
# TODO: add arm and 386
17+
}
18+
private_constant :GOARCH
19+
20+
COMMANDS = %w[
21+
mysqldef
22+
psqldef
23+
sqlite3def
24+
]
25+
private_constant :COMMANDS
26+
27+
@bin = Dir.pwd
28+
29+
class << self
30+
attr_accessor :bin
31+
32+
# @param [String,Symbol] command - mysqldef, psqldef, sqllite3def
33+
# @param [String] path - Schema export path
34+
def export(command:, path:, host:, port: nil, user:, password: nil, database:)
35+
sqldef = download(command)
36+
schema = IO.popen(
37+
[
38+
sqldef,
39+
"--user=#{user}", *(["--password=#{password}"] if password),
40+
"--host=#{host}", *(["--port=#{port}"] if port),
41+
'--export', database,
42+
],
43+
&:read
44+
)
45+
raise "Failed to execute '#{sqldef}'" unless $?.success?
46+
File.write(path, schema)
47+
end
48+
49+
# @param [String,Symbol] command - mysqldef, psqldef, sqllite3def
50+
# @param [String] path - Schema file path
51+
def dry_run(command:, path:, host:, port: nil, user:, password: nil, database:)
52+
sqldef = download(command)
53+
execute(
54+
sqldef,
55+
"--user=#{user}", *(["--password=#{password}"] if password),
56+
"--host=#{host}", *(["--port=#{port}"] if port),
57+
'--dry-run', database,
58+
in: path,
59+
)
60+
end
61+
62+
# @param [String,Symbol] command - mysqldef, psqldef, sqllite3def
63+
# @param [String] path - Schema file path
64+
def apply(command:, path:, host:, port: nil, user:, password: nil, database:)
65+
sqldef = download(command)
66+
execute(
67+
sqldef,
68+
"--user=#{user}", *(["--password=#{password}"] if password),
69+
"--host=#{host}", *(["--port=#{port}"] if port),
70+
database,
71+
in: path,
72+
)
73+
end
74+
75+
# @param [String,Symbol] command - mysqldef, psqldef, sqllite3def
76+
# @return String - command path
77+
def download(command)
78+
path = File.join(bin, command = command.to_s)
79+
return path if File.executable?(path)
80+
81+
print("Downloading '#{command}' under '#{bin}'... ")
82+
resp = get(build_url(command), code: 302) # Latest
83+
resp = get(resp['location'], code: 302) # vX.Y.Z
84+
resp = get(resp['location'], code: 200) # Binary
85+
86+
gzip = Zlib::GzipReader.new(StringIO.new(resp.body))
87+
Gem::Package::TarReader.new(gzip) do |tar|
88+
unless file = tar.find { |f| f.full_name == command }
89+
raise "'#{command}' was not found in the archive"
90+
end
91+
File.binwrite(path, file.read)
92+
end
93+
94+
FileUtils.chmod('+x', path)
95+
puts 'done.'
96+
path
97+
end
98+
99+
private
100+
101+
def execute(*cmd, **opts)
102+
unless system(*cmd, **opts)
103+
raise "Failed to execute '#{cmd.first}'"
104+
end
105+
end
106+
107+
def build_url(command)
108+
unless COMMANDS.include?(command)
109+
raise "Unexpected sqldef command: #{command}"
110+
end
111+
os = Etc.uname.fetch(:sysname).downcase
112+
arch = GOARCH.fetch(Etc.uname.fetch(:machine))
113+
"https://github.com/k0kubun/sqldef/releases/latest/download/#{command}_#{os}_#{arch}.tar.gz"
114+
end
115+
116+
# TODO: Retry transient errors
117+
def get(url, code: nil)
118+
uri = URI.parse(url)
119+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
120+
http.get("#{uri.path}?#{uri.query}")
121+
end.tap do |resp|
122+
if code && resp.code != code.to_s
123+
raise "Expected '#{url}' to return #{code}, but got #{resp.code}: #{resp.body}"
124+
end
125+
end
126+
end
127+
end
8128
end

lib/sqldef/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module Sqldef
4-
VERSION = "0.1.0"
4+
VERSION = '0.1.0'
55
end

0 commit comments

Comments
 (0)