bicho 0.0.10 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +21 -93
- data/.travis.yml +7 -0
- data/{README.rdoc → README.md} +58 -42
- data/Rakefile +10 -12
- data/bicho.gemspec +5 -0
- data/bin/bicho +9 -5
- data/lib/bicho.rb +2 -1
- data/lib/bicho/attachment.rb +72 -0
- data/lib/bicho/bug.rb +8 -2
- data/lib/bicho/cli/command.rb +3 -3
- data/lib/bicho/cli/commands/attachments.rb +75 -0
- data/lib/bicho/cli/commands/history.rb +0 -1
- data/lib/bicho/cli/commands/search.rb +1 -0
- data/lib/bicho/cli/commands/show.rb +2 -1
- data/lib/bicho/cli/commands/version.rb +1 -0
- data/lib/bicho/client.rb +36 -13
- data/lib/bicho/common_client.rb +2 -1
- data/lib/bicho/ext/logger_colors.rb +23 -24
- data/lib/bicho/history.rb +12 -6
- data/lib/bicho/logging.rb +1 -0
- data/lib/bicho/plugins/aliases.rb +1 -2
- data/lib/bicho/plugins/novell.rb +15 -13
- data/lib/bicho/plugins/user.rb +4 -8
- data/lib/bicho/query.rb +2 -4
- data/lib/bicho/version.rb +1 -1
- data/test/helper.rb +8 -1
- data/test/test_attachments.rb +30 -0
- data/test/test_history.rb +10 -4
- data/test/test_novell_plugin.rb +26 -24
- data/test/test_query.rb +6 -5
- data/test/test_user_plugin.rb +1 -2
- data/test/test_version.rb +8 -9
- metadata +64 -3
data/lib/bicho/bug.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'bicho/query'
|
2
2
|
|
3
3
|
module Bicho
|
4
|
+
# A single bug inside a bugzilla instance.
|
4
5
|
class Bug
|
5
6
|
# ActiveRecord like interface
|
6
7
|
#
|
@@ -86,10 +87,15 @@ module Bicho
|
|
86
87
|
@client.get_history(id).first
|
87
88
|
end
|
88
89
|
|
90
|
+
# @return [Array<Attachment>] attachments for this bug
|
91
|
+
def attachments
|
92
|
+
@client.get_attachments(id)
|
93
|
+
end
|
94
|
+
|
89
95
|
# @param format_string For Kernel#sprintf; named params supplied by the bug
|
90
96
|
def format(format_string)
|
91
|
-
sym_data = Hash[@data.to_a.map { |k, v| [k.to_sym, v]}]
|
92
|
-
|
97
|
+
sym_data = Hash[@data.to_a.map { |k, v| [k.to_sym, v] }]
|
98
|
+
Kernel.format(format_string, sym_data)
|
93
99
|
end
|
94
100
|
end
|
95
101
|
end
|
data/lib/bicho/cli/command.rb
CHANGED
@@ -78,8 +78,8 @@ module Bicho
|
|
78
78
|
# with current ARGV
|
79
79
|
def parse_options
|
80
80
|
self.class.parser = Trollop::Parser.new unless self.class.parser
|
81
|
-
|
82
|
-
|
81
|
+
Trollop.with_standard_exception_handling(self.class.parser) do
|
82
|
+
self.class.parser.parse ARGV
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -88,7 +88,7 @@ module Bicho
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def do(_opts, _args)
|
91
|
-
|
91
|
+
raise "No implementation for #{self.class}" if self.class =~ /CommandTemplate/
|
92
92
|
end
|
93
93
|
end
|
94
94
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2011 SUSE LINUX Products GmbH
|
3
|
+
#
|
4
|
+
# Author: Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
# a copy of this software and associated documentation files (the
|
8
|
+
# "Software"), to deal in the Software without restriction, including
|
9
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
# the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be
|
15
|
+
# included in all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#++
|
25
|
+
|
26
|
+
require 'bicho/cli/command'
|
27
|
+
require 'bicho/client'
|
28
|
+
|
29
|
+
module Bicho::CLI::Commands
|
30
|
+
# Command to display bug information.
|
31
|
+
class Attachments < ::Bicho::CLI::Command
|
32
|
+
private
|
33
|
+
|
34
|
+
# check for supportconfigs and download
|
35
|
+
def download(bug, supportconfig_only)
|
36
|
+
bug.attachments.each do |attachment|
|
37
|
+
filename = "bsc#{bug.id}-#{attachment.id}-#{attachment.props['file_name']}"
|
38
|
+
if supportconfig_only
|
39
|
+
next unless attachment.content_type == 'application/x-gzip' ||
|
40
|
+
attachment.content_type == 'application/x-bzip-compressed-tar'
|
41
|
+
next unless attachment.summary =~ /supportconfig/i
|
42
|
+
end
|
43
|
+
t.say("Downloading to #{t.color(filename, :even_row)}")
|
44
|
+
begin
|
45
|
+
data = attachment.data
|
46
|
+
File.open(filename, 'w') do |f|
|
47
|
+
f.write data.read
|
48
|
+
end
|
49
|
+
rescue StandardError => e
|
50
|
+
t.say("#{t.color('Error:', :error)} Download of #{filename} failed: #{e}")
|
51
|
+
raise
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
public
|
57
|
+
|
58
|
+
options do
|
59
|
+
opt :download, 'Download attachments'
|
60
|
+
opt :supportconfig, 'Only download supportconfig attachments'
|
61
|
+
end
|
62
|
+
|
63
|
+
def do(global_opts, opts, args)
|
64
|
+
client = ::Bicho::Client.new(global_opts[:bugzilla])
|
65
|
+
client.get_bugs(*args).each do |bug|
|
66
|
+
if opts[:download]
|
67
|
+
download(bug, opts[:supportconfig])
|
68
|
+
else
|
69
|
+
t.say("Bug #{t.color(bug.id.to_s, :headline)} has #{bug.attachments.size} attachments")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
0
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -31,7 +31,6 @@ module Bicho::CLI::Commands
|
|
31
31
|
# command that shows the history colored as a
|
32
32
|
# changelog
|
33
33
|
class History < ::Bicho::CLI::Command
|
34
|
-
|
35
34
|
def do(global_opts, _opts, args)
|
36
35
|
client = ::Bicho::Client.new(global_opts[:bugzilla])
|
37
36
|
client.get_history(*args).each do |history|
|
@@ -27,9 +27,10 @@ require 'bicho/cli/command'
|
|
27
27
|
require 'bicho/client'
|
28
28
|
|
29
29
|
module Bicho::CLI::Commands
|
30
|
+
# Command to display bug information.
|
30
31
|
class Show < ::Bicho::CLI::Command
|
31
32
|
options do
|
32
|
-
opt :format, "Format string, eg. '%{id}:%{priority}:%{summary}'", :
|
33
|
+
opt :format, "Format string, eg. '%{id}:%{priority}:%{summary}'", type: :string
|
33
34
|
end
|
34
35
|
|
35
36
|
def do(global_opts, opts, args)
|
data/lib/bicho/client.rb
CHANGED
@@ -29,6 +29,7 @@ require 'nokogiri'
|
|
29
29
|
require 'net/https'
|
30
30
|
require 'cgi'
|
31
31
|
|
32
|
+
require 'bicho/attachment'
|
32
33
|
require 'bicho/bug'
|
33
34
|
require 'bicho/history'
|
34
35
|
require 'bicho/query'
|
@@ -54,6 +55,7 @@ class XMLRPC::Client
|
|
54
55
|
end
|
55
56
|
|
56
57
|
module Bicho
|
58
|
+
# Plugins are defined inside this module
|
57
59
|
module Plugins
|
58
60
|
end
|
59
61
|
|
@@ -85,7 +87,7 @@ module Bicho
|
|
85
87
|
# APIs
|
86
88
|
def url
|
87
89
|
warn 'url is deprecated. Use site_url or api_url'
|
88
|
-
|
90
|
+
raise NoMethodError
|
89
91
|
end
|
90
92
|
|
91
93
|
# @param [String] site_url Bugzilla installation site url
|
@@ -104,7 +106,7 @@ module Bicho
|
|
104
106
|
end
|
105
107
|
|
106
108
|
# If the default url is still null, we can't continue
|
107
|
-
|
109
|
+
raise ArgumentError, 'missing bugzilla site' if site_url.nil?
|
108
110
|
|
109
111
|
@plugins.each do |pl_instance|
|
110
112
|
if pl_instance.respond_to?(:transform_site_url_hook)
|
@@ -132,7 +134,7 @@ module Bicho
|
|
132
134
|
|
133
135
|
# User.login sets the credentials cookie for subsequent calls
|
134
136
|
if @client.user && @client.password
|
135
|
-
ret = @client.call('User.login',
|
137
|
+
ret = @client.call('User.login', 'login' => @client.user, 'password' => @client.password, 'remember' => 0)
|
136
138
|
handle_faults(ret)
|
137
139
|
@userid = ret['id']
|
138
140
|
end
|
@@ -144,14 +146,13 @@ module Bicho
|
|
144
146
|
plugin_glob = File.join(File.dirname(__FILE__), 'plugins', '*.rb')
|
145
147
|
Dir.glob(plugin_glob).each do |plugin|
|
146
148
|
logger.debug("Loading file: #{plugin}")
|
147
|
-
|
149
|
+
require plugin
|
148
150
|
end
|
149
151
|
end
|
150
152
|
|
151
153
|
# instantiate all plugin classes in the Bicho::Plugins
|
152
154
|
# module and add them to the list of known plugins
|
153
155
|
def instantiate_plugins!
|
154
|
-
# instantiate plugins
|
155
156
|
::Bicho::Plugins.constants.each do |cnt|
|
156
157
|
pl_class = ::Bicho::Plugins.const_get(cnt)
|
157
158
|
pl_instance = pl_class.new
|
@@ -176,8 +177,9 @@ module Bicho
|
|
176
177
|
def version
|
177
178
|
ret = @client.call('Bugzilla.version')
|
178
179
|
handle_faults(ret)
|
179
|
-
ret[
|
180
|
+
ret['version']
|
180
181
|
end
|
182
|
+
|
181
183
|
# Search for a bug
|
182
184
|
#
|
183
185
|
# +query+ has to be either a +Query+ object or
|
@@ -212,9 +214,7 @@ module Bicho
|
|
212
214
|
# @private
|
213
215
|
# @returns [Array<String>] list of bugs
|
214
216
|
def fetch_named_query_url(url, redirects_left)
|
215
|
-
unless @userid
|
216
|
-
fail 'You need to be authenticated to use named queries'
|
217
|
-
end
|
217
|
+
raise 'You need to be authenticated to use named queries' unless @userid
|
218
218
|
http = Net::HTTP.new(@api_url.host, @api_url.port)
|
219
219
|
http.set_debug_output(Bicho::LoggerIODevice.new)
|
220
220
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
@@ -238,14 +238,14 @@ module Bicho
|
|
238
238
|
end
|
239
239
|
when Net::HTTPRedirection
|
240
240
|
location = response['location']
|
241
|
-
if
|
242
|
-
|
241
|
+
if redirects_left == 0
|
242
|
+
raise "Maximum redirects exceeded (redirected to #{location})"
|
243
243
|
end
|
244
244
|
new_location_uri = URI.parse(location)
|
245
245
|
logger.debug("Moved to #{new_location_uri}")
|
246
246
|
fetch_named_query_url(new_location_uri, redirects_left - 1)
|
247
247
|
else
|
248
|
-
|
248
|
+
raise "Error when expanding named query '#{url.request_uri}': #{response}"
|
249
249
|
end
|
250
250
|
end
|
251
251
|
|
@@ -288,7 +288,7 @@ module Bicho
|
|
288
288
|
end.flatten
|
289
289
|
|
290
290
|
histories = []
|
291
|
-
ret = @client.call(
|
291
|
+
ret = @client.call('Bug.history', params)
|
292
292
|
handle_faults(ret)
|
293
293
|
ret['bugs'].each do |history_data|
|
294
294
|
histories << History.new(self, history_data)
|
@@ -296,5 +296,28 @@ module Bicho
|
|
296
296
|
histories
|
297
297
|
end
|
298
298
|
|
299
|
+
# @return [Array<Attachment>] a list of attachments for the
|
300
|
+
# given bugs.
|
301
|
+
#
|
302
|
+
# Payload is lazy-loaded
|
303
|
+
def get_attachments(*ids)
|
304
|
+
params = {}
|
305
|
+
params[:ids] = ids.collect(&:to_s).map do |what|
|
306
|
+
if what =~ /^[0-9]+$/
|
307
|
+
next what.to_i
|
308
|
+
else
|
309
|
+
next expand_named_query(what)
|
310
|
+
end
|
311
|
+
end.flatten
|
312
|
+
|
313
|
+
ret = @client.call('Bug.attachments',
|
314
|
+
params.merge(exclude_fields: ['data']))
|
315
|
+
handle_faults(ret)
|
316
|
+
ret['bugs'].map do |_, attachments_data|
|
317
|
+
attachments_data.map do |attachment_data|
|
318
|
+
Attachment.new(self, @client, attachment_data)
|
319
|
+
end
|
320
|
+
end.flatten
|
321
|
+
end
|
299
322
|
end
|
300
323
|
end
|
data/lib/bicho/common_client.rb
CHANGED
@@ -24,6 +24,7 @@
|
|
24
24
|
#++
|
25
25
|
require 'logger'
|
26
26
|
|
27
|
+
# All classes go into this module.
|
27
28
|
module Bicho
|
28
29
|
# This module allows the [Bug] and other
|
29
30
|
# classes to offer an ActiveRecord like query
|
@@ -35,7 +36,7 @@ module Bicho
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def self.common_client
|
38
|
-
@common_client
|
39
|
+
@common_client ||= (raise 'No common client set')
|
39
40
|
end
|
40
41
|
|
41
42
|
def common_client
|
@@ -3,47 +3,46 @@
|
|
3
3
|
|
4
4
|
require 'logger'
|
5
5
|
|
6
|
+
# Utility class to color output.
|
6
7
|
class Logger
|
7
8
|
module Colors
|
8
|
-
VERSION = '1.0.0'
|
9
|
+
VERSION = '1.0.0'.freeze
|
9
10
|
|
10
|
-
NOTHING = '0;0'
|
11
|
-
BLACK = '0;30'
|
12
|
-
RED = '0;31'
|
13
|
-
GREEN = '0;32'
|
14
|
-
BROWN = '0;33'
|
15
|
-
BLUE = '0;34'
|
16
|
-
PURPLE = '0;35'
|
17
|
-
CYAN = '0;36'
|
18
|
-
LIGHT_GRAY = '0;37'
|
19
|
-
DARK_GRAY = '1;30'
|
20
|
-
LIGHT_RED = '1;31'
|
21
|
-
LIGHT_GREEN = '1;32'
|
22
|
-
YELLOW = '1;33'
|
23
|
-
LIGHT_BLUE = '1;34'
|
24
|
-
LIGHT_PURPLE = '1;35'
|
25
|
-
LIGHT_CYAN = '1;36'
|
26
|
-
WHITE = '1;37'
|
11
|
+
NOTHING = '0;0'.freeze
|
12
|
+
BLACK = '0;30'.freeze
|
13
|
+
RED = '0;31'.freeze
|
14
|
+
GREEN = '0;32'.freeze
|
15
|
+
BROWN = '0;33'.freeze
|
16
|
+
BLUE = '0;34'.freeze
|
17
|
+
PURPLE = '0;35'.freeze
|
18
|
+
CYAN = '0;36'.freeze
|
19
|
+
LIGHT_GRAY = '0;37'.freeze
|
20
|
+
DARK_GRAY = '1;30'.freeze
|
21
|
+
LIGHT_RED = '1;31'.freeze
|
22
|
+
LIGHT_GREEN = '1;32'.freeze
|
23
|
+
YELLOW = '1;33'.freeze
|
24
|
+
LIGHT_BLUE = '1;34'.freeze
|
25
|
+
LIGHT_PURPLE = '1;35'.freeze
|
26
|
+
LIGHT_CYAN = '1;36'.freeze
|
27
|
+
WHITE = '1;37'.freeze
|
27
28
|
|
28
29
|
SCHEMA = {
|
29
30
|
STDOUT => %w(nothing green brown red purple cyan),
|
30
31
|
STDERR => %w(nothing green yellow light_red light_purple light_cyan)
|
31
|
-
}
|
32
|
+
}.freeze
|
32
33
|
end
|
33
|
-
end
|
34
34
|
|
35
|
-
|
36
|
-
alias_method :format_message_colorless, :format_message
|
35
|
+
alias format_message_colorless format_message
|
37
36
|
|
38
37
|
def format_message(level, *args)
|
39
38
|
if Logger::Colors::SCHEMA[@logdev.dev]
|
40
39
|
color = begin
|
41
40
|
Logger::Colors.const_get \
|
42
|
-
Logger::Colors::SCHEMA[@logdev.dev][Logger.const_get(level.sub
|
41
|
+
Logger::Colors::SCHEMA[@logdev.dev][Logger.const_get(level.sub('ANY', 'UNKNOWN'))].to_s.upcase
|
43
42
|
rescue NameError
|
44
43
|
'0;0'
|
45
44
|
end
|
46
|
-
"\e[#{
|
45
|
+
"\e[#{color}m#{format_message_colorless(level, *args)}\e[0;0m"
|
47
46
|
else
|
48
47
|
format_message_colorless(level, *args)
|
49
48
|
end
|
data/lib/bicho/history.rb
CHANGED
@@ -25,6 +25,9 @@
|
|
25
25
|
require 'stringio'
|
26
26
|
|
27
27
|
module Bicho
|
28
|
+
# Represents a single change inside a bug.
|
29
|
+
# History has multiple ChangeSets, and they have
|
30
|
+
# multiple changes.
|
28
31
|
class Change
|
29
32
|
def field_name
|
30
33
|
@data['field_name']
|
@@ -51,17 +54,19 @@ module Bicho
|
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
57
|
+
# A collection of related changes.
|
54
58
|
class ChangeSet
|
55
|
-
|
56
59
|
include Enumerable
|
57
60
|
|
61
|
+
# return [Date] The date the bug activity/change happened.
|
62
|
+
# @deprecated Use {#timestamp} instead
|
58
63
|
def date
|
59
64
|
warn 'Deprecated. Use timestamp instead'
|
60
65
|
timestamp
|
61
66
|
end
|
62
67
|
|
63
68
|
# return [Date] The date the bug activity/change happened.
|
64
|
-
def
|
69
|
+
def timestamp
|
65
70
|
@data['when'].to_date
|
66
71
|
end
|
67
72
|
|
@@ -98,7 +103,10 @@ module Bicho
|
|
98
103
|
|
99
104
|
# iterate over each changeset
|
100
105
|
def each
|
101
|
-
|
106
|
+
return enum_for(:each) unless block_given?
|
107
|
+
changesets.each do |c|
|
108
|
+
yield c
|
109
|
+
end
|
102
110
|
end
|
103
111
|
|
104
112
|
# @return [Fixnum] number of changesets
|
@@ -122,9 +130,7 @@ module Bicho
|
|
122
130
|
|
123
131
|
# @return [String] The numeric id of the bug
|
124
132
|
def bug
|
125
|
-
unless @bug
|
126
|
-
@bug = @client.get_bug(@data['id'])
|
127
|
-
end
|
133
|
+
@bug = @client.get_bug(@data['id']) unless @bug
|
128
134
|
@bug
|
129
135
|
end
|
130
136
|
|
data/lib/bicho/logging.rb
CHANGED