better_jira 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/better_jira/core_ext.rb +15 -0
- data/lib/better_jira/exceptions.rb +22 -0
- data/lib/better_jira/jira.rb +240 -0
- data/lib/better_jira/jira_issue.rb +99 -0
- data/lib/better_jira/jira_version.rb +19 -0
- data/lib/better_jira/net_http_ssl_hack.rb +12 -0
- data/lib/better_jira/utils.rb +63 -0
- data/lib/better_jira/version.rb +23 -0
- data/lib/better_jira.rb +5 -0
- metadata +118 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
class Hash
|
2
|
+
def symbolize_keys!
|
3
|
+
replace(inject({}) { |h,(k,v)| h[k.to_sym] = v; h })
|
4
|
+
end
|
5
|
+
|
6
|
+
def require_keys!(*keys)
|
7
|
+
missing = []
|
8
|
+
|
9
|
+
keys.each do |key|
|
10
|
+
missing << key unless self.has_key? key
|
11
|
+
end
|
12
|
+
|
13
|
+
raise "Required keys: #{missing.join(", ")}" unless missing.empty?
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module BetterJira
|
2
|
+
module Exceptions
|
3
|
+
def self.wrap_soap
|
4
|
+
begin
|
5
|
+
yield
|
6
|
+
rescue SOAP::FaultError
|
7
|
+
case $!.faultstring.data
|
8
|
+
when "com.atlassian.jira.rpc.exception.RemotePermissionException: This issue does not exist or you don't have permission to view it."
|
9
|
+
raise NoSuchIssueException, "This issue does not exist or you don't have permission to view it."
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end # def wrap_soap
|
13
|
+
|
14
|
+
class JiraException < RuntimeError
|
15
|
+
end
|
16
|
+
|
17
|
+
class NoSuchIssueException < JiraException
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end # module Exceptions
|
22
|
+
end # module BetterJira
|
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'soap/wsdlDriver'
|
2
|
+
require 'better_jira/utils'
|
3
|
+
|
4
|
+
module BetterJira
|
5
|
+
class Jira
|
6
|
+
# Construct the object
|
7
|
+
#
|
8
|
+
# @param [String] jira_url the base url to your jira instance, ie: https://jira.mycompany.com
|
9
|
+
# @param [String] trust_ca the path to a PEM file that contains a CA certificate to trust
|
10
|
+
def initialize(jira_url, trust_ca = nil)
|
11
|
+
@jira_url = jira_url
|
12
|
+
@soap = SOAP::WSDLDriverFactory.new(@jira_url + "/rpc/soap/jirasoapservice-v2?wsdl").create_rpc_driver
|
13
|
+
@client = HTTPClient.new
|
14
|
+
@client.ssl_config.set_trust_ca(trust_ca) unless trust_ca.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
# Login to the jira instance
|
18
|
+
#
|
19
|
+
# @param [String] username your username
|
20
|
+
# @param [String] password your password
|
21
|
+
#
|
22
|
+
# @raise if login fails
|
23
|
+
def login(username, password)
|
24
|
+
@token = @soap.login(username, password)
|
25
|
+
|
26
|
+
destination = '/success'
|
27
|
+
res = @client.post("#{@jira_url}/secure/Dashboard.jspa", {
|
28
|
+
'os_username' => username,
|
29
|
+
'os_password' => password,
|
30
|
+
'os_destination' => destination
|
31
|
+
})
|
32
|
+
raise "Login Fail!" if res.status != 302 || (res.header['Location'] && res.header['Location'].first[-destination.length, destination.length] != destination)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Retrieves all the fields available for edit on the particular issue key
|
36
|
+
#
|
37
|
+
# @param [String] key the issue key to check (ie: TEST-100)
|
38
|
+
# @return [Hash] a hash of jira field id to name
|
39
|
+
def fields_for_edit(key)
|
40
|
+
BetterJira::simple_soap_mapping(@soap.getFieldsForEdit(@token, key))
|
41
|
+
end
|
42
|
+
|
43
|
+
# Iterates over all the issues in a filter, passing each JiraIssue into the block
|
44
|
+
#
|
45
|
+
# @param [Integer] filter_id the filter to load
|
46
|
+
# @param [Hash] options the options to use when iterating
|
47
|
+
# @option options [Integer] :batch_size (50) the number of issues to retrieve at a time
|
48
|
+
# @option options [Integer] :exclude_if_in_filter (nil) a filter to use as an exclude list if present
|
49
|
+
# @yield a block for iterating over the list
|
50
|
+
# @yieldparam [JiraIssue] issue
|
51
|
+
def each_issue_from_filter(filter_id, options ={}, &block)
|
52
|
+
options[:batch_size] ||= 50
|
53
|
+
|
54
|
+
exclude_issues = []
|
55
|
+
|
56
|
+
if (options[:exclude_if_in_filter]) then
|
57
|
+
each_issue_from_filter(options[:exclude_if_in_filter]) { |issue|
|
58
|
+
exclude_issues << issue[:key]
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
offset = 0
|
63
|
+
while( (issues = @soap.getIssuesFromFilterWithLimit(@token, filter_id, offset, options[:batch_size])) != nil)
|
64
|
+
break if offset >= @soap.getIssueCountForFilter(@token, filter_id)
|
65
|
+
offset += issues.length
|
66
|
+
|
67
|
+
issues.each {|issue|
|
68
|
+
issue = JiraIssue.new(issue, self)
|
69
|
+
block.call(issue) unless exclude_issues.include?(issue[:key])
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Retrieves all of the versions for a particular project from the Jira server
|
75
|
+
#
|
76
|
+
# @param [String] project_key the project key to look up, ie: "MYPROJ"
|
77
|
+
def versions_for_project(project_key)
|
78
|
+
@soap.getVersions(@token, project_key).map{|x| BetterJira::JiraVersion.convert_from_soap(x)}
|
79
|
+
end
|
80
|
+
|
81
|
+
def update_issue(key, remote_field_changes)
|
82
|
+
@soap.updateIssue(@token, key, remote_field_changes)
|
83
|
+
end
|
84
|
+
|
85
|
+
def convert_custom_field_value_to_happy_jira_time(value)
|
86
|
+
if (value != nil) then
|
87
|
+
if (Array === value) then
|
88
|
+
value = value.map { |x|
|
89
|
+
q = nil
|
90
|
+
q = x if String === x
|
91
|
+
q = x['id'] if SOAP::Mapping::Object === x
|
92
|
+
q
|
93
|
+
}
|
94
|
+
elsif (SOAP::Mapping::Object === value) then
|
95
|
+
value = [value['id']]
|
96
|
+
elsif (String === value) then
|
97
|
+
value = [value]
|
98
|
+
elsif (DateTime === value) then
|
99
|
+
value = [value.strftime('%d/%b/%y')]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def progress_workflow(key, workflow_action_id, custom_field_values, opts = {})
|
105
|
+
puts "Shit passed in" if JIRA_DEBUG
|
106
|
+
puts "==============" if JIRA_DEBUG
|
107
|
+
p custom_field_values if JIRA_DEBUG
|
108
|
+
puts "" if JIRA_DEBUG
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
cfvs = []
|
113
|
+
|
114
|
+
unless @client.nil?
|
115
|
+
res = @client.get("#{@jira_url}/si/jira.issueviews:issue-xml/#{key}/#{key}.xml")
|
116
|
+
puts res.content if JIRA_DEBUG
|
117
|
+
match = res.content.match(/<timeestimate seconds="(.*?)">(.*?)<\/timeestimate>/)
|
118
|
+
time_estimate = "#{match[1].to_i/60}" unless match.nil?
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
issue = get_issue(key)
|
123
|
+
fields = fields_for_action(key, workflow_action_id)
|
124
|
+
|
125
|
+
puts "Issue" if JIRA_DEBUG
|
126
|
+
p issue if JIRA_DEBUG
|
127
|
+
puts "" if JIRA_DEBUG
|
128
|
+
|
129
|
+
moronic_map = {
|
130
|
+
'issuetype' => 'type',
|
131
|
+
'versions' => 'affectsVersions'
|
132
|
+
}
|
133
|
+
puts "Fields" if JIRA_DEBUG
|
134
|
+
puts "======" if JIRA_DEBUG
|
135
|
+
fields.each {|f|
|
136
|
+
|
137
|
+
p f if JIRA_DEBUG
|
138
|
+
real_field_name = moronic_map[f['id']] ? moronic_map[f['id']] : f['id']
|
139
|
+
|
140
|
+
if (real_field_name != '' && custom_field_values[real_field_name.to_sym] != nil)
|
141
|
+
value = custom_field_values[real_field_name.to_sym]
|
142
|
+
elsif (real_field_name != '' && custom_field_values[real_field_name] != nil)
|
143
|
+
value = custom_field_values[real_field_name]
|
144
|
+
elsif (real_field_name == 'timetracking') then
|
145
|
+
value = time_estimate
|
146
|
+
elsif (real_field_name =~ /customfield_/) then
|
147
|
+
q = issue.customFieldValues.find { |c| c.customfieldId == real_field_name }
|
148
|
+
value = q.values unless q.nil?
|
149
|
+
else
|
150
|
+
value = nil
|
151
|
+
value = issue.send('[]', real_field_name) if not real_field_name.empty?
|
152
|
+
end
|
153
|
+
|
154
|
+
value = convert_custom_field_value_to_happy_jira_time(value)
|
155
|
+
|
156
|
+
puts "" if JIRA_DEBUG
|
157
|
+
p value if JIRA_DEBUG
|
158
|
+
puts "" if JIRA_DEBUG
|
159
|
+
|
160
|
+
cfvs << {:id => f['id'], :values => value}
|
161
|
+
}
|
162
|
+
|
163
|
+
puts "Output!" if JIRA_DEBUG
|
164
|
+
puts "=======" if JIRA_DEBUG
|
165
|
+
p cfvs if JIRA_DEBUG
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
@soap.progressWorkflowAction(@token, key, workflow_action_id, cfvs)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Adds a comment to the issue specified by key
|
173
|
+
#
|
174
|
+
# @param [String] key the issue to comment on
|
175
|
+
# @param [String] comment the comment to use
|
176
|
+
# @param [Hash] options
|
177
|
+
# @option options [String] :body the comment body to use, shouldn't be used
|
178
|
+
# @option options [String] :groupLevel ?
|
179
|
+
# @option options [String] :roleLevel ?
|
180
|
+
def add_comment(key, comment, options={})
|
181
|
+
options[:body] = comment if options[:body].nil?
|
182
|
+
|
183
|
+
@soap.addComment(@token, key, options)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Gets the available actions for an issue from the server
|
187
|
+
#
|
188
|
+
# @param [String] key the issue to look up
|
189
|
+
#
|
190
|
+
# @return [Hash] keys are the jira id, values are the name of the action
|
191
|
+
def available_actions(key)
|
192
|
+
BetterJira::Exceptions.wrap_soap {
|
193
|
+
BetterJira::simple_soap_mapping(@soap.getAvailableActions(@token, key))
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
# Gets the specified issue from the jira server
|
198
|
+
#
|
199
|
+
# @param [String] key the issue key
|
200
|
+
# @return [JiraIssue] the retrieved jira issue
|
201
|
+
def get_issue(key)
|
202
|
+
JiraIssue.new(@soap.getIssue(@token, key), self)
|
203
|
+
end
|
204
|
+
|
205
|
+
# Gets the specified issue from the jira server
|
206
|
+
# @see #get_issue
|
207
|
+
def [](key)
|
208
|
+
get_issue(key)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Gets the available fields for edit during an action
|
212
|
+
#
|
213
|
+
# @param [String] key the issue to look up
|
214
|
+
# @param [Integer] action_id the action to look up
|
215
|
+
#
|
216
|
+
# @return [Hash] keys are the jira id, values are the name of the field
|
217
|
+
def fields_for_action(key, action_id)
|
218
|
+
BetterJira::Exceptions.wrap_soap {
|
219
|
+
BetterJira::simple_soap_mapping(@soap.getFieldsForAction(@token, key, action_id))
|
220
|
+
}
|
221
|
+
end
|
222
|
+
|
223
|
+
def map_version_fields(project, fields, cur_depth = 0, versions = nil)
|
224
|
+
versions = versions_for_project(project)
|
225
|
+
|
226
|
+
if (cur_depth == 0 && Array === fields) then
|
227
|
+
fields.map { |q|
|
228
|
+
map_version_fields(project, q, cur_depth + 1, versions)
|
229
|
+
}.flatten
|
230
|
+
elsif (Fixnum === fields || Integer === fields)
|
231
|
+
[fields.to_s]
|
232
|
+
elsif (String === fields)
|
233
|
+
versions = versions.select { |version| version.name == fields }
|
234
|
+
versions = versions.map { |version| version['id'] }
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end # class Jira
|
238
|
+
|
239
|
+
|
240
|
+
end # module BetterJira
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module BetterJira
|
2
|
+
class JiraIssue
|
3
|
+
attr_reader :custom_fields
|
4
|
+
|
5
|
+
FIELDS = [:summary, :description]
|
6
|
+
|
7
|
+
def initialize(soap_jira_issue, jira)
|
8
|
+
@soap_jira_issue = soap_jira_issue
|
9
|
+
@jira = jira
|
10
|
+
@changes = []
|
11
|
+
@custom_fields = {}
|
12
|
+
@soap_jira_issue.customFieldValues.each { |cf|
|
13
|
+
@custom_fields[cf.customfieldId] = cf.values
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def update_fields(fields)
|
18
|
+
fields[:fixVersions] = fields[:fix_versions] if fields.has_key? :fix_versions
|
19
|
+
fields[:versions] = fields[:affects_versions] if fields.has_key? :affects_versions
|
20
|
+
|
21
|
+
fields.each {|k,v|
|
22
|
+
case k
|
23
|
+
when :fixVersions then
|
24
|
+
fields[k] = @jira.map_version_fields(self[:project], v)
|
25
|
+
when :versions
|
26
|
+
fields[k] = @jira.map_version_fields(self[:project], v)
|
27
|
+
end
|
28
|
+
}
|
29
|
+
|
30
|
+
|
31
|
+
fields = fields.map {|k,v|
|
32
|
+
{:id => k, :values => BetterJira::convert_custom_field_value_to_happy_jira_time(v)}
|
33
|
+
}
|
34
|
+
@jira.update_issue(self[:key], fields)
|
35
|
+
initialize(@jira.get_issue(self[:key]), @jira)
|
36
|
+
end
|
37
|
+
|
38
|
+
def field_value(key)
|
39
|
+
r = self[key]
|
40
|
+
r = r.first unless (r.nil?)
|
41
|
+
return r
|
42
|
+
end
|
43
|
+
|
44
|
+
def field_values(key)
|
45
|
+
self[key]
|
46
|
+
end
|
47
|
+
|
48
|
+
def [](key)
|
49
|
+
if (key.to_s =~ /customfield_/) then
|
50
|
+
BetterJira::custom_field_values(@soap_jira_issue, key.to_s)
|
51
|
+
elsif (Symbol === key) then
|
52
|
+
begin
|
53
|
+
@soap_jira_issue.send "[]", key.to_s
|
54
|
+
rescue NoMethodError => e
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
else
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def field_as_date_time(key)
|
63
|
+
BetterJira::custom_field_value_as_date_time(@soap_jira_issue, key.to_s)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns a list of available actions for this issue
|
67
|
+
def available_actions
|
68
|
+
ret = {}
|
69
|
+
@jira.available_actions(self[:key]).each{|q| ret[q['id']] = q['name']}
|
70
|
+
ret
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns a list of fields for a particular action_id
|
74
|
+
def fields_for_action_id(action_id)
|
75
|
+
ret = {}
|
76
|
+
@jira.fields_for_action(self[:key], action_id).each {|q| ret[q['id']] = q['name']}
|
77
|
+
ret
|
78
|
+
end
|
79
|
+
|
80
|
+
# Adds a comment to the issue
|
81
|
+
def add_comment(comment, options={})
|
82
|
+
@jira.add_comment(self[:key], comment, options)
|
83
|
+
end
|
84
|
+
|
85
|
+
def fields_for_action_name(action_name)
|
86
|
+
action = available_actions.find {|k, v| v == action_name}
|
87
|
+
fields_for_action_id(action[0])
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
def fields_for_edit
|
92
|
+
BetterJira::array_of_remote_fields_to_map(@jira.get_fields_for_edit(self[:key]))
|
93
|
+
end
|
94
|
+
|
95
|
+
def progress_workflow(workflow_action_id, custom_field_values, opts = {})
|
96
|
+
@jira.progress_workflow(self[:key], workflow_action_id, custom_field_values, opts)
|
97
|
+
end
|
98
|
+
end # class JiraIssue
|
99
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BetterJira
|
2
|
+
class JiraVersion
|
3
|
+
attr_accessor :archived, :id, :name, :release_date, :released, :sequence
|
4
|
+
|
5
|
+
def self.convert_from_soap(s)
|
6
|
+
if (s.is_a? SOAP::Mapping::Object) then
|
7
|
+
ret = JiraVersion.new
|
8
|
+
ret.archived = s.archived
|
9
|
+
ret.id = s.id
|
10
|
+
ret.name = s.name
|
11
|
+
ret.release_date = s.releaseDate
|
12
|
+
ret.released = s.released
|
13
|
+
ret.sequence = s.sequence
|
14
|
+
ret
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end # module BetterJira
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Hack for SSL issues
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
class Net::HTTP
|
5
|
+
alias_method :old_initialize, :initialize
|
6
|
+
def initialize(*args)
|
7
|
+
old_initialize(*args)
|
8
|
+
@ssl_context = OpenSSL::SSL::SSLContext.new
|
9
|
+
@ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
10
|
+
end
|
11
|
+
end
|
12
|
+
# /Hack for SSL issues
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module BetterJira
|
2
|
+
def self.custom_field_values(issue, field)
|
3
|
+
issue.customFieldValues.each { |cfv|
|
4
|
+
if (cfv.customfieldId == field) then
|
5
|
+
return cfv.values
|
6
|
+
end
|
7
|
+
}
|
8
|
+
|
9
|
+
return nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.custom_field_value(issue, field, &block)
|
13
|
+
if (block == nil) then
|
14
|
+
block = Proc.new {|x| x}
|
15
|
+
end
|
16
|
+
|
17
|
+
values = custom_field_values(issue, field)
|
18
|
+
|
19
|
+
return block.call(values.first) if (values != nil)
|
20
|
+
|
21
|
+
return nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.custom_field_value_as_date_time(issue, field)
|
25
|
+
custom_field_value(issue, field) { |x| DateTime.parse(x, true) }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Converts an array of RemoteFields into a map of id => name
|
29
|
+
#
|
30
|
+
# @return [Hash] the converted map
|
31
|
+
def self.array_of_remote_fields_to_map(remote_fields)
|
32
|
+
ret = {}
|
33
|
+
remote_fields.each{|q| ret[q['id']] = q['name']}
|
34
|
+
ret
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.simple_soap_mapping(a)
|
38
|
+
ret = {}
|
39
|
+
a.each{|q| ret[q['id']] = q['name']}
|
40
|
+
ret
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.convert_custom_field_value_to_happy_jira_time(value)
|
44
|
+
if (value != nil) then
|
45
|
+
if (Array === value) then
|
46
|
+
value = value.map { |x|
|
47
|
+
q = nil
|
48
|
+
q = x if String === x
|
49
|
+
q = x['id'] if SOAP::Mapping::Object === x
|
50
|
+
q
|
51
|
+
}
|
52
|
+
elsif (SOAP::Mapping::Object === value) then
|
53
|
+
value = [value['id']]
|
54
|
+
elsif (String === value) then
|
55
|
+
value = [value]
|
56
|
+
elsif (DateTime === value) then
|
57
|
+
value = [value.strftime('%d/%b/%y')]
|
58
|
+
else
|
59
|
+
value = [value.to_s]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright (c) 2010 Eric Anderson
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module BetterJira
|
22
|
+
VERSION = "0.0.1"
|
23
|
+
end
|
data/lib/better_jira.rb
ADDED
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: better_jira
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Eric Anderson
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-09-23 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: httpclient
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 2
|
30
|
+
- 1
|
31
|
+
- 5
|
32
|
+
- 2
|
33
|
+
version: 2.1.5.2
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: soap4r
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - "="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
segments:
|
45
|
+
- 1
|
46
|
+
- 5
|
47
|
+
- 8
|
48
|
+
version: 1.5.8
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: rake
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
62
|
+
type: :development
|
63
|
+
version_requirements: *id003
|
64
|
+
description:
|
65
|
+
email:
|
66
|
+
- eric@ericanderson.us
|
67
|
+
executables: []
|
68
|
+
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files: []
|
72
|
+
|
73
|
+
files:
|
74
|
+
- lib/better_jira/core_ext.rb
|
75
|
+
- lib/better_jira/exceptions.rb
|
76
|
+
- lib/better_jira/jira.rb
|
77
|
+
- lib/better_jira/jira_issue.rb
|
78
|
+
- lib/better_jira/jira_version.rb
|
79
|
+
- lib/better_jira/net_http_ssl_hack.rb
|
80
|
+
- lib/better_jira/utils.rb
|
81
|
+
- lib/better_jira/version.rb
|
82
|
+
- lib/better_jira.rb
|
83
|
+
has_rdoc: true
|
84
|
+
homepage: http://github.com/ericanderson/better_jira
|
85
|
+
licenses: []
|
86
|
+
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
version: "0"
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
segments:
|
106
|
+
- 1
|
107
|
+
- 3
|
108
|
+
- 6
|
109
|
+
version: 1.3.6
|
110
|
+
requirements: []
|
111
|
+
|
112
|
+
rubyforge_project:
|
113
|
+
rubygems_version: 1.3.7
|
114
|
+
signing_key:
|
115
|
+
specification_version: 3
|
116
|
+
summary: Yet Another Jira Gem
|
117
|
+
test_files: []
|
118
|
+
|