fogbugz 1.0.1 → 1.0.2

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/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