jiraSOAP 0.6.1 → 0.7.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.
Files changed (59) hide show
  1. data/.yardopts +10 -0
  2. data/ChangeLog +18 -0
  3. data/{LICENSE → LICENSE.txt} +0 -0
  4. data/README.markdown +4 -6
  5. data/lib/jiraSOAP.rb +0 -2
  6. data/lib/jiraSOAP/JIRAservice.rb +5 -5
  7. data/lib/jiraSOAP/api.rb +77 -696
  8. data/lib/jiraSOAP/api/additions.rb +22 -0
  9. data/lib/jiraSOAP/api/attachments.rb +33 -0
  10. data/lib/jiraSOAP/api/avatars.rb +64 -0
  11. data/lib/jiraSOAP/api/comments.rb +33 -0
  12. data/lib/jiraSOAP/api/filters.rb +20 -0
  13. data/lib/jiraSOAP/api/issue_data_types.rb +51 -0
  14. data/lib/jiraSOAP/api/issues.rb +102 -0
  15. data/lib/jiraSOAP/api/project_roles.rb +49 -0
  16. data/lib/jiraSOAP/api/projects.rb +67 -0
  17. data/lib/jiraSOAP/api/schemes.rb +17 -0
  18. data/lib/jiraSOAP/api/server_info.rb +18 -0
  19. data/lib/jiraSOAP/api/users.rb +35 -0
  20. data/lib/jiraSOAP/api/versions.rb +50 -0
  21. data/lib/jiraSOAP/entities.rb +5 -1
  22. data/lib/jiraSOAP/entities/attachment_metadata.rb +9 -22
  23. data/lib/jiraSOAP/entities/avatar.rb +10 -23
  24. data/lib/jiraSOAP/entities/comment.rb +12 -31
  25. data/lib/jiraSOAP/entities/component.rb +1 -1
  26. data/lib/jiraSOAP/entities/custom_field_value.rb +5 -11
  27. data/lib/jiraSOAP/entities/described_entity.rb +4 -4
  28. data/lib/jiraSOAP/entities/dynamic_entity.rb +5 -5
  29. data/lib/jiraSOAP/entities/entity.rb +28 -13
  30. data/lib/jiraSOAP/entities/field.rb +1 -1
  31. data/lib/jiraSOAP/entities/filter.rb +5 -14
  32. data/lib/jiraSOAP/entities/issue.rb +29 -88
  33. data/lib/jiraSOAP/entities/issue_property.rb +4 -4
  34. data/lib/jiraSOAP/entities/issue_security_scheme.rb +1 -1
  35. data/lib/jiraSOAP/entities/issue_type.rb +4 -5
  36. data/lib/jiraSOAP/entities/named_entity.rb +4 -4
  37. data/lib/jiraSOAP/entities/notification_scheme.rb +1 -1
  38. data/lib/jiraSOAP/entities/permission.rb +7 -10
  39. data/lib/jiraSOAP/entities/permission_mapping.rb +5 -10
  40. data/lib/jiraSOAP/entities/permission_scheme.rb +3 -4
  41. data/lib/jiraSOAP/entities/priority.rb +4 -3
  42. data/lib/jiraSOAP/entities/project.rb +9 -30
  43. data/lib/jiraSOAP/entities/project_role.rb +1 -1
  44. data/lib/jiraSOAP/entities/resolution.rb +1 -1
  45. data/lib/jiraSOAP/entities/scheme.rb +1 -1
  46. data/lib/jiraSOAP/entities/server_configuration.rb +14 -53
  47. data/lib/jiraSOAP/entities/server_info.rb +8 -26
  48. data/lib/jiraSOAP/entities/status.rb +1 -1
  49. data/lib/jiraSOAP/entities/time_info.rb +5 -10
  50. data/lib/jiraSOAP/entities/user.rb +5 -15
  51. data/lib/jiraSOAP/entities/username.rb +4 -0
  52. data/lib/jiraSOAP/entities/version.rb +6 -20
  53. data/lib/jiraSOAP/handsoap_extensions.rb +4 -2
  54. data/lib/jiraSOAP/macruby_bonuses.rb +12 -5
  55. data/lib/jiraSOAP/url.rb +13 -24
  56. data/yard-jiraSOAP.rb +65 -0
  57. metadata +52 -92
  58. data/lib/jiraSOAP/api/convenience.rb +0 -12
  59. data/lib/jiraSOAP/entities/remote_entity.rb +0 -7
@@ -0,0 +1,10 @@
1
+ --protected
2
+ --private
3
+ --no-cache
4
+ --markup markdown
5
+ --readme README.markdown
6
+ --load './yard-jiraSOAP.rb'
7
+ lib/**/*.rb
8
+ -
9
+ LICENSE.txt
10
+ ChangeLog
data/ChangeLog CHANGED
@@ -1,3 +1,21 @@
1
+ Version 0.7.1
2
+ * Remove AOT compiled files from gem
3
+
4
+ Version 0.7
5
+
6
+ * Added YARD extension for documentation
7
+ * Removed URL class in favour of directly using underlying objects
8
+ * Added AOT compilation for MacRuby
9
+ * Moved RemoteAPI into the JIRA namespace
10
+ * Alias #get_favourite_filter to #get_favorite_filter
11
+
12
+ * Tweaked parsing logic more in preparation for the builder generalization
13
+ * Various documentation updates
14
+
15
+ * Removed jeweler development dependency
16
+ * Removed yardstick development dependency
17
+ * General tweaking of the rakefile, gemspec, gemfile, and .yardopts
18
+
1
19
  Version 0.6.1
