def available?
return true unless self.class.respond_to?(:_depends_on_opts)
opts = self.class._depends_on_opts
return true if opts == :nothing
is_available = self.class._is_available
if is_available.nil? and opts.nil?
return false
elsif is_available.nil?
all_present = true
missing = {}
kinds = opts.keys
callbacks = kinds.delete(:callbacks)
kinds << callbacks if callbacks
begin
for kind in kinds
next unless opts[kind]
for item in [opts[kind]].flatten
present = \
case kind
when :files
File.exists?(item)
when :directories
File.directory?(item)
when :programs
result = nil
for variant in %w(unix windows)
variant_token = "which_#{variant}".to_sym
begin
driver = interpreter.shell_manager[variant_token]
result = driver.which!(item)
break
rescue ArgumentError, NotImplementedError, NoMethodError => e
end
end
result
when :requires, :libraries
begin
require item
true
rescue LoadError
false
end
when :callbacks
item.call() ? true : false
else
raise TypeError.new("Unknown kind: #{kind}")
end
unless present
all_present = false
missing[kind] ||= []
missing[kind] << item
raise EOFError.new("break")
end
end
end
rescue EOFError => e
raise e unless e.message == "break"
end
self.class._missing_dependencies = missing
self.class._is_available = all_present
log.debug(PNOTE+"Driver #{self.class} #{all_present ? "is" : "isn't"} available")
end
return self.class._is_available
end