summaryrefslogtreecommitdiffstats
path: root/vendor/plugins/engines/tasks/engines.rake
blob: 0ffd7e6e716e1399758daf2c7b2446ce18c286e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# This code lets us redefine existing Rake tasks, which is extremely
# handy for modifying existing Rails rake tasks.
# Credit for the original snippet of code goes to Jeremy Kemper
# http://pastie.caboo.se/9620
unless Rake::TaskManager.methods.include?('redefine_task')
  module Rake
    module TaskManager
      def redefine_task(task_class, args, &block)
        task_name, arg_names, deps = resolve_args([args])
        task_name = task_class.scope_name(@scope, task_name)
        deps = [deps] unless deps.respond_to?(:to_ary)
        deps = deps.collect {|d| d.to_s }
        task = @tasks[task_name.to_s] = task_class.new(task_name, self)
        task.application = self
        task.add_description(@last_description)
        @last_description = nil
        task.enhance(deps, &block)
        task
      end
      
    end
    class Task
      class << self
        def redefine_task(args, &block)
          Rake.application.redefine_task(self, [args], &block)
        end
      end
    end
  end
end

namespace :db do
  namespace :migrate do
    desc 'Migrate database and plugins to current status.'
    task :all => [ 'db:migrate', 'db:migrate:plugins' ]
    
    desc 'Migrate plugins to current status.'
    task :plugins => :environment do
      Engines.plugins.each do |plugin|
        next unless File.exists? plugin.migration_directory
        puts "Migrating plugin #{plugin.name} ..."
        plugin.migrate
      end
    end

    desc 'For engines coming from Rails version < 2.0 or for those previously updated to work with Sven Fuch\'s fork of engines, you need to upgrade the schema info table'
    task :upgrade_plugin_migrations => :environment do
      svens_fork_table_name = 'plugin_schema_migrations'
      
      # Check if app was previously using Sven's fork
      if ActiveRecord::Base.connection.table_exists?(svens_fork_table_name)
        old_sm_table = svens_fork_table_name
      else
        old_sm_table = ActiveRecord::Migrator.proper_table_name(Engines.schema_info_table)
      end
      
      unless ActiveRecord::Base.connection.table_exists?(old_sm_table)
        abort "Cannot find old migration table - assuming nothing needs to be done"
      end
      
      # There are two forms of the engines schema info - pre-fix_plugin_migrations and post
      # We need to figure this out before we continue.
      
      results = ActiveRecord::Base.connection.select_rows(
        "SELECT version, plugin_name FROM #{old_sm_table}"
      ).uniq
      
      def insert_new_version(plugin_name, version)
        version_string = "#{version}-#{plugin_name}"
        new_sm_table = ActiveRecord::Migrator.schema_migrations_table_name
        
        # Check if the row already exists for some reason - maybe run this task more than once.
        return if ActiveRecord::Base.connection.select_rows("SELECT * FROM #{new_sm_table} WHERE version = #{version_string.dump.gsub("\"", "'")}").size > 0
        
        puts "Inserting new version #{version} for plugin #{plugin_name}.."
        ActiveRecord::Base.connection.insert("INSERT INTO #{new_sm_table} (version) VALUES (#{version_string.dump.gsub("\"", "'")})")
      end
      
      # We need to figure out if they already used "fix_plugin_migrations"
      versions = {}
      results.each do |r|
        versions[r[1]] ||= []
        versions[r[1]] << r[0].to_i
      end
      
      if versions.values.find{ |v| v.size > 1 } == nil
        puts "Fixing migration info"
        # We only have one listed migration per plugin - this is pre-fix_plugin_migrations,
        # so we build all versions required. In this case, all migrations should 
        versions.each do |plugin_name, version|
          version = version[0] # There is only one version
          
          # We have to make an assumption that numeric migrations won't get this long..
          # I'm not sure if there is a better assumption, it should work in all
          # current cases.. (touch wood..)
          if version.to_s.size < "YYYYMMDDHHMMSS".size
            # Insert version records for each migration
            (1..version).each do |v|
             insert_new_version(plugin_name, v)
            end
          else
            # If the plugin is new-format "YYYYMMDDHHMMSS", we just copy it across... 
            # The case in which this occurs is very rare..
            insert_new_version(plugin_name, version)
          end
        end
      else
        puts "Moving migration info"
        # We have multiple migrations listed per plugin - thus we can assume they have
        # already applied fix_plugin_migrations - we just copy it across verbatim
        versions.each do |plugin_name, version|
          version.each { |v| insert_new_version(plugin_name, v) }
        end
      end
      
      puts "Migration info successfully migrated - removing old schema info table"
      ActiveRecord::Base.connection.drop_table(old_sm_table)
    end
    
    desc 'Migrate a specified plugin.'
    task({:plugin => :environment}, :name, :version) do |task, args|
      name = args[:name] || ENV['NAME']
      if plugin = Engines.plugins[name]
        version = args[:version] || ENV['VERSION']
        puts "Migrating #{plugin.name} to " + (version ? "version #{version}" : 'latest version') + " ..."
        plugin.migrate(version ? version.to_i : nil)
      else
        puts "Plugin #{name} does not exist."
      end
    end
  end
