comparison lib/tasks/migrate_from_trac.rake @ 1115:433d4f72a19b redmine-2.2

Update to Redmine SVN revision 11137 on 2.2-stable branch
author Chris Cannam
date Mon, 07 Jan 2013 12:01:42 +0000
parents cbb26bc654de
children bb32da3bea34 622f24f53b42 261b3d9a4903
comparison
equal deleted inserted replaced
929:5f33065ddc4b 1115:433d4f72a19b
1 # Redmine - project management software 1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang 2 # Copyright (C) 2006-2012 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.
83 end 83 end
84 end 84 end
85 end 85 end
86 86
87 class TracComponent < ActiveRecord::Base 87 class TracComponent < ActiveRecord::Base
88 set_table_name :component 88 self.table_name = :component
89 end 89 end
90 90
91 class TracMilestone < ActiveRecord::Base 91 class TracMilestone < ActiveRecord::Base
92 set_table_name :milestone 92 self.table_name = :milestone
93 # If this attribute is set a milestone has a defined target timepoint 93 # If this attribute is set a milestone has a defined target timepoint
94 def due 94 def due
95 if read_attribute(:due) && read_attribute(:due) > 0 95 if read_attribute(:due) && read_attribute(:due) > 0
96 Time.at(read_attribute(:due)).to_date 96 Time.at(read_attribute(:due)).to_date
97 else 97 else
112 has_attribute?(:descr) ? read_attribute(:descr) : read_attribute(:description) 112 has_attribute?(:descr) ? read_attribute(:descr) : read_attribute(:description)
113 end 113 end
114 end 114 end
115 115
116 class TracTicketCustom < ActiveRecord::Base 116 class TracTicketCustom < ActiveRecord::Base
117 set_table_name :ticket_custom 117 self.table_name = :ticket_custom
118 end 118 end
119 119
120 class TracAttachment < ActiveRecord::Base 120 class TracAttachment < ActiveRecord::Base
121 set_table_name :attachment 121 self.table_name = :attachment
122 set_inheritance_column :none 122 set_inheritance_column :none
123 123
124 def time; Time.at(read_attribute(:time)) end 124 def time; Time.at(read_attribute(:time)) end
125 125
126 def original_filename 126 def original_filename
157 "#{TracMigrate.trac_attachments_directory}/#{attachment_type}/#{id}/#{trac_file}" 157 "#{TracMigrate.trac_attachments_directory}/#{attachment_type}/#{id}/#{trac_file}"
158 end 158 end
159 end 159 end
160 160
161 class TracTicket < ActiveRecord::Base 161 class TracTicket < ActiveRecord::Base
162 set_table_name :ticket 162 self.table_name = :ticket
163 set_inheritance_column :none 163 set_inheritance_column :none
164 164
165 # ticket changes: only migrate status changes and comments 165 # ticket changes: only migrate status changes and comments
166 has_many :changes, :class_name => "TracTicketChange", :foreign_key => :ticket 166 has_many :ticket_changes, :class_name => "TracTicketChange", :foreign_key => :ticket
167 has_many :attachments, :class_name => "TracAttachment",
168 :finder_sql => "SELECT DISTINCT attachment.* FROM #{TracMigrate::TracAttachment.table_name}" +
169 " WHERE #{TracMigrate::TracAttachment.table_name}.type = 'ticket'" +
170 ' AND #{TracMigrate::TracAttachment.table_name}.id = \'#{TracMigrate::TracAttachment.connection.quote_string(id.to_s)}\''
171 has_many :customs, :class_name => "TracTicketCustom", :foreign_key => :ticket 167 has_many :customs, :class_name => "TracTicketCustom", :foreign_key => :ticket
168
169 def attachments
170 TracMigrate::TracAttachment.all(:conditions => ["type = 'ticket' AND id = ?", self.id.to_s])
171 end
172 172
173 def ticket_type 173 def ticket_type
174 read_attribute(:type) 174 read_attribute(:type)
175 end 175 end
176 176
185 def time; Time.at(read_attribute(:time)) end 185 def time; Time.at(read_attribute(:time)) end
186 def changetime; Time.at(read_attribute(:changetime)) end 186 def changetime; Time.at(read_attribute(:changetime)) end
187 end 187 end
188 188
189 class TracTicketChange < ActiveRecord::Base 189 class TracTicketChange < ActiveRecord::Base
190 set_table_name :ticket_change 190 self.table_name = :ticket_change
191
192 def self.columns
193 # Hides Trac field 'field' to prevent clash with AR field_changed? method (Rails 3.0)
194 super.select {|column| column.name.to_s != 'field'}
195 end
191 196
192 def time; Time.at(read_attribute(:time)) end 197 def time; Time.at(read_attribute(:time)) end
193 end 198 end
194 199
195 TRAC_WIKI_PAGES = %w(InterMapTxt InterTrac InterWiki RecentChanges SandBox TracAccessibility TracAdmin TracBackup TracBrowser TracCgi TracChangeset \ 200 TRAC_WIKI_PAGES = %w(InterMapTxt InterTrac InterWiki RecentChanges SandBox TracAccessibility TracAdmin TracBackup TracBrowser TracCgi TracChangeset \
199 TracTicketsCustomFields TracTimeline TracUnicode TracUpgrade TracWiki WikiDeletePage WikiFormatting \ 204 TracTicketsCustomFields TracTimeline TracUnicode TracUpgrade TracWiki WikiDeletePage WikiFormatting \
200 WikiHtml WikiMacros WikiNewPage WikiPageNames WikiProcessors WikiRestructuredText WikiRestructuredTextLinks \ 205 WikiHtml WikiMacros WikiNewPage WikiPageNames WikiProcessors WikiRestructuredText WikiRestructuredTextLinks \
201 CamelCase TitleIndex) 206 CamelCase TitleIndex)
202 207
203 class TracWikiPage < ActiveRecord::Base 208 class TracWikiPage < ActiveRecord::Base
204 set_table_name :wiki 209 self.table_name = :wiki
205 set_primary_key :name 210 set_primary_key :name
206
207 has_many :attachments, :class_name => "TracAttachment",
208 :finder_sql => "SELECT DISTINCT attachment.* FROM #{TracMigrate::TracAttachment.table_name}" +
209 " WHERE #{TracMigrate::TracAttachment.table_name}.type = 'wiki'" +
210 ' AND #{TracMigrate::TracAttachment.table_name}.id = \'#{TracMigrate::TracAttachment.connection.quote_string(id.to_s)}\''
211 211
212 def self.columns 212 def self.columns
213 # Hides readonly Trac field to prevent clash with AR readonly? method (Rails 2.0) 213 # Hides readonly Trac field to prevent clash with AR readonly? method (Rails 2.0)
214 super.select {|column| column.name.to_s != 'readonly'} 214 super.select {|column| column.name.to_s != 'readonly'}
215 end 215 end
216 216
217 def attachments
218 TracMigrate::TracAttachment.all(:conditions => ["type = 'wiki' AND id = ?", self.id.to_s])
219 end
220
217 def time; Time.at(read_attribute(:time)) end 221 def time; Time.at(read_attribute(:time)) end
218 end 222 end
219 223
220 class TracPermission < ActiveRecord::Base 224 class TracPermission < ActiveRecord::Base
221 set_table_name :permission 225 self.table_name = :permission
222 end 226 end
223 227
224 class TracSessionAttribute < ActiveRecord::Base 228 class TracSessionAttribute < ActiveRecord::Base
225 set_table_name :session_attribute 229 self.table_name = :session_attribute
226 end 230 end
227 231
228 def self.find_or_create_user(username, project_member = false) 232 def self.find_or_create_user(username, project_member = false)
229 return User.anonymous if username.blank? 233 return User.anonymous if username.blank?
230 234
231 u = User.find_by_login(username) 235 u = User.find_by_login(username)
232 if !u 236 if !u
233 # Create a new user if not found 237 # Create a new user if not found
234 mail = username[0,limit_for(User, 'mail')] 238 mail = username[0, User::MAIL_LENGTH_LIMIT]
235 if mail_attr = TracSessionAttribute.find_by_sid_and_name(username, 'email') 239 if mail_attr = TracSessionAttribute.find_by_sid_and_name(username, 'email')
236 mail = mail_attr.value 240 mail = mail_attr.value
237 end 241 end
238 mail = "#{mail}@foo.bar" unless mail.include?("@") 242 mail = "#{mail}@foo.bar" unless mail.include?("@")
239 243
247 251
248 u = User.new :mail => mail.gsub(/[^-@a-z0-9\.]/i, '-'), 252 u = User.new :mail => mail.gsub(/[^-@a-z0-9\.]/i, '-'),
249 :firstname => fn[0, limit_for(User, 'firstname')], 253 :firstname => fn[0, limit_for(User, 'firstname')],
250 :lastname => ln[0, limit_for(User, 'lastname')] 254 :lastname => ln[0, limit_for(User, 'lastname')]
251 255
252 u.login = username[0,limit_for(User, 'login')].gsub(/[^a-z0-9_\-@\.]/i, '-') 256 u.login = username[0, User::LOGIN_LENGTH_LIMIT].gsub(/[^a-z0-9_\-@\.]/i, '-')
253 u.password = 'trac' 257 u.password = 'trac'
254 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')
255 # 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
256 u = User.find(:first) unless u.save 260 u = User.find(:first) unless u.save
257 end 261 end
481 i.assigned_to = find_or_create_user(ticket.owner, true) 485 i.assigned_to = find_or_create_user(ticket.owner, true)
482 Time.fake(ticket.changetime) { i.save } 486 Time.fake(ticket.changetime) { i.save }
483 end 487 end
484 488
485 # Comments and status/resolution changes 489 # Comments and status/resolution changes
486 ticket.changes.group_by(&:time).each do |time, changeset| 490 ticket.ticket_changes.group_by(&:time).each do |time, changeset|
487 status_change = changeset.select {|change| change.field == 'status'}.first 491 status_change = changeset.select {|change| change.field == 'status'}.first
488 resolution_change = changeset.select {|change| change.field == 'resolution'}.first 492 resolution_change = changeset.select {|change| change.field == 'resolution'}.first
489 comment_change = changeset.select {|change| change.field == 'comment'}.first 493 comment_change = changeset.select {|change| change.field == 'comment'}.first
490 494
491 n = Journal.new :notes => (comment_change ? convert_wiki_text(encode(comment_change.newvalue)) : ''), 495 n = Journal.new :notes => (comment_change ? convert_wiki_text(encode(comment_change.newvalue)) : ''),
619 @@trac_directory 623 @@trac_directory
620 end 624 end
621 625
622 def self.set_trac_adapter(adapter) 626 def self.set_trac_adapter(adapter)
623 return false if adapter.blank? 627 return false if adapter.blank?
624 raise "Unknown adapter: #{adapter}!" unless %w(sqlite sqlite3 mysql postgresql).include?(adapter) 628 raise "Unknown adapter: #{adapter}!" unless %w(sqlite3 mysql postgresql).include?(adapter)
625 # If adapter is sqlite or sqlite3, make sure that trac.db exists 629 # If adapter is sqlite or sqlite3, make sure that trac.db exists
626 raise "#{trac_db_path} doesn't exist!" if %w(sqlite sqlite3).include?(adapter) && !File.exist?(trac_db_path) 630 raise "#{trac_db_path} doesn't exist!" if %w(sqlite3).include?(adapter) && !File.exist?(trac_db_path)
627 @@trac_adapter = adapter 631 @@trac_adapter = adapter
628 rescue Exception => e 632 rescue Exception => e
629 puts e 633 puts e
630 return false 634 return false
631 end 635 end
684 @target_project = project.new_record? ? nil : project 688 @target_project = project.new_record? ? nil : project
685 @target_project.reload 689 @target_project.reload
686 end 690 end
687 691
688 def self.connection_params 692 def self.connection_params
689 if %w(sqlite sqlite3).include?(trac_adapter) 693 if trac_adapter == 'sqlite3'
690 {:adapter => trac_adapter, 694 {:adapter => 'sqlite3',
691 :database => trac_db_path} 695 :database => trac_db_path}
692 else 696 else
693 {:adapter => trac_adapter, 697 {:adapter => trac_adapter,
694 :database => trac_db_name, 698 :database => trac_db_name,
695 :host => trac_db_host, 699 :host => trac_db_host,
744 end 748 end
745 749
746 DEFAULT_PORTS = {'mysql' => 3306, 'postgresql' => 5432} 750 DEFAULT_PORTS = {'mysql' => 3306, 'postgresql' => 5432}
747 751
748 prompt('Trac directory') {|directory| TracMigrate.set_trac_directory directory.strip} 752 prompt('Trac directory') {|directory| TracMigrate.set_trac_directory directory.strip}
749 prompt('Trac database adapter (sqlite, sqlite3, mysql, postgresql)', :default => 'sqlite') {|adapter| TracMigrate.set_trac_adapter adapter} 753 prompt('Trac database adapter (sqlite3, mysql2, postgresql)', :default => 'sqlite3') {|adapter| TracMigrate.set_trac_adapter adapter}
750 unless %w(sqlite sqlite3).include?(TracMigrate.trac_adapter) 754 unless %w(sqlite3).include?(TracMigrate.trac_adapter)
751 prompt('Trac database host', :default => 'localhost') {|host| TracMigrate.set_trac_db_host host} 755 prompt('Trac database host', :default => 'localhost') {|host| TracMigrate.set_trac_db_host host}
752 prompt('Trac database port', :default => DEFAULT_PORTS[TracMigrate.trac_adapter]) {|port| TracMigrate.set_trac_db_port port} 756 prompt('Trac database port', :default => DEFAULT_PORTS[TracMigrate.trac_adapter]) {|port| TracMigrate.set_trac_db_port port}
753 prompt('Trac database name') {|name| TracMigrate.set_trac_db_name name} 757 prompt('Trac database name') {|name| TracMigrate.set_trac_db_name name}
754 prompt('Trac database schema', :default => 'public') {|schema| TracMigrate.set_trac_db_schema schema} 758 prompt('Trac database schema', :default => 'public') {|schema| TracMigrate.set_trac_db_schema schema}
755 prompt('Trac database username') {|username| TracMigrate.set_trac_db_username username} 759 prompt('Trac database username') {|username| TracMigrate.set_trac_db_username username}