From cb63dbb586976389ebb30c488ae4a046c5034b52 Mon Sep 17 00:00:00 2001 From: MAEDA Go Date: Sat, 19 Sep 2026 11:10:42 +0900 Subject: [PATCH] Fix stale cached versions when a plugin is migrated more than once in the same process --- lib/redmine/plugin.rb | 11 ++++++++++ test/unit/lib/redmine/plugin_test.rb | 32 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/lib/redmine/plugin.rb b/lib/redmine/plugin.rb index 74ae4efaf..7c72ce4e6 100644 --- a/lib/redmine/plugin.rb +++ b/lib/redmine/plugin.rb @@ -544,6 +544,16 @@ module Redmine def current_version(plugin = current_plugin) get_all_versions(plugin).last || 0 end + + # Discards the cached versions of the given plugin so that they are + # reloaded from the database. Discards those of all plugins if no plugin is given + def clear_cached_versions(plugin = nil) + if plugin + @all_versions&.delete(plugin.id.to_s) + else + @all_versions = nil + end + end end def load_migrated @@ -552,6 +562,7 @@ module Redmine def record_version_state_after_migrating(version) super(version.to_s + "-" + current_plugin.id.to_s) + self.class.clear_cached_versions(current_plugin) end end end diff --git a/test/unit/lib/redmine/plugin_test.rb b/test/unit/lib/redmine/plugin_test.rb index e6945c4d8..3f3f179d0 100644 --- a/test/unit/lib/redmine/plugin_test.rb +++ b/test/unit/lib/redmine/plugin_test.rb @@ -226,6 +226,38 @@ class Redmine::PluginTest < ActiveSupport::TestCase assert Redmine::Plugin.migrate('foo_plugin') end + def test_migrate_should_not_use_stale_cached_versions + plugin = @klass.register :foo_plugin do + name 'Foo plugin' + version '0.0.1' + end + migrator = Redmine::Plugin::Migrator + + Dir.mktmpdir do |dir| + {'001_foo_plugin_stale_cache_first.rb' => 'FooPluginStaleCacheFirst', + '002_foo_plugin_stale_cache_second.rb' => 'FooPluginStaleCacheSecond'}.each do |filename, class_name| + File.write( + File.join(dir, filename), + "class #{class_name} < ActiveRecord::Migration[8.1]\n def up; end\n\n def down; end\nend\n" + ) + end + plugin.stubs(:migration_directory).returns(dir) + + ActiveRecord::Migration.suppress_messages do + plugin.migrate(1) + assert_equal 1, migrator.current_version(plugin) + plugin.migrate + assert_equal 2, migrator.current_version(plugin) + plugin.migrate(0) + assert_equal 0, migrator.current_version(plugin) + plugin.migrate + assert_equal 2, migrator.current_version(plugin) + end + end + ensure + Redmine::Plugin::Migrator.clear_cached_versions + end + def test_migration_context_should_override_current_version plugin = @klass.register :foo_plugin do name 'Foo plugin' -- 2.55.0