bicho 0.0.10 → 0.0.12

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.
@@ -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
- sprintf(format_string, sym_data)
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
@@ -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
- opts = Trollop.with_standard_exception_handling(self.class.parser) do
82
- o = self.class.parser.parse ARGV
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
- fail RuntimeError, "No implementation for #{self.class}" if self.class =~ /CommandTemplate/
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|
@@ -30,6 +30,7 @@ require 'bicho/query'
30
30
  require 'pp'
31
31
 
32
32
  module Bicho::CLI::Commands
33
+ # Command to search for bugs.
33
34
  class Search < ::Bicho::CLI::Command
34
35
  options do
35
36
  # add all fields as command line options of this command
@@ -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}'", :type => :string
33
+ opt :format, "Format string, eg. '%{id}:%{priority}:%{summary}'", type: :string
33
34
  end
34
35
 
35
36
  def do(global_opts, opts, args)
@@ -26,6 +26,7 @@
26
26
  require 'bicho/cli/command'
27
27
 
28
28
  module Bicho::CLI::Commands
29
+ # Command to display Bicho's version.
29
30
  class Version < ::Bicho::CLI::Command
30
31
  def do(_global_opts, _opts, _args)
31
32
  t.say(Bicho::VERSION)
@@ -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
- fail NoMethodError
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
- fail ArgumentError, 'missing bugzilla site' if site_url.nil?
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', 'login' => @client.user, 'password' => @client.password, 'remember' => 0)
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
- load plugin
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["version"]
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 (redirects_left == 0)
242
- fail "Maximum redirects exceeded (redirected to #{location})"
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
- fail "Error when expanding named query '#{url.request_uri}': #{response}"
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("Bug.history", params)
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
@@ -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 || (fail 'No common client set')
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
- class Logger
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 'ANY', 'UNKNOWN')].to_s.upcase
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[#{ color }m#{ format_message_colorless(level, *args) }\e[0;0m"
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
@@ -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 date
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
- changesets.each
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
 
@@ -26,6 +26,7 @@ require 'logger'
26
26
  require 'bicho/ext/logger_colors'
27
27
 
28
28
  module Bicho
29
+ # All logging related classes go into this module.
29
30
  module Logging
30
31
  class << self
31
32
  attr_writer :logger
@@ -1,6 +1,6 @@
1
1
  module Bicho
2
2
  module Plugins
3
-
3
+ # This plugin allows to specify shortcuts for bugzilla urls
4
4
  class Aliases
5
5
  def transform_site_url_hook(url, _logger)
6
6
  case url.to_s
@@ -11,6 +11,5 @@ module Bicho
11
11
  end
12
12
  end
13
13
  end
14
-
15
14
  end
16
15
  end