fogbugz 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/bin/fogbugz-areas CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'rubygems'
4
- require 'typhoeus'
5
- require 'xml'
4
+ require 'net/https'
5
+ require 'uri'
6
+ require 'rexml/document'
6
7
  require 'optparse'
7
8
 
8
9
  api_url = ENV['FOGBUGZ_API_URL']
@@ -12,7 +13,7 @@ unless api_url
12
13
  end
13
14
 
14
15
  api_token = ENV['FOGBUGZ_API_TOKEN']
15
- unless api_url
16
+ unless api_token
16
17
  puts "Environment variable FOGBUGZ_API_TOKEN must be set."
17
18
  exit 1
18
19
  end
@@ -21,44 +22,35 @@ options = {}
21
22
  optparse = OptionParser.new do |opts|
22
23
  opts.banner = "usage: #{File::basename(__FILE__)} [options]"
23
24
 
24
- options[:verbose] = false
25
- opts.on('-v', '--verbose', 'Output verbose debugging information') do
26
- options[:verbose] = true
27
- end
28
-
29
25
  opts.on_tail('-h', '--help') do
30
26
  puts optparse.help
31
27
  exit 1
32
28
  end
33
-
34
- options[:project] = nil
35
- opts.on('--project=<project>', 'Filter by project.') do |project|
36
- options[:project] = project
37
- end
38
29
  end
39
30
  optparse.parse!
40
31
 
41
- response = Typhoeus::Request.get(api_url,
42
- :verbose => options[:verbose],
43
- :params => {
44
- :cmd => 'listAreas',
45
- :token => api_token,
46
- :ixProject => options[:project] })
47
- if response.code != 200
32
+ uri = URI format("#{api_url}?cmd=listAreas&token=%s", URI.escape(api_token))
33
+ http = Net::HTTP.new(uri.host, uri.port)
34
+ if uri.scheme == 'https'
35
+ http.use_ssl = true
36
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
37
+ end
38
+ response = http.start { |h| h.request Net::HTTP::Get.new(uri.request_uri) }
39
+ if response.code != '200'
48
40
  puts "HTTP request to #{api_url} failed with code #{response.code}."
49
41
  exit 1
50
42
  end
51
43
 
52
- result = XML::Parser.string(response.body).parse
53
- error = result.find_first('/response/error')
44
+ result = REXML::Document.new(response.body)
45
+ error = result.elements['/response/error']
54
46
  if error
55
- puts "Failed with error: #{error.content}."
47
+ puts "Failed with error: #{error.text}."
56
48
  exit 1
57
49
  end
58
50
 
59
- result.find('/response/areas/area').each do |status|
51
+ result.elements.each('/response/areas/area') do |area|
60
52
  puts format("%-20.20s %-20.20s %s\n",
61
- status.find_first('sPersonOwner').content,
62
- status.find_first('sProject').content,
63
- status.find_first('sArea').content).strip!
53
+ area.elements['sPersonOwner'].text,
54
+ area.elements['sProject'].text,
55
+ area.elements['sArea'].text).strip!
64
56
  end
data/bin/fogbugz-assign CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'rubygems'
4
- require 'typhoeus'
5
- require 'xml'
4
+ require 'net/https'
5
+ require 'uri'
6
+ require 'rexml/document'
6
7
  require 'optparse'
7
8
 
8
9
  api_url = ENV['FOGBUGZ_API_URL']
@@ -12,7 +13,7 @@ unless api_url
12
13
  end
13
14
 
14
15
  api_token = ENV['FOGBUGZ_API_TOKEN']
15
- unless api_url
16
+ unless api_token
16
17
  puts "Environment variable FOGBUGZ_API_TOKEN must be set."
17
18
  exit 1
18
19
  end
@@ -21,11 +22,6 @@ options = {}
21
22
  optparse = OptionParser.new do |opts|
22
23
  opts.banner = "usage: #{File::basename(__FILE__)} [options] <case> <assignee>"
23
24
 
