]> source.dussan.org Git - redmine.git/commitdiff
Support migration context for plugins (#28934).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 23 Sep 2018 14:22:29 +0000 (14:22 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 23 Sep 2018 14:22:29 +0000 (14:22 +0000)
git-svn-id: http://svn.redmine.org/redmine/trunk@17514 e93f8b46-1217-0410-a6f0-8f06a7374b81

lib/redmine/plugin.rb
test/unit/lib/redmine/plugin_test.rb

index 203c50881039d6541cb4608f2d97bde87f923c2f..8481b0f4497a601475f4f8066485c88537ba4209 100644 (file)
@@ -470,6 +470,36 @@ module Redmine
       end
     end
 
+    class MigrationContext < ActiveRecord::MigrationContext
+      def up(target_version = nil)
+        selected_migrations = if block_given?
+          migrations.select { |m| yield m }
+        else
+          migrations
+        end
+
+        Migrator.new(:up, selected_migrations, target_version).migrate
+      end
+
+      def down(target_version = nil)
+        selected_migrations = if block_given?
+          migrations.select { |m| yield m }
+        else
+          migrations
+        end
+
+        Migrator.new(:down, selected_migrations, target_version).migrate
+      end
+
+      def run(direction, target_version)
+        Migrator.new(direction, migrations, target_version).run
+      end
+
+      def open
+        Migrator.new(:up, migrations, nil)
+      end
+    end
+
     class Migrator < ActiveRecord::Migrator
       # We need to be able to set the 'current' plugin being migrated.
       cattr_accessor :current_plugin
@@ -479,23 +509,29 @@ module Redmine
         def migrate_plugin(plugin, version)
           self.current_plugin = plugin
           return if current_version(plugin) == version
-          migrate(plugin.migration_directory, version)
+
+          MigrationContext.new(plugin.migration_directory).migrate(version)
         end
 
-        def current_version(plugin=current_plugin)
+        def get_all_versions(plugin = current_plugin)
           # Delete migrations that don't match .. to_i will work because the number comes first
-          sm_table = ::ActiveRecord::SchemaMigration.table_name
-          ::ActiveRecord::Base.connection.select_values(
-            "SELECT version FROM #{sm_table}"
-          ).delete_if{ |v| v.match(/-#{plugin.id}$/) == nil }.map(&:to_i).max || 0
+          @all_versions ||= {}
+          @all_versions[plugin.id.to_s] ||= begin
+            sm_table = ::ActiveRecord::SchemaMigration.table_name
+            migration_versions  = ActiveRecord::Base.connection.select_values("SELECT version FROM #{sm_table}")
+            versions_by_plugins = migration_versions.group_by { |version| version.match(/-(.*)$/).try(:[], 1) }
+            @all_versions       = versions_by_plugins.transform_values! {|versions| versions.map!(&:to_i).sort! }
+            @all_versions[plugin.id.to_s] || []
+          end
+        end
+
+        def current_version(plugin = current_plugin)
+          get_all_versions(plugin).last || 0
         end
       end
 
-      def migrated
-        sm_table = ::ActiveRecord::SchemaMigration.table_name
-        ::ActiveRecord::Base.connection.select_values(
-          "SELECT version FROM #{sm_table}"
-        ).delete_if{ |v| v.match(/-#{current_plugin.id}$/) == nil }.map(&:to_i).sort
+      def load_migrated
+        @migrated_versions = Set.new(self.class.get_all_versions(current_plugin))
       end
 
       def record_version_state_after_migrating(version)
index 51ae269be3cb7445c59ccd8cdcff8dd0ae91cd28..42122c9451f09c0755f2bebffe2957b1ad6a5651 100644 (file)
@@ -183,4 +183,13 @@ class Redmine::PluginTest < ActiveSupport::TestCase
     Rails.logger.expects(:warn)
     @klass.register(:bar) { settings :partial => 'foo/settings' }
   end
+
+  def test_migrate_redmine_plugin
+    @klass.register :foo do
+      name 'Foo plugin'
+      version '0.0.1'
+    end
+
+    assert Redmine::Plugin.migrate('foo')
+  end
 end