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.
- 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
|
+
[](https://liberapay.com/infertux/donate)
|
|
4
|
+
[](https://liberapay.com/infertux)
|
|
3
5
|
[](https://rubygems.org/gems/bashcov)
|
|
4
|
-
[](https://coveralls.io/r/infertux/bashcov)
|
|
6
|
-
[](https://gemnasium.com/infertux/bashcov)
|
|
6
|
+
[](https://gitlab.com/infertux/bashcov/-/pipelines)
|
|
7
7
|
[](https://codeclimate.com/github/infertux/bashcov/maintainability)
|
|
8
|
+
[](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
|
|