Skip to content

Add support for zip archive type for Windows and macOS #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 39 additions & 17 deletions lib/sqldef.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require 'stringio'
require 'uri'
require 'zlib'
require 'zip'
require_relative 'sqldef/version'

module Sqldef
Expand All @@ -24,6 +25,13 @@ module Sqldef
]
private_constant :COMMANDS

OS_ARCHIVE = {
'linux' => 'tar.gz',
'windows' => 'zip',
'darwin' => 'zip',
}
private_constant :OS_ARCHIVE

@bin = Dir.pwd

class << self
Expand Down Expand Up @@ -79,16 +87,24 @@ def download(command)
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"
url = build_url(command)
resp = get(url, code: 200, max_retries: 4)

if url.end_with?('.zip')
Zip::File.open_buffer(resp.body) do |zip|
unless entry = zip.find_entry(command)
raise "'#{command}' was not found in the archive"
end
File.binwrite(path, zip.read(entry))
end
else
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
File.binwrite(path, file.read)
end

FileUtils.chmod('+x', path)
Expand All @@ -109,20 +125,26 @@ def build_url(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"
archive = OS_ARCHIVE.fetch(os)
arch = Etc.uname.fetch(:machine)
goarch = GOARCH.fetch(arch, arch)
"https://github.com/sqldef/sqldef/releases/latest/download/#{command}_#{os}_#{goarch}.#{archive}"
end

# TODO: Retry transient errors
def get(url, code: nil)
def get(url, code: nil, max_retries:)
uri = URI.parse(url)
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
resp = 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
if resp.is_a?(Net::HTTPRedirection) && max_retries > 0
# Follow redirects that lead to the current repository (if sqldef/sqldef is moved),
# Latest, vX.Y.Z, and to the binary
return get(resp['location'], code: code, max_retries: max_retries - 1)
elsif code && resp.code != code.to_s
raise "Expected '#{url}' to return #{code}, but got #{resp.code}: #{resp.body}"
end
resp
end
end
end
2 changes: 2 additions & 0 deletions sqldef.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Gem::Specification.new do |spec|
spec.metadata['homepage_uri'] = spec.homepage
spec.metadata['source_code_uri'] = spec.homepage

spec.add_runtime_dependency 'rubyzip'

# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(File.expand_path(__dir__)) do
Expand Down