end


namespace :db do  
  namespace :fixtures do
    namespace :plugins do
      
      desc "Load plugin fixtures into the current environment's database."
      task :load => :environment do
        require 'active_record/fixtures'
        ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
        Dir.glob(File.join(RAILS_ROOT, 'vendor', 'plugins', ENV['PLUGIN'] || '**', 
                 'test', 'fixtures', '*.yml')).each do |fixture_file|
          Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*'))
        end
      end
      
    end
  end
end

# this is just a modification of the original task in railties/lib/tasks/documentation.rake, 
# because the default task doesn't support subdirectories like <plugin>/app or
# <plugin>/component. These tasks now include every file under a plugin's code paths (see
# Plugin#code_paths).
namespace :doc do

  plugins = FileList['vendor/plugins/**'].collect { |plugin| File.basename(plugin) }

  namespace :plugins do

    # Define doc tasks for each plugin
    plugins.each do |plugin|
      desc "Create plugin documentation for '#{plugin}'"
      Rake::Task.redefine_task(plugin => :environment) do
        plugin_base   = RAILS_ROOT + "/vendor/plugins/#{plugin}"
        options       = []
        files         = Rake::FileList.new
        options << "-o doc/plugins/#{plugin}"
        options << "--title '#{plugin.titlecase} Plugin Documentation'"
        options << '--line-numbers' << '--inline-source'
        options << '-T html'

        # Include every file in the plugin's code_paths (see Plugin#code_paths)
        if Engines.plugins[plugin]
          files.include("#{plugin_base}/{#{Engines.plugins[plugin].code_paths.join(",")}}/**/*.rb")
        end
        if File.exists?("#{plugin_base}/README")
          files.include("#{plugin_base}/README")    
          options << "--main '#{plugin_base}/README'"
        end
        files.include("#{plugin_base}/CHANGELOG") if File.exists?("#{plugin_base}/CHANGELOG")

        if files.empty?
          puts "No source files found in #{plugin_base}. No documentation will be generated."
        else
          options << files.to_s
          sh %(rdoc #{options * ' '})
        end
      end
    end
  end
end



namespace :test do
  task :warn_about_multiple_plugin_testing_with_engines do
    puts %{-~============== A Moste Polite Warninge ===========================~-

You may experience issues testing multiple plugins at once when using
the code-mixing features that the engines plugin provides. If you do
experience any problems, please test plugins individually, i.e.

  $ rake test:plugins PLUGIN=my_plugin

or use the per-type plugin test tasks:

  $ rake test:plugins:units
  $ rake test:plugins:functionals
  $ rake test:plugins:integration
  $ rake test:plugins:all

Report any issues on http://dev.rails-engines.org. Thanks!

-~===============( ... as you were ... )============================~-}
  end
  
  namespace :plugins do

    desc "Run the plugin tests in vendor/plugins/**/test (or specify with PLUGIN=name)"
    task :all => [:warn_about_multiple_plugin_testing_with_engines, 
                  :units, :functionals, :integration]
    
    desc "Run all plugin unit tests"
    Rake::TestTask.new(:units => :setup_plugin_fixtures) do |t|
      t.pattern = "vendor/plugins/#{ENV['PLUGIN'] || "**"}/test/unit/**/*_test.rb"
      t.verbose = true
    end
    
    desc "Run all plugin functional tests"
    Rake::TestTask.new(:functionals => :setup_plugin_fixtures) do |t|
      t.pattern = "vendor/plugins/#{ENV['PLUGIN'] || "**"}/test/functional/**/*_test.rb"
      t.verbose = true
    end
    
    desc "Integration test engines"
    Rake::TestTask.new(:integration => :setup_plugin_fixtures) do |t|
      t.pattern = "vendor/plugins/#{ENV['PLUGIN'] || "**"}/test/integration/**/*_test.rb"
      t.verbose = true
    end

    desc "Mirrors plugin fixtures into a single location to help plugin tests"
    task :setup_plugin_fixtures => :environment do
      Engines::Testing.setup_plugin_fixtures
    end
    
    # Patch the default plugin testing task to have setup_plugin_fixtures as a prerequisite
    Rake::Task["test:plugins"].prerequisites << "test:plugins:setup_plugin_fixtures"
  end
end