2
20
 
3
21
  * Added RemoteAPIAdditions module for conveniences
File without changes
@@ -20,7 +20,7 @@ Pick up where `jira4r` left off:
20
20
  - Implement the current API; `jira4r` does not implement APIs from JIRA 4.x
21
21
  - More natural interface; not adhering to the API when the API is weird
22
22
  - Speed; network latency is bad enough
23
- - Excellent documentation, since the documentation given by Atlassian is so terse
23
+ - Excellent documentation, since the documentation given by Atlassian can be terse (the newer APIs are documented)
24
24
 
25
25
 
26
26
  Getting Started
@@ -33,8 +33,7 @@ Getting Started
33
33
 
34
34
  # Building from source
35
35
  git clone git://github.com/Marketcircle/jiraSOAP.git
36
- rake build
37
- rake install
36
+ rake build install
38
37
 
39
38
  Once installed, you can run a quick demo (making appropriate substitutions):
40
39
 
@@ -60,15 +59,14 @@ TODO
60
59
  - Performance optimizations; there are a number of places that can be optimized
61
60
  + Using GCD/Threads for parsing arrays of results; a significant speed up for large types and large arrays (ie. creating issues from JQL searches)
62
61
  - Public test suite
63
- + Needs a mock server
62
+ + Needs a lot of mock data
64
63
 
65
64
 
66
65
  Note on Patches/Pull Requests
67
66
  -----------------------------
68
67
 
69
68
  This project has a tendancy to change drastically between releases as it
70
- is still unstable, so patches may not cleanly apply. It may be better to
71
- just open an issue.
69
+ is still unstable, so patches may not cleanly apply.
72
70
 
73
71
  If you want to help by submitting patches:
74
72
 
@@ -1,4 +1,3 @@
1
- require 'logger'
2
1
  require 'time'
3
2
  require 'uri'
4
3
  require 'nokogiri'
@@ -15,7 +14,6 @@ end
15
14
 
16
15
  require 'jiraSOAP/entities'
17
16
  require 'jiraSOAP/api'
18
- require 'jiraSOAP/api/convenience'
19
17
  require 'jiraSOAP/JIRAservice'
20
18
 
21
19
  require 'jiraSOAP/macruby_bonuses' if RUBY_ENGINE == 'macruby'
@@ -10,8 +10,8 @@
10
10
  # It is best to treat this class as a singleton, but it is not enforced
11
11
  # in case you want to be able to login as multiple users to the same endpoint.
12
12
  class JIRA::JIRAService < Handsoap::Service
13
- include RemoteAPI
14
- include RemoteAPIAdditions
13
+ include JIRA::RemoteAPI
14
+ include JIRA::RemoteAPIAdditions
15
15
 
16
16
  # @return [String]
17
17
  attr_reader :auth_token
@@ -19,7 +19,7 @@ class JIRA::JIRAService < Handsoap::Service
19
19
  # @return [String]
20
20
  attr_reader :user
21
21
 
22
- # @return [URL]
22
+ # @return [String]
23
23
  attr_reader :endpoint_url
24
24
 
25
25
  # Initialize and log in.
@@ -33,9 +33,9 @@ class JIRA::JIRAService < Handsoap::Service
33
33
  jira
34
34
  end
35
35
 
36
- # @param [String,URL] endpoint_url for the JIRA server
36
+ # @param [String,URI::HTTP,NSURL] endpoint_url for the JIRA server
37
37
  def initialize endpoint_url
