redmine_plugins_helper 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 474a2a3d3fd82a0eeedd525edad8db6adaf84f1fda9785e910ffbe06046d8f47
4
+ data.tar.gz: 309ff8226411dadced5b3639b0bff781c8d41ed307f2451ee865317ddc2d2e08
5
+ SHA512:
6
+ metadata.gz: c1714ab95b6af124afe772dbb1e196323a655ef907cd83865ceb6088915a91176f0e739ad9e172909d4141b412ef4fb129e37219cb8278f2e0c2860303488ede
7
+ data.tar.gz: 582161dbc0800d84c89a5ea5faa6a0f2620843123239337083878e44e92db8ad1fd406f2502cd08d51f96a37955ea62fbb98c22081b81f32f0ba599238aa19c4
@@ -0,0 +1,5 @@
1
+ <% Redmine::Plugin.registered_plugins.values.each do |plugin| %>
2
+ <% if plugin.main_javascript_asset_path %>
3
+ <% require_asset plugin.main_javascript_asset_path %>
4
+ <% end %>
5
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <% Redmine::Plugin.registered_plugins.values.each do |plugin| %>
2
+ <% if plugin.main_stylesheet_asset_path %>
3
+ @import "<%= plugin.main_stylesheet_asset_path %>";
4
+ <% end %>
5
+ <% end %>
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'redmine_plugins_helper/hooks/add_assets'
4
+ Rails.application.config.assets.precompile += %w[plugins_autoload.css plugins_autoload.js]
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record/connection_adapters/postgresql/schema_statements'
4
+
5
+ #
6
+ # Monkey-patch the refused Rails 4.2 patch at https://github.com/rails/rails/pull/31330
7
+ #
8
+ # Updates sequence logic to support PostgreSQL 10.
9
+ #
10
+
11
+ module ActiveRecord
12
+ module ConnectionAdapters
13
+ module PostgreSQL
14
+ module SchemaStatements
15
+ # Resets the sequence of a table's primary key to the maximum value.
16
+ def reset_pk_sequence!(table, pkey = nil, sequence = nil) #:nodoc:
17
+ unless pkey && sequence
18
+ default_pk, default_sequence = pk_and_sequence_for(table)
19
+ pkey ||= default_pk
20
+ sequence ||= default_sequence
21
+ end
22
+ reset_pk_sequence_log(sequence, table, pkey)
23
+ return unless pkey && sequence
24
+
25
+ reset_pk_sequence_select_value(sequence, table, pkey)
26
+ end
27
+
28
+ private
29
+
30
+ def reset_pk_sequence_max_pk(table, pkey)
31
+ select_value("SELECT MAX(#{quote_column_name pkey}) FROM #{quote_table_name(table)}")
32
+ end
33
+
34
+ def reset_pk_sequence_minvalue(max_pk, quoted_sequence)
35
+ return nil unless max_pk.nil?
36
+
37
+ if postgresql_version >= 100_000
38
+ select_value('SELECT seqmin FROM pg_sequence WHERE seqrelid = ' \
39
+ "#{quote(quoted_sequence)}::regclass")
40
+ else
41
+ select_value("SELECT min_value FROM #{quoted_sequence}")
42
+ end
43
+ end
44
+
45
+ def reset_pk_sequence_log(sequence, table, pkey)
46
+ return unless @logger && pkey && !sequence
47
+
48
+ @logger.warn "#{table} has primary key #{pkey} with no default sequence"
49
+ end
50
+
51
+ def reset_pk_sequence_select_value(sequence, table, pkey)
52
+ quoted_sequence = quote_table_name(sequence)
53
+ max_pk = reset_pk_sequence_max_pk(table, pkey)
54
+ minvalue = reset_pk_sequence_minvalue(max_pk, quoted_sequence)
55
+ select_value <<-END_SQL, 'SCHEMA'
56
+ SELECT setval(#{quote(quoted_sequence)}, #{max_pk || minvalue}, #{max_pk ? true : false})
57
+ END_SQL
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
data/init.rb ADDED
@@ -0,0 +1,18 @@
1
+ # coding: utf-8
2
+
3
+ require 'redmine'
4
+ require 'redmine_plugins_helper/version'
5
+ require 'redmine_plugins_helper/patches/test_case_patch'
6
+
7
+ Redmine::Plugin.register :redmine_plugins_helper do
8
+ name 'Redmine Plugins\' Helper'
9
+ author ::RedminePluginsHelper::AUTHOR
10
+ description ::RedminePluginsHelper::SUMMARY
11
+ version ::RedminePluginsHelper::VERSION
12
+ end
13
+
14
+ Rails.configuration.to_prepare do
15
+ require_dependency 'redmine_plugins_helper/patches/redmine/plugin_patch'
16
+ ::Redmine::Plugin.registered_plugins.values.each(&:add_assets_paths)
17
+ ::Redmine::Plugin.registered_plugins.values.each(&:load_initializers)
18
+ end
@@ -0,0 +1,100 @@
1
+ module RedminePluginsHelper
2
+ class FixMigrations
3
+ def initialize
4
+ run
5
+ end
6
+
7
+ private
8
+
9
+ def run
10
+ database_plugins_versions.each do |dbv|
11
+ check_database_version(dbv)
12
+ end
13
+ Rails.logger.info("Database versions checked: #{database_plugins_versions.count}")
14
+ Rails.logger.info("Local versions found: #{local_versions.count}")
15
+ end
16
+
17
+ def check_database_version(dbv)
18
+ lv = local_version(dbv[:timestamp])
19
+ return unless lv && lv.count == 1 && dbv[:plugin] != lv.first[:plugin]
20
+ fix_plugin_version(dbv, lv.first[:plugin])
21
+ end
22
+
23
+ def fix_plugin_version(dbv, target_plugin)
24
+ target_version = plugin_version(target_plugin, dbv[:timestamp])
25
+ if database_version?(target_version)
26
+ remove_plugin_version(dbv[:version])
27
+ else
28
+ move_plugin_version(dbv[:version], target_version)
29
+ end
30
+ end
31
+
32
+ def database_version?(version)
33
+ r = ::ActiveRecord::Base.connection.execute(<<EOS.strip_heredoc)
34
+ select exists(
35
+ select 1
36
+ from #{ActiveRecord::Migrator.schema_migrations_table_name}
37
+ where version=#{ActiveRecord::Base.sanitize(version)}
38
+ )
39
+ EOS
40
+ r.getvalue(0, 0) == 't'
41
+ end
42
+
43
+ def remove_plugin_version(source_version)
44
+ Rails.logger.info("Removing #{source_version}")
45
+ ::ActiveRecord::Base.connection.execute(<<EOS.strip_heredoc)
46
+ delete from #{ActiveRecord::Migrator.schema_migrations_table_name}
47
+ where version=#{ActiveRecord::Base.sanitize(source_version)}
48
+ EOS
49
+ end
50
+
51
+ def move_plugin_version(source_version, target_version)
52
+ Rails.logger.info("Moving #{source_version} to plugin \"#{target_version}\"")
53
+ ::ActiveRecord::Base.connection.execute(<<EOS.strip_heredoc)
54
+ update #{ActiveRecord::Migrator.schema_migrations_table_name}
55
+ set version=#{ActiveRecord::Base.sanitize(target_version)}
56
+ where version=#{ActiveRecord::Base.sanitize(source_version)}
57
+ EOS
58
+ end
59
+
60
+ def local_version(timestamp)
61
+ return [] unless local_versions.key?(timestamp)
62
+ local_versions[timestamp]
63
+ end
64
+
65
+ def local_versions
66
+ @local_versions = begin
67
+ r = {}
68
+ Redmine::Plugin.registered_plugins.values.each do |p|
69
+ p.migrations.each do |m|
70
+ r[m] ||= []
71
+ r[m] << { plugin: p.id, timestamp: m, version: plugin_version(p.id, m) }
72
+ end
73
+ end
74
+ r
75
+ end
76
+ end
77
+
78
+ def database_plugins_versions
79
+ @database_plugins_versions = begin
80
+ r = []
81
+ ::RedminePluginsHelper::Migrations.db_all_versions.each do |v|
82
+ pv = parse_plugin_version(v)
83
+ next unless pv
84
+ r << pv
85
+ end
86
+ r
87
+ end
88
+ end
89
+
90
+ def parse_plugin_version(v)
91
+ h = ::RedminePluginsHelper::Migrations.parse_plugin_version(v)
92
+ h[:version] = v if h.is_a?(Hash)
93
+ h
94
+ end
95
+
96
+ def plugin_version(plugin_id, timestamp)
97
+ "#{timestamp}-#{plugin_id}"
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedminePluginsHelper
4
+ module Hooks
5
+ class AddAssets < Redmine::Hook::ViewListener
6
+ def view_layouts_base_html_head(_context = {})
7
+ safe_join([plugins_autoload_stylesheet_tag, plugins_autoload_script_tag])
8
+ end
9
+
10
+ private
11
+
12
+ def plugins_autoload_stylesheet_tag
13
+ tag('link', media: 'all', rel: 'stylesheet',
14
+ href: asset_path('assets/plugins_autoload.css'))
15
+ end
16
+
17
+ def plugins_autoload_script_tag
18
+ content_tag('script', "\n", src: asset_path('assets/plugins_autoload.js'))
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,41 @@
1
+ module RedminePluginsHelper
2
+ class Migrate
3
+ def initialize
4
+ run
5
+ end
6
+
7
+ private
8
+
9
+ def run
10
+ versions_sorted.each do |v|
11
+ migrate_plugin_version(v)
12
+ end
13
+ end
14
+
15
+ def migrate_plugin_version(v)
16
+ return if migrated?(v)
17
+ ::Redmine::Plugin.registered_plugins[v[:plugin]].migrate(v[:timestamp])
18
+ end
19
+
20
+ def versions_sorted
21
+ versions.sort_by { |e| [e[:timestamp]] }
22
+ end
23
+
24
+ def versions
25
+ r = []
26
+ ::RedminePluginsHelper::Migrations.local_versions.each do |plugin, ts|
27
+ ts.each { |t| r << { plugin: plugin, timestamp: t } }
28
+ end
29
+ r
30
+ end
31
+
32
+ def migrated?(v)
33
+ return false unless db_versions.key?(v[:plugin])
34
+ db_versions[v[:plugin]].include?(v[:timestamp])
35
+ end
36
+
37
+ def db_versions
38
+ @db_versions ||= ::RedminePluginsHelper::Migrations.db_versions
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,38 @@
1
+ module RedminePluginsHelper
2
+ class Migrations
3
+ class << self
4
+ def local_versions
5
+ r = {}
6
+ Redmine::Plugin.registered_plugins.values.each do |p|
7
+ p.migrations.each do |ts|
8
+ r[p.id] ||= []
9
+ r[p.id] << ts
10
+ end
11
+ end
12
+ r
13
+ end
14
+
15
+ def db_versions
16
+ r = {}
17
+ db_all_versions.each do |v|
18
+ pv = parse_plugin_version(v)
19
+ next unless pv
20
+ r[pv[:plugin]] ||= []
21
+ r[pv[:plugin]] << pv[:timestamp]
22
+ end
23
+ r
24
+ end
25
+
26
+ def db_all_versions
27
+ ::ActiveRecord::SchemaMigration.create_table
28
+ ::ActiveRecord::SchemaMigration.all.pluck(:version)
29
+ end
30
+
31
+ def parse_plugin_version(v)
32
+ m = v.match(/^(\d+)\-(\S+)$/)
33
+ return nil unless m
34
+ { plugin: m[2].to_sym, timestamp: m[1].to_i }
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,76 @@
1
+ module RedminePluginsHelper
2
+ module Patches
3
+ module Redmine
4
+ module PluginPatch
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ extend ClassMethods
9
+ include InstanceMethods
10
+ end
11
+
12
+ ASSETS_SUBDIRS = %w[stylesheets javascripts images].freeze
13
+
14
+ module ClassMethods
15
+ def post_register(plugin_name, &block)
16
+ plugin = registered_plugins[plugin_name]
17
+ raise "Plugin not registered: #{plugin_name}" unless plugin
18
+
19
+ plugin.instance_eval(&block)
20
+ end
21
+ end
22
+
23
+ module InstanceMethods
24
+ def load_initializers
25
+ Dir["#{initializers_directory}/*.rb"].each { |f| require f }
26
+ end
27
+
28
+ ASSETS_SUBDIRS.each do |assert_subdir|
29
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
30
+ def #{assert_subdir}_directory
31
+ ::File.join(directory, 'app', 'assets', '#{assert_subdir}')
32
+ end
33
+ RUBY_EVAL
34
+ end
35
+
36
+ def add_assets_paths
37
+ ASSETS_SUBDIRS.each do |assert_subdir|
38
+ assets_directory = send("#{assert_subdir}_directory")
39
+ next unless ::File.directory?(assets_directory)
40
+
41
+ Rails.application.config.assets.paths << assets_directory
42
+ end
43
+ end
44
+
45
+ def main_javascript_asset_path
46
+ find_asset(javascripts_directory, %w[js coffee js.coffee])
47
+ end
48
+
49
+ def main_stylesheet_asset_path
50
+ find_asset(stylesheets_directory, %w[css scss])
51
+ end
52
+
53
+ private
54
+
55
+ def initializers_directory
56
+ File.join(directory, 'config', 'initializers')
57
+ end
58
+
59
+ def find_asset(assets_directory, extensions)
60
+ extensions.each do |extension|
61
+ ['', '.erb'].each do |erb_extension|
62
+ path = ::File.join(assets_directory, "#{id}.#{extension}#{erb_extension}")
63
+ return id if ::File.exist?(path)
64
+ end
65
+ end
66
+ nil
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ patch = ::RedminePluginsHelper::Patches::Redmine::PluginPatch
75
+ target = ::Redmine::Plugin
76
+ target.send(:include, patch) unless target.include?(patch)
@@ -0,0 +1,30 @@
1
+ require 'active_support'
2
+
3
+ module RedminePluginsHelper
4
+ module Patches
5
+ module TestCasePatch
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ extend ClassMethods
10
+ end
11
+
12
+ module ClassMethods
13
+ def plugin_fixtures(plugin_name, *files)
14
+ fixtures_dir = File.expand_path(
15
+ 'test/fixtures',
16
+ ::Redmine::Plugin.registered_plugins[plugin_name].directory
17
+ )
18
+ ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, files)
19
+ fixtures(*files)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ unless ActiveSupport::TestCase.included_modules.include?(
27
+ RedminePluginsHelper::Patches::TestCasePatch
28
+ )
29
+ ActiveSupport::TestCase.send(:include, RedminePluginsHelper::Patches::TestCasePatch)
30
+ end
@@ -0,0 +1,25 @@
1
+ require_dependency 'redmine_plugins_helper'
2
+
3
+ module RedminePluginsHelper
4
+ class Settings
5
+ class << self
6
+ def default(plugin, default)
7
+ return unless ::RedminePluginsHelper.settings_table_exist?
8
+ p = plugin_current_setting_value(plugin)
9
+ default.each do |k, v|
10
+ p[k.to_s] = v unless p.key?(k)
11
+ end
12
+ ::Setting.send("plugin_#{plugin}=", p)
13
+ end
14
+
15
+ private
16
+
17
+ def plugin_current_setting_value(plugin)
18
+ p = ::Setting.send("plugin_#{plugin}")
19
+ p = {} unless p.is_a?(::Hash)
20
+ p = p.with_indifferent_access
21
+ p
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ module RedminePluginsHelper
2
+ class StatusMigrations
3
+ def initialize
4
+ run
5
+ end
6
+
7
+ private
8
+
9
+ def run
10
+ local_versions.each do |plugin, timestamps|
11
+ timestamps.each do |timestamp|
12
+ m = migrated_version?(plugin, timestamp) ? 'up' : 'down'
13
+ puts "#{m}\t#{plugin}\t#{timestamp}"
14
+ end
15
+ end
16
+ end
17
+
18
+ def migrated_version?(plugin, timestamp)
19
+ db_versions.key?(plugin) &&
20
+ db_versions[plugin].include?(timestamp)
21
+ end
22
+
23
+ def local_versions
24
+ @local_versions ||= ::RedminePluginsHelper::Migrations.local_versions
25
+ end
26
+
27
+ def db_versions
28
+ @db_versions ||= ::RedminePluginsHelper::Migrations.db_versions
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedminePluginsHelper
4
+ AUTHOR = 'Eduardo Henrique Bogoni'
5
+ SUMMARY = 'Helper for Redmine plugins'
6
+ VERSION = '0.5.2'
7
+ end
@@ -0,0 +1,9 @@
1
+ require 'sass-rails'
2
+
3
+ module RedminePluginsHelper
4
+ class << self
5
+ def settings_table_exist?
6
+ ActiveRecord::Base.connection.table_exists? ::Setting.table_name
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ Rake::Task['redmine:plugins:migrate'].clear
2
+
3
+ namespace :redmine do
4
+ desc 'Run migrations of core Redmine and installed plugins.'
5
+ task migrate: ['db:migrate', 'redmine:plugins:migrate:fix', 'redmine:plugins:migrate'] do
6
+ end
7
+
8
+ namespace :plugins do
9
+ desc 'Migrates installed plugins.'
10
+ task migrate: :environment do
11
+ RedminePluginsHelper::Migrate.new
12
+ Rake::Task['db:schema:dump'].invoke
13
+ end
14
+
15
+ namespace :migrate do
16
+ desc 'Fix migrations moved from a plugin to another'
17
+ task fix: :environment do
18
+ RedminePluginsHelper::FixMigrations.new
19
+ end
20
+
21
+ desc 'Show migrations status of all plugins'
22
+ task status: :environment do
23
+ RedminePluginsHelper::StatusMigrations.new
24
+ end
25
+ end
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redmine_plugins_helper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.2
5
+ platform: ruby
6
+ authors:
7
+ - 0.5.2
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-08-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sass-rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ description:
28
+ email:
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - app/assets/javascripts/plugins_autoload.js.erb
34
+ - app/assets/stylesheets/plugins_autoload.scss.erb
35
+ - config/initializers/assets.rb
36
+ - config/initializers/backport_pg_10_support_to_rails_4.rb
37
+ - init.rb
38
+ - lib/redmine_plugins_helper.rb
39
+ - lib/redmine_plugins_helper/fix_migrations.rb
40
+ - lib/redmine_plugins_helper/hooks/add_assets.rb
41
+ - lib/redmine_plugins_helper/migrate.rb
42
+ - lib/redmine_plugins_helper/migrations.rb
43
+ - lib/redmine_plugins_helper/patches/redmine/plugin_patch.rb
44
+ - lib/redmine_plugins_helper/patches/test_case_patch.rb
45
+ - lib/redmine_plugins_helper/settings.rb
46
+ - lib/redmine_plugins_helper/status_migrations.rb
47
+ - lib/redmine_plugins_helper/version.rb
48
+ - lib/tasks/redmine_plugins_helper.rake
49
+ homepage:
50
+ licenses: []
51
+ metadata: {}
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 2.7.7
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Helper for Redmine plugins
72
+ test_files: []