24
- options[:verbose] = false
25
- opts.on('-v', '--verbose', 'Output verbose debugging information.') do
26
- options[:verbose] = true
27
- end
28
-
29
25
  opts.on_tail('-h', '--help') do
30
26
  puts optparse.help
31
27
  exit 1
@@ -38,21 +34,23 @@ unless ARGV.length == 2
38
34
  exit 1
39
35
  end
40
36
 
41
- response = Typhoeus::Request.get(api_url,
42
- :verbose => options[:verbose],
43
- :params => {
44
- :cmd => 'assign',
45
- :token => api_token,
46
- :ixBug => ARGV[0],
47
- :sPersonAssignedTo => ARGV[1] })
48
- if response.code != 200
37
+ uri = URI format("#{api_url}?cmd=assign&token=%s&ixBug=%s&sPersonAssignedTo=%s",
38
+ URI.escape(api_token), URI.escape(ARGV[0]),
39
+ URI.escape(ARGV[1]))
40
+ http = Net::HTTP.new(uri.host, uri.port)
41
+ if uri.scheme == 'https'
42
+ http.use_ssl = true
43
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
44
+ end
45
+ response = http.start { |h| h.request Net::HTTP::Get.new(uri.request_uri) }
46
+ if response.code != '200'
49
47
  puts "HTTP request to #{api_url} failed with code #{response.code}."
50
48
  exit 1
51
49
  end
52
50
 
53
- result = XML::Parser.string(response.body).parse
54
- error = result.find_first('/response/error')
51
+ result = REXML::Document.new(response.body)
52
+ error = result.elements['/response/error']
55
53
  if error
56
- puts "Failed with error: #{error.content}."
54
+ puts "Failed with error: #{error.text}."
57
55
  exit 1
58
56
  end
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'rubygems'
4
- require 'typhoeus'
5
- require 'xml'
4
+ require 'net/https'
5
+ require 'uri'
6
+ require 'rexml/document'
6
7
  require 'optparse'
7
8
 
8
9
  api_url = ENV['FOGBUGZ_API_URL']
@@ -12,7 +13,7 @@ unless api_url
12
13
  end
13
14
 
14
15
  api_token = ENV['FOGBUGZ_API_TOKEN']
15
- unless api_url
16
+ unless api_token
16
17
  puts "Environment variable FOGBUGZ_API_TOKEN must be set."
17
18
  exit 1
18
19
  end
@@ -21,11 +22,6 @@ options = {}
21
22
  optparse = OptionParser.new do |opts|
22
23
  opts.banner = "usage: #{File::basename(__FILE__)} [options]"
23
24
 
24
- options[:verbose] = false
25
- opts.on('-v', '--verbose', 'Output verbose debugging information') do
26
- options[:verbose] = true
27
- end
28
-
29
25
  opts.on_tail('-h', '--help') do
30
26
  puts optparse.help
31
27
  exit 1
@@ -33,23 +29,25 @@ optparse = OptionParser.new do |opts|
33
29
  end
34
30
  optparse.parse!
35
31
 
36
- response = Typhoeus::Request.get(api_url,
37
- :verbose => options[:verbose],
38
- :params => {
39
- :cmd => 'listCategories',
40
- :token => api_token })
41
- if response.code != 200
32
+ uri = URI format("#{api_url}?cmd=listCategories&token=%s", URI.escape(api_token))
33
+ http = Net::HTTP.new(uri.host, uri.port)
34
+ if uri.scheme == 'https'
35
+ http.use_ssl = true
36
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
37
+ end
38
+ response = http.start { |h| h.request Net::HTTP::Get.new(uri.request_uri) }
39
+ if response.code != '200'
42
40
  puts "HTTP request to #{api_url} failed with code #{response.code}."
43
41
  exit 1
44
42
  end
45
43
 
46
- result = XML::Parser.string(response.body).parse
47
- error = result.find_first('/response/error')
44
+ result = REXML::Document.new(response.body)
45
+ error = result.elements['/response/error']
48
46
  if error
49
- puts "Failed with error: #{error.content}."
47
+ puts "Failed with error: #{error.text}."
50
48
  exit 1
51
49
  end
52
50
 
53
- result.find('/response/categories/category').each do |status|
54
- puts status.find_first('sCategory').content
51
+ result.elements.each('/response/categories/category') do |category|
52
+ puts category.elements['sCategory'].text
55
53
  end
data/bin/fogbugz-close CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'rubygems'
4
- require 'typhoeus'
5
- require 'xml'
4
+ require 'net/https'
5
+ require 'uri'
6
+ require 'rexml/document'
6
7
  require 'optparse'
7
8
 
8
9
  api_url = ENV['FOGBUGZ_API_URL']
@@ -12,7 +13,7 @@ unless api_url
12
13
  end
13
14
 
14
15
  api_token = ENV['FOGBUGZ_API_TOKEN']
15
- unless api_url
16
+ unless api_token
16
17
  puts "Environment variable FOGBUGZ_API_TOKEN must be set."
17
18
  exit 1
18
19
  end
@@ -21,11 +22,6 @@ options = {}
21
22
  optparse = OptionParser.new do |opts|
22
23
  opts.banner = "usage: #{File::basename(__FILE__)} [options] <case>"
23
24
 
24
- options[:verbose] = false
25
- opts.on('-v', '--verbose', 'Output verbose debugging information.') do
26
- options[:verbose] = true
27
- end
28
-
29
25
  opts.on_tail('-h', '--help') do
30
26
  puts optparse.help
31
27
  exit 1
@@ -38,20 +34,22 @@ unless ARGV[0]
38
34
  exit 1
39
35
  end
40
36
 
41
- response = Typhoeus::Request.get(api_url,
42
- :verbose => options[:verbose],
43
- :params => {
44
- :cmd => 'listAreas',
45
- :token => api_token,
46
- :ixBug => ARGV[0] })
47
- if response.code != 200
37
+ uri = URI format("#{api_url}?cmd=close&token=%s&ixBug=%s",
38
+ URI.escape(api_token), URI.escape(ARGV[0]))
39
+ http = Net::HTTP.new(uri.host, uri.port)
40
+ if uri.scheme == 'https'
41
+ http.use_ssl = true
42
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
43
+ end
44
+ response = http.start { |h| h.request Net::HTTP::Get.new(uri.request_uri) }
45
+ if response.code != '200'
48
46
  puts "HTTP request to #{api_url} failed with code #{response.code}."
49
47
  exit 1
50
48
  end
51
49
 
52
- result = XML::Parser.string(response.body).parse
53
- error = result.find_first('/response/error')
50
+ result = REXML::Document.new(response.body)
51
+ error = result.elements['/response/error']
54
52
  if error
55
- puts "Failed with error: #{error.content}."
53
+ puts "Failed with error: #{error.text}."
56
54
  exit 1
57
55
  end
data/bin/fogbugz-edit CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'rubygems'
4
- require 'typhoeus'
5
- require 'xml'
4
+ require 'net/https'
5
+ require 'uri'
6
+ require 'rexml/document'
6
7
  require 'tempfile'
7
8
  require 'optparse'
8
9
  require 'yaml'
@@ -15,7 +16,7 @@ unless api_url
15
16
  end
16
17
 
17
18
  api_token = ENV['FOGBUGZ_API_TOKEN']
18
- unless api_url
19
+ unless api_token
19
20
  puts "Environment variable FOGBUGZ_API_TOKEN must be set."
20
21
  exit 1
21
22
  end
@@ -26,11 +27,6 @@ options = {}
26
27
  optparse = OptionParser.new do |opts|
27
28
  opts.banner = "usage: #{File::basename(__FILE__)} [options] <case>"
28
29
 
29
- options[:verbose] = false
30
- opts.on('-v', '--verbose', 'Output verbose debugging information') do
31
- options[:verbose] = true
32
- end
33
-
34
30
  opts.on_tail('-h', '--help') do
