bashcov 0.0.6 → 0.0.7

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: 6613eed0d116984da22b7fb51ddd45617e148928
4
+ data.tar.gz: 289ef645df22d964dbe8275837458fe5e044d110
5
+ SHA512:
6
+ metadata.gz: 6e461f96cde82d60a97f7458cdf40cfcaac55621c4cf0c0c028ac859880f1d3c3b569b5270331ef7754da2d9cfe77bea3ec892c5e80df27ebeb72a432ab6be3d
7
+ data.tar.gz: 5c4af2c0ad3e0c51e6d7cb5b4ca5288326781b6ef068d22b63ec32abe4cf1898ab518c7bd16dc2ee1709d9f16e1e1dcef3e0b699259dca31478d33771d459893
data/.travis.yml CHANGED
@@ -10,3 +10,4 @@ rvm:
10
10
  matrix:
11
11
  allow_failures:
12
12
  - rvm: ruby-head
13
+ - rvm: rbx-19mode
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Bashcov [![Build Status](https://secure.travis-ci.org/infertux/bashcov.png?branch=master)](https://travis-ci.org/infertux/bashcov) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/infertux/bashcov)
1
+ # Bashcov [![Build Status](https://secure.travis-ci.org/infertux/bashcov.png?branch=master)](https://travis-ci.org/infertux/bashcov) [![Code Climate](https://codeclimate.com/github/infertux/bashcov.png)](https://codeclimate.com/github/infertux/bashcov)
2
2
 
3
3
  [bashcov] is [simplecov] for Bash.
4
4
 
@@ -37,10 +37,6 @@ After a bit of parsing, it sends results through _simplecov_ which generates an
37
37
 
38
38
  And of course, you can take the most of _simplecov_ by adding a `.simplecov` file in your project's root (like [this](https://github.com/infertux/bashcov/blob/master/spec/test_app/.simplecov)).
39
39
 
40
- ## Todo
41
-
42
- - semver
43
-
44
40
  ## License
45
41
 
46
42
  MIT
data/bashcov.gemspec CHANGED
@@ -19,7 +19,6 @@ Gem::Specification.new do |gem|
19
19
  gem.require_paths = ["lib"]
20
20
 
21
21
  gem.add_dependency 'simplecov'
22
- gem.add_dependency 'open4'
23
22
 
24
23
  gem.add_development_dependency 'rake'
25
24
  gem.add_development_dependency 'rspec'
data/lib/bashcov.rb CHANGED
@@ -26,6 +26,42 @@ module Bashcov
26
26
  # @raise [SystemExit] if invalid arguments are given
27
27
  # @return [void]
28
28
  def parse_options! args
29
+ option_parser.parse!(args)
30
+
31
+ if args.empty?
32
+ abort("You must give exactly one command to execute.")
33
+ else
34
+ @options.command = args.join(' ')
35
+ end
36
+ end
37
+
38
+ # @return [String] The project's root directory
39
+ def root_directory
40
+ Dir.getwd
41
+ end
42
+
43
+ # Program name including version for easy consistent output
44
+ # @return [String]
45
+ def name
46
+ "bashcov v#{VERSION}"
47
+ end
48
+
49
+ # Helper to get a pre-filled coverage array for a given file
50
+ # @todo This is generic and should be moved in some helpers file.
51
+ # @api private
52
+ # @param [String] filename The file to cover.
53
+ # @param [nil, Integer] fill Value to fill the array with.
54
+ # @return [Array] An array of the size of the given file.
55
+ # @example
56
+ # coverage_array('file.rb') #=> [0, 0, 0] # assuming file.rb has 3 lines
57
+ def coverage_array(filename, fill = Line::UNCOVERED)
58
+ lines = File.readlines(filename).size
59
+ [fill] * lines
60
+ end
61
+
62
+ private
63
+
64
+ def option_parser
29
65
  OptionParser.new do |opts|
30
66
  opts.program_name = 'bashcov'
31
67
  opts.version = Bashcov::VERSION
@@ -58,39 +94,8 @@ module Bashcov
58
94
  puts opts.ver
59
95
  exit
60
96
  end
61
-
62
- end.parse!(args)
63
-
64
- if args.empty?
65
- abort("You must give exactly one command to execute.")
66
- else
67
- @options.command = args.join(' ')
68
97
  end
69
98
  end
70
-
71
- # @return [String] The project's root directory
72
- def root_directory
73
- Dir.getwd
74
- end
75
-
76
- # Program name including version for easy consistent output
77
- # @return [String]
78
- def name
79
- "bashcov v#{VERSION}"
80
- end
81
-
82
- # Helper to get a pre-filled coverage array for a given file
83
- # @todo This is generic and should be moved in some helpers file.
84
- # @api private
85
- # @param [String] filename The file to cover.
86
- # @param [nil, Integer] fill Value to fill the array with.
87
- # @return [Array] An array of the size of the given file.
88
- # @example
89
- # coverage_array('file.rb') #=> [0, 0, 0] # assuming file.rb has 3 lines
90
- def coverage_array(filename, fill = Line::UNCOVERED)
91
- lines = File.readlines(filename).size
92
- [fill] * lines
93
- end
94
99
  end
95
100
  end
96
101
 
data/lib/bashcov/lexer.rb CHANGED
@@ -28,6 +28,7 @@ module Bashcov
28
28
 
29
29
  line.empty? or
30
30
  start_with.any? { |token| line.start_with? token } or
31
+ end_with.any? { |token| line.end_with? token } or
31
32
  is.any? { |keyword| line == keyword } or
32
33
  line =~ /\A\w+\(\) {/ # function declared like this: "foo() {"
33
34
  end
@@ -41,5 +42,10 @@ module Bashcov
41
42
  def start_with
42
43
  %w(# function)
43
44
  end
45
+
46
+ # Lines ending with one of these tokens are irrelevant for coverage
47
+ def end_with
48
+ %w(\()
49
+ end
44
50
  end
45
51
  end
@@ -1,47 +1,27 @@
1
- require 'open4'
2
-
3
1
  module Bashcov
4
- # Runs a given command capturing output then computes code coverage.
2
+ # Runs a given command with xtrace enabled then computes code coverage.
5
3
  class Runner
6
- # @return [Array] +stdout+ from the last run
7
- attr_reader :stdout
8
-
9
- # @return [Array] +stderr+ from the last run
10
- attr_reader :stderr
11
-
12
4
  # @param [String] command Command to run
13
5
  def initialize command
14
6
  @command = command
15
7
  end
16
8
 
17
- # Runs the command capturing +stdout+ and +stderr+.
9
+ # Runs the command with appropriate xtrace settings.
18
10
  # @note Binds Bashcov +stdin+ to the program executed.
19
- # @note Uses two threads to stream +stdout+ and +stderr+ output in
20
- # realtime.
21
- # @return [void]
11
+ # @return [Process::Status] Status of the executed command
22
12
  def run
23
- setup
13
+ inject_xtrace_flag!
24
14
 
25
- Open4::popen4(@command) do |pid, stdin, stdout, stderr|
26
- stdin = $stdin # bind stdin
15
+ @xtrace = Xtrace.new
16
+ fd = @xtrace.file_descriptor
17
+ @command = "BASH_XTRACEFD=#{fd} PS4='#{Xtrace.ps4}' #{@command}"
18
+ options = {:in => :in, fd => fd} # bind fds to the child process
19
+ options.merge!({out: '/dev/null', err: '/dev/null'}) if Bashcov.options.mute
27
20
 
28
- [
29
- Thread.new { # stdout
30
- stdout.each do |line|
31
- @stdout << line
32
- $stdout.puts line unless Bashcov.options.mute
33
- end
34
- },
35
- Thread.new { # stderr
36
- stderr.each do |line|
37
- @stderr << line
38
- next if Bashcov.options.mute
39
- xtrace = Xtrace.new [line]
40
- $stderr.puts line if xtrace.xtrace_output.empty?
41
- end
42
- }
43
- ].map(&:join)
44
- end
21
+ pid = Process.spawn @command, options
22
+ Process.wait pid
23
+
24
+ $?
45
25
  end
46
26
 
47
27
  # @return [Hash] Coverage hash of the last run
@@ -72,9 +52,7 @@ module Bashcov
72
52
  # @return [Hash] Given hash including coverage result from {Xtrace}
73
53
  # @see Xtrace
74
54
  def add_coverage_result files
75
- xtraced_files = Xtrace.new(@stderr).files
76
-
77
- xtraced_files.each do |file, lines|
55
+ @xtrace.files.each do |file, lines|
78
56
  lines.each_with_index do |line, lineno|
79
57
  files[file] ||= Bashcov.coverage_array(file)
80
58
  files[file][lineno] = line if line
@@ -98,16 +76,7 @@ module Bashcov
98
76
 
99
77
  private
100
78
 
101
- def setup
102
- inject_xtrace_flag
103
-
104
- @stdout = []
105
- @stderr = []
106
-
107
- @command = "PS4='#{Xtrace.ps4}' #{@command}"
108
- end
109
-
110
- def inject_xtrace_flag
79
+ def inject_xtrace_flag!
111
80
  # SHELLOPTS must be exported so we use Ruby's ENV variable
112
81
  existing_flags = (ENV['SHELLOPTS'] || '').split(':')
113
82
  ENV['SHELLOPTS'] = (existing_flags | ['xtrace']).join(':')
@@ -1,4 +1,4 @@
1
1
  module Bashcov
2
2
  # Bashcov version
3
- VERSION = "0.0.6"
3
+ VERSION = "0.0.7"
4
4
  end
@@ -1,19 +1,19 @@
1
+ require 'tempfile'
2
+
1
3
  module Bashcov
2
4
  # This class manages +xtrace+ output.
3
5
  #
4
6
  # @see Runner
5
7
  class Xtrace
6
- # @param [Array] output Array of output lines.
7
- # @raise [ArgumentError] if the given +output+ is not an array
8
- def initialize output
9
- raise ArgumentError, "#{output} must be an array" unless output.is_a? Array
10
- @lines = output
8
+ # Creates a temporary file for xtrace output
9
+ def initialize
10
+ @xtrace_file = Tempfile.new 'xtrace_output'
11
+ @xtrace_file.unlink # unlink on create so other programs cannot access it
11
12
  end
12
13
 
13
- # Filters out non-xtrace lines.
14
- # @return [Array] xtrace output
15
- def xtrace_output
16
- @lines.select { |line| line =~ Xtrace.line_regexp }
14
+ # @return [Fixnum] File descriptor of the output file
15
+ def file_descriptor
16
+ @xtrace_file.fileno
17
17
  end
18
18
 
19
19
  # Parses xtrace output and computes coverage
@@ -22,17 +22,17 @@ module Bashcov
22
22
  def files
23
23
  files = {}
24
24
 
25
- xtrace_output.each do |line|
26
- match = line.match(Xtrace.line_regexp)
25
+ @xtrace_file.rewind
26
+ @xtrace_file.read.each_line do |line|
27
+ match = line.match(self.class.line_regexp)
28
+ next if match.nil? # multiline instruction
29
+
27
30
  filename = File.expand_path(match[:filename], Bashcov.root_directory)
28
31
  next if File.directory? filename
29
32
  raise "#{filename} is not a file" unless File.file? filename
30
33
 
31
- lineno = match[:lineno].to_i
32
- lineno -= 1 if lineno > 0
33
-
34
+ lineno = match[:lineno].to_i - 1
34
35
  files[filename] ||= Bashcov.coverage_array(filename)
35
-
36
36
  files[filename][lineno] += 1
37
37
  end
38
38
 
@@ -46,7 +46,7 @@ module Bashcov
46
46
  # character in filenames on Unix and Windows.
47
47
 
48
48
  # http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in
49
- %Q{#{prefix}$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")/${LINENO} BASHCOV}
49
+ %Q{#{prefix}$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")/${LINENO} BASHCOV: }
50
50
  end
51
51
 
52
52
  private
@@ -62,7 +62,7 @@ module Bashcov
62
62
  end
63
63
 
64
64
  def self.line_regexp
65
- /\A#{depth_character}+#{prefix[1..-1]}(?<filename>.+)\/(?<lineno>\d+) BASHCOV/
65
+ /\A#{depth_character}+#{prefix[1..-1]}(?<filename>.+)\/(?<lineno>\d+) BASHCOV: /
66
66
  end
67
67
  end
68
68
  end
@@ -93,14 +93,14 @@ describe Bashcov::Runner do
93
93
  end
94
94
  end
95
95
 
96
- context "with options.mute = false" do
96
+ context "with options.mute = true" do
97
97
  before do
98
- Bashcov.options.mute = false
98
+ Bashcov.options.mute = true
99
99
  end
100
100
 
101
- it "does not print xtrace output" do
102
- $stderr.should_receive(:puts).at_least(:once) do |line|
103
- line.should_not match Bashcov::Xtrace.line_regexp
101
+ it "does not print the command output" do
102
+ [$stdout, $stderr].each do |io|
103
+ io.should_not_receive :write
104
104
  end
105
105
 
106
106
  runner.run
@@ -29,7 +29,7 @@ end
29
29
  def expected_coverage
30
30
  {
31
31
  "#{test_app}/never_called.sh" => [nil, nil, 0, nil],
32
- "#{test_app}/scripts/case.sh" => [nil, nil, nil, 2, 1, nil, 0, 0, 1, nil, nil, nil, 1, 1, nil],
32
+ "#{test_app}/scripts/case.sh" => [nil, nil, nil, 6, 1, nil, 0, 0, 1, nil, nil, nil, 1, 1, nil],
33
33
  "#{test_app}/scripts/function.sh" => [nil, nil, nil, 2, nil, nil, nil, 1, 1, nil, nil, 1, 1, nil],
34
34
  "#{test_app}/scripts/long_line.sh" => [nil, nil, 1, 1, 1, 0, nil],
35
35
  "#{test_app}/scripts/nested/simple.sh" => [nil, nil, nil, nil, 1, 1, nil, 0, nil, nil, 1, nil, nil],
@@ -37,10 +37,9 @@ def expected_coverage
37
37
  "#{test_app}/scripts/simple.sh" => [nil, nil, nil, nil, 1, 1, nil, 0, nil, nil, 1, nil, nil],
38
38
  "#{test_app}/scripts/source.sh" => [nil, nil, 1, nil, 2, nil],
39
39
  "#{test_app}/scripts/sourced.txt" => [nil, nil, 1, nil],
40
- "#{test_app}/scripts/stdin.sh" => [nil, nil, 1, 1, 1, nil],
41
- "#{test_app}/scripts/multiline.sh" => [nil, nil, 1, 2, 1, 1, 0, nil],
40
+ "#{test_app}/scripts/multiline.sh" => [nil, nil, 1, 2, 1, 1, 0, nil, nil, 0, 1, 2], # XXX the 3 last lines should be [1, 1, 1] - Bash bug
42
41
  "#{test_app}/scripts/executable" => [nil, nil, 1, nil],
43
- "#{test_app}/test_suite.sh" => [nil, nil, 2, nil, nil, 2, nil]
42
+ "#{test_app}/test_suite.sh" => [nil, nil, 2, nil, 1, nil]
44
43
  }
45
44
  end
46
45
 
@@ -6,3 +6,7 @@
6
6
  echo 'what?' || \
7
7
  echo 'no!'
8
8
 
9
+ variable=($(
10
+ echo hi
11
+ ))
12
+ echo after
@@ -2,6 +2,5 @@
2
2
 
3
3
  cd $(dirname $0)
4
4
 
5
- # `date` is sent on stdin for each file
6
- date | find scripts -type f -executable -exec '{}' \;
5
+ find scripts -type f -executable -exec '{}' \;
7
6
 
metadata CHANGED
@@ -1,142 +1,111 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bashcov
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
5
- prerelease:
4
+ version: 0.0.7
6
5
  platform: ruby
7
6
  authors:
8
7
  - Cédric Félizard
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-06 00:00:00.000000000 Z
11
+ date: 2013-03-05 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: simplecov
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
30
- - !ruby/object:Gem::Dependency
31
- name: open4
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
38
- type: :runtime
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
24
+ - - '>='
44
25
  - !ruby/object:Gem::Version
45
26
  version: '0'
46
27
  - !ruby/object:Gem::Dependency
47
28
  name: rake
48
29
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
30
  requirements:
51
- - - ! '>='
31
+ - - '>='
52
32
  - !ruby/object:Gem::Version
53
33
  version: '0'
54
34
  type: :development
55
35
  prerelease: false
56
36
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
37
  requirements:
59
- - - ! '>='
38
+ - - '>='
60
39
  - !ruby/object:Gem::Version
61
40
  version: '0'
62
41
  - !ruby/object:Gem::Dependency
63
42
  name: rspec
64
43
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
44
  requirements:
67
- - - ! '>='
45
+ - - '>='
68
46
  - !ruby/object:Gem::Version
69
47
  version: '0'
70
48
  type: :development
71
49
  prerelease: false
72
50
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
51
  requirements:
75
- - - ! '>='
52
+ - - '>='
76
53
  - !ruby/object:Gem::Version
77
54
  version: '0'
78
55
  - !ruby/object:Gem::Dependency
79
56
  name: guard-rspec
80
57
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
58
  requirements:
83
- - - ! '>='
59
+ - - '>='
84
60
  - !ruby/object:Gem::Version
85
61
  version: '0'
86
62
  type: :development
87
63
  prerelease: false
88
64
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
65
  requirements:
91
- - - ! '>='
66
+ - - '>='
92
67
  - !ruby/object:Gem::Version
93
68
  version: '0'
94
69
  - !ruby/object:Gem::Dependency
95
70
  name: rb-inotify
96
71
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
72
  requirements:
99
- - - ! '>='
73
+ - - '>='
100
74
  - !ruby/object:Gem::Version
101
75
  version: '0'
102
76
  type: :development
103
77
  prerelease: false
104
78
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
79
  requirements:
107
- - - ! '>='
80
+ - - '>='
108
81
  - !ruby/object:Gem::Version
109
82
  version: '0'
110
83
  - !ruby/object:Gem::Dependency
111
84
  name: cane
112
85
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
86
  requirements:
115
- - - ! '>='
87
+ - - '>='
116
88
  - !ruby/object:Gem::Version
117
89
  version: '0'
118
90
  type: :development
119
91
  prerelease: false
120
92
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
93
  requirements:
123
- - - ! '>='
94
+ - - '>='
124
95
  - !ruby/object:Gem::Version
125
96
  version: '0'
126
97
  - !ruby/object:Gem::Dependency
127
98
  name: yard
128
99
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
100
  requirements:
131
- - - ! '>='
101
+ - - '>='
132
102
  - !ruby/object:Gem::Version
133
103
  version: '0'
134
104
  type: :development
135
105
  prerelease: false
136
106
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
107
  requirements:
139
- - - ! '>='
108
+ - - '>='
140
109
  - !ruby/object:Gem::Version
141
110
  version: '0'
142
111
  description: Code coverage tool for Bash
@@ -165,7 +134,6 @@ files:
165
134
  - lib/bashcov/xtrace.rb
166
135
  - spec/bashcov/lexer_spec.rb
167
136
  - spec/bashcov/runner_spec.rb
168
- - spec/bashcov/xtrace_spec.rb
169
137
  - spec/bashcov_spec.rb
170
138
  - spec/spec_helper.rb
171
139
  - spec/support/common.rb
@@ -184,37 +152,34 @@ files:
184
152
  - spec/test_app/scripts/simple.sh
185
153
  - spec/test_app/scripts/source.sh
186
154
  - spec/test_app/scripts/sourced.txt
187
- - spec/test_app/scripts/stdin.sh
188
155
  - spec/test_app/test_suite.sh
189
156
  homepage: https://github.com/infertux/bashcov
190
157
  licenses:
191
158
  - MIT
159
+ metadata: {}
192
160
  post_install_message:
193
161
  rdoc_options: []
194
162
  require_paths:
195
163
  - lib
196
164
  required_ruby_version: !ruby/object:Gem::Requirement
197
- none: false
198
165
  requirements:
199
- - - ! '>='
166
+ - - '>='
200
167
  - !ruby/object:Gem::Version
201
168
  version: '0'
202
169
  required_rubygems_version: !ruby/object:Gem::Requirement
203
- none: false
204
170
  requirements:
205
- - - ! '>='
171
+ - - '>='
206
172
  - !ruby/object:Gem::Version
207
173
  version: '0'
208
174
  requirements: []
209
175
  rubyforge_project:
210
- rubygems_version: 1.8.24
176
+ rubygems_version: 2.0.0
211
177
  signing_key:
212
- specification_version: 3
178
+ specification_version: 4
213
179
  summary: Code coverage tool for Bash
214
180
  test_files:
215
181
  - spec/bashcov/lexer_spec.rb
216
182
  - spec/bashcov/runner_spec.rb
217
- - spec/bashcov/xtrace_spec.rb
218
183
  - spec/bashcov_spec.rb
219
184
  - spec/spec_helper.rb
220
185
  - spec/support/common.rb
@@ -233,6 +198,5 @@ test_files:
233
198
  - spec/test_app/scripts/simple.sh
234
199
  - spec/test_app/scripts/source.sh
235
200
  - spec/test_app/scripts/sourced.txt
236
- - spec/test_app/scripts/stdin.sh
237
201
  - spec/test_app/test_suite.sh
238
202
  has_rdoc:
@@ -1,20 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Bashcov::Xtrace do
4
- let(:xtrace) {
5
- runner = Bashcov::Runner.new test_suite
6
- runner.run
7
- Bashcov::Xtrace.new runner.stderr
8
- }
9
-
10
- describe "#files" do
11
- let(:files) { xtrace.files }
12
- subject { files }
13
-
14
- it { should be_a Hash }
15
-
16
- it "contains expected files" do
17
- subject.keys.should =~ executed_files
18
- end
19
- end
20
- end
@@ -1,6 +0,0 @@
1
- #!/bin/bash
2
-
3
- echo "What's your input?"
4
- read
5
- echo "All right, you entered \`${REPLY}'."
6
-