Class: Bashcov::Detective
- Inherits:
-
Object
- Object
- Bashcov::Detective
- Defined in:
- lib/bashcov/detective.rb
Overview
Detect shell scripts
Constant Summary collapse
- SHELL_BASENAMES =
- Set<String>
-
Basenames of shell executables
Set.new(%w[bash sh ash dash]).freeze
- OTHER_BASENAMES =
- Set<String>
-
Basenames of executables commonly used to
exec
other
processes, including shells
Set.new(%w[env]).freeze
- SHELLSCRIPT_EXTENSIONS =
- Set<String>
-
Filename extensions commonly used for shell scripts
Set.new(%w[.bash .sh]).freeze
Instance Method Summary collapse
-
#initialize(bash_path) ⇒ Detective
constructor
Create an object that can be used for inferring whether a file is or is not a shell script.
-
#shellscript?(filename) ⇒ Boolean
Checks whether the provided file refers to a shell script by determining whether the first line is a shebang that refers to a shell executable, or whether the file has a shellscript extension and contains valid shell syntax.
-
#shellscript_extension?(filename) ⇒ Boolean
extension.
-
#shellscript_shebang?(filename) ⇒ Boolean
Whether
filename
‘s first line is a valid shell shebang. -
#shellscript_shebang_line?(shebang) ⇒ Boolean
Whether the line is a valid shell shebang.
Constructor Details
#initialize(bash_path) ⇒ Detective
Create an object that can be used for inferring whether a file is or is not a shell script.
21 22 23 |
# File 'lib/bashcov/detective.rb', line 21 def initialize(bash_path) @bash_path = bash_path end |
Instance Method Details
#shellscript?(filename) ⇒ Boolean
returns false
when filename
is not readable, even if filename
indeed refers to a shell script.
Checks whether the provided file refers to a shell script by determining whether the first line is a shebang that refers to a shell executable, or whether the file has a shellscript extension and contains valid shell syntax.
33 34 35 36 37 38 39 |
# File 'lib/bashcov/detective.rb', line 33 def shellscript?(filename) return false unless File.exist?(filename) && File.readable?(filename) \ && File.file?(File.realpath(filename)) shellscript_shebang?(filename) || (shellscript_extension?(filename) && shellscript_syntax?(filename)) end |
#shellscript_extension?(filename) ⇒ Boolean
extension
85 86 87 |
# File 'lib/bashcov/detective.rb', line 85 def shellscript_extension?(filename) SHELLSCRIPT_EXTENSIONS.include? File.extname(filename) end |
#shellscript_shebang?(filename) ⇒ Boolean
assumes that filename
is readable and refers to a regular file
Returns whether filename
‘s first line is a valid shell shebang.
45 46 47 48 49 50 51 52 53 54 |
# File 'lib/bashcov/detective.rb', line 45 def shellscript_shebang?(filename) # Handle empty files that cause an immediate EOFError begin shebang = File.open(filename) { |f| f.readline.chomp } rescue EOFError return false end shellscript_shebang_line?(shebang) end |
#shellscript_shebang_line?(shebang) ⇒ Boolean
Returns whether the line is a valid shell shebang.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/bashcov/detective.rb', line 58 def shellscript_shebang_line?(shebang) scanner = StringScanner.new(shebang) begin return false if scanner.scan(/#!\s*/).nil? shell = scanner.scan(/\S+/) return false if shell.nil? args = scanner.skip(/\s+/).nil? ? [] : scanner.rest.split(/\s+/) rescue ArgumentError # Handle "invalid byte sequence in UTF-8" from `StringScanner`. Can # happen when trying to read binary data (e.g. .pngs). return false end shell_basename = File.basename(shell) SHELL_BASENAMES.include?(shell_basename) || (OTHER_BASENAMES.include?(shell_basename) && args.any? { |arg| SHELL_BASENAMES.include?(File.basename(arg)) }) end |