bashcov 1.6.0 → 1.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 69ae560709ca922d5768a2755b4c9f9fa0de60d9
4
- data.tar.gz: c0ccca240348b0736dca3357af5412c98159466a
3
+ metadata.gz: 4f9c5cde335ec3f77c2e8671870587c91c0b7921
4
+ data.tar.gz: 3aa49b58a3030285aa9dbdbd6852d1090f9770b0
5
5
  SHA512:
6
- metadata.gz: 7032cb66094fa7f79ae7916eb93dc58e814d5e46cac8fce6a0006ec8370c9f18a8aba2de2a9f642e5c984e3a992e28e98cd59664a8d5828afa45bf33c5f6f5bf
7
- data.tar.gz: 2ed6423accb917c077797224efe9644668349be5adb05ccd32b37413b8904bc1a560b566c871cde50331017bcd557ffdb6e75309822bd0cd58481ae0a6666f91
6
+ metadata.gz: fe850cf7e3ff9c56889b853bbb128aeaf4cf4da97702308b2df1ba67f24ec4161c1d96f9dd0ca14d308dc0b8ae374850bd295891e55c94cf25bd7ff8e01bb87f
7
+ data.tar.gz: ccf1e25f9be556328f8f6abf311ff95a2161af389f387aa1a2c611fa3f8b8683d954fcd4b710ad337bb5ba6e85d84206cf1dbf2d09ef6c5c2345cdbf215429ab
data/CHANGELOG.md CHANGED
@@ -1,7 +1,15 @@
1
- ## Unreleased ([changes](https://github.com/infertux/bashcov/compare/v1.6.0...master))
1
+ ## Unreleased ([changes](https://github.com/infertux/bashcov/compare/v1.7.0...master))
2
2
 
3
3
  * TBD
4
4
 
5
+ ## v1.7.0, 2017-12-28 ([changes](https://github.com/infertux/bashcov/compare/v1.6.0...v1.7.0))
6
+
7
+ * [MISC] Add support for Ruby 2.5 and drop 2.2
8
+ * [BUGFIX] Fix issue where coverage would be run twice and overwritten (#33)
9
+ * [FEATURE] Enhance shell script detection by parsing shebangs, checking
10
+ filename extensions, and running syntax checks with `bash -n`
11
+ (classes `Detective` & `Runner`) (#30)
12
+
5
13
  ## v1.6.0, 2017-10-24 ([changes](https://github.com/infertux/bashcov/compare/v1.5.1...v1.6.0))
6
14
 
7
15
  * [BUGFIX] Don't crash when files contain invalid UTF-8 characters (#27)
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Bashcov
2
2
 
3
+ [![Gem Version](https://img.shields.io/gem/v/bashcov.svg)](https://rubygems.org/gems/bashcov)
3
4
  [![Build Status](https://secure.travis-ci.org/infertux/bashcov.png?branch=master)](https://travis-ci.org/infertux/bashcov)
4
- [![Dependency Status](https://gemnasium.com/infertux/bashcov.png)](https://gemnasium.com/infertux/bashcov)
5
- [![Code Climate](https://codeclimate.com/github/infertux/bashcov.png)](https://codeclimate.com/github/infertux/bashcov)
6
5
  [![Coverage Status](https://coveralls.io/repos/infertux/bashcov/badge.png?branch=master)](https://coveralls.io/r/infertux/bashcov)
7
- [![Gem Version](https://img.shields.io/gem/v/bashcov.svg)](https://rubygems.org/gems/bashcov)
6
+ [![Dependency Status](https://gemnasium.com/infertux/bashcov.png)](https://gemnasium.com/infertux/bashcov)
7
+ [![Maintainability](https://api.codeclimate.com/v1/badges/083fdbba795049cd5f06/maintainability)](https://codeclimate.com/github/infertux/bashcov/maintainability)
8
8
 
9
9
  **Code coverage for Bash**
10
10
 
data/bashcov.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |gem|
21
21
  gem.executables = gem.files.grep(%r{\Abin/}).map { |f| File.basename(f) }
22
22
  gem.require_paths = ["lib"]
23
23
 
24
- gem.required_ruby_version = ">= 2.2.7"
24
+ gem.required_ruby_version = ">= 2.3.0"
25
25
 
26
26
  gem.add_dependency "simplecov", "~> 0.15"
27
27
 
data/bin/bashcov CHANGED
@@ -16,6 +16,6 @@ require "simplecov"
16
16
 
17
17
  SimpleCov.command_name Bashcov.fullname
18
18
  SimpleCov.root Bashcov.root_directory
19
- SimpleCov::Result.new(coverage).format!
19
+ SimpleCov.at_exit { SimpleCov::Result.new(coverage).format! }
20
20
 
21
21
  exit status.exitstatus
data/lib/bashcov.rb CHANGED
@@ -59,7 +59,13 @@ module Bashcov
59
59
  # @return [String] Program name including version for easy consistent output
60
60
  # @note +fullname+ instead of name to avoid clashing with +Module.name+
61
61
  def fullname
62
- "#{program_name} #{VERSION} (bash #{BASH_VERSION})"
62
+ [
63
+ program_name,
64
+ VERSION,
65
+ "(with Bash #{BASH_VERSION},",
66
+ "Ruby #{RUBY_VERSION},",
67
+ "and SimpleCov #{SimpleCov::VERSION})",
68
+ ].join(" ")
63
69
  end
64
70
 
65
71
  # Wipe the current options and reset default values
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+
5
+ module Bashcov
6
+ # Detect shell scripts
7
+ class Detective
8
+ # [Set<String>] Basenames of shell executables
9
+ SHELL_BASENAMES = Set.new(%w[bash sh ash dash]).freeze
10
+
11
+ # [Set<String>] Basenames of executables commonly used to +exec+ other
12
+ # processes, including shells
13
+ OTHER_BASENAMES = Set.new(%w[env]).freeze
14
+
15
+ # [Set<String>] Filename extensions commonly used for shell scripts
16
+ SHELLSCRIPT_EXTENSIONS = Set.new(%w[.bash .sh]).freeze
17
+
18
+ # Create an object that can be used for inferring whether a file is or is
19
+ # not a shell script.
20
+ # @param [String] bash_path path to a Bash interpreter
21
+ def initialize(bash_path)
22
+ @bash_path = bash_path
23
+ end
24
+
25
+ # Checks whether the provided file refers to a shell script by
26
+ # determining whether the first line is a shebang that refers to a shell
27
+ # executable, or whether the file has a shellscript extension and contains
28
+ # valid shell syntax.
29
+ # @param [String,Pathname] filename the name of the file to be checked
30
+ # @return [Boolean] whether +filename+ refers to a shell script
31
+ # @note returns +false+ when +filename+ is not readable, even if +filename+
32
+ # indeed refers to a shell script.
33
+ def shellscript?(filename)
34
+ return false unless File.exist?(filename) && File.readable?(filename) \
35
+ && File.file?(File.realpath(filename))
36
+
37
+ shellscript_shebang?(filename) || \
38
+ (shellscript_extension?(filename) && shellscript_syntax?(filename))
39
+ end
40
+
41
+ private
42
+
43
+ # @param [String,Pathname] filename the name of the file to be checked
44
+ # @return [Boolean] whether +filename+'s first line is a valid shell
45
+ # shebang
46
+ # @note assumes that +filename+ is readable and refers to a regular file
47
+ def shellscript_shebang?(filename)
48
+ # Handle empty files that cause an immediate EOFError
49
+ begin
50
+ shebang = File.open(filename) { |f| f.readline.chomp }
51
+ rescue EOFError
52
+ return false
53
+ end
54
+
55
+ return false unless shebang[0..1] == "#!"
56
+
57
+ shell, arg = shebang[2..-1].split(/\s+/, 2)
58
+ shell_basename = File.basename(shell)
59
+
60
+ SHELL_BASENAMES.include?(shell_basename) || \
61
+ (OTHER_BASENAMES.include?(shell_basename) && SHELL_BASENAMES.include?(arg))
62
+ end
63
+
64
+ # @param [String,Pathname] filename the name of the file to be checked
65
+ # @return [Boolean] whether +filename+'s extension is a valid shellscript
66
+ # extension
67
+ def shellscript_extension?(filename)
68
+ SHELLSCRIPT_EXTENSIONS.include? File.extname(filename)
69
+ end
70
+
71
+ # @param [String,Pathname] filename the name of the file to be checked
72
+ # @return [Boolean] whether +filename+'s text matches valid shell syntax
73
+ # @note assumes that +filename+ is readable and refers to a regular file
74
+ def shellscript_syntax?(filename)
75
+ system(@bash_path, "-n", filename.to_s, in: :close, out: :close, err: :close)
76
+ $?.success?
77
+ end
78
+ end
79
+ end
@@ -34,9 +34,7 @@ module Bashcov
34
34
  # since the last match, yields empty strings until +field_count+ is
35
35
  # reached.
36
36
  def each(delimiter, field_count, start_match)
37
- unless block_given?
38
- return enum_for(__method__, delimiter, field_count, start_match)
39
- end
37
+ return enum_for(__method__, delimiter, field_count, start_match) unless block_given?
40
38
 
41
39
  # Whether the current field is the start-of-fields match
42
40
  matched_start = nil
data/lib/bashcov/lexer.rb CHANGED
@@ -22,9 +22,7 @@ module Bashcov
22
22
  @filename = filename
23
23
  @coverage = coverage
24
24
 
25
- unless File.file?(@filename) # rubocop:disable Style/GuardClause
26
- raise ArgumentError, "#{@filename} is not a file"
27
- end
25
+ raise ArgumentError, "#{@filename} is not a file" unless File.file?(@filename)
28
26
  end
29
27
 
30
28
  # Process and complete initial coverage.
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bashcov/detective"
3
4
  require "bashcov/errors"
4
5
  require "bashcov/field_stream"
5
6
  require "bashcov/lexer"
@@ -11,6 +12,7 @@ module Bashcov
11
12
  # @param [String] command Command to run
12
13
  def initialize(command)
13
14
  @command = command
15
+ @detective = Detective.new(Bashcov.bash_path)
14
16
  end
15
17
 
16
18
  # Runs the command with appropriate xtrace settings.
@@ -74,8 +76,11 @@ module Bashcov
74
76
  private
75
77
 
76
78
  def write_warning(message)
77
- warn format "%s: warning: %s", Bashcov.program_name,
78
- message.gsub(/^\s+/, "").lines.map(&:chomp).join(" ")
79
+ warn [
80
+ Bashcov.program_name,
81
+ ": warning: ",
82
+ message.gsub(/^\s+/, "").lines.map(&:chomp).join(" "),
83
+ ].join
79
84
  end
80
85
 
81
86
  def run_xtrace(fd, env, options)
@@ -123,8 +128,10 @@ module Bashcov
123
128
  def find_bash_files!
124
129
  return if Bashcov.skip_uncovered
125
130
 
126
- Pathname.glob("#{Bashcov.root_directory}/**/*.sh").each do |filename|
127
- @coverage[filename] = [] unless @coverage.include?(filename)
131
+ Pathname.new(Bashcov.root_directory).find do |filename|
132
+ if !@coverage.include?(filename) && @detective.shellscript?(filename)
133
+ @coverage[filename] = []
134
+ end
128
135
  end
129
136
  end
130
137
 
@@ -3,5 +3,5 @@
3
3
  # :nodoc:
4
4
  module Bashcov
5
5
  # Current Bashcov version
6
- VERSION = "1.6.0".freeze
6
+ VERSION = "1.7.0"
7
7
  end
@@ -12,10 +12,10 @@ module Bashcov
12
12
  class Xtrace
13
13
  # [String] Character that will be used to indicate the nesting level of
14
14
  # +xtrace+d instructions
15
- DEPTH_CHAR = "+".freeze
15
+ DEPTH_CHAR = "+"
16
16
 
17
17
  # [String] Prefix used in +PS4+ to identify relevant output
18
- PREFIX = "BASHCOV>".freeze
18
+ PREFIX = "BASHCOV>"
19
19
 
20
20
  # [Array<String>] A collection of Bash internal variables to expand in the
21
21
  # {PS4}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bashcov
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cédric Félizard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-24 00:00:00.000000000 Z
11
+ date: 2017-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simplecov
@@ -127,6 +127,7 @@ files:
127
127
  - bin/bashcov
128
128
  - lib/bashcov.rb
129
129
  - lib/bashcov/bash_info.rb
130
+ - lib/bashcov/detective.rb
130
131
  - lib/bashcov/errors.rb
131
132
  - lib/bashcov/field_stream.rb
132
133
  - lib/bashcov/lexer.rb
@@ -146,7 +147,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
146
147
  requirements:
147
148
  - - ">="
148
149
  - !ruby/object:Gem::Version
149
- version: 2.2.7
150
+ version: 2.3.0
150
151
  required_rubygems_version: !ruby/object:Gem::Requirement
151
152
  requirements:
152
153
  - - ">="
@@ -154,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
155
  version: '0'
155
156
  requirements: []
156
157
  rubyforge_project:
157
- rubygems_version: 2.6.13
158
+ rubygems_version: 2.6.14
158
159
  signing_key:
159
160
  specification_version: 4
160
161
  summary: Code coverage tool for Bash