35
31
  puts optparse.help
36
32
  exit 1
@@ -56,26 +52,28 @@ unless ARGV.length == 1
56
52
  end
57
53
  case_id = ARGV[0]
58
54
 
59
- response = Typhoeus::Request.get(api_url,
60
- :verbose => options[:verbose],
61
- :params => {
62
- :cmd => 'search',
63
- :token => api_token,
64
- :cols => 'ixBug,ixBugParent,tags,sTitle,sProject,sArea,sFixFor,sCategory,sPersonAssignedTo,sPriority,hrsCurrEst,events',
65
- :q => case_id })
66
- if response.code != 200
55
+ uri = URI format("#{api_url}?cmd=search&token=%s&cols=%s&q=%s&max=1",
56
+ URI.escape(api_token), URI.escape('ixBug,ixBugParent,tags,sTitle,sProject,sArea,sFixFor,sCategory,sPersonAssignedTo,sPriority,hrsCurrEst,events'),
57
+ URI.escape(case_id))
58
+ http = Net::HTTP.new(uri.host, uri.port)
59
+ if uri.scheme == 'https'
60
+ http.use_ssl = true
61
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
62
+ end
63
+ response = http.start { |h| h.request Net::HTTP::Get.new(uri.request_uri) }
64
+ if response.code != '200'
67
65
  puts "HTTP request to #{api_url} failed with code #{response.code}."
68
66
  exit 1
69
67
  end
70
68
 
71
- result = XML::Parser.string(response.body).parse
72
- error = result.find_first('/response/error')
69
+ result = REXML::Document.new(response.body)
70
+ error = result.elements['/response/error']
73
71
  if error
74
- puts "Failed with error: #{error.content}."
72
+ puts "Failed with error: #{error.text}."
75
73
  exit 1
76
74
  end
77
75
 
78
- bug = result.find_first("/response/cases/case[@ixBug='#{case_id}']")
76
+ bug = result.elements["/response/cases/case[@ixBug='#{case_id}']"]
79
77
  unless bug
80
78
  puts "Case #{case_id} does not exist."
81
79
  exit 1
@@ -103,99 +101,99 @@ else
103
101
  # Fill in metadata for the case.
104
102
  HERE
105
103
 
106
- sTitle = bug.find_first('sTitle')
107
- if sTitle and sTitle.content and not sTitle.content.empty?
108
- template << "# title: #{sTitle.content}\n"
104
+ sTitle = bug.elements['sTitle']
105
+ if sTitle and sTitle.text and not sTitle.text.empty?
106
+ template << "# title: #{sTitle.text}\n"
109
107
  else
110
108
  template << "# title: <title>\n"
111
109
  end
112
110
 
113
- sPersonAssignedTo = bug.find_first('sPersonAssignedTo')
114
- if sPersonAssignedTo and sPersonAssignedTo.content and
115
- not sPersonAssignedTo.content.empty?
116
- template << "# assignee: #{sPersonAssignedTo.content}\n"
111
+ sPersonAssignedTo = bug.elements['sPersonAssignedTo']
112
+ if sPersonAssignedTo and sPersonAssignedTo.text and
113
+ not sPersonAssignedTo.text.empty?
114
+ template << "# assignee: #{sPersonAssignedTo.text}\n"
117
115
  else
118
116
  template << "# assignee: <person>\n"
119
117
  end
120
118
 
121
- ixBugParent = bug.find_first('ixBugParent')
122
- if ixBugParent and ixBugParent.content and not ixBugParent.content.empty? and
123
- ixBugParent.content != '0'
124
- template << "# parent: #{ixBugParent.content}\n"
119
+ ixBugParent = bug.elements['ixBugParent']
120
+ if ixBugParent and ixBugParent.text and not ixBugParent.text.empty? and
121
+ ixBugParent.text != '0'
122
+ template << "# parent: #{ixBugParent.text}\n"
125
123
  else
