This is a re-roll of [1] which teaches --chain-lint to detect broken
&&-chains in subshells since the existing implementation[2] detects
breakage only at the top-level. It is built atop 'es/test-fixes', which
was split off of [1] and submitted separately[3], and which fixes many
broken &&-chains.

The major difference since v1 is that broken &&-chains in subshells are
now detected by pure textual inspection rather than by merging subshell
commands into the top-level &&-chain. Thus, v2 entirely sidesteps the
primary objection[4] raised during v1 review of possible unintended
side-effects of test code executing outside of the intended directory.
The pure textual detection implemented by v2 can have no such
side-effects.

A second important difference since v1 is that the "linter" itself, a
complex 'sed' script, now has its own tests to ensure correct behavior.
Not only do the tests protect against regressions, but they help to
document (for humans) expected behavior, which is important since 'sed'
scripts can seem rather inscrutable due to looking like line-noise and
due to the 'sed' "language" being stack-oriented (albeit with a very
tiny stack) which, like other stack-oriented languages (Forth,
Postscript, etc.) can be difficult to reason about.

Although the 'sed' script in v1 was already well-commented, the comments
have been improved in v2. More importantly, a high-level overview of the
script's operation has been added at the top of the file to aid
comprehension.

Thanks to Elijah, Hannes, Jonathan Nieder, Jonathan Tan, Junio, Luke,
Peff, and Stefan for comments on v1.

[1]: https://public-inbox.org/git/20180626073001.6555-1-sunsh...@sunshineco.com/
[2]: https://public-inbox.org/git/20150320100429.ga17...@peff.net/
[3]: https://public-inbox.org/git/20180702002405.3042-1-sunsh...@sunshineco.com/
[4]: https://public-inbox.org/git/xmqqwouljr5e....@gitster-ct.c.googlers.com/

