1
|
#!/usr/bin/env ruby
|
2
|
|
3
|
RAILS_ENV = 'test'
|
4
|
REDMINE_ROOT = '/var/www/html/redmine/'
|
5
|
# This does _NOT_ work. I looked back 3 revisions and found the correct line
|
6
|
#require File.dirname(__FILE__) + '/../config/boot'
|
7
|
require REDMINE_ROOT + 'config/environment'
|
8
|
|
9
|
require 'getoptlong'
|
10
|
|
11
|
class BugMail
|
12
|
|
13
|
attr_accessor :issue, :desc, :subject, :category, :project, :status,
|
14
|
:tracker, :priority, :author, :email, :allow_override,
|
15
|
:use_email_header, :input, :debug
|
16
|
|
17
|
def initialize
|
18
|
|
19
|
@issue = nil
|
20
|
@desc = nil
|
21
|
@subject = nil
|
22
|
@category = nil
|
23
|
@project = nil
|
24
|
@status = nil
|
25
|
@tracker = 'Bug'
|
26
|
@priority = nil
|
27
|
@author = nil
|
28
|
@email = nil
|
29
|
@allow_override = false
|
30
|
@use_email_header = false
|
31
|
@debug = false
|
32
|
end
|
33
|
|
34
|
def process(msg)
|
35
|
@issue = line_match(msg, "Issue", @issue)
|
36
|
@subject = line_match(msg, "Subject", @subject)
|
37
|
# we can generalize via mail-aliases setup to be <project>@<fqdn>
|
38
|
@project = match(msg, /^To:.*?(\w+)@.*$/, @project) if(@use_email_header)
|
39
|
@project = line_match(msg, "Project", @project)
|
40
|
@status = line_match(msg, "Status", @status)
|
41
|
@tracker = line_match(msg, "Tracker", @racker)
|
42
|
@priority = line_match(msg, "Priority", @priority)
|
43
|
@category = line_match(msg, "Category", @category)
|
44
|
@email = match(msg, /^From:.*?(\w+@[A-Za-z0-9.-]+).*?$/, @email) if(@use_email_header)
|
45
|
@author = line_match(msg, "Author", @author)
|
46
|
|
47
|
@desc = block_match(msg, "Description", @desc)
|
48
|
|
49
|
puts "Issue: [#{@issue}]" if @debug
|
50
|
puts "Project: [#{@project}]" if @debug
|
51
|
puts "Subject: [#{@subject}]" if @debug
|
52
|
puts "Tracker: [#{@tracker}]" if @debug
|
53
|
puts "Priority: [#{@priority}]" if @debug
|
54
|
puts "Category: [#{@category}]" if @debug
|
55
|
puts "Status: [#{@status}]" if @debug
|
56
|
puts "Author/email: [#{@author}/#{@email}]" if @debug
|
57
|
puts "Desc: [#{@desc}]" if @debug
|
58
|
|
59
|
ic = Iconv.new('UTF-8', 'UTF-8')
|
60
|
|
61
|
p = Project.find_by_identifier(@project)
|
62
|
if(! p)
|
63
|
puts 'Unable to find project [#{@project}]'
|
64
|
return false
|
65
|
end
|
66
|
|
67
|
priorities = Enumeration.get_values('IPRI')
|
68
|
@DEFAULT_PRIORITY = priorities[0]
|
69
|
@DEFAULT_TRACKER = p.trackers.find_by_position(1) || Tracker.find_by_position(1)
|
70
|
@PRIORITY_MAPPING = {}
|
71
|
priorities.each { |prio| @PRIORITY_MAPPING[prio.name] = prio }
|
72
|
|
73
|
puts "Searching for user [#{author}/#{email}]" if debug
|
74
|
|
75
|
u = User.find_by_login(@author)
|
76
|
if(! u && @use_email_header)
|
77
|
puts "Searching for user via email: [#{@email}]" if @debug
|
78
|
u = User.find_by_mail(@email)
|
79
|
end
|
80
|
|
81
|
if(!u)
|
82
|
puts "Unable to find user"
|
83
|
return false
|
84
|
else
|
85
|
puts "Found user [#{u.login}/#{u.mail}]"
|
86
|
end
|
87
|
|
88
|
puts "Searching for issue [#{@issue}]" if @debug
|
89
|
i = Issue.find_by_id(@issue)
|
90
|
|
91
|
if(i == nil)
|
92
|
prio = @PRIORITY_MAPPING[@priority] || @DEFAULT_PRIORITY
|
93
|
st = IssueStatus.find_by_name(@status) || IssueStatus.default
|
94
|
t = p.trackers.find_by_name(@tracker) || @DEFAULT_TRACKER
|
95
|
c = p.issue_categories.find_by_name(@category)
|
96
|
i = Issue.create( :priority => prio,
|
97
|
:status => st,
|
98
|
:tracker => t,
|
99
|
:project => p,
|
100
|
:category => c,
|
101
|
:start_date => Date.today,
|
102
|
:author => u,
|
103
|
:description => ic.iconv(@desc),
|
104
|
:subject => ic.iconv(@subject) )
|
105
|
puts "Created issue [#{i.id}] [#{i.to_yaml}]" if @debug
|
106
|
|
107
|
if(!i.save)
|
108
|
puts "Failed to save new issue"
|
109
|
exit 1
|
110
|
end
|
111
|
else
|
112
|
puts "Issue exists, adding comment..."
|
113
|
n = Journal.new(:notes => ic.iconv(@desc),
|
114
|
:journalized => i,
|
115
|
:user => u);
|
116
|
if(!n.save)
|
117
|
puts "Failed to add comment"
|
118
|
return false
|
119
|
end
|
120
|
end
|
121
|
|
122
|
return true
|
123
|
end
|
124
|
|
125
|
private
|
126
|
def match(msg, regex, default)
|
127
|
if((@allow_override || default == nil) && (msg =~ regex))
|
128
|
return $1
|
129
|
end
|
130
|
return default
|
131
|
end
|
132
|
|
133
|
|
134
|
def line_match(msg, label, default)
|
135
|
return match(msg, /^#{label}:[ \t]*(.*)$/, default)
|
136
|
end
|
137
|
|
138
|
def block_match(msg, label, default)
|
139
|
return match(msg, /^#{label}:[ \t]*(.*)$/m, default)
|
140
|
end
|
141
|
|
142
|
end
|
143
|
|
144
|
opts = GetoptLong.new(
|
145
|
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
146
|
[ '--debug', GetoptLong::NO_ARGUMENT ],
|
147
|
[ '--issue', '-i', GetoptLong::REQUIRED_ARGUMENT ],
|
148
|
[ '--desc', '-d', GetoptLong::REQUIRED_ARGUMENT ],
|
149
|
[ '--subject', '-s', GetoptLong::REQUIRED_ARGUMENT ],
|
150
|
[ '--category', '-c', GetoptLong::REQUIRED_ARGUMENT ],
|
151
|
[ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ],
|
152
|
[ '--tracker', '-t', GetoptLong::REQUIRED_ARGUMENT ],
|
153
|
[ '--status', GetoptLong::REQUIRED_ARGUMENT ],
|
154
|
[ '--priority', GetoptLong::REQUIRED_ARGUMENT ],
|
155
|
[ '--author', '-a', GetoptLong::REQUIRED_ARGUMENT ],
|
156
|
[ '--file', '-f', GetoptLong::REQUIRED_ARGUMENT ],
|
157
|
[ '--allow-override', GetoptLong::NO_ARGUMENT ],
|
158
|
[ '--use-email-header', GetoptLong::NO_ARGUMENT ]
|
159
|
)
|
160
|
|
161
|
def usage
|
162
|
puts "Usage: [--help] [--debug] [--allow-override] [--use-email-header] [--file <filename> ] [--<param> <value> ...]"
|
163
|
puts " --help show this help"
|
164
|
puts " --debug show extra debug information"
|
165
|
puts " --allow-override allow message contents to override cmd line args"
|
166
|
puts " --use-email-header search in email header for user, subject and project"
|
167
|
puts " --file get input from a file instead of STDIN"
|
168
|
puts " --<param> set a parameter's value. Parameter is one of:"
|
169
|
puts " issue, project, subject, desc, status, tracker, priority"
|
170
|
puts " category, author"
|
171
|
exit
|
172
|
end
|
173
|
|
174
|
input = $stdin
|
175
|
mailer = BugMail.new
|
176
|
|
177
|
opts.each do |opt, arg|
|
178
|
case opt
|
179
|
when '--help'
|
180
|
usage
|
181
|
when '--issue'
|
182
|
mailer.issue = arg.to_i
|
183
|
when '--project'
|
184
|
mailer.project = arg
|
185
|
when '--subject'
|
186
|
mailer.subject = arg
|
187
|
when '--desc'
|
188
|
mailer.desc = arg
|
189
|
when '--status'
|
190
|
mailer.status = arg
|
191
|
when '--tracker'
|
192
|
mailer.tracker = arg
|
193
|
when '--priority'
|
194
|
mailer.priority = arg
|
195
|
when '--category'
|
196
|
mailer.category = arg
|
197
|
when '--author'
|
198
|
mailer.author = arg
|
199
|
when '--file'
|
200
|
input = FILE.open(arg, "r")
|
201
|
when '--debug'
|
202
|
mailer.debug = true
|
203
|
when '--allow-override'
|
204
|
mailer.allow_override = true
|
205
|
when '--use-email-header'
|
206
|
mailer.use_email_header = true
|
207
|
end
|
208
|
end
|
209
|
|
210
|
msg = input.read
|
211
|
|
212
|
mailer.process(msg)
|
213
|
|