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