bashcov 1.8.1 → 3.0.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.
@@ -23,7 +23,7 @@ module Bashcov
23
23
  end
24
24
  end
25
25
 
26
- # Yields fields extracted from a input stream
26
+ # Yields fields extracted from an input stream
27
27
  # @param [String, nil] delimiter the field separator
28
28
  # @param [Integer] field_count the number of fields to extract
29
29
  # @param [Regexp] start_match a +Regexp+ that, when matched against the
@@ -33,39 +33,51 @@ module Bashcov
33
33
  # +start_match+ is matched with fewer than +field_count+ fields yielded
34
34
  # since the last match, yields empty strings until +field_count+ is
35
35
  # reached.
36
- def each(delimiter, field_count, start_match)
36
+ def each(delimiter, field_count, start_match, &block)
37
37
  return enum_for(__method__, delimiter, field_count, start_match) unless block_given?
38
38
 
39
- # The number of fields processed since passing the last start-of-fields
40
- # match
41
- seen_fields = 0
39
+ chunked = each_field(delimiter).chunk(&chunk_matches(start_match))
42
40
 
43
- fields = each_field(delimiter)
41
+ yield_fields = lambda do |(_, chunk)|
42
+ chunk.each(&block)
43
+ (field_count - chunk.size).times { yield "" }
44
+ end
45
+
46
+ # Skip junk that might appear before the first start-of-fields match
47
+ begin
48
+ n, chunk = chunked.next
49
+ yield_fields.call([n, chunk]) unless n.zero?
50
+ rescue StopIteration
51
+ return
52
+ end
44
53
 
45
- # Close over +field_count+ and +seen_fields+ to yield empty strings to
46
- # the caller when we've already hit the next start-of-fields match
47
- yield_remaining = -> { (field_count - seen_fields).times { yield "" } }
54
+ chunked.each(&yield_fields)
55
+ end
48
56
 
49
- # Advance until the first start-of-fields match
50
- loop { break if fields.next =~ start_match }
57
+ private
51
58
 
52
- fields.each do |field|
53
- # If the current field is the start-of-fields match...
54
- if field =~ start_match
55
- # Fill out any remaining (unparseable) fields with empty strings
56
- yield_remaining.call
59
+ # @param [Regexp] start_match a +Regexp+ that, when matched against the
60
+ # input stream, signifies the beginning of the next series of fields to
61
+ # yield
62
+ # @return [Proc] a unary +Proc+ that returns +nil+ if the argument mathes
63
+ # the +start_match+ +Regexp+, and otherwise returns the number of
64
+ # start-of-fields signifiers so far encountered.
65
+ # @example
66
+ # chunker = chunk_matches /<=>/
67
+ # chunked = %w[foo fighters <=> bar none <=> baz luhrmann].chunk(&chunker)
68
+ # chunked.to_a
69
+ # #=> [[0, ["foo", "fighters"]], [1, ["bar", "none"]], [2, ["baz", "luhrmann"]]]
70
+ def chunk_matches(start_match)
71
+ i = 0
57
72
 
58
- seen_fields = 0
59
- elsif seen_fields < field_count
60
- yield field
61
- seen_fields += 1
73
+ lambda do |e|
74
+ if e.match?(start_match)
75
+ i += 1
76
+ nil
77
+ else
78
+ i
62
79
  end
63
80
  end
64
-
65
- # One last filling-out of empty fields if we're at the end of the stream
66
- yield_remaining.call
67
-
68
- read.close unless read.closed?
69
81
  end
70
82
  end
71
83
  end
data/lib/bashcov/lexer.rb CHANGED
@@ -27,8 +27,8 @@ module Bashcov
27
27
 
28
28
  # Process and complete initial coverage.
29
29
  # @return [void]
30
- def complete_coverage # rubocop:disable Metrics/MethodLength
31
- lines = IO.read(@filename).encode("utf-8", invalid: :replace).lines
30
+ def complete_coverage
31
+ lines = File.read(@filename).encode("utf-8", invalid: :replace).lines
32
32
 
33
33
  lines.each_with_index do |line, lineno|
34
34
  # multi-line arrays
@@ -41,7 +41,7 @@ module Bashcov
41
41
  # heredoc
