tty-which 0.1.0

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: a5024ca88ff5be5656247e0686827463e5f0cea3
4
+ data.tar.gz: ee9eaeddd82f8eede886aabb018842b87b5335fe
5
+ SHA512:
6
+ metadata.gz: 96fcfce47fd6a6ec990e74c21266890efc9ef0355dadd2b054a5ed23207902a095c2ae470869a26a726a124262b1065e7c4019baeb741082a7f70aac240217e5
7
+ data.tar.gz: bf4197d3b5588999005df72b4e9232ff523d75a04fc764fc70eb5d46121f8364dc678d5eeeaf254d7fb94914e77290c6c6f63f0a03e0d4bb907dfc1ad39559b4
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --warnings
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0
data/.travis.yml ADDED
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+ bundler_args: --without yard guard benchmarks
3
+ script: "bundle exec rake ci"
4
+ rvm:
5
+ - 1.9
6
+ - 2.0
7
+ - 2.1
8
+ - 2.2
9
+ - ruby-head
10
+ - rbx-2
11
+ - jruby-19mode
12
+ matrix:
13
+ include:
14
+ - rvm: jruby-head
15
+ allow_failures:
16
+ - rvm: ruby-head
17
+ - rvm: jruby-head
18
+ fast_finish: true
19
+ branches:
20
+ only: master
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rake', '~> 10.4.2'
7
+ gem 'rspec', '~> 3.2.0'
8
+ gem 'yard', '~> 0.8.7'
9
+ end
10
+
11
+ group :metrics do
12
+ gem 'coveralls', '~> 0.8.1'
13
+ gem 'simplecov', '~> 0.10.0'
14
+ gem 'yardstick', '~> 0.9.9'
15
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Piotr Murach
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # TTY::Which
2
+ [![Gem Version](https://badge.fury.io/rb/tty-which.svg)][gem]
3
+ [![Build Status](https://secure.travis-ci.org/peter-murach/tty-which.svg?branch=master)][travis]
4
+ [![Code Climate](https://codeclimate.com/github/peter-murach/tty-which/badges/gpa.svg)][codeclimate]
5
+ [![Coverage Status](https://coveralls.io/repos/peter-murach/tty-which/badge.svg?branch=master)][coveralls]
6
+ [![Inline docs](http://inch-ci.org/github/peter-murach/tty-which.svg?branch=master)][inchpages]
7
+
8
+ [gem]: http://badge.fury.io/rb/tty-which
9
+ [travis]: http://travis-ci.org/peter-murach/tty-which
10
+ [codeclimate]: https://codeclimate.com/github/peter-murach/tty-which
11
+ [coveralls]: https://coveralls.io/r/peter-murach/tty-which
12
+ [inchpages]: http://inch-ci.org/github/peter-murach/tty-which
13
+
14
+ > Platform independent implementation of Unix `which` utility that searches for executable file in the path.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ gem 'tty-which'
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install tty-which
29
+
30
+ ## Usage
31
+
32
+ **TTY::Which** exposes `which` method that searches the path for executable file that would be run had the command been invoked.
33
+
34
+ For example, to find location for a single command do:
35
+
36
+ ```ruby
37
+ TTY::Which.which('less') # => '/usr/bin/less'
38
+ TTY::Which.which('git') # => 'C:\Program Files\Git\bin\git'
39
+ ```
40
+
41
+ You can also check an absolute path:
42
+
43
+ ```ruby
44
+ TTY::Which.which('/usr/bin/ruby') # => '/usr/bin/ruby'
45
+ ```
46
+
47
+ ## Contributing
48
+
49
+ 1. Fork it ( https://github.com/peter-murach/tty-which/fork )
50
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
51
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
52
+ 4. Push to the branch (`git push origin my-new-feature`)
53
+ 5. Create a new Pull Request
54
+
55
+ ## Copyright
56
+
57
+ Copyright (c) 2015 Piotr Murach. See LICENSE for further details.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # coding: utf-8
2
+
3
+ require 'bundler/gem_tasks'
4
+
5
+ FileList['tasks/**/*.rake'].each(&method(:import))
6
+
7
+ desc 'Run all specs'
8
+ task ci: %w[ spec ]
data/lib/tty-which.rb ADDED
@@ -0,0 +1,3 @@
1
+ # coding: utf-8
2
+
3
+ require 'tty/which'
data/lib/tty/which.rb ADDED
@@ -0,0 +1,134 @@
1
+ # coding: utf-8
2
+
3
+ require 'tty/which/version'
4
+
5
+ module TTY
6
+ # A class responsible for finding an executable in the PATH
7
+ module Which
8
+ extend self
9
+ # Find an executable in a platform independent way
10
+ #
11
+ # @param [String] command
12
+ # the command to search for
13
+ #
14
+ # @example
15
+ # which('ruby') # => '/usr/local/bin/ruby'
16
+ # which('/usr/local/bin/ruby') # => '/usr/local/bin/ruby'
17
+ # which('foo') # => nil
18
+ #
19
+ # @return [String, nil]
20
+ # the absolute path to executable if found, `nil` otherwise
21
+ #
22
+ # @api public
23
+ def which(cmd, search_path = nil)
24
+ if path_with_executable_file?(cmd)
25
+ return cmd if executable_file?(cmd)
26
+ extensions.each do |ext|
27
+ exe = File.join(cmd, ext)
28
+ return File.absolute_path(exe) if executable_file?(exe)
29
+ end
30
+ return nil
31
+ end
32
+
33
+ search_path ||= search_paths
34
+ search_path.each do |path|
35
+ if executable_file_with_ext?(cmd)
36
+ exe = File.join(path, cmd)
37
+ return File.absolute_path(exe) if executable_file?(exe)
38
+ end
39
+ extensions.each do |ext|
40
+ exe = File.join(path, "#{cmd}#{ext}")
41
+ return File.absolute_path(exe) if executable_file?(exe)
42
+ end
43
+ end
44
+ nil
45
+ end
46
+
47
+ private
48
+
49
+ # Find default system paths
50
+ #
51
+ # @return [Array[String]]
52
+ # the array of paths to search
53
+ #
54
+ # @api private
55
+ def search_paths
56
+ paths = if ENV['PATH']
57
+ ENV['PATH'].split(File::PATH_SEPARATOR)
58
+ else
59
+ %w(/usr/local/bin /usr/ucb /usr/bin /bin)
60
+ end
61
+ paths.select { |path| Dir.exist?(path) }
62
+ end
63
+
64
+ # All files that contain a '.' in name
65
+ #
66
+ # @example
67
+ # extensions('.exe;cmd;.bat')
68
+ # # => ['.exe','.bat']
69
+ #
70
+ # @param [String] path_ext
71
+ # a string of semicolon separated filename extensions
72
+ #
73
+ # @return [Array[String]]
74
+ # an array with valid file extensions
75
+ #
76
+ # @api private
77
+ def extensions(path_ext = ENV['PATHEXT'])
78
+ return [''] unless path_ext
79
+ path_ext.split(';').select { |part| part.include?('.') }
80
+ end
81
+
82
+ # Determines if filename is an executable file
83
+ #
84
+ # @example Basic usage
85
+ # executable_file?('/usr/bin/less') # => true
86
+ #
87
+ # @example Executable in directory
88
+ # executable_file?('less', '/usr/bin') # => true
89
+ # executable_file?('less', '/usr') # => false
90
+ #
91
+ # @param [String] filename
92
+ # the path to file
93
+ # @param [String] dir
94
+ # the directory within which to search for filename
95
+ #
96
+ # @return [Boolean]
97
+ #
98
+ # @api private
99
+ def executable_file?(filename, dir = nil)
100
+ path = File.join(dir, filename) if dir
101
+ path ||= filename
102
+ File.file?(path) && File.executable?(path)
103
+ end
104
+
105
+ # Check if command itself has extension
106
+ #
107
+ # @param [String] filename
108
+ # the path to file
109
+ #
110
+ # @example
111
+ # executable_file_with_ext?("file.bat") # => true
112
+ #
113
+ # @return [Boolean]
114
+ #
115
+ # @api private
116
+ def executable_file_with_ext?(filename)
117
+ extension = File.extname(filename)
118
+ return false if extension.empty?
119
+ extensions.any? { |ext| extension.casecmp(ext) }
120
+ end
121
+
122
+ # Check if executable file is part of absolute/relative path
123
+ #
124
+ # @param [String] cmd
125
+ # the executable to check
126
+ #
127
+ # @return [Boolean]
128
+ #
129
+ # @api private
130
+ def path_with_executable_file?(cmd)
131
+ File.expand_path(cmd) == cmd
132
+ end
133
+ end # Which
134
+ end # TTY
@@ -0,0 +1,7 @@
1
+ # coding: utf-8
2
+
3
+ module TTY
4
+ module Which
5
+ VERSION = "0.1.0"
6
+ end # Which
7
+ end # TTY
@@ -0,0 +1,45 @@
1
+ # coding: utf-8
2
+
3
+ if RUBY_VERSION > '1.9' and (ENV['COVERAGE'] || ENV['TRAVIS'])
4
+ require 'simplecov'
5
+ require 'coveralls'
6
+
7
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
8
+ SimpleCov::Formatter::HTMLFormatter,
9
+ Coveralls::SimpleCov::Formatter
10
+ ]
11
+
12
+ SimpleCov.start do
13
+ command_name 'spec'
14
+ add_filter 'spec'
15
+ end
16
+ end
17
+
18
+ require 'tty-which'
19
+
20
+ RSpec.configure do |config|
21
+ config.expect_with :rspec do |expectations|
22
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
23
+ end
24
+
25
+ config.mock_with :rspec do |mocks|
26
+ mocks.verify_partial_doubles = true
27
+ end
28
+
29
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
30
+ config.disable_monkey_patching!
31
+
32
+ # This setting enables warnings. It's recommended, but in some cases may
33
+ # be too noisy due to issues in dependencies.
34
+ config.warnings = true
35
+
36
+ if config.files_to_run.one?
37
+ config.default_formatter = 'doc'
38
+ end
39
+
40
+ config.profile_examples = 2
41
+
42
+ config.order = :random
43
+
44
+ Kernel.srand config.seed
45
+ end
@@ -0,0 +1,117 @@
1
+ # coding: utf-8
2
+
3
+ RSpec.describe TTY::Which, '#which' do
4
+
5
+ before { stub_const("Which", described_class) }
6
+
7
+ context "without extension" do
8
+ let(:path) { "/bin:/usr/bin:/usr/local/bin:/opt/local/bin" }
9
+ let(:cmds) { %w(/usr/bin/ls /bin/sh /usr/bin/ruby /usr/local/git/bin/git) }
10
+
11
+ before {
12
+ allow(ENV).to receive(:[]).with('PATHEXT').and_return(nil)
13
+ allow(ENV).to receive(:[]).with('PATH').and_return(path)
14
+ stub_const("File::PATH_SEPARATOR", ':')
15
+ stub_const("File::SEPARATOR", '/')
16
+ allow(Dir).to receive(:exist?) { true }
17
+ }
18
+
19
+ it "handles path with executable file /bin/sh" do
20
+ allow(Which).to receive(:path_with_executable_file?) { true }
21
+ allow(Which).to receive(:executable_file?) { true }
22
+
23
+ expect(Which.which('/bin/sh')).to eq('/bin/sh')
24
+ end
25
+
26
+ it "fails to find path executable" do
27
+ allow(Which).to receive(:path_with_executable_file?) { true }
28
+ allow(Which).to receive(:executable_file?) { false }
29
+
30
+ expect(Which.which('/bin/sh')).to eq(nil)
31
+ end
32
+
33
+ it "searches executable file git" do
34
+ dir_path = "/usr/local/bin"
35
+ cmd = "git"
36
+ expected_path = "#{dir_path}/#{cmd}"
37
+ allow(Which).to receive(:path_with_executable_file?) { false }
38
+ allow(Which).to receive(:executable_file_with_ext?) { false }
39
+
40
+ allow(File).to receive(:join)
41
+ allow(File).to receive(:join).with(dir_path, cmd).and_return(expected_path)
42
+ allow(Which).to receive(:executable_file?) { false }
43
+ allow(Which).to receive(:executable_file?).with(expected_path) { true }
44
+ allow(File).to receive(:absolute_path).with(expected_path).
45
+ and_return(expected_path)
46
+
47
+ expect(Which.which(cmd)).to eq(expected_path)
48
+ end
49
+ end
50
+
51
+ context "with extension" do
52
+ let(:path) { "C:\\Program Files\\Git\\bin;" }
53
+ let(:exts) { ".com;.exe;.bat;.cmd" }
54
+
55
+ before {
56
+ allow(ENV).to receive(:[]).with('PATHEXT').and_return(exts)
57
+ allow(ENV).to receive(:[]).with('PATH').and_return(path)
58
+ stub_const("File::PATH_SEPARATOR", ';')
59
+ stub_const("File::SEPARATOR", '\\')
60
+ allow(Dir).to receive(:exist?) { true }
61
+ }
62
+
63
+ it "handles path with executable file C:\\Program Files\\Git\\bin\\git" do
64
+ allow(Which).to receive(:path_with_executable_file?) { true }
65
+ allow(Which).to receive(:executable_file?).with(any_args) { false }
66
+
67
+ path_with_exe_file = 'C:\Program Files\Git\bin\git'
68
+ expected_path = "#{path_with_exe_file}.exe"
69
+
70
+ allow(File).to receive(:join).with(path_with_exe_file, any_args).
71
+ and_return(path_with_exe_file)
72
+ allow(File).to receive(:join).with(path_with_exe_file, '.exe').
73
+ and_return(expected_path)
74
+ allow(Which).to receive(:executable_file?).with(expected_path) { true }
75
+ allow(File).to receive(:absolute_path).and_return(expected_path)
76
+
77
+ expect(Which.which(path_with_exe_file)).to eq(expected_path)
78
+ end
79
+
80
+ it "searches path for executable git.exe" do
81
+ dir_path = "C:\\Program Files\\Git\\bin"
82
+ cmd = 'git.exe'
83
+ expected_path = "#{dir_path}\\#{cmd}"
84
+ allow(Which).to receive(:path_with_executable_file?) { false }
85
+ allow(Which).to receive(:executable_file_with_ext?).with(cmd) { true }
86
+
87
+ allow(File).to receive(:join).with(dir_path, any_args)
88
+ allow(File).to receive(:join).with(dir_path, cmd).and_return(expected_path)
89
+ allow(Which).to receive(:executable_file?).with(any_args) { false }
90
+ allow(Which).to receive(:executable_file?).with(expected_path) { true }
91
+ allow(File).to receive(:absolute_path).with(expected_path).
92
+ and_return(expected_path)
93
+
94
+ expect(Which.which(cmd)).to eq(expected_path)
95
+ expect(File).to have_received(:absolute_path).with(expected_path)
96
+ end
97
+
98
+ it "searches path for executable git" do
99
+ dir_path = "C:\\Program Files\\Git\\bin"
100
+ cmd = 'git'
101
+ expected_path = "#{dir_path}\\#{cmd}.exe"
102
+ allow(Which).to receive(:path_with_executable_file?) { false }
103
+ allow(Which).to receive(:executable_file_with_ext?).with(cmd) { false }
104
+
105
+ allow(File).to receive(:join).with(dir_path, any_args)
106
+ allow(File).to receive(:join).with(dir_path, "#{cmd}.exe").
107
+ and_return(expected_path)
108
+ allow(Which).to receive(:executable_file?).with(any_args) { false }
109
+ allow(Which).to receive(:executable_file?).with(expected_path) { true }
110
+ allow(File).to receive(:absolute_path).with(expected_path).
111
+ and_return(expected_path)
112
+
113
+ expect(Which.which(cmd)).to eq(expected_path)
114
+ expect(File).to have_received(:absolute_path).with(expected_path)
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ desc 'Load gem inside irb console'
4
+ task :console do
5
+ require 'irb'
6
+ require 'irb/completion'
7
+ require File.join(__FILE__, '../../lib/tty-which')
8
+ ARGV.clear
9
+ IRB.start
10
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ desc 'Measure code coverage'
4
+ task :coverage do
5
+ begin
6
+ original, ENV['COVERAGE'] = ENV['COVERAGE'], 'true'
7
+ Rake::Task['spec'].invoke
8
+ ensure
9
+ ENV['COVERAGE'] = original
10
+ end
11
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc 'Run all specs'
7
+ RSpec::Core::RakeTask.new(:spec) do |task|
8
+ task.pattern = 'spec/{unit,integration}{,/*/**}/*_spec.rb'
9
+ end
10
+
11
+ namespace :spec do
12
+ desc 'Run unit specs'
13
+ RSpec::Core::RakeTask.new(:unit) do |task|
14
+ task.pattern = 'spec/unit{,/*/**}/*_spec.rb'
15
+ end
16
+
17
+ desc 'Run integration specs'
18
+ RSpec::Core::RakeTask.new(:integration) do |task|
19
+ task.pattern = 'spec/integration{,/*/**}/*_spec.rb'
20
+ end
21
+ end
22
+
23
+ rescue LoadError
24
+ %w[spec spec:unit spec:integration].each do |name|
25
+ task name do
26
+ $stderr.puts "In order to run #{name}, do `gem install rspec`"
27
+ end
28
+ end
29
+ end
data/tty-which.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tty/which/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tty-which"
8
+ spec.version = TTY::Which::VERSION
9
+ spec.authors = ["Piotr Murach"]
10
+ spec.email = [""]
11
+ spec.summary = %q{Platform independent implementation of Unix which command.}
12
+ spec.description = %q{Platform independent implementation of Unix which command.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tty-which
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Piotr Murach
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ description: Platform independent implementation of Unix which command.
28
+ email:
29
+ - ''
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - .gitignore
35
+ - .rspec
36
+ - .ruby-version
37
+ - .travis.yml
38
+ - Gemfile
39
+ - LICENSE.txt
40
+ - README.md
41
+ - Rakefile
42
+ - lib/tty-which.rb
43
+ - lib/tty/which.rb
44
+ - lib/tty/which/version.rb
45
+ - spec/spec_helper.rb
46
+ - spec/unit/which_spec.rb
47
+ - tasks/console.rake
48
+ - tasks/coverage.rake
49
+ - tasks/spec.rake
50
+ - tty-which.gemspec
51
+ homepage: ''
52
+ licenses:
53
+ - MIT
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 2.0.3
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: Platform independent implementation of Unix which command.
75
+ test_files:
76
+ - spec/spec_helper.rb
77
+ - spec/unit/which_spec.rb
78
+ has_rdoc: