sshkit 0.0.25 → 0.0.26

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cbb3f36f6373d515b4313fc92514655ba7ca36e0
4
+ data.tar.gz: 484fd64e12a264d5bdaffe1e0a680194739930c5
5
+ SHA512:
6
+ metadata.gz: e2d81fb0548c2a2d66763cb9a3ca7afa71753955264da34a8d5c9c6b83cefbaa2a073970f3a4059d87597f3c6998d57c687cdedbf596dbcd6a7efb099725e675
7
+ data.tar.gz: 3c2e49e6cff7cc951097ece2084824ea7350a3d36bb34008a82ce3b14af31b420d9019c5e71c6b9a5cae0217f30f0a70cc70264ea437b994345bd3609391798f
data/.travis.yml CHANGED
@@ -2,5 +2,6 @@ before_install: echo 'yes' | gem uninstall ffi -a -I || true
2
2
  language: ruby
3
3
  rvm:
4
4
  - 1.9.3
5
+ - 2.0.0
5
6
  - jruby-19mode
6
7
  - rbx-19mode
data/CHANGELOG.md CHANGED
@@ -3,6 +3,21 @@
3
3
  This file is written in reverse chronological order, newer releases will
4
4
  appear at the top.
5
5
 
6
+ ## 0.0.26
7
+
8
+ * Pretty output no longer prints white text. ("Command.....")
9
+ * Fixed a double-output bug, where upon receiving the exit status from a
10
+ remote command, the last data packet that it sent would be re-printed
11
+ by the pretty formatter.
12
+ * Integration tests now use an Ubuntu Precise 64 Vagrant base box.
13
+ * Additional host declaration syntax, `SSHKit::Host` can now take a hash of
14
+ host properties in addition to a number of new (common sense) DSN type
15
+ syntaxes.
16
+ * Changes to the constants used for logging, we no longer re-define a
17
+ `Logger::TRACE` constant on the global `Logger` class, rather everyhing
18
+ now uses `SSHKit::Logger` (Thanks to Rafa Garcia)
19
+ * Various syntax and documentation fixes.
20
+
6
21
  ## 0.0.25
7
22
 
8
23
  * `upload!` and `download!` now log to different levels depending on
@@ -34,7 +49,7 @@ appear at the top.
34
49
  * `upload!` and `download!` now print progress reports at the `Logger::INFO`
35
50
  verbosity level.
36
51
 
37
- ## 0.0.23
52
+ ## 0.0.23
38
53
 
39
54
  * Explicitly rely on `net-scp` gem.
40
55
 
@@ -166,7 +181,7 @@ appear at the top.
166
181
  can be used to set, for example a umask of `007` for allowing users with
167
182
  the same primary group to share code without stepping on eachother's toes.
168
183
 
169
- ## 0.0.13
184
+ ## 0.0.13
170
185
 
171
186
  * Correctly quote `as(user)` commands, previously it would expand to:
172
187
  `sudo su user -c /usr/bin/env echo "Hello World"`, in which the command to
@@ -220,7 +235,7 @@ descriptors and redirecting them. Programs that re-open, or otherwise
220
235
  manipulate their own file descriptors may lock up when the SSH session is
221
236
  disconnected, often they block writing to, or reading from stdin/out.
222
237
 
223
- ## 0.0.7
238
+ ## 0.0.7
224
239
 
225
240
  * DSL method `execute()` will now raise `SSHKit::Command::Failed` when the
226
241
  exit status is non-zero. The message of the exception will be whatever the
@@ -314,7 +329,7 @@ version `0.0.5`.
314
329
 
315
330
  * Refactor the runner classes into an abstract heirarchy.
316
331
 
317
- ## 0.0.2
332
+ ## 0.0.2
318
333
 
319
334
  * Include a *Pretty* formatter
320
335
  * Modify example to use Pretty formatter.
data/Vagrantfile CHANGED
@@ -5,15 +5,15 @@
5
5
  Vagrant::Config.run do |config|
6
6
 
7
7
  config.vm.define :one do |one|
8
- one.vm.box = "lucid32"
8
+ one.vm.box = "precise64"
9
9
  end
10
10
 
11
11
  config.vm.define :two do |one|
12
- one.vm.box = "lucid32"
12
+ one.vm.box = "precise64"
13
13
  end
14
14
 
15
15
  config.vm.define :three do |one|
16
- one.vm.box = "lucid32"
16
+ one.vm.box = "precise64"
17
17
  end
18
18
 
19
19
  end
data/lib/sshkit/all.rb CHANGED
@@ -8,6 +8,7 @@ require_relative 'command'
8
8
  require_relative 'configuration'
9
9
  require_relative 'coordinator'
10
10
 
11
+ require_relative 'logger'
11
12
  require_relative 'log_message'
12
13
 
13
14
  require_relative 'formatters/abstract'
@@ -42,6 +42,10 @@ module SSHKit
42
42
  output << LogMessage.new(Logger::DEBUG, messages)
43
43
  end
44
44
 
45
+ def trace(messages)
46
+ output << LogMessage.new(Logger::TRACE, messages)
47
+ end
48
+
45
49
  def make(commands=[])
46
50
  raise MethodUnavailableError
47
51
  end
@@ -2,6 +2,27 @@ require 'net/ssh'
2
2
  require 'net/scp'
3
3
 
4
4
  module SSHKit
5
+
6
+ class Logger
7
+
8
+ class Net::SSH::LogLevelShim
9
+ attr_reader :output
10
+ def initialize(output)
11
+ @output = output
12
+ end
13
+ def debug(args)
14
+ output << LogMessage.new(Logger::TRACE, args)
15
+ end
16
+ def error(args)
17
+ output << LogMessage.new(Logger::ERROR, args)
18
+ end
19
+ def lwarn(args)
20
+ output << LogMessage.new(Logger::WARN, args)
21
+ end
22
+ end
23
+
24
+ end
25
+
5
26
  module Backend
6
27
 
7
28
  class Netssh < Printer
@@ -90,8 +111,9 @@ module SSHKit
90
111
  output << cmd
91
112
  end
92
113
  chan.on_request("exit-status") do |ch, data|
93
- exit_status = data.read_long
94
- cmd.exit_status = exit_status
114
+ cmd.stdout = ''
115
+ cmd.stderr = ''
116
+ cmd.exit_status = data.read_long
95
117
  output << cmd
96
118
  end
97
119
  #chan.on_request("exit-signal") do |ch, data|
@@ -124,8 +146,7 @@ module SSHKit
124
146
  Net::SSH.start(
125
147
  host.hostname,
126
148
  host.username,
127
- port: host.port,
128
- password: host.password,
149
+ host.netssh_options
129
150
  )
130
151
  end
131
152
  end
@@ -106,8 +106,8 @@ module SSHKit
106
106
  args: args,
107
107
  options: options,
108
108
  exit_status: exit_status,
109
- stdout: stdout,
110
- stderr: stderr,
109
+ stdout: full_stdout,
110
+ stderr: full_stderr,
111
111
  started_at: @started_at,
112
112
  finished_at: @finished_at,
113
113
  runtime: runtime,
@@ -23,7 +23,7 @@ module SSHKit
23
23
  unless command.started?
24
24
  original_output << level(command.verbosity) + uuid(command) + "Running #{c.yellow(c.bold(String(command)))} on #{c.blue(command.host.to_s)}\n"
25
25
  if SSHKit.config.output_verbosity == Logger::DEBUG
26
- original_output << level(Logger::DEBUG) + uuid(command) + c.white("Command: #{c.blue(command.to_command)}") + "\n"
26
+ original_output << level(Logger::DEBUG) + uuid(command) + "Command: #{c.blue(command.to_command)}" + "\n"
27
27
  end
28
28
  end
29
29
 
data/lib/sshkit/host.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'etc'
1
2
  require 'ostruct'
2
3
 
3
4
  module SSHKit
@@ -6,34 +7,58 @@ module SSHKit
6
7
 
7
8
  class Host
8
9
 
9
- attr_reader :hostname, :port, :username
10
+ attr_accessor :password, :hostname, :port, :user
10
11
 
11
- attr_accessor :password
12
+ def key=(new_key)
13
+ @keys = [new_key]
14
+ end
12
15
 
13
- def initialize(host_string)
16
+ def keys=(new_keys)
17
+ @keys = new_keys
18
+ end
14
19
 
15
- suitable_parsers = [
16
- SimpleHostParser,
17
- HostWithPortParser,
18
- IPv6HostWithPortParser,
19
- HostWithUsernameParser,
20
- HostWithUsernameAndPortParser
21
- ].select do |p|
22
- p.suitable?(host_string)
23
- end
20
+ def keys
21
+ Array(@keys)
22
+ end
23
+
24
+ def initialize(host_string_or_options_hash)
25
+
26
+ unless host_string_or_options_hash.is_a?(Hash)
27
+ suitable_parsers = [
28
+ SimpleHostParser,
29
+ HostWithPortParser,
30
+ HostWithUsernameAndPortParser,
31
+ IPv6HostWithPortParser,
32
+ HostWithUsernameParser,
33
+ HostWithUsernameAndPortParser
34
+ ].select do |p|
35
+ p.suitable?(host_string_or_options_hash)
36
+ end
24
37
 
25
- if suitable_parsers.any?
26
- suitable_parsers.first.tap do |parser|
27
- @username, @hostname, @port = parser.new(host_string).attributes
38
+ if suitable_parsers.any?
39
+ suitable_parsers.first.tap do |parser|
40
+ @user, @hostname, @port = parser.new(host_string_or_options_hash).attributes
41
+ end
42
+ else
43
+ raise UnparsableHostStringError, "Cannot parse host string #{host_string_or_options_hash}"
28
44
  end
29
45
  else
30
- raise UnparsableHostStringError, "Cannot parse host string #{host_string}"
46
+ host_string_or_options_hash.each do |key, value|
47
+ if self.respond_to?("#{key}=")
48
+ send("#{key}=", value)
49
+ else
50
+ raise ArgumentError, "Unknown host property #{key}"
51
+ end
52
+ end
31
53
  end
32
-
33
54
  end
34
55
 
35
56
  def hash
36
- username.hash ^ hostname.hash ^ port.hash
57
+ user.hash ^ hostname.hash ^ port.hash
58
+ end
59
+
60
+ def username
61
+ user
37
62
  end
38
63
 
39
64
  def eql?(other_host)
@@ -50,6 +75,15 @@ module SSHKit
50
75
  sprintf("%s@%s:%d", username, hostname, port)
51
76
  end
52
77
 
78
+ def netssh_options
79
+ {
80
+ keys: keys,
81
+ port: port,
82
+ user: user,
83
+ password: password
84
+ }
85
+ end
86
+
53
87
  def properties
54
88
  @properties ||= OpenStruct.new
55
89
  end
@@ -69,7 +103,7 @@ module SSHKit
69
103
  end
70
104
 
71
105
  def username
72
- `whoami`.chomp
106
+ Etc.getlogin
73
107
  end
74
108
 
75
109
  def port
@@ -88,6 +122,26 @@ module SSHKit
88
122
 
89
123
  # @private
90
124
  # :nodoc:
125
+ class HostWithUsernameAndPortParser < SimpleHostParser
126
+
127
+ def self.suitable?(host_string)
128
+ !host_string.match /.*@.*\:.*/
129
+ end
130
+
131
+ def username
132
+ @host_string.split('@').last.to_i
133
+ end
134
+
135
+ def port
136
+ @host_string.split(':').last.to_i
137
+ end
138
+
139
+ def hostname
140
+ @host_string.split(/@|\:/)[1]
141
+ end
142
+
143
+ end
144
+
91
145
  class HostWithPortParser < SimpleHostParser
92
146
 
93
147
  def self.suitable?(host_string)
