Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module PluginManager
- MBOX = Win32API.new('user32', 'MessageBox', ['I','P','P','I'], 'I')
- @@Plugins = {}
- def self.register(options)
- name = nil
- version = nil
- link = nil
- dependencies = nil
- order = [:name, :version, :link, :dependencies, :incompatibilities]
- keys = options.keys.sort { |a, b| order.index(a) || order.size <=> order.index(b) || order.size }
- for key in keys
- value = options[key]
- case key
- when :name
- if nil_or_empty(value)
- self.error "Plugin name must be a non-empty string."
- end
- if !@@Plugins[value].nil?
- self.error "Plugin by the name of '#{value}' already exists."
- end
- name = value
- when :version
- if nil_or_empty(value)
- self.error "Plugin version must be a string."
- end
- version = value
- when :link
- if nil_or_empty(value)
- self.error "Plugin link must be a string."
- end
- link = value
- when :dependencies
- dependencies = value
- dependencies = [dependencies] if !dependencies.is_a?(Array) || !dependencies[0].is_a?(Array)
- for dep in value
- if dep.is_a?(String)
- if !self.installed?(dep)
- self.error "Plugin '#{name}' requires plugin '#{dep}' to be installed."
- end
- elsif dep.is_a?(Array)
- if dep.size == 1
- if dep[0].is_a?(String)
- dep_name = dep[0]
- if !self.installed?(dep_name)
- self.error "Plugin '#{name}' requires plugin '#{dep_name}' to be installed."
- end
- else
- self.error "Expected the plugin name as a string, but got #{dep[0].inspect}."
- end
- elsif dep.size == 2
- if dep[0].is_a?(Symbol)
- self.error "Cannot specify dependency version check modifier without specifying a version."
- elsif dep[0].is_a?(String) && dep[1].is_a?(String)
- dep_name = dep[0]
- dep_version = dep[1]
- if self.installed?(dep_name, dep_version)
- elsif self.installed?(dep_name)
- msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} or later, " +
- "but the installed version is #{self.version(dep_name)}."
- if dep_link = self.link(dep_name)
- msg += "\n\nThe plugin may be updated from: #{dep_link}"
- end
- self.error msg
- else
- self.error "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} or later " +
- "to be installed."
- end
- end
- elsif dep.size == 3
- if !dep[0].is_a?(Symbol)
- self.error "Expected first dependency argument to be a symbol, but got #{dep[0].inspect}."
- end
- if !dep[1].is_a?(String)
- self.error "Expected second dependency argument to be a plugin name, but got #{dep[1].inspect}."
- end
- if !dep[2].is_a?(String)
- self.error "Expected third dependency argument to be the plugin version, but got #{dep[2].inspect}."
- end
- dep_arg = dep[0]
- dep_name = dep[1]
- dep_version = dep[2]
- optional = false
- exact = false
- if dep_arg == :optional || dep_arg == :exact || dep_arg == :optional_exact
- optional = dep_arg == :optional || dep_arg == :optional_exact
- exact = dep_arg == :exact || dep_arg == :optional_exact
- else
- self.error "Expected first dependency argument to be one of :optional, :exact or :optional_exact, " +
- "but got #{dep_arg.inspect}."
- end
- type = :gteq
- type = :eq if exact
- if optional
- if self.installed?(dep_name) && !self.installed?(dep_name, dep_version, type)
- msg = "Plugin '#{name}' requires plugin '#{dep_name}', if installed, to be version #{dep_version}"
- msg << " or later " if !exact
- msg << ", but the installed version was #{self.version(dep_name)}."
- if dep_link = self.link(dep_name)
- msg << "\n\nThe plugin may be updated from: #{dep_link}"
- end
- self.error msg
- end
- else
- if self.installed?(dep_name, dep_version, type)
- elsif self.installed?(dep_name)
- msg = "Plugin '#{name}' requires plugin '#{dep_name}' to be version #{dep_version}"
- msg << " or later " if !exact
- msg << ", but the installed version was #{self.version(dep_name)}."
- if dep_link = self.link(dep_name)
- msg << "\n\nThe plugin may be updated from: #{dep_link}"
- end
- self.error msg
- else
- msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} "
- msg << "or later " if !exact
- msg << "to be installed."
- self.error msg
- end
- end
- end
- end
- end
- when :incompatibilities
- incompats = value
- incompats = [incompats] if !incompats.is_a?(Array)
- for incompat in incompats
- if self.installed?(incompat)
- self.error "Plugin '#{name}' is incompatible with '#{incompat}'. They cannot both be used at the same time."
- end
- end
- else
- self.error "Invalid plugin registry key '#{key}'."
- end
- end
- @@Plugins[name] = {
- :name => name,
- :version => version,
- :link => link,
- :dependencies => dependencies
- }
- end
- def self.error(msg)
- Graphics.update
- t = Thread.new do
- MBOX.call(Win32API.pbFindRgssWindow, msg, "Plugin Error", 0x10)
- Thread.exit
- end
- while t.status
- Graphics.update
- end
- Kernel.exit! true
- end
- def self.installed?(plugin_name, plugin_version = nil, compare_type = :gteq)
- plugin = @@Plugins[plugin_name]
- return false if plugin.nil?
- return true if plugin_version.nil?
- comparison = compare_versions(plugin[:version], plugin_version)
- return true if compare_type == :gteq && comparison >= 0
- return true if compare_type == :eq && comparison == 0
- end
- def self.version(plugin_name)
- return if !installed?(plugin_name)
- return @@Plugins[plugin_name][:version]
- end
- def self.link(plugin_name)
- return if !installed?(plugin_name)
- return @@Plugins[plugin_name][:link]
- end
- def self.nil_or_empty(string)
- return string.nil? || !string.is_a?(String) || string.size == 0
- end
- def self.compare_versions(v1, v2)
- d1 = v1.split("")
- d1.insert(0, "0") if d1[0] == "."
- while d1[-1] == "."; d1 = d1[0..-2]; end
- d2 = v2.split("")
- d2.insert(0, "0") if d2[0] == "."
- while d2[-1] == "."; d2 = d2[0..-2]; end
- for i in 0...[d1.size, d2.size].max
- c1 = d1[i]
- c2 = d2[i]
- if c1
- if c2
- if c1.to_i(16) > c2.to_i(16)
- return 1
- elsif c1.to_i(16) < c2.to_i(16)
- return -1
- end
- else
- return 1
- end
- else
- if c2
- return -1
- end
- end
- end
- return 0
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement