ChiliProject is not maintained anymore. Please be advised that there will be no more updates.
We do not recommend that you setup new ChiliProject instances and we urge all existing users to migrate their data to a maintained system, e.g. Redmine. We will provide a migration script later. In the meantime, you can use the instructions by Christian Daehn.
migrate_from_mantis.rake
1 | # redMine - project management software
|
---|---|
2 | # Copyright (C) 2006-2007 Jean-Philippe Lang
|
3 | #
|
4 | # This program is free software; you can redistribute it and/or
|
5 | # modify it under the terms of the GNU General Public License
|
6 | # as published by the Free Software Foundation; either version 2
|
7 | # of the License, or (at your option) any later version.
|
8 | #
|
9 | # This program is distributed in the hope that it will be useful,
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12 | # GNU General Public License for more details.
|
13 | #
|
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
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
17 | |
18 | desc 'Mantis migration script'
|
19 | |
20 | require 'active_record'
|
21 | require 'iconv'
|
22 | require 'pp'
|
23 | |
24 | namespace :redmine do |
25 | task :migrate_from_mantis => :environment do |
26 | |
27 | module ActiveSupport |
28 | module Dependencies |
29 | extend self
|
30 | |
31 | #def load_missing_constant(from_mod, const_name)
|
32 | |
33 | def forgiving_load_missing_constant( from_mod, const_name ) |
34 | begin
|
35 | old_load_missing_constant(from_mod, const_name) |
36 | rescue ArgumentError => arg_err |
37 | if arg_err.message == "#{from_mod} is not missing constant #{const_name}!" |
38 | return from_mod.const_get(const_name)
|
39 | else
|
40 | raise |
41 | end
|
42 | end
|
43 | end
|
44 | alias :old_load_missing_constant :load_missing_constant |
45 | alias :load_missing_constant :forgiving_load_missing_constant |
46 | end
|
47 | end
|
48 | |
49 | module MantisMigrate |
50 | |
51 | DEFAULT_STATUS = IssueStatus.default |
52 | assigned_status = IssueStatus.find_by_position(2) |
53 | resolved_status = IssueStatus.find_by_position(3) |
54 | feedback_status = IssueStatus.find_by_position(4) |
55 | closed_status = IssueStatus.find :first, :conditions => { :is_closed => true } |
56 | STATUS_MAPPING = {10 => DEFAULT_STATUS, # new |
57 | 20 => feedback_status, # feedback |
58 | 30 => DEFAULT_STATUS, # acknowledged |
59 | 40 => DEFAULT_STATUS, # confirmed |
60 | 50 => assigned_status, # assigned |
61 | 80 => resolved_status, # resolved |
62 | 90 => closed_status # closed |
63 | } |
64 | |
65 | priorities = IssuePriority.all
|
66 | DEFAULT_PRIORITY = priorities[2] |
67 | PRIORITY_MAPPING = {10 => priorities[1], # none |
68 | 20 => priorities[1], # low |
69 | 30 => priorities[2], # normal |
70 | 40 => priorities[3], # high |
71 | 50 => priorities[4], # urgent |
72 | 60 => priorities[5] # immediate |
73 | } |
74 | |
75 | TRACKER_BUG = Tracker.find_by_position(1) |
76 | TRACKER_FEATURE = Tracker.find_by_position(2) |
77 | |
78 | roles = Role.find(:all, :conditions => {:builtin => 0}, :order => 'position ASC') |
79 | manager_role = roles[0]
|
80 | developer_role = roles[1]
|
81 | DEFAULT_ROLE = roles.last
|
82 | ROLE_MAPPING = {10 => DEFAULT_ROLE, # viewer |
83 | 25 => DEFAULT_ROLE, # reporter |
84 | 40 => DEFAULT_ROLE, # updater |
85 | 55 => developer_role, # developer |
86 | 70 => manager_role, # manager |
87 | 90 => manager_role # administrator |
88 | } |
89 | |
90 | CUSTOM_FIELD_TYPE_MAPPING = {0 => 'string', # String |
91 | 1 => 'int', # Numeric |
92 | 2 => 'int', # Float |
93 | 3 => 'list', # Enumeration |
94 | 4 => 'string', # Email |
95 | 5 => 'bool', # Checkbox |
96 | 6 => 'list', # List |
97 | 7 => 'list', # Multiselection list |
98 | 8 => 'date', # Date |
99 | } |
100 | |
101 | RELATION_TYPE_MAPPING = {1 => IssueRelation::TYPE_RELATES, # related to |
102 | 2 => IssueRelation::TYPE_RELATES, # parent of |
103 | 3 => IssueRelation::TYPE_RELATES, # child of |
104 | 0 => IssueRelation::TYPE_DUPLICATES, # duplicate of |
105 | 4 => IssueRelation::TYPE_DUPLICATES # has duplicate |
106 | } |
107 | |
108 | HISTORY_MAPPING = {'handler_id' => ['assigned_to_id'], |
109 | 'status' => ['status_id', STATUS_MAPPING], |
110 | 'priority' => ['priority_id', PRIORITY_MAPPING] |
111 | } |
112 | |
113 | class MantisUser < ActiveRecord::Base |
114 | set_table_name :mantis_user_table
|
115 | |
116 | def firstname |
117 | @firstname = realname.blank? ? username : realname.split.first[0..29] |
118 | @firstname.gsub!(/[^\w\s\'\-]/i, '') |
119 | @firstname
|
120 | end
|
121 | |
122 | def lastname |
123 | @lastname = realname.blank? ? '-' : realname.split[1..-1].join(' ')[0..29] |
124 | @lastname.gsub!(/[^\w\s\'\-]/i, '') |
125 | @lastname = '-' if @lastname.blank? |
126 | @lastname
|
127 | end
|
128 | |
129 | def email |
130 | if read_attribute(:email).match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i) && |
131 | !User.find_by_mail(read_attribute(:email)) |
132 | @email = read_attribute(:email) |
133 | else
|
134 | @email = "#{username}@foo.bar" |
135 | end
|
136 | end
|
137 | |
138 | def username |
139 | read_attribute(:username)[0..29].gsub(/[^a-zA-Z0-9_\-@\.]/, '-') |
140 | end
|
141 | end
|
142 | |
143 | class MantisProject < ActiveRecord::Base |
144 | set_table_name :mantis_project_table
|
145 | has_many :versions, :class_name => "MantisVersion", :foreign_key => :project_id |
146 | has_many :categories, :class_name => "MantisCategory", :foreign_key => :project_id |
147 | has_many :news, :class_name => "MantisNews", :foreign_key => :project_id |
148 | has_many :members, :class_name => "MantisProjectUser", :foreign_key => :project_id |
149 | |
150 | def name |
151 | read_attribute(:name)[0..29] |
152 | end
|
153 | |
154 | def identifier |
155 | read_attribute(:name).underscore[0..19].gsub(/[^a-z0-9\-]/, '-') |
156 | end
|
157 | end
|
158 | |
159 | class MantisVersion < ActiveRecord::Base |
160 | set_table_name :mantis_project_version_table
|
161 | |
162 | def version |
163 | read_attribute(:version)[0..29] |
164 | end
|
165 | |
166 | def description |
167 | read_attribute(:description)[0..254] |
168 | end
|
169 | end
|
170 | |
171 | class MantisCategory < ActiveRecord::Base |
172 | set_table_name :mantis_category_table
|
173 | end
|
174 | |
175 | class MantisProjectUser < ActiveRecord::Base |
176 | set_table_name :mantis_project_user_list_table
|
177 | end
|
178 | |
179 | class MantisBug < ActiveRecord::Base |
180 | set_table_name :mantis_bug_table
|
181 | belongs_to :bug_text, :class_name => "MantisBugText", :foreign_key => :bug_text_id |
182 | has_many :bug_notes, :class_name => "MantisBugNote", :foreign_key => :bug_id |
183 | has_many :bug_files, :class_name => "MantisBugFile", :foreign_key => :bug_id |
184 | has_many :bug_monitors, :class_name => "MantisBugMonitor", :foreign_key => :bug_id |
185 | has_many :bug_history, :class_name => "MantisBugHistory", :foreign_key => :bug_id |
186 | end
|
187 | |
188 | class MantisBugText < ActiveRecord::Base |
189 | set_table_name :mantis_bug_text_table
|
190 | |
191 | # Adds Mantis steps_to_reproduce and additional_information fields
|
192 | # to description if any
|
193 | def full_description |
194 | full_description = description |
195 | full_description += "\n\n*Steps to reproduce:*\n\n#{steps_to_reproduce}" unless steps_to_reproduce.blank? |
196 | full_description += "\n\n*Additional information:*\n\n#{additional_information}" unless additional_information.blank? |
197 | full_description |
198 | end
|
199 | end
|
200 | |
201 | class MantisBugNote < ActiveRecord::Base |
202 | set_table_name :mantis_bugnote_table
|
203 | belongs_to :bug, :class_name => "MantisBug", :foreign_key => :bug_id |
204 | belongs_to :bug_note_text, :class_name => "MantisBugNoteText", :foreign_key => :bugnote_text_id |
205 | end
|
206 | |
207 | class MantisBugNoteText < ActiveRecord::Base |
208 | set_table_name :mantis_bugnote_text_table
|
209 | end
|
210 | |
211 | class MantisBugHistory < ActiveRecord::Base |
212 | set_table_name :mantis_bug_history_table
|
213 | set_inheritance_column :none
|
214 | belongs_to :bug, :class_name => "MantisBug", :foreign_key => :bug_id |
215 | end
|
216 | |
217 | class MantisBugFile < ActiveRecord::Base |
218 | set_table_name :mantis_bug_file_table
|
219 | |
220 | def size |
221 | filesize |
222 | end
|
223 | |
224 | def original_filename |
225 | MantisMigrate.encode(filename)
|
226 | end
|
227 | |
228 | def content_type |
229 | file_type |
230 | end
|
231 | |
232 | def read(*args) |
233 | if @read_finished |
234 | nil
|
235 | else
|
236 | @read_finished = true |
237 | content |
238 | end
|
239 | end
|
240 | end
|
241 | |
242 | class MantisBugRelationship < ActiveRecord::Base |
243 | set_table_name :mantis_bug_relationship_table
|
244 | end
|
245 | |
246 | class MantisBugMonitor < ActiveRecord::Base |
247 | set_table_name :mantis_bug_monitor_table
|
248 | end
|
249 | |
250 | class MantisNews < ActiveRecord::Base |
251 | set_table_name :mantis_news_table
|
252 | end
|
253 | |
254 | class MantisCustomField < ActiveRecord::Base |
255 | set_table_name :mantis_custom_field_table
|
256 | set_inheritance_column :none
|
257 | has_many :values, :class_name => "MantisCustomFieldString", :foreign_key => :field_id |
258 | has_many :projects, :class_name => "MantisCustomFieldProject", :foreign_key => :field_id |
259 | |
260 | def format |
261 | read_attribute :type
|
262 | end
|
263 | |
264 | def name |
265 | read_attribute(:name)[0..29].gsub(/[^\w\s\'\-]/, '-') |
266 | end
|
267 | end
|
268 | |
269 | class MantisCustomFieldProject < ActiveRecord::Base |
270 | set_table_name :mantis_custom_field_project_table
|
271 | end
|
272 | |
273 | class MantisCustomFieldString < ActiveRecord::Base |
274 | set_table_name :mantis_custom_field_string_table
|
275 | end
|
276 | |
277 | def self.mantis_date_convert(time_stamp) |
278 | DateTime.strptime(time_stamp.to_s, "%s") |
279 | end
|
280 | |
281 | def self.migrate |
282 | |
283 | # Users
|
284 | print "Migrating users"
|
285 | User.delete_all "login <> 'admin'" |
286 | users_map = {} |
287 | users_migrated = 0
|
288 | MantisUser.find(:all).each do |user| |
289 | u = User.new :firstname => encode(user.firstname), |
290 | :lastname => encode(user.lastname),
|
291 | :mail => user.email,
|
292 | :last_login_on => user.last_visit
|
293 | u.login = user.username |
294 | u.password = 'mantis'
|
295 | u.status = User::STATUS_LOCKED if user.enabled != 1 |
296 | u.admin = true if user.access_level == 90 |
297 | next unless u.save! |
298 | users_migrated += 1
|
299 | users_map[user.id] = u.id |
300 | print '.'
|
301 | STDOUT.flush
|
302 | end
|
303 | puts |
304 | |
305 | # Projects
|
306 | print "Migrating projects"
|
307 | Project.destroy_all
|
308 | projects_map = {} |
309 | versions_map = {} |
310 | categories_map = {} |
311 | MantisProject.find(:all).each do |project| |
312 | p = Project.new :name => encode(project.name), |
313 | :description => encode(project.description),
|
314 | :trackers => [TRACKER_BUG, TRACKER_FEATURE] |
315 | p.identifier = project.identifier |
316 | next unless p.save |
317 | projects_map[project.id] = p.id |
318 | p.enabled_module_names = ['issue_tracking', 'news', 'wiki'] |
319 | p.save |
320 | print '.'
|
321 | STDOUT.flush
|
322 | |
323 | # Project members
|
324 | project.members.each do |member|
|
325 | m = Member.new :user => User.find_by_id(users_map[member.user_id]), |
326 | :roles => [ROLE_MAPPING[member.access_level] || DEFAULT_ROLE] |
327 | m.project = p |
328 | m.save |
329 | end
|
330 | |
331 | # Project versions
|
332 | project.versions.each do |version|
|
333 | v = Version.new :name => encode(version.version), |
334 | :description => encode(version.description),
|
335 | :effective_date => mantis_date_convert(version.date_order).to_date
|
336 | v.project = p |
337 | v.save |
338 | versions_map[version.id] = v.id |
339 | end
|
340 | |
341 | # Project categories
|
342 | project.categories.each do |category|
|
343 | g = IssueCategory.new :name => category.name[0,30] |
344 | g.project = p |
345 | g.save |
346 | categories_map[category.name] = g.id |
347 | end
|
348 | end
|
349 | puts |
350 | |
351 | # Bugs
|
352 | print "Migrating bugs"
|
353 | Issue.destroy_all
|
354 | issues_map = {} |
355 | keep_bug_ids = (Issue.count == 0) |
356 | MantisBug.find_each(:batch_size => 200) do |bug| |
357 | next unless projects_map[bug.project_id] && users_map[bug.reporter_id] |
358 | i = Issue.new :project_id => projects_map[bug.project_id], |
359 | :subject => encode(bug.summary),
|
360 | :description => encode(bug.bug_text.full_description),
|
361 | :priority => PRIORITY_MAPPING[bug.priority] || DEFAULT_PRIORITY, |
362 | :created_on => mantis_date_convert(bug.date_submitted),
|
363 | :updated_on => mantis_date_convert(bug.last_updated)
|
364 | i.author = User.find_by_id(users_map[bug.reporter_id])
|
365 | i.category = IssueCategory.find_by_project_id_and_id(i.project_id, bug.category_id) unless bug.category_id.blank? |
366 | i.fixed_version = Version.find_by_project_id_and_name(i.project_id, bug.fixed_in_version) unless bug.fixed_in_version.blank? |
367 | i.status = STATUS_MAPPING[bug.status] || DEFAULT_STATUS |
368 | i.tracker = (bug.severity == 10 ? TRACKER_FEATURE : TRACKER_BUG) |
369 | i.id = bug.id if keep_bug_ids
|
370 | i.updated_on = mantis_date_convert(bug.last_updated) |
371 | # Assignee
|
372 | # Redmine checks that the assignee is a project member
|
373 | if (bug.handler_id && users_map[bug.handler_id])
|
374 | i.assigned_to = User.find_by_id(users_map[bug.handler_id])
|
375 | end
|
376 | |
377 | next unless i.save_with_validation(false) |
378 | issues_map[bug.id] = i.id |
379 | print '.'
|
380 | STDOUT.flush
|
381 | |
382 | Journal.class_exec {
|
383 | def touch_journaled_after_creation |
384 | end
|
385 | } |
386 | # Bug notes
|
387 | bug.bug_notes.each do |note|
|
388 | next unless users_map[note.reporter_id] |
389 | n = Journal.new(:user => User.find_by_id(users_map[note.reporter_id]), |
390 | :notes => encode(note.bug_note_text.note))
|
391 | n.created_at = mantis_date_convert(note.date_submitted) |
392 | n.version = i.journals.last.version + 1
|
393 | n.activity_type = 'issues'
|
394 | n.journaled_id = i.id |
395 | n.changes = '--- {}'
|
396 | n.type = 'IssueJournal'
|
397 | n.journalized = i |
398 | n.save unless n.notes.blank?
|
399 | end
|
400 | |
401 | # Bug history
|
402 | bug.bug_history.each do |hist|
|
403 | next unless HISTORY_MAPPING.has_key? hist.field_name |
404 | field = HISTORY_MAPPING[hist.field_name][0] |
405 | if HISTORY_MAPPING[hist.field_name][1] |
406 | m = HISTORY_MAPPING[hist.field_name][1] |
407 | old = m[hist.old_value.to_i].id |
408 | new = m[hist.new_value.to_i].id |
409 | else
|
410 | if hist.field_name = 'handler_id' |
411 | m = users_map |
412 | old = m[hist.old_value.to_i] |
413 | new = m[hist.new_value.to_i] |
414 | else
|
415 | old = hist.old_value |
416 | new = hist.new_value |
417 | end
|
418 | end
|
419 | n = Journal.new(:user => User.find_by_id(users_map[hist.user_id])) |
420 | n.created_at = mantis_date_convert(hist.date_modified) |
421 | n.version = i.journals.last.version + 1
|
422 | n.notes = ""
|
423 | n.activity_type = 'issues'
|
424 | n.journaled_id = i.id |
425 | n.changes = "--- \n#{field}:\n- #{old}\n- #{new}"
|
426 | n.type = 'IssueJournal'
|
427 | n.journalized = i |
428 | n.save |
429 | end
|
430 | |
431 | # Bug files
|
432 | bug.bug_files.each do |file|
|
433 | a = Attachment.new :created_on => mantis_date_convert(file.date_added) |
434 | a.file = file |
435 | a.author = User.find :first |
436 | a.container = i |
437 | a.save |
438 | end
|
439 | |
440 | # Bug monitors
|
441 | bug.bug_monitors.each do |monitor|
|
442 | next unless users_map[monitor.user_id] |
443 | i.add_watcher(User.find_by_id(users_map[monitor.user_id]))
|
444 | end
|
445 | end
|
446 | |
447 | # update issue id sequence if needed (postgresql)
|
448 | Issue.connection.reset_pk_sequence!(Issue.table_name) if Issue.connection.respond_to?('reset_pk_sequence!') |
449 | puts |
450 | |
451 | # Bug relationships
|
452 | print "Migrating bug relations"
|
453 | MantisBugRelationship.find(:all).each do |relation| |
454 | next unless issues_map[relation.source_bug_id] && issues_map[relation.destination_bug_id] |
455 | r = IssueRelation.new :relation_type => RELATION_TYPE_MAPPING[relation.relationship_type] |
456 | r.issue_from = Issue.find_by_id(issues_map[relation.source_bug_id])
|
457 | r.issue_to = Issue.find_by_id(issues_map[relation.destination_bug_id])
|
458 | pp r unless r.save
|
459 | print '.'
|
460 | STDOUT.flush
|
461 | end
|
462 | puts |
463 | |
464 | # News
|
465 | print "Migrating news"
|
466 | News.destroy_all
|
467 | MantisNews.find(:all, :conditions => 'project_id > 0').each do |news| |
468 | next unless projects_map[news.project_id] |
469 | n = News.new :project_id => projects_map[news.project_id], |
470 | :title => encode(news.headline[0..59]), |
471 | :description => encode(news.body),
|
472 | :created_on => mantis_date_convert(news.date_posted)
|
473 | n.author = User.find_by_id(users_map[news.poster_id])
|
474 | n.save |
475 | print '.'
|
476 | STDOUT.flush
|
477 | end
|
478 | puts |
479 | |
480 | # Custom fields
|
481 | print "Migrating custom fields"
|
482 | IssueCustomField.destroy_all
|
483 | MantisCustomField.find(:all).each do |field| |
484 | f = IssueCustomField.new :name => field.name[0..29], |
485 | :field_format => CUSTOM_FIELD_TYPE_MAPPING[field.format], |
486 | :min_length => field.length_min,
|
487 | :max_length => field.length_max,
|
488 | :regexp => field.valid_regexp,
|
489 | :possible_values => field.possible_values.split('|'), |
490 | :is_required => field.require_report?
|
491 | next unless f.save |
492 | print '.'
|
493 | STDOUT.flush
|
494 | |
495 | # Trackers association
|
496 | f.trackers = Tracker.find :all |
497 | |
498 | # Projects association
|
499 | field.projects.each do |project|
|
500 | f.projects << Project.find_by_id(projects_map[project.project_id]) if projects_map[project.project_id] |
501 | end
|
502 | |
503 | # Values
|
504 | field.values.each do |value|
|
505 | v = CustomValue.new :custom_field_id => f.id, |
506 | :value => value.value
|
507 | v.customized = Issue.find_by_id(issues_map[value.bug_id]) if issues_map[value.bug_id] |
508 | v.save |
509 | end unless f.new_record? |
510 | grep end
|
511 | puts |
512 | |
513 | puts |
514 | puts "Users: #{users_migrated}/#{MantisUser.count}"
|
515 | puts "Projects: #{Project.count}/#{MantisProject.count}"
|
516 | puts "Memberships: #{Member.count}/#{MantisProjectUser.count}"
|
517 | puts "Versions: #{Version.count}/#{MantisVersion.count}"
|
518 | puts "Categories: #{IssueCategory.count}/#{MantisCategory.count}"
|
519 | puts "Bugs: #{Issue.count}/#{MantisBug.count}"
|
520 | puts "Bug notes: #{Journal.count}/#{MantisBugNote.count}"
|
521 | puts "Bug files: #{Attachment.count}/#{MantisBugFile.count}"
|
522 | puts "Bug relations: #{IssueRelation.count}/#{MantisBugRelationship.count}"
|
523 | puts "Bug monitors: #{Watcher.count}/#{MantisBugMonitor.count}"
|
524 | puts "News: #{News.count}/#{MantisNews.count}"
|
525 | puts "Custom fields: #{IssueCustomField.count}/#{MantisCustomField.count}"
|
526 | end
|
527 | |
528 | def self.encoding(charset) |
529 | @ic = Iconv.new('UTF-8', charset) |
530 | rescue Iconv::InvalidEncoding |
531 | return false |
532 | end
|
533 | |
534 | def self.establish_connection(params) |
535 | constants.each do |const|
|
536 | klass = const_get(const) |
537 | next unless klass.respond_to? 'establish_connection' |
538 | klass.establish_connection params |
539 | end
|
540 | end
|
541 | |
542 | def self.encode(text) |
543 | @ic.iconv text
|
544 | rescue
|
545 | text |
546 | end
|
547 | end
|
548 | |
549 | puts |
550 | if Redmine::DefaultData::Loader.no_data? |
551 | puts "Redmine configuration need to be loaded before importing data."
|
552 | puts "Please, run this first:"
|
553 | puts |
554 | puts " rake redmine:load_default_data RAILS_ENV=\"#{ENV['RAILS_ENV']}\""
|
555 | exit |
556 | end
|
557 | |
558 | puts "WARNING: Your Redmine data will be deleted during this process."
|
559 | print "Are you sure you want to continue ? [y/N] "
|
560 | break unless STDIN.gets.match(/^y$/i) |
561 | |
562 | # Default Mantis database settings
|
563 | db_params = {:adapter => 'mysql', |
564 | :database => 'bugtracker', |
565 | :host => 'localhost', |
566 | :username => 'root', |
567 | :password => '' } |
568 | |
569 | puts |
570 | puts "Please enter settings for your Mantis database"
|
571 | [:adapter, :host, :database, :username, :password].each do |param| |
572 | print "#{param} [#{db_params[param]}]: "
|
573 | value = STDIN.gets.chomp!
|
574 | db_params[param] = value unless value.blank?
|
575 | end
|
576 | |
577 | while true |
578 | print "encoding [UTF-8]: "
|
579 | encoding = STDIN.gets.chomp!
|
580 | encoding = 'UTF-8' if encoding.blank? |
581 | break if MantisMigrate.encoding encoding |
582 | puts "Invalid encoding!"
|
583 | end
|
584 | puts |
585 | |
586 | # Make sure bugs can refer bugs in other projects
|
587 | Setting.cross_project_issue_relations = 1 if Setting.respond_to? 'cross_project_issue_relations' |
588 | |
589 | # Turn off email notifications
|
590 | Setting.notified_events = []
|
591 | |
592 | MantisMigrate.establish_connection db_params
|
593 | MantisMigrate.migrate
|
594 | end
|
595 | end
|