Mercurial > hg > soundsoftware-site
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? |