@@ -81,36 +81,6 namespace :redmine do | |||
|
81 | 81 | set_table_name :ticket_custom |
|
82 | 82 | end |
|
83 | 83 | |
|
84 | class TracTicket < ActiveRecord::Base | |
|
85 | set_table_name :ticket | |
|
86 | set_inheritance_column :none | |
|
87 | ||
|
88 | # ticket changes: only migrate status changes and comments | |
|
89 | has_many :changes, :class_name => "TracTicketChange", :foreign_key => :ticket, :conditions => "field = 'comment' OR field='status'" | |
|
90 | has_many :attachments, :class_name => "TracAttachment", :foreign_key => :id, :conditions => "type = 'ticket'" | |
|
91 | has_many :customs, :class_name => "TracTicketCustom", :foreign_key => :ticket | |
|
92 | ||
|
93 | def ticket_type | |
|
94 | read_attribute(:type) | |
|
95 | end | |
|
96 | ||
|
97 | def summary | |
|
98 | read_attribute(:summary).blank? ? "(no subject)" : read_attribute(:summary) | |
|
99 | end | |
|
100 | ||
|
101 | def description | |
|
102 | read_attribute(:description).blank? ? summary : read_attribute(:description) | |
|
103 | end | |
|
104 | ||
|
105 | def time; Time.at(read_attribute(:time)) end | |
|
106 | end | |
|
107 | ||
|
108 | class TracTicketChange < ActiveRecord::Base | |
|
109 | set_table_name :ticket_change | |
|
110 | ||
|
111 | def time; Time.at(read_attribute(:time)) end | |
|
112 | end | |
|
113 | ||
|
114 | 84 | class TracAttachment < ActiveRecord::Base |
|
115 | 85 | set_table_name :attachment |
|
116 | 86 | set_inheritance_column :none |
@@ -141,6 +111,36 namespace :redmine do | |||
|
141 | 111 | end |
|
142 | 112 | end |
|
143 | 113 | |
|
114 | class TracTicket < ActiveRecord::Base | |
|
115 | set_table_name :ticket | |
|
116 | set_inheritance_column :none | |
|
117 | ||
|
118 | # ticket changes: only migrate status changes and comments | |
|
119 | has_many :changes, :class_name => "TracTicketChange", :foreign_key => :ticket | |
|
120 | has_many :attachments, :class_name => "TracAttachment", :foreign_key => :id, :conditions => "#{TracMigrate::TracAttachment.table_name}.type = 'ticket'" | |
|
121 | has_many :customs, :class_name => "TracTicketCustom", :foreign_key => :ticket | |
|
122 | ||
|
123 | def ticket_type | |
|
124 | read_attribute(:type) | |
|
125 | end | |
|
126 | ||
|
127 | def summary | |
|
128 | read_attribute(:summary).blank? ? "(no subject)" : read_attribute(:summary) | |
|
129 | end | |
|
130 | ||
|
131 | def description | |
|
132 | read_attribute(:description).blank? ? summary : read_attribute(:description) | |
|
133 | end | |
|
134 | ||
|
135 | def time; Time.at(read_attribute(:time)) end | |
|
136 | end | |
|
137 | ||
|
138 | class TracTicketChange < ActiveRecord::Base | |
|
139 | set_table_name :ticket_change | |
|
140 | ||
|
141 | def time; Time.at(read_attribute(:time)) end | |
|
142 | end | |
|
143 | ||
|
144 | 144 | class TracWikiPage < ActiveRecord::Base |
|
145 | 145 | set_table_name :wiki |
|
146 | 146 | end |
@@ -250,6 +250,15 namespace :redmine do | |||
|
250 | 250 | end |
|
251 | 251 | puts |
|
252 | 252 |
|
|
253 | # Trac 'resolution' field as a Redmine custom field | |
|
254 | r = IssueCustomField.new :name => 'Resolution', | |
|
255 | :field_format => 'list', | |
|
256 | :is_filter => true | |
|
257 | r.trackers = Tracker.find(:all) | |
|
258 | r.projects << @target_project | |
|
259 | r.possible_values = %w(fixed invalid wontfix duplicate worksforme) | |
|
260 | custom_field_map['resolution'] = r if r.save | |
|
261 | ||
|
253 | 262 | # Tickets |
|
254 | 263 | print "Migrating tickets" |
|
255 | 264 | TracTicket.find(:all).each do |ticket| |
@@ -265,6 +274,7 namespace :redmine do | |||
|
265 | 274 | i.status = STATUS_MAPPING[ticket.status] || DEFAULT_STATUS |
|
266 | 275 | i.tracker = TRACKER_MAPPING[ticket.ticket_type] || DEFAULT_TRACKER |
|
267 | 276 | i.id = ticket.id |
|
277 | i.custom_values << CustomValue.new(:custom_field => custom_field_map['resolution'], :value => ticket.resolution) unless ticket.resolution.blank? | |
|
268 | 278 | next unless i.save |
|
269 | 279 | migrated_tickets += 1 |
|
270 | 280 | |
@@ -274,9 +284,10 namespace :redmine do | |||
|
274 | 284 | i.save |
|
275 | 285 | end |
|
276 | 286 | |
|
277 | # Comments and status changes | |
|
287 | # Comments and status/resolution changes | |
|
278 | 288 | ticket.changes.group_by(&:time).each do |time, changeset| |
|
279 | 289 | status_change = changeset.select {|change| change.field == 'status'}.first |
|
290 | resolution_change = changeset.select {|change| change.field == 'resolution'}.first | |
|
280 | 291 | comment_change = changeset.select {|change| change.field == 'comment'}.first |
|
281 | 292 | |
|
282 | 293 | n = Journal.new :notes => (comment_change ? convert_wiki_text(encode(comment_change.newvalue)) : ''), |
@@ -292,7 +303,13 namespace :redmine do | |||
|
292 | 303 | :old_value => STATUS_MAPPING[status_change.oldvalue].id, |
|
293 | 304 | :value => STATUS_MAPPING[status_change.newvalue].id) |
|
294 | 305 | end |
|
295 |
|
|
|
306 | if resolution_change | |
|
307 | n.details << JournalDetail.new(:property => 'cf', | |
|
308 | :prop_key => custom_field_map['resolution'].id, | |
|
309 | :old_value => resolution_change.oldvalue, | |
|
310 | :value => resolution_change.newvalue) | |
|
311 | end | |
|
312 | n.save unless n.details.empty? && n.notes.blank? | |
|
296 | 313 | end |
|
297 | 314 | |
|
298 | 315 | # Attachments |
@@ -424,7 +441,7 namespace :redmine do | |||
|
424 | 441 | end |
|
425 | 442 | |
|
426 | 443 | prompt('Trac directory') {|directory| TracMigrate.set_trac_directory directory} |
|
427 |
prompt(' |
|
|
444 | prompt('Trac database encoding', :default => 'UTF-8') {|encoding| TracMigrate.encoding encoding} | |
|
428 | 445 | prompt('Target project identifier') {|identifier| TracMigrate.target_project_identifier identifier} |
|
429 | 446 | puts |
|
430 | 447 |
General Comments 0
You need to be logged in to leave comments.
Login now