From: Jean-Philippe Lang Date: Sun, 23 Sep 2018 14:22:29 +0000 (+0000) Subject: Support migration context for plugins (#28934). X-Git-Tag: 4.0.0~158 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=daa7d2ba181627baf42f1e1efea04e4750e05331;p=redmine.git Support migration context for plugins (#28934). git-svn-id: http://svn.redmine.org/redmine/trunk@17514 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- diff --git a/lib/redmine/plugin.rb b/lib/redmine/plugin.rb index 203c50881..8481b0f44 100644 --- a/lib/redmine/plugin.rb +++ b/lib/redmine/plugin.rb @@ -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) diff --git a/test/unit/lib/redmine/plugin_test.rb b/test/unit/lib/redmine/plugin_test.rb index 51ae269be..42122c945 100644 --- a/test/unit/lib/redmine/plugin_test.rb +++ b/test/unit/lib/redmine/plugin_test.rb @@ -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