@@ -0,0 +1,10 @@
1
+ module SSHKit
2
+ class Logger
3
+ TRACE = -1
4
+ DEBUG = 0
5
+ INFO = 1
6
+ WARN = 2
7
+ ERROR = 3
8
+ FATAL = 4
9
+ end
10
+ end
@@ -1,3 +1,3 @@
1
1
  module SSHKit
2
- VERSION = "0.0.25"
2
+ VERSION = "0.0.26"
3
3
  end
@@ -17,6 +17,13 @@ module SSHKit
17
17
  assert_equal 'example.com', h.hostname
18
18
  end
19
19
 
20
+ def test_ipv4_with_username_and_port
21
+ h = Host.new 'user@127.0.0.1:2222'
22
+ assert_equal 2222, h.port
23
+ assert_equal 'user', h.username
24
+ assert_equal '127.0.0.1', h.hostname
25
+ end
26
+
20
27
  def test_host_with_port
21
28
  h = Host.new 'example.com:2222'
22
29
  assert_equal 2222, h.port
@@ -67,6 +74,31 @@ module SSHKit
67
74
  assert_equal [:web, :app], h.properties.roles
68
75
  end
69
76
 
77
+ def test_setting_up_a_host_with_a_hash
78
+ h = Host.new(hostname: 'example.com', port: 1234, key: "~/.ssh/example_com.key")
79
+ assert_equal "example.com", h.hostname
80
+ assert_equal 1234, h.port
81
+ assert_equal "~/.ssh/example_com.key", h.keys.first
82
+ end
83
+
84
+ def test_setting_up_a_host_with_a_hash_raises_on_unknown_keys
85
+ assert_raises ArgumentError do
86
+ Host.new({this_key_doesnt_exist: nil})
87
+ end
88
+ end
89
+
90
+ def test_turning_a_host_into_ssh_options
91
+ Host.new('someuser@example.com:2222').tap do |host|
92
+ host.password = "andthisdoesntevenmakeanysense"
93
+ host.keys = ["~/.ssh/some_key_here"]
94
+ host.netssh_options.tap do |sho|
95
+ assert_equal 2222, sho.fetch(:port)
96
+ assert_equal 'andthisdoesntevenmakeanysense', sho.fetch(:password)
97
+ assert_equal ['~/.ssh/some_key_here'], sho.fetch(:keys)
98
+ end
99
+ end
100
+ end
101
+
70
102
  end
71
103
 
72
104
  end
@@ -0,0 +1,18 @@
1
+ require 'helper'
2
+
3
+ module SSHKit
4
+
5
+ class TestLogger < UnitTest
6
+
7
+ def test_logger_severity_constants
8
+ assert_equal Logger::TRACE, -1
9
+ assert_equal Logger::DEBUG, 0
10
+ assert_equal Logger::INFO, 1
11
+ assert_equal Logger::WARN, 2
12
+ assert_equal Logger::ERROR, 3
13
+ assert_equal Logger::FATAL, 4
14
+ end
15
+
16
+ end
17
+
18
+ end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sshkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.25
5
- prerelease:
4
+ version: 0.0.26
6
5
  platform: ruby
7
6
  authors:
8
7
  - Lee Hambley
@@ -10,62 +9,55 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-04-04 00:00:00.000000000 Z
12
+ date: 2013-06-14 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: net-ssh
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ! '>='
18
+ - - '>='
21
19
  - !ruby/object:Gem::Version
22
20
  version: '0'
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
- - - ! '>='
25
+ - - '>='
29
26
  - !ruby/object:Gem::Version
30
27
  version: '0'
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: net-scp
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ! '>='
32
+ - - '>='
37
33
  - !ruby/object:Gem::Version
38
34
  version: '0'
39
35
  type: :runtime
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ! '>='
39
+ - - '>='
45
40
  - !ruby/object:Gem::Version
46
41
  version: '0'
47
42
  - !ruby/object:Gem::Dependency
48
43
  name: term-ansicolor
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
- - - ! '>='
46
+ - - '>='
53
47
  - !ruby/object:Gem::Version
54
48
  version: '0'
