bicho 0.0.10 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -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