forked from mfkp/github_issue_importer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
issuetransfer.rb
187 lines (165 loc) · 5.97 KB
/
issuetransfer.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env ruby
require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'httparty'
require 'uri'
require 'net/http'
require 'json'
class GitHub
include HTTParty
def initialize
puts 'Tracker URL to be imported (example: http://gforge.unl.edu/gf/project/unl_mediayak/tracker/ ):'
@url = STDIN.gets.chomp
puts 'Import issues to which github project?'
@project = STDIN.gets.chomp
puts 'Which user owns this project?'
@pushToUser = STDIN.gets.chomp
puts 'If using github:enterprise, what is your server (no trailing slash; press enter if not)?'
githubUri = STDIN.gets.chomp
if (githubUri == '')
githubUri = 'http://github.com'
@gistUri = 'http://gist.github.com'
else
@gistUri = githubUri + '/gist'
end
self.class.base_uri(githubUri + '/api/v2/json');
File.open('credentials.config', 'r') do |config|
@login = config.gets.chomp
@token = config.gets.chomp
@gforgeBaseUrl = config.gets.chomp
end
getGforgeIssues(@url)
puts 'Done.'
end
def getGforgeIssues(url)
page = Nokogiri::HTML(open(url))
#First, get the category links from the main page
rows = page.search('.main .tabular tr')
rows = rows[7..rows.size-2]
rows.each do |row|
cells = row.search('td')
items = cells[cells.size-2].text.to_i
link = row.search('td a').first
tag = link.text
tag = tag[2..tag.size-1].gsub(/e*s$/, '')
#rename tags for standardization
if (tag == 'Features/Bug')
tag = 'Bug'
end
if (tag == 'Support Issu' || tag == 'User input support')
tag = 'Support'
end
if (items > 0)
puts '================'
puts tag + ' items: ' + items.to_s
puts '================'
#Second, visit each page and pull all the issue links
start = 0
while (items > 0)
fullUrl = @gforgeBaseUrl + link[:href] + '&start=' + start.to_s
page2 = Nokogiri::HTML(open(fullUrl))
rows = page2.search('.main .tabular tr')
rows = rows[1..rows.size-2]
#Finally, parse through each tracker item and add it to github
rows.each do |row|
itemLink = row.search('td a').first
fullItemLink = @gforgeBaseUrl + itemLink[:href]
page3 = Nokogiri::HTML(open(fullItemLink))
submittedBy = page3.xpath("//a[href_matches_regex(., '.*/gf/user/.*')]", RegexHelper.new).first.to_s.gsub(/<\/?[^>]+>/, '')
dataTable = page3.css('table')[1].to_s
status = dataTable.match(/<strong>Status<\/strong>:<br\s*[\/]*>\s*(.*)\s*<\/td>/).to_s.gsub(/<\/?[^>]+>/, '').chomp.strip.gsub(/Status:/, '') || ''
title = dataTable.match(/<strong>Summary<\/strong><br\s*[\/]*>\s*(.*)\s*<\/tr>/).to_s.gsub(/<\/?[^>]+>/, '').gsub(/Summary/, '').chomp.strip || ''
body = page3.at_css('#details_readonly pre').to_s.gsub(/<\/?[^>]+>/, '') || ''
case tag
when 'Patch'
patchUrl = @gforgeBaseUrl + page3.css('table.tabular')[1].css('td a').first[:href]
fileName = page3.css('table.tabular')[1].css('td a').first.to_s.gsub(/<\/?[^>]+>/, '')
content = Net::HTTP.get(URI.parse(patchUrl))
gistUrl = createGist(fileName, content)
if (gistUrl.size > 0)
body += '<br/><br/>Patch: ' + gistUrl
end
when 'Bug', 'Support'
bugUrl = dataTable.match(/<strong>URL<\/strong>:<br\s*[\/]*>\s*(.*)\s*<\/td>/).to_s.gsub(/<\/?[^>]+>/, '').gsub(/URL:/, '').chomp.strip || ''
if (bugUrl.size > 0)
body += '<br/><br/>URL: ' + bugUrl
end
end
body += '<br/><br/>Originally submitted by: ' + submittedBy
puts 'Adding ' + tag + ': ' + title
#create issue
issueNumber = newIssue(title, body)
#add label based on gforge category
if (!addLabel(issueNumber, tag))
puts 'Error: could not add comment for issue ' + issueNumber.to_s
end
#add each comment
page3.css('table.tabular')[0].css('td pre').each do |comment|
c = comment.to_s.gsub(/<\/?[^>]+>/, '')
if (!addComment(issueNumber, c))
puts 'Error: could not add comment for issue ' + issueNumber.to_s
end
end
#check status and close ticket
if (status === 'Closed')
puts 'Closing issue.'
if (!closeIssue(issueNumber))
puts 'Error: could not close issue ' + issueNumber.to_s
end
end
puts '------------------'
end
start += 25
items -= 25
end
end
end
end
def newIssue(title, body)
options = {:body => {:title => title, :body => body, :login => @login, :token => @token}}
response = self.class.post('/issues/open/' + @pushToUser + '/' + @project, options)
issueNumber = response['issue']['number']
sleep 1
return issueNumber
end
def addLabel(issueNumber, label)
options = {:body => {:login => @login, :token => @token}}
response = self.class.post('/issues/label/add/' + @pushToUser + '/' + @project + '/' + URI.escape(label.to_s) + '/' + issueNumber.to_s, options)
success = response.message
sleep 1
return success.to_s === 'OK'
end
def addComment(issueNumber, comment)
options = {:body => {:comment => comment, :login => @login, :token => @token}}
response = self.class.post('/issues/comment/' + @pushToUser + '/' + @project + '/' + issueNumber.to_s, options)
success = response.message
sleep 1
return success.to_s === 'Created'
end
def closeIssue(issueNumber)
options = {:body => {:login => @login, :token => @token}}
response = self.class.post('/issues/close/' + @pushToUser + '/' + @project + '/' + issueNumber.to_s, options)
success = response.message
sleep 1
return success.to_s === 'OK'
end
def createGist(name, content)
response = Net::HTTP.post_form(URI.parse(@gistUri + '/api/v1/json/new'), {
"files[#{name}]" => content,
"description" => '',
"login" => @login,
"token" => @token
})
response = JSON.parse(response.body)
gist = @gistUri + '/' + response['gists'][0]['repo']
sleep 1
return gist
end
end
class RegexHelper
def href_matches_regex node_set, regex_string
! node_set.select { |node| node['href'] =~ /#{regex_string}/ }.empty?
end
end
GitHub.new