comparison lib/tasks/migrate_from_trac.rake @ 1298:4f746d8966dd redmine_2.3_integration

Merge from redmine-2.3 branch to create new branch redmine-2.3-integration
author Chris Cannam
date Fri, 14 Jun 2013 09:28:30 +0100
parents bb32da3bea34 622f24f53b42
children
comparison
equal deleted inserted replaced
1297:0a574315af3e 1298:4f746d8966dd
1 # Redmine - project management software 1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang 2 # Copyright (C) 2006-2013 Jean-Philippe Lang
3 # 3 #
4 # This program is free software; you can redistribute it and/or 4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License 5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2 6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version. 7 # of the License, or (at your option) any later version.
14 # You should have received a copy of the GNU General Public License 14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software 15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 require 'active_record' 18 require 'active_record'
19 require 'iconv' 19 require 'iconv' if RUBY_VERSION < '1.9'
20 require 'pp' 20 require 'pp'
21 21
22 namespace :redmine do 22 namespace :redmine do
23 desc 'Trac migration script' 23 desc 'Trac migration script'
24 task :migrate_from_trac => :environment do 24 task :migrate_from_trac => :environment do
28 28
29 DEFAULT_STATUS = IssueStatus.default 29 DEFAULT_STATUS = IssueStatus.default
30 assigned_status = IssueStatus.find_by_position(2) 30 assigned_status = IssueStatus.find_by_position(2)
31 resolved_status = IssueStatus.find_by_position(3) 31 resolved_status = IssueStatus.find_by_position(3)
32 feedback_status = IssueStatus.find_by_position(4) 32 feedback_status = IssueStatus.find_by_position(4)
33 closed_status = IssueStatus.find :first, :conditions => { :is_closed => true } 33 closed_status = IssueStatus.where(:is_closed => true).first
34 STATUS_MAPPING = {'new' => DEFAULT_STATUS, 34 STATUS_MAPPING = {'new' => DEFAULT_STATUS,
35 'reopened' => feedback_status, 35 'reopened' => feedback_status,
36 'assigned' => assigned_status, 36 'assigned' => assigned_status,
37 'closed' => closed_status 37 'closed' => closed_status
38 } 38 }
59 'enhancement' => TRACKER_FEATURE, 59 'enhancement' => TRACKER_FEATURE,
60 'task' => TRACKER_FEATURE, 60 'task' => TRACKER_FEATURE,
61 'patch' =>TRACKER_FEATURE 61 'patch' =>TRACKER_FEATURE
62 } 62 }
63 63
64 roles = Role.find(:all, :conditions => {:builtin => 0}, :order => 'position ASC') 64 roles = Role.where(:builtin => 0).order('position ASC').all
65 manager_role = roles[0] 65 manager_role = roles[0]
66 developer_role = roles[1] 66 developer_role = roles[1]
67 DEFAULT_ROLE = roles.last 67 DEFAULT_ROLE = roles.last
68 ROLE_MAPPING = {'admin' => manager_role, 68 ROLE_MAPPING = {'admin' => manager_role,
69 'developer' => developer_role 69 'developer' => developer_role
255 255
256 u.login = username[0, User::LOGIN_LENGTH_LIMIT].gsub(/[^a-z0-9_\-@\.]/i, '-') 256 u.login = username[0, User::LOGIN_LENGTH_LIMIT].gsub(/[^a-z0-9_\-@\.]/i, '-')
257 u.password = 'trac' 257 u.password = 'trac'
258 u.admin = true if TracPermission.find_by_username_and_action(username, 'admin') 258 u.admin = true if TracPermission.find_by_username_and_action(username, 'admin')
259 # finally, a default user is used if the new user is not valid 259 # finally, a default user is used if the new user is not valid
260 u = User.find(:first) unless u.save 260 u = User.first unless u.save
261 end 261 end
262 # Make sure he is a member of the project 262 # Make sure he is a member of the project
263 if project_member && !u.member_of?(@target_project) 263 if project_member && !u.member_of?(@target_project)
264 role = DEFAULT_ROLE 264 role = DEFAULT_ROLE
265 if u.admin 265 if u.admin
388 wiki_edit_count = 0 388 wiki_edit_count = 0
389 389
390 # Components 390 # Components
391 print "Migrating components" 391 print "Migrating components"
392 issues_category_map = {} 392 issues_category_map = {}
393 TracComponent.find(:all).each do |component| 393 TracComponent.all.each do |component|
394 print '.' 394 print '.'
395 STDOUT.flush 395 STDOUT.flush
396 c = IssueCategory.new :project => @target_project, 396 c = IssueCategory.new :project => @target_project,
397 :name => encode(component.name[0, limit_for(IssueCategory, 'name')]) 397 :name => encode(component.name[0, limit_for(IssueCategory, 'name')])
398 next unless c.save 398 next unless c.save
402 puts 402 puts
403 403
404 # Milestones 404 # Milestones
405 print "Migrating milestones" 405 print "Migrating milestones"
406 version_map = {} 406 version_map = {}
407 TracMilestone.find(:all).each do |milestone| 407 TracMilestone.all.each do |milestone|
408 print '.' 408 print '.'
409 STDOUT.flush 409 STDOUT.flush
410 # First we try to find the wiki page... 410 # First we try to find the wiki page...
411 p = wiki.find_or_new_page(milestone.name.to_s) 411 p = wiki.find_or_new_page(milestone.name.to_s)
412 p.content = WikiContent.new(:page => p) if p.new_record? 412 p.content = WikiContent.new(:page => p) if p.new_record?
441 # Or create a new one 441 # Or create a new one
442 f ||= IssueCustomField.create(:name => encode(field.name[0, limit_for(IssueCustomField, 'name')]).humanize, 442 f ||= IssueCustomField.create(:name => encode(field.name[0, limit_for(IssueCustomField, 'name')]).humanize,
443 :field_format => 'string') 443 :field_format => 'string')
444 444
445 next if f.new_record? 445 next if f.new_record?
446 f.trackers = Tracker.find(:all) 446 f.trackers = Tracker.all
447 f.projects << @target_project 447 f.projects << @target_project
448 custom_field_map[field.name] = f 448 custom_field_map[field.name] = f
449 end 449 end
450 puts 450 puts
451 451
452 # Trac 'resolution' field as a Redmine custom field 452 # Trac 'resolution' field as a Redmine custom field
453 r = IssueCustomField.find(:first, :conditions => { :name => "Resolution" }) 453 r = IssueCustomField.where(:name => "Resolution").first
454 r = IssueCustomField.new(:name => 'Resolution', 454 r = IssueCustomField.new(:name => 'Resolution',
455 :field_format => 'list', 455 :field_format => 'list',
456 :is_filter => true) if r.nil? 456 :is_filter => true) if r.nil?
457 r.trackers = Tracker.find(:all) 457 r.trackers = Tracker.all
458 r.projects << @target_project 458 r.projects << @target_project
459 r.possible_values = (r.possible_values + %w(fixed invalid wontfix duplicate worksforme)).flatten.compact.uniq 459 r.possible_values = (r.possible_values + %w(fixed invalid wontfix duplicate worksforme)).flatten.compact.uniq
460 r.save! 460 r.save!
461 custom_field_map['resolution'] = r 461 custom_field_map['resolution'] = r
462 462
547 puts 547 puts
548 548
549 # Wiki 549 # Wiki
550 print "Migrating wiki" 550 print "Migrating wiki"
551 if wiki.save 551 if wiki.save
552 TracWikiPage.find(:all, :order => 'name, version').each do |page| 552 TracWikiPage.order('name, version').all.each do |page|
553 # Do not migrate Trac manual wiki pages 553 # Do not migrate Trac manual wiki pages
554 next if TRAC_WIKI_PAGES.include?(page.name) 554 next if TRAC_WIKI_PAGES.include?(page.name)
555 wiki_edit_count += 1 555 wiki_edit_count += 1
556 print '.' 556 print '.'
557 STDOUT.flush 557 STDOUT.flush
601 def self.limit_for(klass, attribute) 601 def self.limit_for(klass, attribute)
602 klass.columns_hash[attribute.to_s].limit 602 klass.columns_hash[attribute.to_s].limit
603 end 603 end
604 604
605 def self.encoding(charset) 605 def self.encoding(charset)
606 @ic = Iconv.new('UTF-8', charset) 606 @charset = charset
607 rescue Iconv::InvalidEncoding
608 puts "Invalid encoding!"
609 return false
610 end 607 end
611 608
612 def self.set_trac_directory(path) 609 def self.set_trac_directory(path)
613 @@trac_directory = path 610 @@trac_directory = path
614 raise "This directory doesn't exist!" unless File.directory?(path) 611 raise "This directory doesn't exist!" unless File.directory?(path)
711 next unless klass.respond_to? 'establish_connection' 708 next unless klass.respond_to? 'establish_connection'
712 klass.establish_connection connection_params 709 klass.establish_connection connection_params
713 end 710 end
714 end 711 end
715 712
716 private
717 def self.encode(text) 713 def self.encode(text)
718 @ic.iconv text 714 if RUBY_VERSION < '1.9'
719 rescue 715 @ic ||= Iconv.new('UTF-8', @charset)
720 text 716 @ic.iconv text
717 else
718 text.to_s.force_encoding(@charset).encode('UTF-8')
719 end
721 end 720 end
722 end 721 end
723 722
724 puts 723 puts
725 if Redmine::DefaultData::Loader.no_data? 724 if Redmine::DefaultData::Loader.no_data?