126
124
  template << "# parent: <case>\n"
127
125
  end
128
126
 
129
- tags = bug.find('tags/tag').collect { |tag| tag.content }
127
+ tags = bug.elements.collect('tags/tag') { |tag| tag.text }
130
128
  if tags and not tags.empty?
131
129
  template << "# tags: [#{tags.join(', ')}]\n"
132
130
  else
133
131
  template << "# tags: [bug, enhancement]\n"
134
132
  end
135
133
 
136
- sProject = bug.find_first('sProject')
137
- if sProject and sProject.content and not sProject.content.empty?
138
- template << "# project: #{sProject.content}\n"
134
+ sProject = bug.elements['sProject']
135
+ if sProject and sProject.text and not sProject.text.empty?
136
+ template << "# project: #{sProject.text}\n"
139
137
  else
140
138
  template << "# project: <project>\n"
141
139
  end
142
140
 
143
- sArea = bug.find_first('sArea')
144
- if sArea and sArea.content and not sArea.content.empty?
145
- template << "# area: #{sArea.content}\n"
141
+ sArea = bug.elements['sArea']
142
+ if sArea and sArea.text and not sArea.text.empty?
143
+ template << "# area: #{sArea.text}\n"
146
144
  else
147
145
  template << "# area: <area>\n"
148
146
  end
149
147
 
150
- sFixFor = bug.find_first('sFixFor')
151
- if sFixFor and sFixFor.content and not sFixFor.content.empty?
152
- template << "# milestone: #{sFixFor.content}\n"
148
+ sFixFor = bug.elements['sFixFor']
149
+ if sFixFor and sFixFor.text and not sFixFor.text.empty?
150
+ template << "# milestone: #{sFixFor.text}\n"
153
151
  else
154
152
  template << "# milestone: <milestone>"
155
153
  end
156
154
 
157
- sCategory = bug.find_first('sCategory')
158
- if sCategory and sCategory.content and not sCategory.content.empty?
159
- template << "# category: #{sCategory.content}\n"
155
+ sCategory = bug.elements['sCategory']
156
+ if sCategory and sCategory.text and not sCategory.text.empty?
157
+ template << "# category: #{sCategory.text}\n"
160
158
  else
161
159
  template << "# category: <category>"
162
160
  end
163
161
 
164
- sPriority = bug.find_first('sPriority')
165
- if sPriority and sPriority.content and not sPriority.content.empty?
166
- template << "# priority: #{sPriority.content}\n"
162
+ sPriority = bug.elements['sPriority']
163
+ if sPriority and sPriority.text and not sPriority.text.empty?
164
+ template << "# priority: #{sPriority.text}\n"
167
165
  else
168
166
  template << "# priority: <priority>"
169
167
  end
170
168
 
171
- hrsCurrEst = bug.find_first('hrsCurrEst')
172
- if hrsCurrEst and hrsCurrEst.content and not hrsCurrEst.content.empty? and
173
- hrsCurrEst.content != '0'
174
- template << "# estimate: #{hrsCurrEst.content}\n"
169
+ hrsCurrEst = bug.elements['hrsCurrEst']
170
+ if hrsCurrEst and hrsCurrEst.text and not hrsCurrEst.text.empty? and
171
+ hrsCurrEst.text != '0'
172
+ template << "# estimate: #{hrsCurrEst.text}\n"
175
173
  else
176
174
  template << "# estimate: <estimate>\n"
177
175
  end
178
176
 
179
177
  template << "\n"
