lib/config_curator/package_lookup.rb
require 'mkmf'
require 'open3'
module ConfigCurator
# Lookup if a package is installed on the system.
# See {TOOLS} for supported package tools.
# If {#tool} is not explicitly set, it will try and choose one automatically.
# @example Lookup a package
# PackageLookup.new.installed? 'ruby' #=> true
# @example Lookup a package using `pacman`
# PackageLookup.new(tool: :pacman).installed? 'ruby' #=> true
class PackageLookup
include Utils
# Error when a package lookup cannot be completed.
class LookupFailed < RuntimeError; end
# Default list of supported package tools.
# @see #tools
TOOLS = {
dpkg: 'dpkg',
pacman: 'pacman',
pkgng: 'pkg',
brew: 'brew'
}
attr_accessor :tool, :tools
def initialize(tool: nil)
self.tool = tool
end
# Package tools that support package lookup ordered by preference.
# Each key is an identifier and each value is the command to check for.
# @return [Hash] hash of supported package tools
def tools
@tools ||= TOOLS
end
# The package tool to use for this instance.
# @return [Symbol] tool to use
def tool
return @tool if @tool
tools.each do |k, v|
next unless command? v
return @tool = k
end
@tool
end
# Checks if package is installed.
# @param package [String] package name to check
# @return [Boolean] if package is installed
def installed?(package)
fail LookupFailed, 'No supported package tool found.' if tool.nil?
cmd = tools[tool]
fail LookupFailed, "Package tool '#{cmd}' not found." if command?(cmd).nil?
send tool, package
end
private
#
# Tool specific package lookup methods below.
#
def dpkg(package)
cmd = command? 'dpkg'
Open3.popen3 cmd, '-s', package do |_, _, _, wait_thr|
wait_thr.value.to_i == 0
end
end
def pacman(package)
cmd = command? 'pacman'
Open3.popen3 cmd, '-qQ', package do |_, _, _, wait_thr|
wait_thr.value.to_i == 0
end
end
def pkgng(package)
cmd = command? 'pkg'
Open3.popen3 cmd, 'info', package do |_, _, _, wait_thr|
wait_thr.value.to_i == 0
end
end
def brew(package)
cmd = command? 'brew'
stdout = `#{cmd} ls --versions #{package}`
!stdout.empty?
end
end
end