55
49
  type: :runtime
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
- - - ! '>='
53
+ - - '>='
61
54
  - !ruby/object:Gem::Version
62
55
  version: '0'
63
56
  - !ruby/object:Gem::Dependency
64
57
  name: minitest
65
58
  requirement: !ruby/object:Gem::Requirement
66
- none: false
67
59
  requirements:
68
- - - ! '>='
60
+ - - '>='
69
61
  - !ruby/object:Gem::Version
70
62
  version: 2.11.3
71
63
  - - <
@@ -74,9 +66,8 @@ dependencies:
74
66
  type: :development
75
67
  prerelease: false
76
68
  version_requirements: !ruby/object:Gem::Requirement
77
- none: false
78
69
  requirements:
79
- - - ! '>='
70
+ - - '>='
80
71
  - !ruby/object:Gem::Version
81
72
  version: 2.11.3
82
73
  - - <
@@ -85,129 +76,113 @@ dependencies:
85
76
  - !ruby/object:Gem::Dependency
86
77
  name: rake
87
78
  requirement: !ruby/object:Gem::Requirement
88
- none: false
89
79
  requirements:
90
- - - ! '>='
80
+ - - '>='
91
81
  - !ruby/object:Gem::Version
92
82
  version: '0'
93
83
  type: :development
94
84
  prerelease: false
95
85
  version_requirements: !ruby/object:Gem::Requirement
96
- none: false
97
86
  requirements:
98
- - - ! '>='
87
+ - - '>='
99
88
  - !ruby/object:Gem::Version
100
89
  version: '0'
101
90
  - !ruby/object:Gem::Dependency
102
91
  name: turn
103
92
  requirement: !ruby/object:Gem::Requirement
104
- none: false
105
93
  requirements:
106
- - - ! '>='
94
+ - - '>='
107
95
  - !ruby/object:Gem::Version
108
96
  version: '0'
109
97
  type: :development
110
98
  prerelease: false
111
99
  version_requirements: !ruby/object:Gem::Requirement
112
- none: false
113
100
  requirements:
114
- - - ! '>='
101
+ - - '>='
115
102
  - !ruby/object:Gem::Version
116
103
  version: '0'
117
104
  - !ruby/object:Gem::Dependency
118
105
  name: unindent
119
106
  requirement: !ruby/object:Gem::Requirement
120
- none: false
121
107
  requirements:
122
- - - ! '>='
108
+ - - '>='
123
109
  - !ruby/object:Gem::Version
124
110
  version: '0'
125
111
  type: :development
126
112
  prerelease: false
127
113
  version_requirements: !ruby/object:Gem::Requirement
128
- none: false
129
114
  requirements:
130
- - - ! '>='
115
+ - - '>='
131
116
  - !ruby/object:Gem::Version
132
117
  version: '0'
133
118
  - !ruby/object:Gem::Dependency
134
119
  name: mocha
135
120
  requirement: !ruby/object:Gem::Requirement
136
- none: false
137
121
  requirements:
138
- - - ! '>='
122
+ - - '>='
139
123
  - !ruby/object:Gem::Version
140
124
  version: '0'
141
125
  type: :development
142
126
  prerelease: false
143
127
  version_requirements: !ruby/object:Gem::Requirement
144
- none: false
145
128
  requirements:
146
- - - ! '>='
129
+ - - '>='
147
130
  - !ruby/object:Gem::Version
148
131
  version: '0'
149
132
  - !ruby/object:Gem::Dependency
150
133
  name: debugger
151
134
  requirement: !ruby/object:Gem::Requirement
152
- none: false
153
135
  requirements:
154
- - - ! '>='
136
+ - - '>='
155
137
  - !ruby/object:Gem::Version
156
138
  version: '0'
157
139
  type: :development
158
140
  prerelease: false
159
141
  version_requirements: !ruby/object:Gem::Requirement
160
- none: false
161
142
  requirements:
162
- - - ! '>='
143
+ - - '>='
163
144
  - !ruby/object:Gem::Version
164
145
  version: '0'
