bashcov 1.8.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.build.yml +11 -0
- data/.github/FUNDING.yml +3 -0
- data/.gitignore +19 -0
- data/.gitlab-ci.yml +57 -0
- data/.rspec +4 -0
- data/.rubocop.yml +55 -0
- data/.simplecov +9 -0
- data/CHANGELOG.md +23 -1
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +39 -120
- data/Rakefile +7 -2
- data/TESTING.md +4 -0
- data/USAGE.md +66 -0
- data/bashcov.gemspec +33 -27
- data/bin/bashcov +13 -3
- data/lib/bashcov/detective.rb +3 -3
- data/lib/bashcov/field_stream.rb +37 -25
- data/lib/bashcov/lexer.rb +10 -7
- data/lib/bashcov/runner.rb +65 -44
- data/lib/bashcov/version.rb +1 -1
- data/lib/bashcov/xtrace.rb +10 -5
- data/lib/bashcov.rb +33 -10
- data/test.sh +10 -0
- metadata +50 -25
- data/lib/bashcov/bash_info.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dffc7667dad0e51e2e47f4c4df861d52be6240aff021c7c7771c2e4f8219f862
|
4
|
+
data.tar.gz: d720302f22dacf1ac91853301d65ac0a24ac3ff17415fa7fdb42fc1e6b906079
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 284281285d8c60d800753fd0f4ff697d0a5e6faf246a64dfd1509f2cca4f3c6e0f5e91e417e76de2014937b91ada9fee4fcc266ad16dc8d1d106a3912cb6f524
|
7
|
+
data.tar.gz: cf79ef6c4e814d112c1255fe9fc59956537b7ad830eda345063395f5c7676895efcdbf7ec899185563e50577df756afb929bf6cb71b9106daeeef93d330dd5a9
|
data/.build.yml
ADDED
data/.github/FUNDING.yml
ADDED
data/.gitignore
ADDED
data/.gitlab-ci.yml
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Official language image. Look for the different tagged releases at:
|
2
|
+
# https://hub.docker.com/r/library/ruby/tags/
|
3
|
+
image: ruby:latest
|
4
|
+
|
5
|
+
before_script:
|
6
|
+
- ruby -v
|
7
|
+
- bundle install -j $(nproc)
|
8
|
+
- ./spec/install_bash.sh
|
9
|
+
- bash --version
|
10
|
+
- id
|
11
|
+
- env
|
12
|
+
|
13
|
+
audit:
|
14
|
+
script:
|
15
|
+
- bundle exec rake bundle:audit:update
|
16
|
+
- bundle exec rake bundle:audit:check
|
17
|
+
|
18
|
+
build:
|
19
|
+
script:
|
20
|
+
- bundle exec rake build
|
21
|
+
- bundle exec rake build:checksum
|
22
|
+
- cat checksums/*
|
23
|
+
|
24
|
+
cucumber:
|
25
|
+
script: bundle exec rake cucumber
|
26
|
+
|
27
|
+
# Current Bash versions can be found at https://git.savannah.gnu.org/cgit/bash.git
|
28
|
+
rspec-bash-5.2:
|
29
|
+
variables:
|
30
|
+
INSTALL_BASH_VERSION: "5.2"
|
31
|
+
script: bundle exec rake spec
|
32
|
+
|
33
|
+
rspec-bash-5.1:
|
34
|
+
variables:
|
35
|
+
INSTALL_BASH_VERSION: "5.1"
|
36
|
+
script: bundle exec rake spec
|
37
|
+
|
38
|
+
rspec-bash-5.0:
|
39
|
+
variables:
|
40
|
+
INSTALL_BASH_VERSION: "5.0"
|
41
|
+
script: bundle exec rake spec
|
42
|
+
|
43
|
+
rspec-bash-4.4:
|
44
|
+
variables:
|
45
|
+
INSTALL_BASH_VERSION: "4.4"
|
46
|
+
script: bundle exec rake spec
|
47
|
+
|
48
|
+
rspec-bash-4.3:
|
49
|
+
variables:
|
50
|
+
INSTALL_BASH_VERSION: "4.3"
|
51
|
+
script: bundle exec rake spec
|
52
|
+
|
53
|
+
rubocop:
|
54
|
+
script: bundle exec rake rubocop
|
55
|
+
|
56
|
+
yard:
|
57
|
+
script: bundle exec yard stats --list-undoc
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rake
|
3
|
+
- rubocop-rspec
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
TargetRubyVersion: 3.0
|
7
|
+
NewCops: enable
|
8
|
+
|
9
|
+
Metrics:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Gemspec/DevelopmentDependencies:
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
Layout/AccessModifierIndentation:
|
16
|
+
EnforcedStyle: outdent
|
17
|
+
|
18
|
+
Layout/LineLength:
|
19
|
+
Enabled: 100
|
20
|
+
|
21
|
+
Lint/RedundantSplatExpansion:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
RSpec/ExampleLength:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
RSpec/InstanceVariable:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
RSpec/MessageSpies:
|
31
|
+
EnforcedStyle: receive
|
32
|
+
|
33
|
+
RSpec/MultipleExpectations:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
RSpec/NamedSubject:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
RSpec/NestedGroups:
|
40
|
+
Enabled: false
|
41
|
+
|
42
|
+
Style/ParallelAssignment:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
Style/StringLiterals:
|
46
|
+
EnforcedStyle: double_quotes
|
47
|
+
|
48
|
+
Style/SpecialGlobalVars:
|
49
|
+
Enabled: false
|
50
|
+
|
51
|
+
Style/TrailingCommaInArrayLiteral:
|
52
|
+
EnforcedStyleForMultiline: comma
|
53
|
+
|
54
|
+
Style/TrailingCommaInHashLiteral:
|
55
|
+
EnforcedStyleForMultiline: comma
|
data/.simplecov
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,29 @@
|
|
1
|
-
## Unreleased ([changes](https://github.com/infertux/bashcov/compare/
|
1
|
+
## Unreleased ([changes](https://github.com/infertux/bashcov/compare/v3.0.0...master))
|
2
2
|
|
3
3
|
* TBD
|
4
4
|
|
5
|
+
## v3.0.0, 2023-04-10 ([changes](https://github.com/infertux/bashcov/compare/v1.8.2...v3.0.0))
|
6
|
+
|
7
|
+
* [MISC] New minimum Bash version supported is 4.3
|
8
|
+
* [MISC] New minimum Ruby version supported is 3.0
|
9
|
+
* [BUGFIX] Running Bashcov as root is now working (especially useful with Docker) although it is not recommended (#31, #43 and #56)
|
10
|
+
* [BUGFIX] Fix comments preceded by tabs not filtered out (#68)
|
11
|
+
* [BUGFIX] Fix two-line multilines not being treated as related (#67)
|
12
|
+
* [BUGFIX] Redefine `BASH_VERSION` when `bash_path` is read from command options (#57)
|
13
|
+
* [BUGFIX] Mute output from Bashcov and SimpleCov when requested (#54)
|
14
|
+
* [BUGFIX] Correctly handle empty scripts by short-circuiting
|
15
|
+
`FieldStream#each` if the reader stream is at end-of-file before
|
16
|
+
the start-of-fields pattern is encountered (#41)
|
17
|
+
* [FEATURE] Bashcov omits from the coverage results any files that match one
|
18
|
+
or more of the filters in `SimpleCov.filters` (#38)
|
19
|
+
* [FEATURE] Ensure that files matching the `SimpleCov.tracked_files` glob
|
20
|
+
pattern are included in the coverage results, regardless of
|
21
|
+
whether `Bashcov.skip_uncovered` is enabled (#38)
|
22
|
+
|
23
|
+
## v1.8.2, 2018-03-27 ([changes](https://github.com/infertux/bashcov/compare/v1.8.1...v1.8.2))
|
24
|
+
|
25
|
+
* [BUGFIX] Fix coverage for complex heredoc constructions (#32)
|
26
|
+
|
5
27
|
## v1.8.1, 2018-03-01 ([changes](https://github.com/infertux/bashcov/compare/v1.8.0...v1.8.1))
|
6
28
|
|
7
29
|
* [BUGFIX] Fix incorrect coverage for some multiline strings (#35)
|
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,146 +1,65 @@
|
|
1
1
|
# Bashcov
|
2
2
|
|
3
|
+
[![Funding](https://img.shields.io/liberapay/patrons/infertux.svg?logo=liberapay)](https://liberapay.com/infertux/donate)
|
4
|
+
[![Sponsors](https://img.shields.io/liberapay/patrons/infertux)](https://liberapay.com/infertux)
|
3
5
|
[![Gem Version](https://img.shields.io/gem/v/bashcov.svg)](https://rubygems.org/gems/bashcov)
|
4
|
-
[![Build Status](https://
|
5
|
-
[![Coverage Status](https://coveralls.io/repos/infertux/bashcov/badge.png?branch=master)](https://coveralls.io/r/infertux/bashcov)
|
6
|
-
[![Dependency Status](https://gemnasium.com/infertux/bashcov.png)](https://gemnasium.com/infertux/bashcov)
|
6
|
+
[![Build Status](https://gitlab.com/infertux/bashcov/badges/master/pipeline.svg)](https://gitlab.com/infertux/bashcov/-/pipelines)
|
7
7
|
[![Maintainability](https://api.codeclimate.com/v1/badges/083fdbba795049cd5f06/maintainability)](https://codeclimate.com/github/infertux/bashcov/maintainability)
|
8
|
+
[![Inline docs](http://inch-ci.org/github/infertux/bashcov.svg)](http://inch-ci.org/github/infertux/bashcov)
|
8
9
|
|
9
|
-
**
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
[
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
[
|
26
|
-
[
|
27
|
-
[Bashcov]: https://github.com/infertux/bashcov
|
28
|
-
[SimpleCov]: https://github.com/colszowka/simplecov "Bashcov is backed by SimpleCov to generate awesome coverage report"
|
29
|
-
[Test app demo]: https://infertux.github.com/bashcov/test_app/ "Coverage for the bundled test application"
|
30
|
-
|
31
|
-
You should check out these coverage examples - it's worth a thousand words:
|
32
|
-
|
33
|
-
- [Test app demo]
|
34
|
-
- [RVM demo](https://infertux.github.com/bashcov/rvm/ "Coverage for RVM")
|
10
|
+
Bashcov is a **code coverage analysis tool for Bash**.
|
11
|
+
|
12
|
+
In most cases, you'll want overall coverage results for your project from
|
13
|
+
[shUnit2](https://github.com/kward/shunit2),
|
14
|
+
[Bats](https://github.com/bats-core/bats-core),
|
15
|
+
[bash_unit](https://github.com/pgrange/bash_unit),
|
16
|
+
[assert.sh](https://github.com/lehmannro/assert.sh),
|
17
|
+
[bashaspec](https://github.com/d10n/bashaspec),
|
18
|
+
etc.
|
19
|
+
Bashcov automatically takes care of this by caching and merging results when generating reports,
|
20
|
+
so your report includes coverage across your test suites and thereby gives you a better picture of blank spots.
|
21
|
+
|
22
|
+
It uses the [SimpleCov](https://github.com/colszowka/simplecov) coverage library to generate HTML reports.
|
23
|
+
SimpleCov gets installed automatically when you install Bashcov.
|
24
|
+
|
25
|
+
Here are example coverages generated by Bashcov:
|
26
|
+
[test app demo](https://infertux.github.io/bashcov/test_app/ "Coverage for the bundled test application") &
|
27
|
+
[RVM demo](https://infertux.github.io/bashcov/rvm/ "Coverage for RVM").
|
35
28
|
|
36
29
|
## Installation
|
37
30
|
|
38
|
-
|
31
|
+
`gem install bashcov`
|
32
|
+
|
33
|
+
If the `gem` command is unavailable, you need to [install Ruby](https://www.ruby-lang.org/en/documentation/installation/) first.
|
39
34
|
|
40
35
|
## Usage
|
41
36
|
|
42
|
-
|
43
|
-
Here are some examples:
|
37
|
+
`bashcov --help` prints all available options. Here are some examples:
|
44
38
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
39
|
+
bashcov ./script.sh
|
40
|
+
bashcov --skip-uncovered ./script.sh
|
41
|
+
bashcov -- ./script.sh --some --flags
|
42
|
+
bashcov --skip-uncovered -- ./script.sh --some --flags
|
49
43
|
|
50
|
-
|
51
|
-
Bashcov will keep track of all executed scripts.
|
44
|
+
`./script.sh` can be a mere Bash script or typically your CI script. Bashcov will keep track of all executed scripts.
|
52
45
|
|
53
|
-
|
54
|
-
Open `./coverage/index.html` to browse the coverage report.
|
46
|
+
It will create a directory named `./coverage/`, you may open `./coverage/index.html` to browse the coverage report.
|
55
47
|
|
56
48
|
### SimpleCov integration
|
57
49
|
|
58
|
-
You can
|
59
|
-
your project's root
|
60
|
-
See [
|
61
|
-
information.
|
62
|
-
|
63
|
-
#### Controlling the command name
|
64
|
-
|
65
|
-
Bashcov respects all of your `.simplecov` settings save one --
|
66
|
-
[`SimpleCov.command_name`](http://www.rubydoc.info/gems/simplecov/SimpleCov/Configuration#command_name-instance_method),
|
67
|
-
which is the tag that SimpleCov attaches to coverage results from a particular
|
68
|
-
test suite. You can set the value of `SimpleCov.command_name` by using
|
69
|
-
Bashcov's `--command-name` option, or by assigning a value to the environment
|
70
|
-
variable `BASHCOV_COMMAND_NAME`. Otherwise, Bashcov will generate a command
|
71
|
-
name for you based on the name of the currently-executing Bash script and any
|
72
|
-
arguments passed to it. For example, assuming your Bash lives at `/bin/bash`
|
73
|
-
and you run the command
|
74
|
-
|
75
|
-
```
|
76
|
-
$ bashcov -- ./test_suite.sh --and some --flags
|
77
|
-
```
|
78
|
-
|
79
|
-
Bashcov will set `SimpleCov.command_name` to `"/bin/bash ./test_suite.sh --and
|
80
|
-
some --flags"`. Basing `SimpleCov.command_name` on the executing command helps
|
81
|
-
to ensure that multiple coverage runs don't [overwrite each other's
|
82
|
-
results](https://github.com/colszowka/simplecov#test-suite-names) due to
|
83
|
-
SimpleCov identifying multiple runs by the same tag. The `--command-name` and
|
84
|
-
`BASHCOV_COMMAND_NAME` knobs are there for you to twiddle in case your test
|
85
|
-
suite runs the exact same `bashcov` command more than once, in which case the
|
86
|
-
generated command name will not distinguish each invocation from the others.
|
87
|
-
|
88
|
-
For more info on `SimpleCov.command_name` and its relation to SimpleCov's
|
89
|
-
result-merging behavior, see the [SimpleCov
|
90
|
-
README](https://github.com/colszowka/simplecov#merging-results).
|
91
|
-
|
92
|
-
### Some gory details
|
93
|
-
|
94
|
-
Figuring out where an executing Bash script lives in the file system can be
|
95
|
-
surprisingly difficult. Bash offers a fair amount of [introspection into its
|
96
|
-
internals](https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html),
|
97
|
-
but the location of the current script has to be inferred from the limited
|
98
|
-
information available through `BASH_SOURCE`, `PWD`, and `OLDPWD` (and
|
99
|
-
potentially `DIRSTACK` if you are using `pushd`/`popd`). For this purpose,
|
100
|
-
Bashcov puts Bash in debug mode and sets up a `PS4` that expands the values of
|
101
|
-
these variables, reading them on each command that Bash executes. But, given
|
102
|
-
that:
|
103
|
-
|
104
|
-
* `BASH_SOURCE` is only an absolute path if the script was invoked using an
|
105
|
-
absolute path,
|
106
|
-
* the builtins `cd`, `pushd`, and `popd` alter `PWD` and `OLDPWD`, and
|
107
|
-
* none of these variables are read-only and can therefore be `unset` or
|
108
|
-
otherwise altered,
|
109
|
-
|
110
|
-
it can be easy to lose track of where we are.
|
111
|
-
|
112
|
-
_"Wait a minute, what about `pwd`, `readlink`, and so on?"_ That would be great,
|
113
|
-
except that subshells executed as part of expanding the `PS4` can cause Bash to
|
114
|
-
report [extra executions](https://github.com/infertux/bashcov/commit/4130874e30a05b7ab6ea66fb96a19acaa973c178)
|
115
|
-
for [certain lines](https://github.com/infertux/bashcov/pull/16). Also,
|
116
|
-
subshells are slow as the `PS4` is expanded on each and every command when Bash
|
117
|
-
is in debug mode.
|
118
|
-
|
119
|
-
To deal with these limitations, Bashcov uses the expedient of maintaining two
|
120
|
-
stacks that track changes to `PWD` and `OLDPWD`. To determine the full path to
|
121
|
-
the executing script, Bashcov iterates in reverse over the `PWD` stack, testing
|
122
|
-
for the first `$PWD/$BASH_SOURCE` combination that refers to an existing file.
|
123
|
-
This heuristic is susceptible to false positives -- under certain combinations
|
124
|
-
of directory structure, script invocation paths, and working directory changes,
|
125
|
-
it may yield a path that doesn't refer to the currently-running script.
|
126
|
-
However, it performs well under the various working directory changes performed
|
127
|
-
in the [test app demo] and avoids the spurious extra hits caused by using
|
128
|
-
subshells in the `PS4`.
|
129
|
-
|
130
|
-
One final note on innards: Bash 4.3 fixed a bug in which `PS4` expansion is
|
131
|
-
truncated to a maximum of 128 characters. On platforms whose Bash version
|
132
|
-
suffers from this bug, Bashcov uses the ASCII record separator character to
|
133
|
-
delimit the `PS4` fields, whereas it uses a long random string on Bash 4.3 and
|
134
|
-
above. When the field delimiter appears in the path of a script under test or
|
135
|
-
in a command the script executes, Bashcov won't correctly parse the `PS4` and
|
136
|
-
will abort early with incomplete coverage results.
|
50
|
+
You can leverage the underlying library [SimpleCov](https://github.com/colszowka/simplecov)
|
51
|
+
by adding a `.simplecov` file in your project's root, like [this](https://github.com/infertux/bashcov/blob/master/spec/test_app/.simplecov).
|
52
|
+
See [advanced usage](./USAGE.md) for more information.
|
137
53
|
|
138
54
|
## Contributing
|
139
55
|
|
140
56
|
Bug reports and patches are most welcome.
|
141
57
|
See the [contribution guidelines](https://github.com/infertux/bashcov/blob/master/CONTRIBUTING.md).
|
142
58
|
|
59
|
+
## Sponsorship
|
60
|
+
|
61
|
+
Bashcov was [created in 2012](https://github.com/infertux/bashcov/commit/f65e65e5aa3377beb334beee9924136a34a913e8) and it needs your help. I have been maintaining the project for over a decade and keeping it working with new releases of Bash and Ruby takes time. If you use Bashcov professionally, please considerer supporting it on [Liberapay](https://liberapay.com/infertux) through your employer or directly. Thank you for supporting *Free and Open-Source Software*.
|
62
|
+
|
143
63
|
## License
|
144
64
|
|
145
65
|
MIT
|
146
|
-
|
data/Rakefile
CHANGED
@@ -2,8 +2,13 @@
|
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
|
5
|
+
require "bundler/audit/task"
|
6
|
+
Bundler::Audit::Task.new
|
7
|
+
|
5
8
|
require "cucumber/rake/task"
|
6
|
-
Cucumber::Rake::Task.new
|
9
|
+
Cucumber::Rake::Task.new do |t|
|
10
|
+
t.cucumber_opts = %w[--publish-quiet]
|
11
|
+
end
|
7
12
|
|
8
13
|
require "rspec/core/rake_task"
|
9
14
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
@@ -13,4 +18,4 @@ end
|
|
13
18
|
require "rubocop/rake_task"
|
14
19
|
RuboCop::RakeTask.new
|
15
20
|
|
16
|
-
task default: %i[
|
21
|
+
task default: %i[bundle:audit cucumber spec rubocop]
|
data/TESTING.md
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
`bundle exec rake` will run a quick test suite with the current Bash and Ruby version.
|
2
|
+
|
3
|
+
`./test.sh` will run all [GitLab CI pipelines](https://gitlab.com/infertux/bashcov/-/pipelines) locally.
|
4
|
+
You'll need [Docker](https://www.docker.com/) and [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) installed on your machine.
|
data/USAGE.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
### Controlling the command name
|
2
|
+
|
3
|
+
Bashcov respects all of your `.simplecov` settings save one --
|
4
|
+
[`SimpleCov.command_name`](http://www.rubydoc.info/gems/simplecov/SimpleCov/Configuration#command_name-instance_method),
|
5
|
+
which is the tag that SimpleCov attaches to coverage results from a particular
|
6
|
+
test suite. You can set the value of `SimpleCov.command_name` by using
|
7
|
+
Bashcov's `--command-name` option, or by assigning a value to the environment
|
8
|
+
variable `BASHCOV_COMMAND_NAME`. Otherwise, Bashcov will generate a command
|
9
|
+
name for you based on the name of the currently-executing Bash script and any
|
10
|
+
arguments passed to it. For example, assuming your Bash lives at `/bin/bash`
|
11
|
+
and you run the command
|
12
|
+
|
13
|
+
```
|
14
|
+
bashcov -- ./test_suite.sh --and some --flags
|
15
|
+
```
|
16
|
+
|
17
|
+
Bashcov will set `SimpleCov.command_name` to `"/bin/bash ./test_suite.sh --and
|
18
|
+
some --flags"`. Basing `SimpleCov.command_name` on the executing command helps
|
19
|
+
to ensure that multiple coverage runs don't [overwrite each other's
|
20
|
+
results](https://github.com/colszowka/simplecov#test-suite-names) due to
|
21
|
+
SimpleCov identifying multiple runs by the same tag. The `--command-name` and
|
22
|
+
`BASHCOV_COMMAND_NAME` knobs are there for you to twiddle in case your test
|
23
|
+
suite runs the exact same `bashcov` command more than once, in which case the
|
24
|
+
generated command name will not distinguish each invocation from the others.
|
25
|
+
|
26
|
+
For more info on `SimpleCov.command_name` and its relation to SimpleCov's
|
27
|
+
result-merging behavior, see the [SimpleCov
|
28
|
+
README](https://github.com/colszowka/simplecov#merging-results).
|
29
|
+
|
30
|
+
### Some gory details
|
31
|
+
|
32
|
+
Figuring out where an executing Bash script lives in the file system can be
|
33
|
+
surprisingly difficult. Bash offers a fair amount of [introspection into its
|
34
|
+
internals](https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html),
|
35
|
+
but the location of the current script has to be inferred from the limited
|
36
|
+
information available through `BASH_SOURCE`, `PWD`, and `OLDPWD` (and
|
37
|
+
potentially `DIRSTACK` if you are using `pushd`/`popd`). For this purpose,
|
38
|
+
Bashcov puts Bash in debug mode and sets up a `PS4` that expands the values of
|
39
|
+
these variables, reading them on each command that Bash executes. But, given
|
40
|
+
that:
|
41
|
+
|
42
|
+
* `BASH_SOURCE` is only an absolute path if the script was invoked using an
|
43
|
+
absolute path,
|
44
|
+
* the builtins `cd`, `pushd`, and `popd` alter `PWD` and `OLDPWD`, and
|
45
|
+
* none of these variables are read-only and can therefore be `unset` or
|
46
|
+
otherwise altered,
|
47
|
+
|
48
|
+
it can be easy to lose track of where we are.
|
49
|
+
|
50
|
+
_"Wait a minute, what about `pwd`, `readlink`, and so on?"_ That would be great,
|
51
|
+
except that subshells executed as part of expanding the `PS4` can cause Bash to
|
52
|
+
report [extra executions](https://github.com/infertux/bashcov/commit/4130874e30a05b7ab6ea66fb96a19acaa973c178)
|
53
|
+
for [certain lines](https://github.com/infertux/bashcov/pull/16). Also,
|
54
|
+
subshells are slow as the `PS4` is expanded on each and every command when Bash
|
55
|
+
is in debug mode.
|
56
|
+
|
57
|
+
To deal with these limitations, Bashcov uses the expedient of maintaining two
|
58
|
+
stacks that track changes to `PWD` and `OLDPWD`. To determine the full path to
|
59
|
+
the executing script, Bashcov iterates in reverse over the `PWD` stack, testing
|
60
|
+
for the first `$PWD/$BASH_SOURCE` combination that refers to an existing file.
|
61
|
+
This heuristic is susceptible to false positives -- under certain combinations
|
62
|
+
of directory structure, script invocation paths, and working directory changes,
|
63
|
+
it may yield a path that doesn't refer to the currently-running script.
|
64
|
+
However, it performs well under the various working directory changes performed
|
65
|
+
in the [test app demo] and avoids the spurious extra hits caused by using
|
66
|
+
subshells in the `PS4`.
|
data/bashcov.gemspec
CHANGED
@@ -1,36 +1,42 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require "bashcov/version"
|
3
|
+
require_relative "lib/bashcov/version"
|
6
4
|
|
7
|
-
Gem::Specification.new do |
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
gem.description = "Code coverage tool for Bash"
|
13
|
-
gem.summary = gem.description
|
14
|
-
gem.homepage = "https://github.com/infertux/bashcov"
|
15
|
-
gem.license = "MIT"
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "bashcov"
|
7
|
+
spec.version = Bashcov::VERSION
|
8
|
+
spec.authors = ["Cédric Félizard"]
|
9
|
+
spec.email = ["cedric@felizard.fr"]
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
spec.summary = spec.description
|
12
|
+
spec.description = "Code coverage tool for Bash"
|
13
|
+
spec.homepage = "https://github.com/infertux/bashcov"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = ">= 3.0.0"
|
20
16
|
|
21
|
-
|
22
|
-
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/infertux/bashcov"
|
19
|
+
spec.metadata["changelog_uri"] = "https://github.com/infertux/bashcov/blob/master/CHANGELOG.md"
|
23
20
|
|
24
|
-
gem
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
25
29
|
|
26
|
-
|
30
|
+
spec.add_dependency "simplecov", "~> 0.21.2"
|
27
31
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
spec.add_development_dependency "aruba"
|
33
|
+
spec.add_development_dependency "bundler-audit"
|
34
|
+
spec.add_development_dependency "cucumber"
|
35
|
+
spec.add_development_dependency "rake"
|
36
|
+
spec.add_development_dependency "rspec"
|
37
|
+
spec.add_development_dependency "rubocop"
|
38
|
+
spec.add_development_dependency "rubocop-rake"
|
39
|
+
spec.add_development_dependency "rubocop-rspec"
|
40
|
+
spec.add_development_dependency "yard"
|
41
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
36
42
|
end
|
data/bin/bashcov
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
lib = File.expand_path("
|
4
|
+
lib = File.expand_path("../lib", __dir__)
|
5
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
6
|
|
7
7
|
require "bashcov"
|
@@ -26,8 +26,18 @@ if SimpleCov.use_merging
|
|
26
26
|
end
|
27
27
|
|
28
28
|
SimpleCov.at_exit do
|
29
|
-
puts "Run completed using #{Bashcov.fullname}"
|
30
|
-
|
29
|
+
puts "Run completed using #{Bashcov.fullname}" unless Bashcov.mute
|
30
|
+
|
31
|
+
begin
|
32
|
+
# XXX: suppress output from https://github.com/colszowka/simplecov-html/blob/9ec41504ab139fabfaddfc786dfdab5d6aca0bab/lib/simplecov-html.rb#L25
|
33
|
+
# See https://github.com/infertux/bashcov/issues/53
|
34
|
+
original_stdout = $stdout
|
35
|
+
$stdout = StringIO.new if Bashcov.mute
|
36
|
+
|
37
|
+
result.format!
|
38
|
+
ensure
|
39
|
+
$stdout = original_stdout
|
40
|
+
end
|
31
41
|
end
|
32
42
|
|
33
43
|
exit status.exitstatus
|
data/lib/bashcov/detective.rb
CHANGED
@@ -34,7 +34,7 @@ module Bashcov
|
|
34
34
|
return false unless File.exist?(filename) && File.readable?(filename) \
|
35
35
|
&& File.file?(File.realpath(filename))
|
36
36
|
|
37
|
-
shellscript_shebang?(filename) ||
|
37
|
+
shellscript_shebang?(filename) ||
|
38
38
|
(shellscript_extension?(filename) && shellscript_syntax?(filename))
|
39
39
|
end
|
40
40
|
|
@@ -54,10 +54,10 @@ module Bashcov
|
|
54
54
|
|
55
55
|
return false unless shebang[0..1] == "#!"
|
56
56
|
|
57
|
-
shell, arg = shebang[2
|
57
|
+
shell, arg = shebang[2..].split(/\s+/, 2)
|
58
58
|
shell_basename = File.basename(shell)
|
59
59
|
|
60
|
-
SHELL_BASENAMES.include?(shell_basename) ||
|
60
|
+
SHELL_BASENAMES.include?(shell_basename) ||
|
61
61
|
(OTHER_BASENAMES.include?(shell_basename) && SHELL_BASENAMES.include?(arg))
|
62
62
|
end
|
63
63
|
|