diff --git a/lib/redmine/plugin.rb b/lib/redmine/plugin.rb index ccd804f06..0fc6985f4 100644 --- a/lib/redmine/plugin.rb +++ b/lib/redmine/plugin.rb @@ -18,6 +18,7 @@ module Redmine #:nodoc: class PluginNotFound < StandardError; end + class PluginRequirementError < StandardError; end # Base class for Redmine plugins. # Plugins are registered using the register class method that acts as the public constructor. @@ -93,6 +94,40 @@ module Redmine #:nodoc: def <=>(plugin) self.id.to_s <=> plugin.id.to_s end + + # Sets a requirement on Redmine version + # Raises a PluginRequirementError exception if the requirement is not met + # + # Examples + # # Requires Redmine 0.7.3 or higher + # requires_redmine :version_or_higher => '0.7.3' + # requires_redmine '0.7.3' + # + # # Requires a specific Redmine version + # requires_redmine :version => '0.7.3' # 0.7.3 only + # requires_redmine :version => ['0.7.3', '0.8.0'] # 0.7.3 or 0.8.0 + def requires_redmine(arg) + arg = { :version_or_higher => arg } unless arg.is_a?(Hash) + arg.assert_valid_keys(:version, :version_or_higher) + + current = Redmine::VERSION.to_a + arg.each do |k, v| + v = [] << v unless v.is_a?(Array) + versions = v.collect {|s| s.split('.').collect(&:to_i)} + case k + when :version_or_higher + raise ArgumentError.new("wrong number of versions (#{versions.size} for 1)") unless versions.size == 1 + unless (current <=> versions.first) >= 0 + raise PluginRequirementError.new("#{id} plugin requires Redmine #{v} or higher but current is #{current.join('.')}") + end + when :version + unless versions.include?(current.slice(0,3)) + raise PluginRequirementError.new("#{id} plugin requires one the following Redmine versions: #{v.join(', ')} but current is #{current.join('.')}") + end + end + end + true + end # Adds an item to the given +menu+. # The +id+ parameter (equals to the project id) is automatically added to the url. diff --git a/lib/redmine/version.rb b/lib/redmine/version.rb index 104efe7dd..eefdb86aa 100644 --- a/lib/redmine/version.rb +++ b/lib/redmine/version.rb @@ -34,8 +34,10 @@ module Redmine end REVISION = self.revision - STRING = [MAJOR, MINOR, TINY, BRANCH, REVISION].compact.join('.') + ARRAY = [MAJOR, MINOR, TINY, BRANCH, REVISION].compact + STRING = ARRAY.join('.') + def self.to_a; ARRAY end def self.to_s; STRING end end end diff --git a/test/unit/lib/redmine/plugin_test.rb b/test/unit/lib/redmine/plugin_test.rb index 48e868e52..e6237c216 100644 --- a/test/unit/lib/redmine/plugin_test.rb +++ b/test/unit/lib/redmine/plugin_test.rb @@ -52,4 +52,27 @@ class Redmine::PluginTest < Test::Unit::TestCase assert_equal 'This is a test plugin', plugin.description assert_equal '0.0.1', plugin.version end + + def test_requires_redmine + test = self + version = Redmine::VERSION.to_a.slice(0,3).join('.') + + @klass.register :foo do + test.assert requires_redmine(:version_or_higher => '0.1.0') + test.assert requires_redmine(:version_or_higher => version) + test.assert requires_redmine(version) + test.assert_raise Redmine::PluginRequirementError do + requires_redmine(:version_or_higher => '99.0.0') + end + + test.assert requires_redmine(:version => version) + test.assert requires_redmine(:version => [version, '99.0.0']) + test.assert_raise Redmine::PluginRequirementError do + requires_redmine(:version => '99.0.0') + end + test.assert_raise Redmine::PluginRequirementError do + requires_redmine(:version => ['98.0.0', '99.0.0']) + end + end + end end