180
- bug.find('events/event').each do |event|
181
- evtDescription = event.find_first('evtDescription')
182
- if evtDescription and evtDescription.content and
183
- not evtDescription.content.empty?
184
- time = Time.parse(event.find_first('dt').content).localtime
185
- template << format("# %s at %s on %s.\n", evtDescription.content,
178
+ bug.elements.each('events/event') do |event|
179
+ evtDescription = event.elements['evtDescription']
180
+ if evtDescription and evtDescription.text and
181
+ not evtDescription.text.empty?
182
+ time = Time.parse(event.elements['dt'].text).localtime
183
+ template << format("# %s at %s on %s.\n", evtDescription.text,
186
184
  time.strftime('%-l:%M %p'),
187
185
  time.strftime('%A, %B %e %Y'))
188
186
  end
189
187
 
190
- sChanges = event.find_first('sChanges')
191
- if sChanges and sChanges.content and not sChanges.content.empty?
192
- commented = sChanges.content.gsub(/\n/, "\n# ")
188
+ sChanges = event.elements['sChanges']
189
+ if sChanges and sChanges.text and not sChanges.text.empty?
190
+ commented = sChanges.text.gsub(/\n/, "\n# ")
193
191
  template << "# #{commented}\n"
194
192
  end
195
193
 
196
- summary = event.find_first('s')
197
- if summary and summary.content and not summary.content.empty?
198
- commented = summary.content.gsub(/\n/, "\n# ")
194
+ summary = event.elements['s']
195
+ if summary and summary.text and not summary.text.empty?
196
+ commented = summary.text.gsub(/\n/, "\n# ")
199
197
  template << "# #{commented}\n"
200
198
  end
201
199
  template << "\n"
@@ -251,31 +249,33 @@ if not data or data.empty?
251
249
  exit 1
252
250
  end
253
251
 
254
- response = Typhoeus::Request.get(api_url,
255
- :verbose => options[:verbose],
256
- :params => {
257
- :cmd => 'edit',
258
- :token => api_token,
259
- :ixBug => case_id,
260
- :sTitle => data['title'],
261
- :ixBugParent => data['parent'],
262
- :sTags => data['tags'] ? data['tags'].join(',') : nil,
263
- :sProject => data['project'],
264
- :sArea => data['area'],
265
- :sFixFor => data['milestone'],
266
- :sCategory => data['category'],
267
- :sPersonAssignedTo => data['assignee'],
268
- :sPriority => data['priority'],
269
- :hrsCurrEst => data['estimate'],
270
- :sEvent => data['body'] })
271
- if response.code != 200
252
+ uri = URI format("#{api_url}?cmd=edit&token=%s&ixBug=%s%s%s%s%s%s%s%s%s%s%s%s",
253
+ URI.escape(api_token), URI.escape(case_id),
254
+ data['title'] ? URI.escape(data['title'].to_s) : '',
255
+ data['parent'] ? URI.escape(data['parent'].to_s) : '',
256
+ data['tags'] ? URI.escape(data['tags'].join(',')) : '',
257
+ data['project'] ? URI.escape(data['project'].to_s) : '',
258
+ data['area'] ? URI.escape(data['area'].to_s) : '',
259
+ data['milestone'] ? URI.escape(data['milestone'].to_s) : '',
260
+ data['category'] ? URI.escape(data['category'].to_s) : '',
261
+ data['assignee'] ? URI.escape(data['assignee'].to_s) : '',
262
+ data['priority'] ? URI.escape(data['priority'].to_s) : '',
263
+ data['estimate'] ? URI.escape(data['estimate'].to_s) : '',
264
+ data['body'] ? URI.escape(data['body'].to_s) : '')
265
+ http = Net::HTTP.new(uri.host, uri.port)
266
+ if uri.scheme == 'https'
267
+ http.use_ssl = true
268
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
269
+ end
270
+ response = http.start { |h| h.request Net::HTTP::Get.new(uri.request_uri) }
271
+ if response.code != '200'
272
272
  puts "HTTP request to #{api_url} failed with code #{response.code}."
273
273
  exit 1
274
274
  end
275
275
 
276
- result = XML::Parser.string(response.body).parse
277
- error = result.find_first('/response/error')
276
+ result = REXML::Document.new(response.body)
277
+ error = result.elements['/response/error']
278
278
  if error
279
- puts "Failed with error: #{error.content}."
279
+ puts "Failed with error: #{error.text}."
280
280
  exit 1
281
281
  end