| 1 | # jira2trac.rb |
|---|
| 2 | # by Jan Szumiec <jan.szumiec@infiniteloop.eu> |
|---|
| 3 | |
|---|
| 4 | require 'rexml/document' |
|---|
| 5 | require 'date' |
|---|
| 6 | require 'sqlite3' |
|---|
| 7 | |
|---|
| 8 | if ARGV.size < 2 |
|---|
| 9 | puts "Usage: jira2trac.rb <input RSS feed (XML)> <trac sqlite database filename>" |
|---|
| 10 | exit |
|---|
| 11 | end |
|---|
| 12 | |
|---|
| 13 | class String |
|---|
| 14 | def quote |
|---|
| 15 | "'#{gsub(/'/, "''")}'" |
|---|
| 16 | end |
|---|
| 17 | end |
|---|
| 18 | |
|---|
| 19 | class Numeric |
|---|
| 20 | alias quote inspect |
|---|
| 21 | end |
|---|
| 22 | |
|---|
| 23 | class NilClass |
|---|
| 24 | def quote |
|---|
| 25 | "NULL" |
|---|
| 26 | end |
|---|
| 27 | end |
|---|
| 28 | |
|---|
| 29 | class JIRAFeedConverter |
|---|
| 30 | Ticket = Struct.new(:id, :type, :time, :changetime, :component, :severity, :priority, :owner, :reporter, :cc, :version, :milestone, :status, :resolution, :summary, :description, :keywords) |
|---|
| 31 | class Ticket |
|---|
| 32 | def to_sql |
|---|
| 33 | columns = []; values = [] |
|---|
| 34 | each_pair do |k,v| |
|---|
| 35 | columns << k |
|---|
| 36 | values << v.quote |
|---|
| 37 | end |
|---|
| 38 | "(#{columns.join(',')}) VALUES (#{values.join(',')})" |
|---|
| 39 | end |
|---|
| 40 | end |
|---|
| 41 | |
|---|
| 42 | def initialize(input, output) |
|---|
| 43 | @document = REXML::Document.new(File.new(input)) |
|---|
| 44 | @database = SQLite3::Database.new(output) |
|---|
| 45 | end |
|---|
| 46 | |
|---|
| 47 | def process |
|---|
| 48 | @database.transaction do |
|---|
| 49 | @document.elements.each("/rss/channel/item") do |item| |
|---|
| 50 | t = Ticket.new |
|---|
| 51 | t.id, t.summary = parse_jira_title(item.elements["title"].text) |
|---|
| 52 | t.type = item.elements["type"].text |
|---|
| 53 | t.time = DateTime.parse(item.elements["created"].text).strftime("%s").to_i |
|---|
| 54 | t.changetime = DateTime.parse(item.elements["updated"].text).strftime("%s").to_i |
|---|
| 55 | t.component = item.elements["component"].text if item.elements["component"] |
|---|
| 56 | t.severity = t.priority = item.elements["priority"].text |
|---|
| 57 | t.reporter = item.elements["reporter"].text |
|---|
| 58 | t.owner = item.elements["assignee"].text |
|---|
| 59 | t.status = item.elements["status"].text |
|---|
| 60 | t.resolution = item.elements["resolution"].text |
|---|
| 61 | t.description = item.elements["description"].text |
|---|
| 62 | @database.execute("INSERT INTO ticket #{t.to_sql}") |
|---|
| 63 | end |
|---|
| 64 | end |
|---|
| 65 | end |
|---|
| 66 | |
|---|
| 67 | def parse_jira_title(title) |
|---|
| 68 | identifier, title = title.split(/ /, 2) |
|---|
| 69 | _, identifier = identifier[1..-2].split(/-/, 2) |
|---|
| 70 | return identifier.to_i, title |
|---|
| 71 | end |
|---|
| 72 | end |
|---|
| 73 | |
|---|
| 74 | JIRAFeedConverter.new(ARGV[0], ARGV[1]).process |
|---|