165
146
  - !ruby/object:Gem::Dependency
166
147
  name: vagrant
167
148
  requirement: !ruby/object:Gem::Requirement
168
- none: false
169
149
  requirements:
170
- - - ! '>='
150
+ - - '>='
171
151
  - !ruby/object:Gem::Version
172
152
  version: '0'
173
153
  type: :development
174
154
  prerelease: false
175
155
  version_requirements: !ruby/object:Gem::Requirement
176
- none: false
177
156
  requirements:
178
- - - ! '>='
157
+ - - '>='
179
158
  - !ruby/object:Gem::Version
180
159
  version: '0'
181
160
  - !ruby/object:Gem::Dependency
182
161
  name: yard
183
162
  requirement: !ruby/object:Gem::Requirement
184
- none: false
185
163
  requirements:
186
- - - ! '>='
164
+ - - '>='
187
165
  - !ruby/object:Gem::Version
188
166
  version: '0'
189
167
  type: :development
190
168
  prerelease: false
191
169
  version_requirements: !ruby/object:Gem::Requirement
192
- none: false
193
170
  requirements:
194
- - - ! '>='
171
+ - - '>='
195
172
  - !ruby/object:Gem::Version
196
173
  version: '0'
197
174
  - !ruby/object:Gem::Dependency
198
175
  name: redcarpet
199
176
  requirement: !ruby/object:Gem::Requirement
200
- none: false
201
177
  requirements:
202
- - - ! '>='
178
+ - - '>='
203
179
  - !ruby/object:Gem::Version
204
180
  version: '0'
205
181
  type: :development
206
182
  prerelease: false
207
183
  version_requirements: !ruby/object:Gem::Requirement
208
- none: false
209
184
  requirements:
210
- - - ! '>='
185
+ - - '>='
211
186
  - !ruby/object:Gem::Version
212
187
  version: '0'
213
188
  description: A comprehensive toolkit for remotely running commands in a structured
@@ -251,6 +226,7 @@ files:
251
226
  - lib/sshkit/formatters/pretty.rb
252
227
  - lib/sshkit/host.rb
253
228
  - lib/sshkit/log_message.rb
229
+ - lib/sshkit/logger.rb
254
230
  - lib/sshkit/runners/abstract.rb
255
231
  - lib/sshkit/runners/group.rb
256
232
  - lib/sshkit/runners/parallel.rb
@@ -269,29 +245,29 @@ files:
269
245
  - test/unit/test_configuration.rb
270
246
  - test/unit/test_coordinator.rb
271
247
  - test/unit/test_host.rb
248
+ - test/unit/test_logger.rb
272
249
  homepage: http://wacku.github.com/sshkit
273
250
  licenses: []
251
+ metadata: {}
274
252
  post_install_message:
275
253
  rdoc_options: []
276
254
  require_paths:
277
255
  - lib
278
256
  required_ruby_version: !ruby/object:Gem::Requirement
279
- none: false
280
257
  requirements:
281
- - - ! '>='
258
+ - - '>='
282
259
  - !ruby/object:Gem::Version
283
260
  version: '0'
284
261
  required_rubygems_version: !ruby/object:Gem::Requirement
285
- none: false
286
262
  requirements:
287
- - - ! '>='
263
+ - - '>='
288
264
  - !ruby/object:Gem::Version
289
265
  version: '0'
290
266
  requirements: []
291
267
  rubyforge_project:
292
- rubygems_version: 1.8.23
268
+ rubygems_version: 2.0.2
293
269
  signing_key:
294
- specification_version: 3
270
+ specification_version: 4
295
271
  summary: SSHKit makes it easy to write structured, testable SSH commands in Ruby
296
272
  test_files:
297
273
  - test/functional/backends/test_netssh.rb
@@ -306,4 +282,5 @@ test_files:
306
282
  - test/unit/test_configuration.rb
307
283
  - test/unit/test_coordinator.rb
308
284
  - test/unit/test_host.rb
285
+ - test/unit/test_logger.rb
309
286
  has_rdoc: