module Kanrisuru::OsPackage::Include
Public Instance Methods
os_include(mod, opts = {})
click to toggle source
# File lib/kanrisuru/os_package.rb, line 90 def os_include(mod, opts = {}) os_method_properties = mod.instance_variable_get(:@os_method_properties) os_method_names = os_method_properties.keys ## Need to encapsulate any helper methods called in the module ## to bind to the host instance. This acts as a psudeo module include. os_methods = mod.instance_variable_get(:@os_methods) public_methods = mod.instance_methods(false) - os_methods.to_a private_methods = mod.private_instance_methods(false) protected_methods = mod.protected_instance_methods(false) include_methods = (public_methods + protected_methods + private_methods).flatten include_method_bindings = proc do include_methods.each do |method_name| define_method method_name do |*args, &block| unbound_method = mod.instance_method(method_name) bind_method(unbound_method, *args, &block) end end private_methods.each { |method_name| private(method_name) } protected_methods.each { |method_name| protected(method_name) } private if RUBY_VERSION < '2.7' define_method 'bind_method' do |unbound_method, *args, &block| unbound_method.bind(self).call(*args, &block) end else define_method 'bind_method' do |unbound_method, *args, &block| unbound_method.bind_call(self, *args, &block) end end end namespace = opts[:namespace] namespace_class = nil namespace_instance = nil if namespace ## Define the namespace as an eigen class instance within the host class. ## Namespaced instances will access core host methods ## with @host instance variable. ## Check to see if the namespace was defined. If so, additional methods will be appended to the ## existing namespace class definition, otherwise, a new namespace class and instance will be ## defined with the methods added. if Kanrisuru::Remote::Host.instance_variable_defined?("@#{namespace}") namespace_class = Kanrisuru::Remote::Host.const_get(Kanrisuru::Util.camelize(namespace)) namespace_instance = Kanrisuru::Remote::Host.instance_variable_get("@#{namespace}") else namespace_class = Kanrisuru::Remote::Host.const_set(Kanrisuru::Util.camelize(namespace), Class.new) namespace_instance = Kanrisuru::Remote::Host.instance_variable_set("@#{namespace}", namespace_class.new) class_eval do define_method namespace do namespace_instance.instance_variable_set(:@host, self) namespace_instance end end end namespace_class.class_eval(&include_method_bindings) else class_eval(&include_method_bindings) end class_eval do os_method_names.each do |method_name| if namespace namespace_class.class_eval do define_method method_name do |*args, &block| unbound_method = nil host = namespace_instance.instance_variable_get(:@host) os_method_cache = host.instance_variable_get(:@os_method_cache) || {} if os_method_cache.key?("#{namespace}.#{method_name}") unbound_method = os_method_cache["#{namespace}.#{method_name}"] else ## Find the correct method to resolve based on the OS for the remote host. defined_method_name = host.resolve_os_method_name(os_method_properties, method_name) unless defined_method_name raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" end ## Get reference to the unbound method defined in module unbound_method = mod.instance_method(defined_method_name) raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" unless unbound_method ## Cache the unbound method on this host instance for faster resolution on ## the next invocation of this method os_method_cache["#{namespace}.#{method_name}"] = unbound_method host.instance_variable_set(:@os_method_cache, os_method_cache) end ## Bind the method to host instance and ## call it with args and block bind_method(unbound_method, *args, &block) end end else define_method method_name do |*args, &block| unbound_method = nil host = self os_method_cache = host.instance_variable_get(:@os_method_cache) || {} if os_method_cache.key?(method_name) unbound_method = os_method_cache[method_name] else ## Find the correct method to resolve based on the OS for the remote host. defined_method_name = host.resolve_os_method_name(os_method_properties, method_name) raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" unless defined_method_name ## Get reference to the unbound method defined in module unbound_method = mod.instance_method(defined_method_name) raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" unless unbound_method ## Cache the unbound method on this host instance for faster resolution on ## the next invocation of this method os_method_cache[method_name] = unbound_method host.instance_variable_set(:@os_method_cache, os_method_cache) end ## Bind the method to host instance and ## call it with args and block bind_method(unbound_method, *args, &block) end end end def resolve_os_method_name(properties, method_name) kernel = os.kernel.downcase release = os.release.downcase properties[method_name].each do |property| os_name = property[:os_name] strict = property[:options] ? property[:options][:strict] : false except = property[:options] ? property[:options][:except] : '' next if except && (except == release || except.include?(release)) if release == os_name || kernel == os_name || (Kanrisuru::Util::OsFamily.family_include_distribution?(os_name, release) && !strict) || (Kanrisuru::Util::OsFamily.upstream_include_distribution?(os_name, release) && !strict) return property[:method_name] end end nil end end end
resolve_os_method_name(properties, method_name)
click to toggle source
# File lib/kanrisuru/os_package.rb, line 223 def resolve_os_method_name(properties, method_name) kernel = os.kernel.downcase release = os.release.downcase properties[method_name].each do |property| os_name = property[:os_name] strict = property[:options] ? property[:options][:strict] : false except = property[:options] ? property[:options][:except] : '' next if except && (except == release || except.include?(release)) if release == os_name || kernel == os_name || (Kanrisuru::Util::OsFamily.family_include_distribution?(os_name, release) && !strict) || (Kanrisuru::Util::OsFamily.upstream_include_distribution?(os_name, release) && !strict) return property[:method_name] end end nil end