Eric Sunshine (10):
  t/test-lib: teach --chain-lint to detect broken &&-chains in subshells
  t/Makefile: add machinery to check correctness of chainlint.sed
  t/chainlint: add chainlint "basic" test cases
  t/chainlint: add chainlint "whitespace" test cases
  t/chainlint: add chainlint "one-liner" test cases
  t/chainlint: add chainlint "nested subshell" test cases
  t/chainlint: add chainlint "loop" and "conditional" test cases
  t/chainlint: add chainlint "cuddled" test cases
  t/chainlint: add chainlint "complex" test cases
  t/chainlint: add chainlint "specialized" test cases

 t/.gitignore                                  |   1 +
 t/Makefile                                    |  25 +-
 t/chainlint.sed                               | 346 ++++++++++++++++++
 t/chainlint/arithmetic-expansion.expect       |   9 +
 t/chainlint/arithmetic-expansion.test         |  11 +
 t/chainlint/bash-array.expect                 |  10 +
 t/chainlint/bash-array.test                   |  12 +
 t/chainlint/blank-line.expect                 |   4 +
 t/chainlint/blank-line.test                   |  10 +
 t/chainlint/block.expect                      |  12 +
 t/chainlint/block.test                        |  15 +
 t/chainlint/broken-chain.expect               |   6 +
 t/chainlint/broken-chain.test                 |   8 +
 t/chainlint/case.expect                       |  19 +
 t/chainlint/case.test                         |  23 ++
 .../close-nested-and-parent-together.expect   |   4 +
 .../close-nested-and-parent-together.test     |   3 +
 t/chainlint/close-subshell.expect             |  25 ++
 t/chainlint/close-subshell.test               |  27 ++
 t/chainlint/command-substitution.expect       |   9 +
 t/chainlint/command-substitution.test         |  11 +
 t/chainlint/comment.expect                    |   4 +
 t/chainlint/comment.test                      |  11 +
 t/chainlint/complex-if-in-cuddled-loop.expect |  10 +
 t/chainlint/complex-if-in-cuddled-loop.test   |  11 +
 t/chainlint/cuddled-if-then-else.expect       |   7 +
 t/chainlint/cuddled-if-then-else.test         |   7 +
 t/chainlint/cuddled-loop.expect               |   5 +
 t/chainlint/cuddled-loop.test                 |   7 +
 t/chainlint/cuddled.expect                    |  21 ++
 t/chainlint/cuddled.test                      |  23 ++
 t/chainlint/exit-loop.expect                  |  24 ++
 t/chainlint/exit-loop.test                    |  27 ++
 t/chainlint/exit-subshell.expect              |   5 +
 t/chainlint/exit-subshell.test                |   6 +
 t/chainlint/for-loop.expect                   |  11 +
 t/chainlint/for-loop.test                     |  19 +
 t/chainlint/here-doc.expect                   |   3 +
 t/chainlint/here-doc.test                     |  16 +
 t/chainlint/if-in-loop.expect                 |  12 +
 t/chainlint/if-in-loop.test                   |  15 +
 t/chainlint/if-then-else.expect               |  19 +
 t/chainlint/if-then-else.test                 |  28 ++
 t/chainlint/incomplete-line.expect            |   4 +
 t/chainlint/incomplete-line.test              |  12 +
 t/chainlint/inline-comment.expect             |   9 +
 t/chainlint/inline-comment.test               |  12 +
 t/chainlint/loop-in-if.expect                 |  12 +
 t/chainlint/loop-in-if.test                   |  15 +
 ...ti-line-nested-command-substitution.expect |   9 +
 ...ulti-line-nested-command-substitution.test |   9 +
 t/chainlint/multi-line-string.expect          |   9 +
 t/chainlint/multi-line-string.test            |  15 +
 t/chainlint/negated-one-liner.expect          |   5 +
 t/chainlint/negated-one-liner.test            |   7 +
 t/chainlint/nested-cuddled-subshell.expect    |  19 +
 t/chainlint/nested-cuddled-subshell.test      |  31 ++
 t/chainlint/nested-here-doc.expect            |   5 +
 t/chainlint/nested-here-doc.test              |  23 ++
 t/chainlint/nested-subshell-comment.expect    |  11 +
 t/chainlint/nested-subshell-comment.test      |  13 +
 t/chainlint/nested-subshell.expect            |  12 +
 t/chainlint/nested-subshell.test              |  14 +
 t/chainlint/one-liner.expect                  |   9 +
 t/chainlint/one-liner.test                    |  12 +
 t/chainlint/p4-filespec.expect                |   4 +
 t/chainlint/p4-filespec.test                  |   5 +
 t/chainlint/pipe.expect                       |   8 +
 t/chainlint/pipe.test                         |  12 +
 t/chainlint/semicolon.expect                  |  20 +
 t/chainlint/semicolon.test                    |  25 ++
 t/chainlint/subshell-here-doc.expect          |   5 +
 t/chainlint/subshell-here-doc.test            |  23 ++
 t/chainlint/subshell-one-liner.expect         |  14 +
 t/chainlint/subshell-one-liner.test           |  24 ++
 t/chainlint/while-loop.expect                 |  11 +
 t/chainlint/while-loop.test                   |  19 +
 t/test-lib.sh                                 |   3 +-
 78 files changed, 1316 insertions(+), 5 deletions(-)
 create mode 100644 t/chainlint.sed
 create mode 100644 t/chainlint/arithmetic-expansion.expect
 create mode 100644 t/chainlint/arithmetic-expansion.test
 create mode 100644 t/chainlint/bash-array.expect
 create mode 100644 t/chainlint/bash-array.test
 create mode 100644 t/chainlint/blank-line.expect
 create mode 100644 t/chainlint/blank-line.test
 create mode 100644 t/chainlint/block.expect
 create mode 100644 t/chainlint/block.test
 create mode 100644 t/chainlint/broken-chain.expect
 create mode 100644 t/chainlint/broken-chain.test
 create mode 100644 t/chainlint/case.expect
 create mode 100644 t/chainlint/case.test
 create mode 100644 t/chainlint/close-nested-and-parent-together.expect
 create mode 100644 t/chainlint/close-nested-and-parent-together.test
 create mode 100644 t/chainlint/close-subshell.expect
 create mode 100644 t/chainlint/close-subshell.test
 create mode 100644 t/chainlint/command-substitution.expect
 create mode 100644 t/chainlint/command-substitution.test
 create mode 100644 t/chainlint/comment.expect
 create mode 100644 t/chainlint/comment.test
 create mode 100644 t/chainlint/complex-if-in-cuddled-loop.expect
 create mode 100644 t/chainlint/complex-if-in-cuddled-loop.test
 create mode 100644 t/chainlint/cuddled-if-then-else.expect
 create mode 100644 t/chainlint/cuddled-if-then-else.test
 create mode 100644 t/chainlint/cuddled-loop.expect
 create mode 100644 t/chainlint/cuddled-loop.test
 create mode 100644 t/chainlint/cuddled.expect
 create mode 100644 t/chainlint/cuddled.test
 create mode 100644 t/chainlint/exit-loop.expect
 create mode 100644 t/chainlint/exit-loop.test
 create mode 100644 t/chainlint/exit-subshell.expect
 create mode 100644 t/chainlint/exit-subshell.test
 create mode 100644 t/chainlint/for-loop.expect
 create mode 100644 t/chainlint/for-loop.test
 create mode 100644 t/chainlint/here-doc.expect
 create mode 100644 t/chainlint/here-doc.test
 create mode 100644 t/chainlint/if-in-loop.expect
 create mode 100644 t/chainlint/if-in-loop.test
 create mode 100644 t/chainlint/if-then-else.expect
 create mode 100644 t/chainlint/if-then-else.test
 create mode 100644 t/chainlint/incomplete-line.expect
 create mode 100644 t/chainlint/incomplete-line.test
 create mode 100644 t/chainlint/inline-comment.expect
 create mode 100644 t/chainlint/inline-comment.test
 create mode 100644 t/chainlint/loop-in-if.expect
 create mode 100644 t/chainlint/loop-in-if.test
 create mode 100644 t/chainlint/multi-line-nested-command-substitution.expect
 create mode 100644 t/chainlint/multi-line-nested-command-substitution.test
 create mode 100644 t/chainlint/multi-line-string.expect
 create mode 100644 t/chainlint/multi-line-string.test
 create mode 100644 t/chainlint/negated-one-liner.expect
 create mode 100644 t/chainlint/negated-one-liner.test
 create mode 100644 t/chainlint/nested-cuddled-subshell.expect
 create mode 100644 t/chainlint/nested-cuddled-subshell.test
 create mode 100644 t/chainlint/nested-here-doc.expect
 create mode 100644 t/chainlint/nested-here-doc.test
 create mode 100644 t/chainlint/nested-subshell-comment.expect
 create mode 100644 t/chainlint/nested-subshell-comment.test
 create mode 100644 t/chainlint/nested-subshell.expect
 create mode 100644 t/chainlint/nested-subshell.test
 create mode 100644 t/chainlint/one-liner.expect
 create mode 100644 t/chainlint/one-liner.test
 create mode 100644 t/chainlint/p4-filespec.expect
 create mode 100644 t/chainlint/p4-filespec.test
 create mode 100644 t/chainlint/pipe.expect
 create mode 100644 t/chainlint/pipe.test
 create mode 100644 t/chainlint/semicolon.expect
 create mode 100644 t/chainlint/semicolon.test
 create mode 100644 t/chainlint/subshell-here-doc.expect
 create mode 100644 t/chainlint/subshell-here-doc.test
 create mode 100644 t/chainlint/subshell-one-liner.expect
 create mode 100644 t/chainlint/subshell-one-liner.test
 create mode 100644 t/chainlint/while-loop.expect
 create mode 100644 t/chainlint/while-loop.test

-- 
2.18.0.203.gfac676dfb9

Reply via email to