42
42
  mark_multiline(
43
43
  lines, lineno,
44
- /\A[^\n]+<<-?'?(\w+)'?\s*$.*\1/m
44
+ /\A[^\n]+<<-?'?(\w+)'?.*$.*\1/m
45
45
  )
46
46
 
47
47
  # multiline string concatenated with backslashes
@@ -72,7 +72,7 @@ module Bashcov
72
72
  private
73
73
 
74
74
  def mark_multiline(lines, lineno, regexp, forward: true)
75
- seek_forward = lines[lineno..-1].join
75
+ seek_forward = lines[lineno..].join
76
76
  return unless (multiline_match = seek_forward.match(regexp))
77
77
 
78
78
  length = multiline_match.to_s.count($/)
@@ -80,6 +80,9 @@ module Bashcov
80
80
  range = (forward ? first.upto(last) : (last - 1).downto(first - 1))
81
81
  reference_lineno = (forward ? first - 1 : last)
82
82
 
83
+ # don't seek backward if first line is already covered
84
+ return if !forward && @coverage[first - 1]
85
+
83
86
  range.each do |sub_lineno|
84
87
  # mark related lines with the same coverage as the reference line
85
88
  @coverage[sub_lineno] ||= @coverage[reference_lineno]
@@ -92,8 +95,8 @@ module Bashcov
92
95
  @coverage[lineno] = Bashcov::Line::UNCOVERED if relevant?(line)
93
96
  end
94
97
 
95
- def relevant?(line) # rubocop:disable Metrics/CyclomaticComplexity
96
- line.sub!(/ #.*\Z/, "") # remove comments
98
+ def relevant?(line)
99
+ line.sub!(/\s#.*\Z/, "") # remove comments
97
100
  line.strip!
98
101
 
99
102
  relevant = true
@@ -104,7 +107,7 @@ module Bashcov
104
107
  line.end_with?(*IGNORE_END_WITH)
105
108
 
106
109
  relevant &= false if line =~ /\A\w+\(\)/ # function declared without the `function` keyword
107
- relevant &= false if line =~ /\A[^\)]+\)\Z/ # case statement selector, e.g. `--help)`
110
+ relevant &= false if line =~ /\A[^)]+\)\Z/ # case statement selector, e.g. `--help)`
108
111
 
109
112
  relevant
110
113
  end
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "tempfile"
4
+
5
+ require "simplecov"
6
+
3
7
  require "bashcov/detective"
4
8
  require "bashcov/errors"
5
9
  require "bashcov/field_stream"
@@ -18,23 +22,40 @@ module Bashcov
18
22
  # Runs the command with appropriate xtrace settings.
19
23
  # @note Binds Bashcov +stdin+ to the program being executed.
20
24
  # @return [Process::Status] Status of the executed command
21
- def run # rubocop:disable Metrics/MethodLength
25
+ def run
22
26
  # Clear out previous run
23
27
  @result = nil
24
28
 
25
29
  field_stream = FieldStream.new
26
30
  @xtrace = Xtrace.new(field_stream)
27
-
28
31
  fd = @xtrace.file_descriptor
29
- env = { "PS4" => Xtrace.ps4 }
32
+
30
33
  options = { in: :in }
34
+ options[fd] = fd # bind FDs to the child process
31
35
 
32
36
  if Bashcov.options.mute
33
37
  options[:out] = "/dev/null"
34
38
  options[:err] = "/dev/null"
35
39
  end
36
40
 
37
- run_xtrace(fd, env, options) do
41
+ env =
42
+ if Process.uid.zero?
43
+ # if running as root, Bash 4.4+ does not inherit $PS4 from the environment
44
+ # https://github.com/infertux/bashcov/issues/43#issuecomment-450605839
45
+ write_warning "running as root is NOT recommended, Bashcov may not work properly."
46
+
47
+ temp_file = Tempfile.new("bashcov_bash_env")
48
+ temp_file.write("export PS4='#{Xtrace.ps4}'\n")
49
+ temp_file.close
50
+
51
+ { "BASH_ENV" => temp_file.path }
52
+ else
53
+ { "PS4" => Xtrace.ps4 }
54
+ end
55
+
56
+ env["BASH_XTRACEFD"] = fd.to_s
57
+
58
+ with_xtrace_flag do
38
59
  command_pid = Process.spawn env, *@command, options # spawn the command
39
60
 
40
61
  begin
@@ -58,6 +79,8 @@ module Bashcov
58
79
  end
59
80
  end
60
81
 
82
+ temp_file&.unlink
83
+
61
84
  $?
62
85
  end
63
86
 
@@ -83,39 +106,13 @@ module Bashcov
83
106
  ].join
84
107
  end
85
108
 
86
- def run_xtrace(fd, env, options)
87
- # Older versions of Bash (< 4.1) don't have the BASH_XTRACEFD variable
88
- if Bashcov.bash_xtracefd?
89
- options[fd] = fd # bind FDs to the child process
90
-
91
- env["BASH_XTRACEFD"] = fd.to_s
92
- else
93
- # Send subprocess standard error to @xtrace.file_descriptor
94
- options[:err] = fd
95
-
96
- # Don't bother issuing warning if we're silencing output anyway
97
- unless Bashcov.mute
98
- write_warning <<-WARNING
99
- you are using a version of Bash that does not support
100
- BASH_XTRACEFD. All xtrace output will print to standard error, and
101
- your script's output on standard error will not be printed to the
102
- console.
103
- WARNING
104
- end
105
- end
106
-
107
- with_xtrace_flag do
108
- yield
109
- end
110
- end
111
-
112
109
  # @note +SHELLOPTS+ must be exported so we use Ruby's {ENV} variable
113
110
  # @yield [void] adds "xtrace" to +SHELLOPTS+ and then runs the provided
114
111
  # block
115
112
  # @return [Object, ...] the value returned by the calling block
116
113
  def with_xtrace_flag
117
- existing_flags_s = ENV["SHELLOPTS"]
118
- existing_flags = (existing_flags_s || "").split(":")
114
+ existing_flags_s = ENV.fetch("SHELLOPTS", "")
115
+ existing_flags = existing_flags_s.split(":")
119
116
  ENV["SHELLOPTS"] = (existing_flags | ["xtrace"]).join(":")
120
117
 
121
118
  yield
@@ -126,25 +123,49 @@ module Bashcov
126
123
  # Add files which have not been executed at all (i.e. with no coverage)
127
124
  # @return [void]
128
125
  def find_bash_files!
129
- return if Bashcov.skip_uncovered
126
+ filtered_files.each do |filename|
127
+ @coverage[filename] = [] if !@coverage.include?(filename) && @detective.shellscript?(filename)
128
+ end
129
+ end
130
130
 
131
- Pathname.new(Bashcov.root_directory).find do |filename|
132
- if !@coverage.include?(filename) && @detective.shellscript?(filename)
133
- @coverage[filename] = []
134
- end
131
+ # @return [Array<Pathname>] the list of files that should be included in
132
+ # coverage results, unless filtered by one or more SimpleCov filters
133
+ def tracked_files
134
+ return @tracked_files if defined? @tracked_files
135
+
136
+ mandatory = SimpleCov.tracked_files ? Pathname.glob(SimpleCov.tracked_files) : []
137
+ under_root = Bashcov.skip_uncovered ? [] : Pathname.new(Bashcov.root_directory).find.to_a
138
+
139
+ @tracked_files = (mandatory + under_root).uniq
140
+ end
141
+
142
+ # @return [Array<Pathname>] the list of files that should be included in
143
+ # coverage results
144
+ def filtered_files
145
+ return @filtered_files if defined? @filtered_files
146
+
147
+ source_files = tracked_files.map do |file|
148
+ SimpleCov::SourceFile.new(file.to_s, @coverage.fetch(file, []))
149
+ end
150
+
151
+ source_file_to_tracked_file = source_files.zip(tracked_files).to_h
152
+
153
+ @filtered_files = SimpleCov.filtered(source_files).map do |source_file|
154
+ source_file_to_tracked_file[source_file]
135
155
  end
136
156
  end
137
157
 
138
158
  # @return [void]
139
159
  def expunge_invalid_files!
140
160
  @coverage.each_key do |filename|
141
- next if filename.file?
161
+ if !filename.file?
162
+ @coverage.delete filename
163
+ write_warning "#{filename} was executed but has been deleted since then - it won't be reported in coverage."
142
164
 
143
- @coverage.delete filename
144
- write_warning <<-WARNING
145
- #{filename} was executed but has been deleted since then - it won't
146
- be reported in coverage.
147
- WARNING
165
+ elsif !@detective.shellscript?(filename)
166
+ @coverage.delete filename
167
+ write_warning "#{filename} was partially executed but has invalid Bash syntax - it won't be reported in coverage."
168
+ end
148
169
  end
149
170
  end
150
171
 
@@ -158,7 +179,7 @@ module Bashcov
158
179
  end
159
180
 
160
181
  def convert_coverage
161
- Hash[@coverage.map { |filename, coverage| [filename.to_s, coverage] }]
182
+ @coverage.transform_keys(&:to_s)
162
183
  end
163
184
  end
164
185
  end
@@ -3,5 +3,5 @@
3
3
  # :nodoc:
4
4
  module Bashcov
5
5
  # Current Bashcov version
6
- VERSION = "1.8.1"
6
+ VERSION = "3.0.0"
7
7
  end
@@ -24,11 +24,10 @@ module Bashcov
24
24
  class << self
25
25
  attr_writer :delimiter, :ps4
26
26
 
27
- # [String] A randomly-generated UUID or the ASCII RS (record separator)
28
- # character, depending on whether the current Bash suffers from the
29
- # truncated +PS4+ bug. Used for delimiting the fields of the +PS4+.
27
+ # [String] A randomly-generated UUID used for delimiting the fields of
28
+ # the +PS4+.
30
29
  def delimiter
31
- @delimiter ||= Bashcov.truncated_ps4? ? "\x1E" : SecureRandom.uuid
30
+ @delimiter ||= SecureRandom.uuid
32
31
  end
33
32
 
34
33
  # @return [String] +PS4+ variable used for xtrace output. Expands to
@@ -93,9 +92,12 @@ module Bashcov
93
92
  # play nicely with +Enumerator+s backed by +IO+ objects.
94
93
  loop do
95
94
  break if (hit = (1..field_count).map { fields.next }).empty?
95
+
96
96
  parse_hit!(*hit)
97
97
  end
98
98
 
99
+ @read.close unless @read.closed?
100
+
99
101
  @files
100
102
  end
101
103
 
@@ -115,8 +117,11 @@ module Bashcov
115
117
  # If +LINENO+ isn't a series of digits, something has gone wrong. Add
116
118
  # +@files+ to the exception in order to propagate the existing coverage
117
119
  # data back to the {Bashcov::Runner} instance.
118
- if lineno =~ /\A\d+\z/
120
+ if /\A\d+\z/.match?(lineno)
119
121
  lineno = lineno.to_i
122
+ elsif lineno == "${LINENO-}"
123
+ # the variable doesn't expand on line misses so we can safely ignore it
124
+ return
120
125
  else
121
126
  raise XtraceError.new(
122
127
  "expected integer for LINENO, got #{lineno.inspect}", @files
data/lib/bashcov.rb CHANGED
@@ -3,15 +3,12 @@
3
3
  require "optparse"
4
4
  require "pathname"
5
5
 
6
- require "bashcov/bash_info"
7
6
  require "bashcov/runner"
8
7
  require "bashcov/version"
9
8
 
10
9
  # Bashcov default module
11
10
  # @note Keep it short!
12
11
  module Bashcov
13
- extend Bashcov::BashInfo
14
-
15
12
  # A +Struct+ to store Bashcov configuration
16
13
  Options = Struct.new(
17
14
  *%i[skip_uncovered mute bash_path root_directory command command_name]
@@ -55,8 +52,9 @@ module Bashcov
55
52
  VERSION,
56
53
  "with Bash #{BASH_VERSION},",
57
54
  "Ruby #{RUBY_VERSION},",
58
- "and SimpleCov #{SimpleCov::VERSION}.",
59
- ].join(" ")
55
+ "and SimpleCov #{SimpleCov::VERSION}",
56
+ (Process.uid.zero? ? " as root user (NOT recommended)" : nil),
57
+ ].compact.join(" ")
60
58
  end
61
59
 
62
60
  # @return [String] The value to use as +SimpleCov.command_name+. Uses the
@@ -65,17 +63,35 @@ module Bashcov
65
63
  # representation of {Bashcov#command}.
66
64
  def command_name
67
65
  return @options.command_name if @options.command_name
68
- return ENV["BASHCOV_COMMAND_NAME"] unless ENV.fetch("BASHCOV_COMMAND_NAME", "").empty?
66
+ return ENV.fetch("BASHCOV_COMMAND_NAME", nil) unless ENV.fetch("BASHCOV_COMMAND_NAME", "").empty?
67
+
69
68
  command.compact.join(" ")
70
69
  end
71
70
 
71
+ def bash_path
72
+ # First attempt to use the value from `options`, but ignore all exceptions.
73
+ # This is used early for the `BASH_VERSION` definition, so first use will likely error.
74
+ begin
75
+ return @options.bash_path if @options.bash_path
76
+ rescue NoMethodError; end # rubocop:disable Lint/SuppressedException
77
+
78
+ # Support the same `BASHCOV_BASH_PATH` environment variable used in the spec tests.
79
+ return ENV.fetch("BASHCOV_BASH_PATH", nil) unless ENV.fetch("BASHCOV_BASH_PATH", "").empty?
80
+
81
+ # Fall back to standard Bash location.
82
+ "/bin/bash"
83
+ end
84
+
85
+ def bash_version
86
+ `#{bash_path} -c 'echo -n ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}'`
87
+ end
88
+
72
89
  # Wipe the current options and reset default values
73
90
  def set_default_options!
74
91
  @options = Options.new
75
92
 
76
93
  @options.skip_uncovered = false
77
94
  @options.mute = false
78
- @options.bash_path = "/bin/bash"
79
95
  @options.root_directory = Dir.getwd
80
96
  end
81
97
 
@@ -103,8 +119,8 @@ module Bashcov
103
119
  HELP
104
120
  end
105
121
 
106
- def option_parser # rubocop:disable Metrics/MethodLength
107
- OptionParser.new do |opts| # rubocop:disable Metrics/BlockLength
122
+ def option_parser
123
+ OptionParser.new do |opts|
108
124
  opts.program_name = program_name
109
125
  opts.version = Bashcov::VERSION
110
126
  opts.banner = help
@@ -119,10 +135,17 @@ module Bashcov
119
135
  end
120
136
  opts.on("--bash-path PATH", "Path to Bash executable") do |p|
121
137
  raise Errno::ENOENT, p unless File.file? p
138
+
122
139
  options.bash_path = p
140
+
141
+ # Redefine `BASH_VERSION` constant with upated `bash_path`.
142
+ # This is hacky, but a lot of code references that constant and this should only have to be done once.
143
+ send(:remove_const, "BASH_VERSION")
144
+ const_set("BASH_VERSION", bash_version.freeze)
123
145
  end
124
146
  opts.on("--root PATH", "Project root directory") do |d|
125
147
  raise Errno::ENOENT, d unless File.directory? d
148
+
126
149
  options.root_directory = d
127
150
  end
128
151
  opts.on("--command-name NAME", "Value to use as SimpleCov.command_name") do |c|
@@ -143,5 +166,5 @@ module Bashcov
143
166
  end
144
167
 
145
168
  # Current Bash version (e.g. 4.2)
146
- BASH_VERSION = `#{bash_path} -c 'echo -n ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}'`.freeze
169
+ BASH_VERSION = bash_version.freeze
147
170
  end
data/test.sh ADDED
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ set -euo pipefail
4
+
5
+ jobs=$(grep -o '^[a-z].*:$' .gitlab-ci.yml | tr -d ':' | grep -Ev '^(before_script)$')
6
+
7
+ for job in $jobs; do
8
+ echo "Running ${job}..."
9
+ gitlab-runner exec docker "$job"
10
+ done
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.8.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cédric Félizard
8
- autorequire:
9
- bindir: bin
8
+ autorequire:
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2018-03-01 00:00:00.000000000 Z
11
+ date: 2023-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simplecov
@@ -16,30 +16,30 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.15'
19
+ version: 0.21.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.15'
26
+ version: 0.21.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: aruba
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.14.3
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 0.14.3
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: coveralls
42
+ name: bundler-audit
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: mutant-rspec
70
+ name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rake
84
+ name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: rspec
98
+ name: rubocop
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,7 +109,21 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: rubocop
112
+ name: rubocop-rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rspec
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - ">="
@@ -139,11 +153,17 @@ dependencies:
139
153
  description: Code coverage tool for Bash
140
154
  email:
141
155
  - cedric@felizard.fr
142
- executables:
143
- - bashcov
156
+ executables: []
144
157
  extensions: []
145
158
  extra_rdoc_files: []
146
159
  files:
160
+ - ".build.yml"
161
+ - ".github/FUNDING.yml"
162
+ - ".gitignore"
163
+ - ".gitlab-ci.yml"
164
+ - ".rspec"
165
+ - ".rubocop.yml"
166
+ - ".simplecov"
147
167
  - CHANGELOG.md
148
168
  - CONTRIBUTING.md
149
169
  - Gemfile
@@ -151,10 +171,11 @@ files:
151
171
  - LICENSE.txt
152
172
  - README.md
153
173
  - Rakefile
174
+ - TESTING.md
175
+ - USAGE.md
154
176
  - bashcov.gemspec
155
177
  - bin/bashcov
156
178
  - lib/bashcov.rb
157
- - lib/bashcov/bash_info.rb
158
179
  - lib/bashcov/detective.rb
159
180
  - lib/bashcov/errors.rb
160
181
  - lib/bashcov/field_stream.rb
@@ -163,11 +184,16 @@ files:
163
184
  - lib/bashcov/runner.rb
164
185
  - lib/bashcov/version.rb
165
186
  - lib/bashcov/xtrace.rb
187
+ - test.sh
166
188
  homepage: https://github.com/infertux/bashcov
167
189
  licenses:
168
190
  - MIT
169
- metadata: {}
170
- post_install_message:
191
+ metadata:
192
+ homepage_uri: https://github.com/infertux/bashcov
193
+ source_code_uri: https://github.com/infertux/bashcov
194
+ changelog_uri: https://github.com/infertux/bashcov/blob/master/CHANGELOG.md
195
+ rubygems_mfa_required: 'true'
196
+ post_install_message:
171
197
  rdoc_options: []
172
198
  require_paths:
173
199
  - lib
@@ -175,16 +201,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
175
201
  requirements:
176
202
  - - ">="
177
203
  - !ruby/object:Gem::Version
178
- version: 2.3.0
204
+ version: 3.0.0
179
205
  required_rubygems_version: !ruby/object:Gem::Requirement
180
206
  requirements:
181
207
  - - ">="
182
208
  - !ruby/object:Gem::Version
183
209
  version: '0'
184
210
  requirements: []
185
- rubyforge_project:
186
- rubygems_version: 2.7.4
187
- signing_key:
211
+ rubygems_version: 3.4.10
212
+ signing_key:
188
213
  specification_version: 4
189
- summary: Code coverage tool for Bash
214
+ summary: ''
190
215
  test_files: []
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bashcov
4
- # Module exposing information concerning the installed Bash version
5
- # @note methods do not cache results because +bash_path+ can change at
6
- # runtime
7
- # @note receiver is expected to implement +bash_path+
8
- module BashInfo
9
- # @return [Boolean] Whether Bash supports +BASH_XTRACEFD+
10
- def bash_xtracefd?
11
- BASH_VERSION >= "4.1"
12
- end
13
-
14
- # @param [Integer] length the number of bytes to test; default 128
15
- # @return [Boolean] whether Bash supports a +PS4+ of at least a given
16
- # number of bytes
17
- # @see https://tiswww.case.edu/php/chet/bash/CHANGES
18
- # @note Item +i.+ under the +bash-4.2-release+ to +bash-4.3-alpha+ change
19
- # list notes that version 4.2 truncates +PS4+ if it is greater than 128
20
- # bytes.
21
- def truncated_ps4?(length = 128)
22
- ps4 = SecureRandom.base64(length)
23
- !`PS4=#{ps4} #{bash_path} 2>&1 1>&- -xc 'echo hello'`.start_with?(ps4)
24
- end
25
- end
26
- end