From de42c627c5c4b9b061f79357ae049e108f2da61d Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Mon, 27 Apr 2015 13:06:53 -0400 Subject: [PATCH] Allow plugins to specify a minimum `requires version` --- lib/discourse.rb | 15 ++++++++-- lib/plugin/instance.rb | 15 +++++----- lib/plugin/metadata.rb | 4 +-- lib/version.rb | 20 +++++++++++++ spec/components/plugin/metadata_spec.rb | 2 ++ spec/components/version_spec.rb | 40 +++++++++++++++++++++++++ 6 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 spec/components/version_spec.rb diff --git a/lib/discourse.rb b/lib/discourse.rb index 46f27f8fce2..b4527dfd068 100644 --- a/lib/discourse.rb +++ b/lib/discourse.rb @@ -1,6 +1,7 @@ require 'cache' require_dependency 'plugin/instance' require_dependency 'auth/default_current_user_provider' +require_dependency 'version' module Discourse @@ -78,8 +79,18 @@ module Discourse end def self.activate_plugins! - @plugins = Plugin::Instance.find_all("#{Rails.root}/plugins") - @plugins.each { |plugin| plugin.activate! } + all_plugins = Plugin::Instance.find_all("#{Rails.root}/plugins") + + @plugins = [] + all_plugins.each do |p| + v = p.metadata.required_version || Discourse::VERSION::STRING + if Discourse.has_needed_version?(Discourse::VERSION::STRING, v) + p.activate! + @plugins << p + else + STDERR.puts "Could not activate #{p.metadata.name}, discourse does not meet required version (#{v})" + end + end end def self.disabled_plugin_names diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb index 027e8cf3cf2..deb3c4f4030 100644 --- a/lib/plugin/instance.rb +++ b/lib/plugin/instance.rb @@ -31,13 +31,6 @@ class Plugin::Instance def initialize(metadata=nil, path=nil) @metadata = metadata @path = path - - if @path - # Automatically include all ES6 JS and hbs files - root_path = "#{File.dirname(@path)}/assets/javascripts" - DiscoursePluginRegistry.register_glob(root_path, 'js.es6') - DiscoursePluginRegistry.register_glob(root_path, 'hbs') - end end def add_admin_route(label, location) @@ -216,6 +209,14 @@ class Plugin::Instance # this allows us to present information about a plugin in the UI # prior to activations def activate! + + if @path + # Automatically include all ES6 JS and hbs files + root_path = "#{File.dirname(@path)}/assets/javascripts" + DiscoursePluginRegistry.register_glob(root_path, 'js.es6') + DiscoursePluginRegistry.register_glob(root_path, 'hbs') + end + self.instance_eval File.read(path), path if auto_assets = generate_automatic_assets! assets.concat auto_assets.map{|a| [a]} diff --git a/lib/plugin/metadata.rb b/lib/plugin/metadata.rb index d031e2b2112..f154d2a2e27 100644 --- a/lib/plugin/metadata.rb +++ b/lib/plugin/metadata.rb @@ -2,7 +2,7 @@ module Plugin; end class Plugin::Metadata - FIELDS ||= [:name, :about, :version, :authors, :url] + FIELDS ||= [:name, :about, :version, :authors, :url, :required_version] attr_accessor *FIELDS def self.parse(text) @@ -21,7 +21,7 @@ class Plugin::Metadata attribute, *description = line[1..-1].split(":") description = description.join(":") - attribute = attribute.strip.to_sym + attribute = attribute.strip.gsub(/ /, '_').to_sym if FIELDS.include?(attribute) self.send("#{attribute}=", description.strip) diff --git a/lib/version.rb b/lib/version.rb index 5c47cbe4960..b75cfd429f1 100644 --- a/lib/version.rb +++ b/lib/version.rb @@ -10,4 +10,24 @@ module Discourse STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') end end + + def self.has_needed_version?(current, needed) + current_split = current.split('.') + needed_split = needed.split('.') + + (0..[current_split.size, needed_split.size].max).each do |idx| + current_str = current_split[idx] || '' + + c0 = (needed_split[idx] || '').sub('beta', '').to_i + c1 = (current_str || '').sub('beta', '').to_i + + # beta is less than stable + return false if current_str.include?('beta') && (c0 == 0) && (c1 > 0) + + return true if c1 > c0 + return false if c0 > c1 + end + + true + end end diff --git a/spec/components/plugin/metadata_spec.rb b/spec/components/plugin/metadata_spec.rb index 7e922e2a4c6..782b9a6ed4b 100644 --- a/spec/components/plugin/metadata_spec.rb +++ b/spec/components/plugin/metadata_spec.rb @@ -10,6 +10,7 @@ describe Plugin::Metadata do # version: 0.1 # authors: Frank Zappa # url: http://discourse.org +# required version: 1.3.0beta6+48 some_ruby TEXT @@ -19,6 +20,7 @@ TEXT expect(metadata.version).to eq("0.1") expect(metadata.authors).to eq("Frank Zappa") expect(metadata.url).to eq("http://discourse.org") + expect(metadata.required_version).to eq("1.3.0beta6+48") end end diff --git a/spec/components/version_spec.rb b/spec/components/version_spec.rb new file mode 100644 index 00000000000..8bf3e28512a --- /dev/null +++ b/spec/components/version_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' +require 'version' + +describe Discourse::VERSION do + + context "has_needed_version?" do + + it "works for major comparisons" do + expect(Discourse.has_needed_version?('1.0.0', '1.0.0')).to eq(true) + expect(Discourse.has_needed_version?('2.0.0', '1.0.0')).to eq(true) + expect(Discourse.has_needed_version?('0.0.1', '1.0.0')).to eq(false) + end + + it "works for minor comparisons" do + expect(Discourse.has_needed_version?('1.1.0', '1.1.0')).to eq(true) + expect(Discourse.has_needed_version?('1.2.0', '1.1.0')).to eq(true) + expect(Discourse.has_needed_version?('2.0.0', '1.1.0')).to eq(true) + expect(Discourse.has_needed_version?('0.1.0', '0.1.0')).to eq(true) + + expect(Discourse.has_needed_version?('1.0.0', '1.1.0')).to eq(false) + expect(Discourse.has_needed_version?('0.0.1', '0.1.0')).to eq(false) + end + + it "works for tiny comparisons" do + expect(Discourse.has_needed_version?('2.0.0', '2.0.0')).to eq(true) + expect(Discourse.has_needed_version?('2.0.1', '2.0.0')).to eq(true) + expect(Discourse.has_needed_version?('1.12.0', '2.0.0')).to eq(false) + expect(Discourse.has_needed_version?('1.12.0', '2.12.5')).to eq(false) + end + + it "works for beta comparisons" do + expect(Discourse.has_needed_version?('1.3.0.beta3', '1.2.9')).to eq(true) + expect(Discourse.has_needed_version?('1.3.0.beta3', '1.3.0.beta1')).to eq(true) + expect(Discourse.has_needed_version?('1.3.0.beta3', '1.3.0.beta4')).to eq(false) + expect(Discourse.has_needed_version?('1.3.0.beta3', '1.3.0')).to eq(false) + end + + end +end +