38
- @endpoint_url = endpoint_url
38
+ @endpoint_url = endpoint_url.to_s
39
39
  JIRA::JIRAService.endpoint({
40
40
  uri:"#{endpoint_url.to_s}/rpc/soap/jirasoapservice-v2",
41
41
  version:2
@@ -1,13 +1,31 @@
1
+ require 'jiraSOAP/api/users'
2
+ require 'jiraSOAP/api/avatars'
3
+ require 'jiraSOAP/api/versions'
4
+ require 'jiraSOAP/api/projects'
5
+ require 'jiraSOAP/api/project_roles'
6
+ require 'jiraSOAP/api/schemes'
7
+ require 'jiraSOAP/api/issues'
8
+ require 'jiraSOAP/api/filters'
9
+ require 'jiraSOAP/api/server_info'
10
+ require 'jiraSOAP/api/attachments'
11
+ require 'jiraSOAP/api/comments'
12
+ require 'jiraSOAP/api/issue_data_types'
13
+ require 'jiraSOAP/api/additions'
14
+
15
+ module JIRA
16
+
1
17
  # Contains the API defined by Atlassian for the [JIRA SOAP service](http://docs.atlassian.com/software/jira/docs/api/rpc-jira-plugin/latest/com/atlassian/jira/rpc/soap/JiraSoapService.html).
2
18
  #
3
19
  # There are several cases where this API diverges from the one defined by
4
20
  # Atlassian; most notably, this API tries to be more idomatically Ruby by using
5
- # snake case for method names.
21
+ # snake case for method names, default values, varargs, etc..
6
22
  # @todo logging
7
- # @todo code refactoring and de-duplication
8
- # @todo break the API down by task, like Apple's developer documentation;
9
- # I can break the tasks down by CRUD or by what they affect, or both
10
- # @todo progressWorkflowAction and friends [target v0.7]
23
+ # @todo progressWorkflowAction and friends [target v0.8]
24
+ # @todo get Nokogiri element directly and monkey patch nokogiri directly
25
+ # instead of the handsoap wrapper
26
+ # @todo remove the get_ prefix from api methods that don't need them
27
+ # @todo monkey patch Array to include a #to_soap method
28
+ # @todo document how to override the url_class setting
11
29
  module RemoteAPI
12
30
 
13
31
  # XPath constant to get a node containing a response array.
@@ -15,713 +33,76 @@ module RemoteAPI
15
33
  # cannot use a more blunt XPath expression.
16
34
  RESPONSE_XPATH = '/node()[1]/node()[1]/node()[1]/node()[2]'
17
35
 
36
+
37
+ # @group Logging in/out
38
+
39
+ # @todo change method name to #login! since we are changing internal state?
18
40
  # The first method to call; other methods will fail until you are logged in.
19
41
  # @param [String] user JIRA user name to login with
20
42
  # @param [String] password
21
- # @return [true]
22
- def login(user, password)
23
- response = invoke('soap:login') { |msg|
24
- msg.add 'soap:in0', user
25
- msg.add 'soap:in1', password
26
- }
27
- # cache now that we know it is safe to do so
28
- @user = user
43
+ # @return [Boolean] true if successful
44
+ def login username, password
45
+ response = build 'login', username, password
29
46
  @auth_token = response.document.xpath('//loginReturn').first.to_s
47
+ @user = user
30
48
  true
31
49
  end
32
50
 
51
+ # @todo change method name to #logout! since we are changing internal state?
33
52
  # You only need to call this to make an explicit logout; normally, a session
34
53
  # will automatically expire after a set time (configured on the server).
35
- # @return [true,false] true if successful, otherwise false
54
+ # @return [Boolean] true if successful, otherwise false
36
55
  def logout
37
- response = invoke('soap:logout') { |msg|
38
- msg.add 'soap:in0', @auth_token
39
- }
40
- response.document.xpath('//logoutReturn').to_boolean
41
- end
42
-
43
- # @return [[JIRA::Priority]]
44
- def get_priorities
45
- response = invoke('soap:getPriorities') { |msg|
46
- msg.add 'soap:in0', @auth_token
47
- }
48
- response.document.xpath("#{RESPONSE_XPATH}/getPrioritiesReturn").map {
49
- |frag| JIRA::Priority.new_with_xml frag
50
- }
51
- end
52
-
53
- # @return [[JIRA::Resolution]]
54
- def get_resolutions
55
- response = invoke('soap:getResolutions') { |msg|
56
- msg.add 'soap:in0', @auth_token
57
- }
58
- response.document.xpath("#{RESPONSE_XPATH}/getResolutionsReturn").map {
59
- |frag| JIRA::Resolution.new_with_xml frag
60
- }
61
- end
62
-
63
- # @return [[JIRA::Field]]
64
- def get_custom_fields
65
- response = invoke('soap:getCustomFields') { |msg|
66
- msg.add 'soap:in0', @auth_token
67
- }
68
- response.document.xpath("#{RESPONSE_XPATH}/getCustomFieldsReturn").map {
69
- |frag| JIRA::Field.new_with_xml frag
70
- }
71
- end
72
-
73
- # @return [[JIRA::IssueType]]
74
- def get_issue_types
75
- response = invoke('soap:getIssueTypes') { |msg|
76
- msg.add 'soap:in0', @auth_token
77
- }
78
- response.document.xpath("#{RESPONSE_XPATH}/getIssueTypesReturn").map {
79
- |frag| JIRA::IssueType.new_with_xml frag
80
- }
81
- end
82
-
83
- # @return [[JIRA::Status]]
84
- def get_statuses
85
- response = invoke('soap:getStatuses') { |msg|
86
- msg.add 'soap:in0', @auth_token
87
- }
88
- response.document.xpath("#{RESPONSE_XPATH}/getStatusesReturn").map {
89
- |frag| JIRA::Status.new_with_xml frag
90
- }
91
- end
92
-
93
- # @return [[JIRA::NotificationScheme]]
94
- def get_notification_schemes
95
- response = invoke('soap:getNotificationSchemes') { |msg|
96
- msg.add 'soap:in0', @auth_token
97
- }
98
- response.document.xpath("#{RESPONSE_XPATH}/getNotificationSchemesReturn").map {
99
- |frag| JIRA::NotificationScheme.new_with_xml frag
100
- }
101
- end
102
-
103
- # @param [String] project_key
104
- # @return [[JIRA::Version]]
105
- def get_versions_for_project(project_key)
106
- response = invoke('soap:getVersions') { |msg|
107
- msg.add 'soap:in0', @auth_token
108
- msg.add 'soap:in1', project_key
109
- }
110
- response.document.xpath("#{RESPONSE_XPATH}/getVersionsReturn").map {
111
- |frag| JIRA::Version.new_with_xml frag
112
- }
113
- end
114
-
115
- # You need to explicitly ask for schemes in order to get them. By
116
- # default, most project fetching methods purposely leave out all
117
- # the scheme information as permission schemes can be very large.
118
- # @param [String] project_key
119
- # @return [JIRA::Project]
120
- def get_project_with_key(project_key)
121
- response = invoke('soap:getProjectByKey') { |msg|
122
- msg.add 'soap:in0', @auth_token
123
- msg.add 'soap:in1', project_key
124
- }
125
- JIRA::Project.new_with_xml response.document.xpath('//getProjectByKeyReturn').first
126
- end
127
-
128
- # @param [String] user_name
129
- # @return [JIRA::User]
130
- def get_user_with_name(user_name)
131
- response = invoke('soap:getUser') { |msg|
132
- msg.add 'soap:in0', @auth_token
133
- msg.add 'soap:in1', user_name
134
- }
135
- JIRA::User.new_with_xml response.document.xpath('//getUserReturn').first
136
- end
137
-
138
- # Gets you the default avatar image for a project; if you want all
139
- # the avatars for a project, use {#get_project_avatars_for_key}.
140
- # @param [String] project_key
141
- # @return [JIRA::Avatar]
142
- def get_project_avatar_for_key(project_key)
143
- response = invoke('soap:getProjectAvatar') { |msg|
144
- msg.add 'soap:in0', @auth_token
145
- msg.add 'soap:in1', project_key
146
- }
147
- JIRA::Avatar.new_with_xml response.document.xpath('//getProjectAvatarReturn').first
148
- end
149
-
150
- # Gets ALL avatars for a given project with this method; if you
151
- # just want the project avatar, use {#get_project_avatar_for_key}.
152
- # @param [String] project_key
153
- # @param [true,false] include_default_avatars
154
- # @return [[JIRA::Avatar]]
155
- def get_project_avatars_for_key(project_key, include_default_avatars = false)
156
- response = invoke('soap:getProjectAvatars') { |msg|
157
- msg.add 'soap:in0', @auth_token
158
- msg.add 'soap:in1', project_key
159
- msg.add 'soap:in2', include_default_avatars
160
- }
161
- response.document.xpath("#{RESPONSE_XPATH}/getProjectAvatarsReturn").map {
162
- |frag| JIRA::Avatar.new_with_xml frag
163
- }
164
- end
165
-
166
- # This method is the equivalent of making an advanced search from the
167
- # web interface.
168
- #
169
- # During my own testing, I found that HTTP requests could timeout for really
170
- # large requests (~2500 results). So I set a more reasonable upper limit;
171
- # feel free to override it, but be aware of the potential issues.
172
- #
173
- # The JIRA::Issue structure does not include any comments or attachments.
174
- # @param [String] jql_query JQL query as a string
175
- # @param [Fixnum] max_results limit on number of returned results;
176
- # the value may be overridden by the server if max_results is too large
177
- # @return [[JIRA::Issue]]
178
- def get_issues_from_jql_search(jql_query, max_results = 2000)
179
- response = invoke('soap:getIssuesFromJqlSearch') { |msg|
180
- msg.add 'soap:in0', @auth_token
181
- msg.add 'soap:in1', jql_query
182
- msg.add 'soap:in2', max_results
183
- }
184
- response.document.xpath("#{RESPONSE_XPATH}/getIssuesFromJqlSearchReturn").map {
185
- |frag| JIRA::Issue.new_with_xml frag
186
- }
187
- end
188
-
189
- # This method can update most, but not all, issue fields. Some limitations
190
- # are because of how the API is designed, and some are because I have not
191
- # yet implemented the ability to update fields made of custom objects (things
192
- # in the JIRA module).
193
- #
194
- # Fields known to not update via this method:
195
- # - status - use {#progress_workflow_action}
196
- # - attachments - use {#add_base64_encoded_attachments_to_issue_with_key}
197
- #
198
- # Though JIRA::FieldValue objects have an id field, they do not expect to be
199
- # given id values. You must use the name of the field you wish to update.
200
- # @example Usage With A Normal Field
201
- # summary = JIRA::FieldValue.new 'summary', ['My new summary']
202
- # @example Usage With A Custom Field
203
- # custom_field = JIRA::FieldValue.new 'customfield_10060', ['123456']
204
- # @example Setting a field to be blank/nil
205
- # description = JIRA::FieldValue.new 'description'
206
- # @example Calling the method to update an issue
207
- # jira_service_instance.update_issue 'PROJECT-1', description, custom_field
208
- # @param [String] issue_key
209
- # @param [JIRA::FieldValue] *field_values
210
- # @return [JIRA::Issue]
211
- def update_issue(issue_key, *field_values)
212
- response = invoke('soap:updateIssue') { |msg|
213
- msg.add 'soap:in0', @auth_token
214
- msg.add 'soap:in1', issue_key
215
- msg.add 'soap:in2' do |submsg|
216
- field_values.each { |fv| fv.soapify_for submsg }
217
- end
218
- }
219
- JIRA::Issue.new_with_xml response.document.xpath('//updateIssueReturn').first
220
- end
221
-
222
- # Some fields will be ignored when an issue is created.
223
- # - reporter - you cannot override this value at creation
224
- # - resolution
225
- # - attachments
226
- # - votes
227
- # - status
228
- # - due date - I think this is a bug in jiraSOAP or JIRA
229
- # - environment - I think this is a bug in jiraSOAP or JIRA
230
- # @param [JIRA::Issue] issue
231
- # @return [JIRA::Issue]
232
- def create_issue_with_issue(issue)
233
- response = invoke('soap:createIssue') { |msg|
234
- msg.add 'soap:in0', @auth_token
235
- msg.add 'soap:in1' do |submsg|
236
- issue.soapify_for submsg
237
- end
238
- }
239
- JIRA::Issue.new_with_xml response.document.xpath('//createIssueReturn').first
240
- end
241
-
242
- # @param [String] issue_key
243
- # @return [JIRA::Issue]
244
- def get_issue_with_key(issue_key)
245
- response = invoke('soap:getIssue') { |msg|
246
- msg.add 'soap:in0', @auth_token
247
- msg.add 'soap:in1', issue_key
248
- }
249
- JIRA::Issue.new_with_xml response.document.xpath('//getIssueReturn').first
250
- end
251
-
252
- # @param [String] issue_id
253
- # @return [JIRA::Issue]
254
- def get_issue_with_id(issue_id)
255
- response = invoke('soap:getIssueById') { |msg|
256
- msg.add 'soap:in0', @auth_token
257
- msg.add 'soap:in1', issue_id
258
- }
259
- JIRA::Issue.new_with_xml response.document.xpath('//getIssueByIdReturn').first
260
- end
261
-
262
- # @param [String] issue_key
263
- # @return [[JIRA::Attachment]]
264
- def get_attachments_for_issue_with_key(issue_key)
265
- response = invoke('soap:getAttachmentsFromIssue') { |msg|
266
- msg.add 'soap:in0', @auth_token
267
- msg.add 'soap:in1', issue_key
268
- }
269
- response.document.xpath("#{RESPONSE_XPATH}/getAttachmentsFromIssueReturn").map {
270
- |frag| JIRA::AttachmentMetadata.new_with_xml frag
271
- }
272
- end
273
-
274
- # New versions cannot have the archived bit set and the release date
275
- # field will ignore the time of day you give it and instead insert
276
- # the time zone offset as the time of day.
277
- #
278
- # Remember that the @release_date field is the tentative release date,
279
- # so its value is independant of the @released flag.
280
- #
281
- # Descriptions do not appear to be included with JIRA::Version objects
282
- # that SOAP API provides.
283
- # @param [String] project_key
284
- # @param [JIRA::Version] version
285
- # @return [JIRA::Version]
286
- def add_version_to_project_with_key(project_key, version)
287
- response = invoke('soap:addVersion') { |msg|
288
- msg.add 'soap:in0', @auth_token
289
- msg.add 'soap:in1', project_key
290
- msg.add 'soap:in2' do |submsg| version.soapify_for submsg end
291
- }
292
- JIRA::Version.new_with_xml response.document.xpath('//addVersionReturn').first
293
- end
294
-
295
- # The archive state can only be set to true for versions that have not been
296
- # released. However, this is not reflected by the return value of this method.
297
- # @param [String] project_key
298
- # @param [String] version_name
299
- # @param [true,false] state
300
- # @return [true]
301
- def set_archive_state_for_version_for_project(project_key, version_name, state)
302
- invoke('soap:archiveVersion') { |msg|
303
- msg.add 'soap:in0', @auth_token
304
- msg.add 'soap:in1', project_key
305
- msg.add 'soap:in2', version_name
306
- msg.add 'soap:in3', state
307
- }
308
- true
309
- end
310
-
311
- # Requires you to set at least a project name, key, and lead.
312
- # However, it is also a good idea to set other project properties, such as
313
- # the permission scheme as the default permission scheme can be too
314
- # restrictive in most cases.
315
- # @param [JIRA::Project] project
316
- # @return [JIRA::Project]
317
- def create_project_with_project(project)
318
- response = invoke('soap:createProjectFromObject') { |msg|
319
- msg.add 'soap:in0', @auth_token
320
- msg.add 'soap:in1' do |submsg| project.soapify_for submsg end
321
- }
322
- JIRA::Project.new_with_xml response.document.xpath('//createProjectFromObjectReturn').first
323
- end
324
-
325
- # You can set the release state for a project with this method.
326
- # @param [String] project_name
327
- # @param [JIRA::Version] version
328
- # @return [true]
329
- def release_state_for_version_for_project(project_name, version)
330
- invoke('soap:releaseVersion') { |msg|
331
- msg.add 'soap:in0', @auth_token
332
- msg.add 'soap:in1', project_name
333
- msg.add 'soap:in2' do |submsg| version.soapify_for submsg end
334
- }
335
- true
336
- end
337
-
338
- # The id of the project is the only field that you cannot update. Or, at
339
- # least the only field I know that you cannot update.
340
- # @param [JIRA::Project] project
341
- # @return [JIRA::Project]
342
- def update_project_with_project(project)
343
- response = invoke('soap:updateProject') { |msg|
344
- msg.add 'soap:in0', @auth_token
345
- msg.add 'soap:in1' do |submsg| project.soapify_for submsg end
346
- }
347
- JIRA::Project.new_with_xml response.document.xpath('//updateProjectReturn').first
348
- end
349
-
350
- # It seems that creating a user without any permission groups will trigger
351
- # an exception on some versions of JIRA. The irony is that this method provides
352
- # no way to add groups. The good news though, is that the creation will still
353
- # happen; but the user will have no permissions.
354
- # @param [String] username
355
- # @param [String] password
356
- # @param [String] full_name
357
- # @param [String] email
358
- # @return [JIRA::User,nil] depending on your JIRA version, this method may
359
- # always raise an exception instead of actually returning anythin
360
- def create_user(username, password, full_name, email)
361
- response = invoke('soap:createUser') { |msg|
362
- msg.add 'soap:in0', @auth_token
363
- msg.add 'soap:in1', username
364
- msg.add 'soap:in2', password
365
- msg.add 'soap:in3', full_name
366
- msg.add 'soap:in4', email
367
- }
368
- JIRA::User.new_with_xml response.document.xpath('//createUserReturn').first
369
- end
370
-
371
- # @param [String] username
372
- # @return [true]
373
- def delete_user_with_name(username)
374
- invoke('soap:deleteUser') { |msg|
375
- msg.add 'soap:in0', @auth_token
376
- msg.add 'soap:in1', username
377
- }
378
- true
379
- end
380
-
381
- # @param [String] project_id
382
- # @return [JIRA::Project]
383
- def get_project_with_id(project_id)
384
- response = invoke('soap:getProjectById') { |msg|
385
- msg.add 'soap:in0', @auth_token
386
- msg.add 'soap:in1', project_id
387
- }
388
- JIRA::Project.new_with_xml response.document.xpath('//getProjectByIdReturn').first
389
- end
390
-
391
- # @todo parse the permission scheme
392
- # Note: this method does not yet include the permission scheme.
393
- # @param [String] project_id
394
- # @return [JIRA::Project]
395
- def get_project_including_schemes_with_id(project_id)
396
- response = invoke('soap:getProjectWithSchemesById') { |msg|
397
- msg.add 'soap:in0', @auth_token
398
- msg.add 'soap:in1', project_id
399
- }
400
- JIRA::Project.new_with_xml response.document.xpath('//getProjectWithSchemesByIdReturn').first
401
- end
402
-
403
- # @param [String] issue_key
404
- # @param [JIRA::Comment] comment
405
- # @return [true]
406
- def add_comment_to_issue_with_key(issue_key, comment)
407
- invoke('soap:addComment') { |msg|
408
- msg.add 'soap:in0', @auth_token
409
- msg.add 'soap:in1', issue_key
410
- msg.add 'soap:in2' do |submsg| comment.soapify_for submsg end
411
- }
412
- true
413
- end
414
-
415
- # @param [String] id
416
- # @return [JIRA::Comment]
417
- def get_comment_with_id(id)
418
- response = invoke('soap:getComment') { |msg|
419
- msg.add 'soap:in0', @auth_token
420
- msg.add 'soap:in1', id
421
- }
422
- JIRA::Comment.new_with_xml response.document.xpath('//getCommentReturn').first
423
- end
424
-
425
- # @param [String] issue_key
426
- # @return [[JIRA::Comment]]
427
- def get_comments_for_issue_with_key(issue_key)
428
- response = invoke('soap:getComments') { |msg|
429
- msg.add 'soap:in0', @auth_token
430
- msg.add 'soap:in1', issue_key
431
- }
432
- response.document.xpath("#{RESPONSE_XPATH}/getCommentsReturn").map {
433
- |frag| JIRA::Comment.new_with_xml frag
434
- }
435
- end
436
-
437
- # @param [String] project_name
438
- # @return [[JIRA::IssueType]]
439
- def get_issue_types_for_project_with_id(project_id)
440
- response = invoke('soap:getIssueTypesForProject') { |msg|
441
- msg.add 'soap:in0', @auth_token
442
- msg.add 'soap:in1', project_id
443
- }
444
- response.document.xpath("#{RESPONSE_XPATH}/getIssueTypesForProjectReturn").map {
445
- |frag| JIRA::IssueType.new_with_xml frag
446
- }
447
- end
448
-
449
- # @param [JIRA::Comment] comment
450
- # @return [JIRA::Comment]
451
- def update_comment(comment)
452
- response = invoke('soap:editComment') { |msg|
453
- msg.add 'soap:in0', @auth_token
454
- msg.add 'soap:in1' do |submsg| comment.soapify_for submsg end
455
- }
456
- frag = response.document.xpath('//editCommentReturn').first
457
- JIRA::Comment.new_with_xml frag
458
- end
459
-
460
- # @return [[JIRA::IssueType]]
461
- def get_subtask_issue_types
462
- response = invoke('soap:getSubTaskIssueTypes') { |msg|
463
- msg.add 'soap:in0', @auth_token
464
- }
465
- response.document.xpath("#{RESPONSE_XPATH}/getSubTaskIssueTypesReturn").map {
466
- |frag| JIRA::IssueType.new_with_xml frag
467
- }
468
- end
469
-
470
- # @param [String] project_id
471
- # @return [[JIRA::IssueType]]
472
- def get_subtask_issue_types_for_project_with_id(project_id)
473
- response = invoke('soap:getSubTaskIssueTypesForProject') { |msg|
474
- msg.add 'soap:in0', @auth_token
475
- msg.add 'soap:in1', project_id
476
- }
477
- response.document.xpath("#{RESPONSE_XPATH}/getSubtaskIssueTypesForProjectReturn").map {
478
- |frag| JIRA::IssueType.new_with_xml frag
479
- }
480
- end
481
-
482
- # I have no idea what this method does.
483
- # @todo find out what this method does
484
- # @return [true]
485
- def refresh_custom_fields
486
- invoke('soap:refreshCustomFields') { |msg|
487
- msg.add 'soap:in0', @auth_token
488
- }
489
- true
490
- end
491
-
492
- # Retrieves favourite filters for the currently logged in user.
493
- # @return [[JIRA::Filter]]
494
- def get_favourite_filters
495
- response = invoke('soap:getFavouriteFilters') { |msg|
496
- msg.add 'soap:in0', @auth_token
497
- }
498
- response.document.xpath("#{RESPONSE_XPATH}/getFavouriteFiltersReturn").map {
499
- |frag| JIRA::Filter.new_with_xml frag
500
- }
501
- end
502
-
503
- # @param [String] id
504
- # @param [Fixnum] max_results
505
- # @param [Fixnum] offset
506
- # @return [[JIRA::Issue]]
507
- def get_issues_from_filter_with_id(id, max_results = 500, offset = 0)
508
- response = invoke('soap:getIssuesFromFilterWithLimit') { |msg|
509
- msg.add 'soap:in0', @auth_token
510
- msg.add 'soap:in1', id
511
- msg.add 'soap:in2', offset
512
- msg.add 'soap:in3', max_results
513
- }
514
- response.document.xpath("#{RESPONSE_XPATH}/getIssuesFromFilterWithLimitReturn").map {
515
- |frag| JIRA::Issue.new_with_xml frag
516
- }
517
- end
518
-
519
- # @param [String] id
520
- # @return [Fixnum]
521
- def get_issue_count_for_filter_with_id(id)
522
- response = invoke('soap:getIssueCountForFilter') { |msg|
523
- msg.add 'soap:in0', @auth_token
524
- msg.add 'soap:in1', id
525
- }
526
- response.document.xpath('//getIssueCountForFilterReturn').to_i
527
- end
528
-
529
- # @todo optimize building the message, try a single pass
530
- # Expect this method to be slow.
531
- # @param [String] issue_key
532
- # @param [[String]] filenames names to put on the files
533
- # @param [[String]] data base64 encoded data
534
- # @return [true]
535
- def add_base64_encoded_attachments_to_issue_with_key(issue_key, filenames, data)
536
- invoke('soap:addBase64EncodedAttachmentsToIssue') { |msg|
537
- msg.add 'soap:in0', @auth_token
538
- msg.add 'soap:in1', issue_key
539
- msg.add 'soap:in2' do |submsg|
540
- filenames.each { |filename| submsg.add 'filenames', filename }
56
+ call( 'logout' ).to_boolean
57
+ end
58
+
59
+ # @endgroup
60
+
61
+
62
+ private
63
+
64
+ # @todo make this method less ugly
65
+ # @todo double check the return type
66
+ # A generic method for calling a SOAP method and soapifying all
67
+ # the arguments, adapted for usage with jiraSOAP.
68
+ # @param [String] method
69
+ # @param [Object] *args
70
+ # @return [Handsoap::Response]
71
+ def build method, *args
72
+ invoke "soap:#{method}" do |msg|
73
+ for i in 0...args.size
74
+ arg = args.shift
75
+ case arg
76
+ when JIRA::Entity
77
+ msg.add "soap:in#{i}", do |submsg| arg.soapify_for submsg end
78
+ else
79
+ msg.add "soap:in#{i}", arg
80
+ end
541
81
  end
542
- msg.add 'soap:in3' do |submsg|
543
- data.each { |datum| submsg.add 'base64EncodedData', datum }
544
- end
545
- }
546
- true
82
+ end
547
83
  end
548
84
 
549
- # The @build_date attribute is a Time value, but does not include a time.
550
- # @return [JIRA::ServerInfo]
551
- def get_server_info
552
- response = invoke('soap:getServerInfo') { |msg|
553
- msg.add 'soap:in0', @auth_token
554
- }
555
- JIRA::ServerInfo.new_with_xml response.document.xpath('//getServerInfoReturn').first
85
+ # @todo find a less blunt XPath expression
86
+ # A simple call, for methods that will return a single object.
87
+ # @param [String] method
88
+ # @param [Object] *args
89
+ # @return [Handsoap::XmlQueryFront::NodeSelection]
90
+ def call method, *args
91
+ response = build method, @auth_token, *args
92
+ response .document.xpath "//#{method}Return"
556
93
  end
557
94
 
558
- # @return [JIRA::ServerConfiguration]
559
- def get_server_configuration
560
- response = invoke('soap:getConfiguration') { |msg|
561
- msg.add 'soap:in0', @auth_token
562
- }
563
- JIRA::ServerConfiguration.new_with_xml response.document.xpath('//getConfigurationReturn').first
95
+ # A more complex form of {#call} that does a little more work for
96
+ # you when you need to build an array of return values.
97
+ # @param [String] method
98
+ # @param [Object] *args
99
+ # @return [Handsoap::XmlQueryFront::NodeSelection]
100
+ def jira_call type, method, *args
101
+ response = build method, @auth_token, *args
102
+ frags = response.document.xpath("#{RESPONSE_XPATH}/#{method}Return")
103
+ frags.map { |frag| type.new_with_xml frag }
564
104
  end
565
105
 
566
- # @note This will not fill in JIRA::Scheme data for the projects.
567
- # @return [[JIRA::Project]]
568
- def get_projects_without_schemes
569
- response = invoke('soap:getProjectsNoSchemes') { |msg|
570
- msg.add 'soap:in0', @auth_token
571
- }
572
- response.document.xpath("#{RESPONSE_XPATH}/getProjectsNoSchemesReturn").map {
573
- |frag| JIRA::Project.new_with_xml frag
574
- }
575
- end
576
-
577
- # @param [#to_s] issue_id
578
- # @return [Time]
579
- def get_resolution_date_for_issue_with_id issue_id
580
- response = invoke('soap:getResolutionDateById') { |msg|
581
- msg.add 'soap:in0', @auth_token
582
- msg.add 'soap:in1', issue_id
583
- }
584
- response.document.xpath('//getResolutionDateByIdReturn').to_date
585
- end
586
-
587
- # @param [String] issue_key
588
- # @return [Time]
589
- def get_resolution_date_for_issue_with_key issue_key
590
- response = invoke('soap:getResolutionDateByKey') { |msg|
591
- msg.add 'soap:in0', @auth_token
592
- msg.add 'soap:in1', issue_key
593
- }
594
- response.document.xpath('//getResolutionDateByKeyReturn').to_date
595
- end
596
-
597
- # @param [String] project_key
598
- # @return [true]
599
- def delete_project_with_key project_key
600
- invoke('soap:deleteProject') { |msg|
601
- msg.add 'soap:in0', @auth_token
602
- msg.add 'soap:in1', project_key
603
- }
604
- true
605
- end
606
-
607
- # @todo add tests for this method
608
- # @note You cannot delete the system avatar
609
- # @note You need project administration permissions to delete an avatar
610
- # @param [#to_s] avatar_id
611
- # @return [true]
612
- def delete_project_avatar_with_id avatar_id
613
- invoke('soap:deleteProjectAvatar') { |msg|
614
- msg.add 'soap:in0', @auth_token
615
- msg.add 'soap:in1', avatar_id
616
- }
617
- true
618
- end
619
-
620
- # @note You need project administration permissions to edit an avatar
621
- # @note JIRA does not care if the avatar_id is valid
622
- # Change the project avatar to another existing avatar. If you want to
623
- # upload a new avatar and set it to be the new project avatar use
624
- # {#set_new_project_avatar} instead.
625
- # @return [true]
626
- def set_project_avatar_for_project_with_key project_key, avatar_id
627
- invoke('soap:setProjectAvatar') { |msg|
628
- msg.add 'soap:in0', @auth_token
629
- msg.add 'soap:in1', project_key
630
- msg.add 'soap:in2', avatar_id
631
- }
632
- true
633
- end
634
-
635
- # @note You need project administration permissions to edit an avatar
636
- # Use this method to create a new custom avatar for a project and set it
637
- # to be current avatar for the project.
638
- #
639
- # The image, provided as base64 encoded data, should be a 48x48 pixel square.
640
- # If the image is larger, the top left 48 pixels are taken, if it is smaller
641
- # then it will be upscaled to 48 pixels.
642
- # The small version of the avatar image (16 pixels) is generated
643
- # automatically.
644
- # If you want to switch a project avatar to an avatar that already exists on
645
- # the system then use {#set_project_avatar_for_project_with_key} instead.
646
- # @param [String] project_key
647
- # @param [String] mime_type
648
- # @param [#to_s] base64_image
649
- # @return [true]
650
- def set_new_project_avatar_for_project_with_key project_key, mime_type, base64_image
651
- invoke('soap:setNewProjectAvatar') { |msg|
652
- msg.add 'soap:in0', @auth_token
653
- msg.add 'soap:in1', project_key
654
- msg.add 'soap:in2', mime_type
655
- msg.add 'soap:in3', base64_image
656
- }
657
- true
658
- end
659
-
660
- # @return [[JIRA::ProjectRole]]
661
- def get_project_roles
662
- response = invoke('soap:getProjectRoles') { |msg|
663
- msg.add 'soap:in0', @auth_token
664
- }
665
- response.document.xpath("#{RESPONSE_XPATH}/getProjectRolesReturn").map {
666
- |frag| JIRA::ProjectRole.new_with_xml frag
667
- }
668
- end
669
-
670
- # @param [#to_s] role_id
671
- # @return [JIRA::ProjectRole]
672
- def get_project_role_with_id role_id
673
- response = invoke('soap:getProjectRole') { |msg|
674
- msg.add 'soap:in0', @auth_token
675
- msg.add 'soap:in1', role_id
676
- }
677
- JIRA::ProjectRole.new_with_xml response.document.xpath('//getProjectRoleReturn').first
678
- end
679
-
680
- # @param [JIRA::ProjectRole] project_role
681
- # @return [JIRA::ProjectRole] the role that was created
682
- def create_project_role_with_role project_role
683
- response = invoke('soap:createProjectRole') { |msg|
684
- msg.add 'soap:in0', @auth_token
685
- msg.add 'soap:in1' do |submsg| project_role.soapify_for submsg end
686
- }
687
- JIRA::ProjectRole.new_with_xml response.document.xpath('//createProjectRoleReturn').first
688
- end
689
-
690
- # @note JIRA 4.0 returns an exception if the name already exists
691
- # Returns true if the name does not exist.
692
- # @param [String] project_role_name
693
- # @return [true,false]
694
- def project_role_name_unique? project_role_name
695
- response = invoke('soap:isProjectRoleNameUnique') { |msg|
696
- msg.add 'soap:in0', @auth_token
697
- msg.add 'soap:in1', project_role_name
698
- }
699
- response.document.xpath('//isProjectRoleNameUniqueReturn').to_boolean
700
- end
701
-
702
- # @note the confirm argument appears to do nothing (at least on JIRA 4.0)
703
- # @param [JIRA::ProjectRole] project_role
704
- # @param [true,false] confirm
705
- # @return [true]
706
- def delete_project_role project_role, confirm = true
707
- invoke('soap:deleteProjectRole') { |msg|
708
- msg.add 'soap:in0', @auth_token
709
- msg.add 'soap:in1' do |submsg| project_role.soapify_for submsg end
710
- msg.add 'soap:in2', confirm
711
- }
712
- true
713
- end
714
-
715
- # @note JIRA 4.0 will not update project roles, it will instead throw
716
- # an exception telling you that the project role already exists
717
- # @param [JIRA::ProjectRole] project_role
718
- # @return [JIRA::ProjectRole] the role after the update
719
- def update_project_role_with_role project_role
720
- response = invoke('soap:updateProjectRole') { |msg|
721
- msg.add 'soap:in0', @auth_token
722
- msg.add 'soap:in1' do |submsg| project_role.soapify_for submsg end
723
- }
724
- JIRA::ProjectRole.new_with_xml response.document.xpath('//updateProjectRoleReturn').first
725
- end
106
+ end
726
107
 
727
108
  end