Module: FzfRuby::Installer
- Defined in:
- ext/fzf/extconf.rb
Defined Under Namespace
Classes: InstallError
Constant Summary collapse
- FZF_VERSION =
Release of fzf to install. Overridable so a project can pin a different version at install time: FZF_VERSION=0.70.0 bundle install
ENV.fetch("FZF_VERSION", "0.74.1").freeze
- RELEASE_BASE =
Where release assets live.
"https://github.com/junegunn/fzf/releases/download".freeze
- FZF_INSTALL_URL =
Upstream installation instructions, cited when we cannot help further.
"https://github.com/junegunn/fzf#installation".freeze
- ASSET_TEMPLATE =
Asset name templates. Both are published for every release.
"fzf-%<version>s-%<slug>s.tar.gz".freeze
- CHECKSUMS_TEMPLATE =
"fzf_%<version>s_checksums.txt".freeze
- BIN_DIR =
Final resting place of the binary, inside the installed gem.
File.("../../lib/fzf/bin", __dir__).freeze
- DOWNLOAD_TIMEOUT =
Seconds to wait on each network call before giving up.
60
Class Method Summary collapse
-
.expected_checksum(asset) ⇒ Object
Expected SHA256 for an asset, read from the release's checksums file.
-
.fetch(url) ⇒ Object
Download a URL into memory, surfacing network failures as InstallError.
-
.install ⇒ Object
Download, verify and unpack the release, leaving the binary at BIN_DIR/fzf.
-
.unsupported_platform_error ⇒ Object
No prebuilt release matches this machine, so there is nothing to install.
Class Method Details
.expected_checksum(asset) ⇒ Object
Expected SHA256 for an asset, read from the release's checksums file.
The file lists one "
61 62 63 64 65 66 67 |
# File 'ext/fzf/extconf.rb', line 61 def self.expected_checksum(asset) checksums = fetch("#{RELEASE_BASE}/v#{FZF_VERSION}/#{format(CHECKSUMS_TEMPLATE, version: FZF_VERSION)}") line = checksums.lines.find { |l| l.split(/\s+/).last == asset } raise InstallError, "No checksum listed for #{asset}" unless line line.split(/\s+/).first end |
.fetch(url) ⇒ Object
Download a URL into memory, surfacing network failures as InstallError.
47 48 49 50 51 52 53 54 55 56 57 |
# File 'ext/fzf/extconf.rb', line 47 def self.fetch(url) URI.parse(url).open(open_timeout: DOWNLOAD_TIMEOUT, read_timeout: DOWNLOAD_TIMEOUT, &:read) rescue StandardError => e raise InstallError, <<~MSG Could not download #{url} #{e.class}: #{e.} If this machine has no network access, install fzf yourself and point the gem at it with FZF_PATH=/path/to/fzf, or see #{FZF_INSTALL_URL} MSG end |
.install ⇒ Object
Download, verify and unpack the release, leaving the binary at BIN_DIR/fzf.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'ext/fzf/extconf.rb', line 70 def self.install slug = FzfRuby::Platform.slug raise unsupported_platform_error unless slug asset = format(ASSET_TEMPLATE, version: FZF_VERSION, slug: slug) url = "#{RELEASE_BASE}/v#{FZF_VERSION}/#{asset}" puts "fzf-ruby: downloading #{asset}" tarball = fetch(url) # Verify before unpacking — never execute an unverified download. actual = Digest::SHA256.hexdigest(tarball) expected = expected_checksum(asset) unless actual == expected raise InstallError, "Checksum mismatch for #{asset}\n expected #{expected}\n actual #{actual}" end Dir.mktmpdir("fzf-install") do |tmpdir| archive = File.join(tmpdir, asset) File.binwrite(archive, tarball) # The release tarballs contain a single `fzf` binary at the root. unless system("tar", "-xzf", archive, "-C", tmpdir) raise InstallError, "Failed to unpack #{asset}" end extracted = File.join(tmpdir, "fzf") raise InstallError, "#{asset} did not contain an fzf binary" unless File.exist?(extracted) FileUtils.mkdir_p(BIN_DIR) FileUtils.cp(extracted, File.join(BIN_DIR, "fzf")) FileUtils.chmod(0o755, File.join(BIN_DIR, "fzf")) end puts "fzf-ruby: installed fzf #{FZF_VERSION} to #{BIN_DIR}/fzf" end |
.unsupported_platform_error ⇒ Object
No prebuilt release matches this machine, so there is nothing to install.
108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'ext/fzf/extconf.rb', line 108 def self.unsupported_platform_error InstallError.new(<<~MSG) fzf-ruby: no prebuilt fzf release exists for this platform host_os: #{RbConfig::CONFIG["host_os"]} host_cpu: #{RbConfig::CONFIG["host_cpu"]} Install fzf by hand and point the gem at it: export FZF_PATH=/path/to/fzf Installation options, including building from source: #{FZF_INSTALL_URL} MSG end |