diff options
Diffstat (limited to 't/chainlint')
144 files changed, 1900 insertions, 0 deletions
diff --git a/t/chainlint/arithmetic-expansion.expect b/t/chainlint/arithmetic-expansion.expect new file mode 100644 index 0000000..46ee104 --- /dev/null +++ b/t/chainlint/arithmetic-expansion.expect @@ -0,0 +1,9 @@ +( + foo && + bar=$((42 + 1)) && + baz +) && +( + bar=$((42 + 1)) ?!AMP?! + baz +) diff --git a/t/chainlint/arithmetic-expansion.test b/t/chainlint/arithmetic-expansion.test new file mode 100644 index 0000000..1620696 --- /dev/null +++ b/t/chainlint/arithmetic-expansion.test @@ -0,0 +1,11 @@ +( + foo && +# LINT: closing ")" of $((...)) not misinterpreted as subshell-closing ")" + bar=$((42 + 1)) && + baz +) && +( +# LINT: missing "&&" on $((...)) + bar=$((42 + 1)) + baz +) diff --git a/t/chainlint/bash-array.expect b/t/chainlint/bash-array.expect new file mode 100644 index 0000000..4c34eae --- /dev/null +++ b/t/chainlint/bash-array.expect @@ -0,0 +1,10 @@ +( + foo && + bar=(gumbo stumbo wumbo) && + baz +) && +( + foo && + bar=${#bar[@]} && + baz +) diff --git a/t/chainlint/bash-array.test b/t/chainlint/bash-array.test new file mode 100644 index 0000000..92bbb77 --- /dev/null +++ b/t/chainlint/bash-array.test @@ -0,0 +1,12 @@ +( + foo && +# LINT: ")" in Bash array assignment not misinterpreted as subshell-closing ")" + bar=(gumbo stumbo wumbo) && + baz +) && +( + foo && +# LINT: Bash array length operator not misinterpreted as comment + bar=${#bar[@]} && + baz +) diff --git a/t/chainlint/blank-line-before-esac.expect b/t/chainlint/blank-line-before-esac.expect new file mode 100644 index 0000000..48ed4eb --- /dev/null +++ b/t/chainlint/blank-line-before-esac.expect @@ -0,0 +1,18 @@ +test_done ( ) { + case "$test_failure" in + 0 ) + test_at_end_hook_ + + exit 0 ;; + + * ) + if test $test_external_has_tap -eq 0 + then + say_color error "# failed $test_failure among $msg" + say "1..$test_count" + fi + + exit 1 ;; + + esac +} diff --git a/t/chainlint/blank-line-before-esac.test b/t/chainlint/blank-line-before-esac.test new file mode 100644 index 0000000..cecccad --- /dev/null +++ b/t/chainlint/blank-line-before-esac.test @@ -0,0 +1,19 @@ +# LINT: blank line before "esac" +test_done () { + case "$test_failure" in + 0) + test_at_end_hook_ + + exit 0 ;; + + *) + if test $test_external_has_tap -eq 0 + then + say_color error "# failed $test_failure among $msg" + say "1..$test_count" + fi + + exit 1 ;; + + esac +} diff --git a/t/chainlint/blank-line.expect b/t/chainlint/blank-line.expect new file mode 100644 index 0000000..f76fde1 --- /dev/null +++ b/t/chainlint/blank-line.expect @@ -0,0 +1,4 @@ +( + nothing && + something +) diff --git a/t/chainlint/blank-line.test b/t/chainlint/blank-line.test new file mode 100644 index 0000000..0fdf15b --- /dev/null +++ b/t/chainlint/blank-line.test @@ -0,0 +1,10 @@ +( + + nothing && + + something +# LINT: ignore blank lines since final _statement_ before subshell end is +# LINT: significant to "&&"-check, not final _line_ (which might be blank) + + +) diff --git a/t/chainlint/block-comment.expect b/t/chainlint/block-comment.expect new file mode 100644 index 0000000..df2beea --- /dev/null +++ b/t/chainlint/block-comment.expect @@ -0,0 +1,8 @@ +( + { + # show a + echo a && + # show b + echo b + } +) diff --git a/t/chainlint/block-comment.test b/t/chainlint/block-comment.test new file mode 100644 index 0000000..df2beea --- /dev/null +++ b/t/chainlint/block-comment.test @@ -0,0 +1,8 @@ +( + { + # show a + echo a && + # show b + echo b + } +) diff --git a/t/chainlint/block.expect b/t/chainlint/block.expect new file mode 100644 index 0000000..a3bcea4 --- /dev/null +++ b/t/chainlint/block.expect @@ -0,0 +1,23 @@ +( + foo && + { + echo a ?!AMP?! + echo b + } && + bar && + { + echo c + } ?!AMP?! + baz +) && + +{ + echo a ; ?!AMP?! echo b +} && +{ echo a ; ?!AMP?! echo b ; } && + +{ + echo "${var}9" && + echo "done" +} && +finis diff --git a/t/chainlint/block.test b/t/chainlint/block.test new file mode 100644 index 0000000..4ab69a4 --- /dev/null +++ b/t/chainlint/block.test @@ -0,0 +1,27 @@ +( +# LINT: missing "&&" after first "echo" + foo && + { + echo a + echo b + } && + bar && +# LINT: missing "&&" at closing "}" + { + echo c + } + baz +) && + +# LINT: ";" not allowed in place of "&&" +{ + echo a; echo b +} && +{ echo a; echo b; } && + +# LINT: "}" inside string not mistaken as end of block +{ + echo "${var}9" && + echo "done" +} && +finis diff --git a/t/chainlint/broken-chain.expect b/t/chainlint/broken-chain.expect new file mode 100644 index 0000000..cfb58fb --- /dev/null +++ b/t/chainlint/broken-chain.expect @@ -0,0 +1,6 @@ +( + foo && + bar ?!AMP?! + baz && + wop +) diff --git a/t/chainlint/broken-chain.test b/t/chainlint/broken-chain.test new file mode 100644 index 0000000..2a44aa7 --- /dev/null +++ b/t/chainlint/broken-chain.test @@ -0,0 +1,8 @@ +( + foo && +# LINT: missing "&&" from "bar" + bar + baz && +# LINT: final statement before closing ")" legitimately lacks "&&" + wop +) diff --git a/t/chainlint/case-comment.expect b/t/chainlint/case-comment.expect new file mode 100644 index 0000000..641c157 --- /dev/null +++ b/t/chainlint/case-comment.expect @@ -0,0 +1,11 @@ +( + case "$x" in + # found foo + x) foo ;; + # found other + *) + # treat it as bar + bar + ;; + esac +) diff --git a/t/chainlint/case-comment.test b/t/chainlint/case-comment.test new file mode 100644 index 0000000..641c157 --- /dev/null +++ b/t/chainlint/case-comment.test @@ -0,0 +1,11 @@ +( + case "$x" in + # found foo + x) foo ;; + # found other + *) + # treat it as bar + bar + ;; + esac +) diff --git a/t/chainlint/case.expect b/t/chainlint/case.expect new file mode 100644 index 0000000..31f280d --- /dev/null +++ b/t/chainlint/case.expect @@ -0,0 +1,19 @@ +( + case "$x" in + x) foo ;; + *) bar ;; + esac && + foobar +) && +( + case "$x" in + x) foo ;; + *) bar ;; + esac ?!AMP?! + foobar +) && +( + case "$x" in 1) true;; esac && + case "$y" in 2) false;; esac ?!AMP?! + foobar +) diff --git a/t/chainlint/case.test b/t/chainlint/case.test new file mode 100644 index 0000000..4cb086b --- /dev/null +++ b/t/chainlint/case.test @@ -0,0 +1,23 @@ +( +# LINT: "...)" arms in "case" not misinterpreted as subshell-closing ")" + case "$x" in + x) foo ;; + *) bar ;; + esac && + foobar +) && +( +# LINT: missing "&&" on "esac" + case "$x" in + x) foo ;; + *) bar ;; + esac + foobar +) && +( +# LINT: "...)" arm in one-liner "case" not misinterpreted as closing ")" + case "$x" in 1) true;; esac && +# LINT: same but missing "&&" + case "$y" in 2) false;; esac + foobar +) diff --git a/t/chainlint/chain-break-background.expect b/t/chainlint/chain-break-background.expect new file mode 100644 index 0000000..28f9114 --- /dev/null +++ b/t/chainlint/chain-break-background.expect @@ -0,0 +1,9 @@ +JGIT_DAEMON_PID= && +git init --bare empty.git && +> empty.git/git-daemon-export-ok && +mkfifo jgit_daemon_output && +{ + jgit daemon --port="$JGIT_DAEMON_PORT" . > jgit_daemon_output & + JGIT_DAEMON_PID=$! +} && +test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git diff --git a/t/chainlint/chain-break-background.test b/t/chainlint/chain-break-background.test new file mode 100644 index 0000000..e10f656 --- /dev/null +++ b/t/chainlint/chain-break-background.test @@ -0,0 +1,10 @@ +JGIT_DAEMON_PID= && +git init --bare empty.git && +>empty.git/git-daemon-export-ok && +mkfifo jgit_daemon_output && +{ +# LINT: exit status of "&" is always 0 so &&-chaining immaterial + jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output & + JGIT_DAEMON_PID=$! +} && +test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git diff --git a/t/chainlint/chain-break-continue.expect b/t/chainlint/chain-break-continue.expect new file mode 100644 index 0000000..47a3457 --- /dev/null +++ b/t/chainlint/chain-break-continue.expect @@ -0,0 +1,12 @@ +git ls-tree --name-only -r refs/notes/many_notes | +while read path +do + test "$path" = "foobar/non-note.txt" && continue + test "$path" = "deadbeef" && continue + test "$path" = "de/adbeef" && continue + + if test $(expr length "$path") -ne $hexsz + then + return 1 + fi +done diff --git a/t/chainlint/chain-break-continue.test b/t/chainlint/chain-break-continue.test new file mode 100644 index 0000000..f0af71d --- /dev/null +++ b/t/chainlint/chain-break-continue.test @@ -0,0 +1,13 @@ +git ls-tree --name-only -r refs/notes/many_notes | +while read path +do +# LINT: broken &&-chain okay if explicit "continue" + test "$path" = "foobar/non-note.txt" && continue + test "$path" = "deadbeef" && continue + test "$path" = "de/adbeef" && continue + + if test $(expr length "$path") -ne $hexsz + then + return 1 + fi +done diff --git a/t/chainlint/chain-break-false.expect b/t/chainlint/chain-break-false.expect new file mode 100644 index 0000000..989766f --- /dev/null +++ b/t/chainlint/chain-break-false.expect @@ -0,0 +1,9 @@ +if condition not satisified +then + echo it did not work... + echo failed! + false +else + echo it went okay ?!AMP?! + congratulate user +fi diff --git a/t/chainlint/chain-break-false.test b/t/chainlint/chain-break-false.test new file mode 100644 index 0000000..a5aaff8 --- /dev/null +++ b/t/chainlint/chain-break-false.test @@ -0,0 +1,10 @@ +# LINT: broken &&-chain okay if explicit "false" signals failure +if condition not satisified +then + echo it did not work... + echo failed! + false +else + echo it went okay + congratulate user +fi diff --git a/t/chainlint/chain-break-return-exit.expect b/t/chainlint/chain-break-return-exit.expect new file mode 100644 index 0000000..1732d22 --- /dev/null +++ b/t/chainlint/chain-break-return-exit.expect @@ -0,0 +1,19 @@ +case "$(git ls-files)" in +one ) echo pass one ;; +* ) echo bad one ; return 1 ;; +esac && +( + case "$(git ls-files)" in + two ) echo pass two ;; + * ) echo bad two ; exit 1 ;; +esac +) && +case "$(git ls-files)" in +dir/two"$LF"one ) echo pass both ;; +* ) echo bad ; return 1 ;; +esac && + +for i in 1 2 3 4 ; do + git checkout main -b $i || return $? + test_commit $i $i $i tag$i || return $? +done diff --git a/t/chainlint/chain-break-return-exit.test b/t/chainlint/chain-break-return-exit.test new file mode 100644 index 0000000..46542ed --- /dev/null +++ b/t/chainlint/chain-break-return-exit.test @@ -0,0 +1,23 @@ +case "$(git ls-files)" in +one) echo pass one ;; +# LINT: broken &&-chain okay if explicit "return 1" signals failuire +*) echo bad one; return 1 ;; +esac && +( + case "$(git ls-files)" in + two) echo pass two ;; +# LINT: broken &&-chain okay if explicit "exit 1" signals failuire + *) echo bad two; exit 1 ;; + esac +) && +case "$(git ls-files)" in +dir/two"$LF"one) echo pass both ;; +# LINT: broken &&-chain okay if explicit "return 1" signals failuire +*) echo bad; return 1 ;; +esac && + +for i in 1 2 3 4 ; do +# LINT: broken &&-chain okay if explicit "return $?" signals failure + git checkout main -b $i || return $? + test_commit $i $i $i tag$i || return $? +done diff --git a/t/chainlint/chain-break-status.expect b/t/chainlint/chain-break-status.expect new file mode 100644 index 0000000..f4bada9 --- /dev/null +++ b/t/chainlint/chain-break-status.expect @@ -0,0 +1,9 @@ +OUT=$(( ( large_git ; echo $? 1 >& 3 ) | : ) 3 >& 1) && +test_match_signal 13 "$OUT" && + +{ test-tool sigchain > actual ; ret=$? ; } && +{ + test_match_signal 15 "$ret" || + test "$ret" = 3 +} && +test_cmp expect actual diff --git a/t/chainlint/chain-break-status.test b/t/chainlint/chain-break-status.test new file mode 100644 index 0000000..a6602a7 --- /dev/null +++ b/t/chainlint/chain-break-status.test @@ -0,0 +1,11 @@ +# LINT: broken &&-chain okay if next command handles "$?" explicitly +OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) && +test_match_signal 13 "$OUT" && + +# LINT: broken &&-chain okay if next command handles "$?" explicitly +{ test-tool sigchain >actual; ret=$?; } && +{ + test_match_signal 15 "$ret" || + test "$ret" = 3 +} && +test_cmp expect actual diff --git a/t/chainlint/chained-block.expect b/t/chainlint/chained-block.expect new file mode 100644 index 0000000..574cdce --- /dev/null +++ b/t/chainlint/chained-block.expect @@ -0,0 +1,9 @@ +echo nobody home && { + test the doohicky ?!AMP?! + right now +} && + +GIT_EXTERNAL_DIFF=echo git diff | { + read path oldfile oldhex oldmode newfile newhex newmode && + test "z$oh" = "z$oldhex" +} diff --git a/t/chainlint/chained-block.test b/t/chainlint/chained-block.test new file mode 100644 index 0000000..86f81ec --- /dev/null +++ b/t/chainlint/chained-block.test @@ -0,0 +1,11 @@ +# LINT: start of block chained to preceding command +echo nobody home && { + test the doohicky + right now +} && + +# LINT: preceding command pipes to block on same line +GIT_EXTERNAL_DIFF=echo git diff | { + read path oldfile oldhex oldmode newfile newhex newmode && + test "z$oh" = "z$oldhex" +} diff --git a/t/chainlint/chained-subshell.expect b/t/chainlint/chained-subshell.expect new file mode 100644 index 0000000..af0369d --- /dev/null +++ b/t/chainlint/chained-subshell.expect @@ -0,0 +1,10 @@ +mkdir sub && ( + cd sub && + foo the bar ?!AMP?! + nuff said +) && + +cut "-d " -f actual | ( read s1 s2 s3 && +test -f $s1 ?!AMP?! +test $(cat $s2) = tree2path1 && +test $(cat $s3) = tree3path1 ) diff --git a/t/chainlint/chained-subshell.test b/t/chainlint/chained-subshell.test new file mode 100644 index 0000000..4ff6ddd --- /dev/null +++ b/t/chainlint/chained-subshell.test @@ -0,0 +1,13 @@ +# LINT: start of subshell chained to preceding command +mkdir sub && ( + cd sub && + foo the bar + nuff said +) && + +# LINT: preceding command pipes to subshell on same line +cut "-d " -f actual | (read s1 s2 s3 && +test -f $s1 +test $(cat $s2) = tree2path1 && +# LINT: closing subshell ")" correctly detected on same line as "$(...)" +test $(cat $s3) = tree3path1) diff --git a/t/chainlint/close-nested-and-parent-together.expect b/t/chainlint/close-nested-and-parent-together.expect new file mode 100644 index 0000000..72d482f --- /dev/null +++ b/t/chainlint/close-nested-and-parent-together.expect @@ -0,0 +1,3 @@ +(cd foo && + (bar && + baz)) diff --git a/t/chainlint/close-nested-and-parent-together.test b/t/chainlint/close-nested-and-parent-together.test new file mode 100644 index 0000000..72d482f --- /dev/null +++ b/t/chainlint/close-nested-and-parent-together.test @@ -0,0 +1,3 @@ +(cd foo && + (bar && + baz)) diff --git a/t/chainlint/close-subshell.expect b/t/chainlint/close-subshell.expect new file mode 100644 index 0000000..2192a28 --- /dev/null +++ b/t/chainlint/close-subshell.expect @@ -0,0 +1,26 @@ +( + foo +) && +( + bar +) >out && +( + baz +) 2>err && +( + boo +) <input && +( + bip +) | wuzzle && +( + bop +) | fazz \ + fozz && +( + bup +) | +fuzzle && +( + yop +) diff --git a/t/chainlint/close-subshell.test b/t/chainlint/close-subshell.test new file mode 100644 index 0000000..508ca44 --- /dev/null +++ b/t/chainlint/close-subshell.test @@ -0,0 +1,27 @@ +# LINT: closing ")" with various decorations ("&&", ">", "|", etc.) +( + foo +) && +( + bar +) >out && +( + baz +) 2>err && +( + boo +) <input && +( + bip +) | wuzzle && +( + bop +) | fazz \ + fozz && +( + bup +) | +fuzzle && +( + yop +) diff --git a/t/chainlint/command-substitution-subsubshell.expect b/t/chainlint/command-substitution-subsubshell.expect new file mode 100644 index 0000000..ab2f79e --- /dev/null +++ b/t/chainlint/command-substitution-subsubshell.expect @@ -0,0 +1,2 @@ +OUT=$(( ( large_git 1 >& 3 ) | : ) 3 >& 1) && +test_match_signal 13 "$OUT" diff --git a/t/chainlint/command-substitution-subsubshell.test b/t/chainlint/command-substitution-subsubshell.test new file mode 100644 index 0000000..321de29 --- /dev/null +++ b/t/chainlint/command-substitution-subsubshell.test @@ -0,0 +1,3 @@ +# LINT: subshell nested in subshell nested in command substitution +OUT=$( ((large_git 1>&3) | :) 3>&1 ) && +test_match_signal 13 "$OUT" diff --git a/t/chainlint/command-substitution.expect b/t/chainlint/command-substitution.expect new file mode 100644 index 0000000..c72e4df --- /dev/null +++ b/t/chainlint/command-substitution.expect @@ -0,0 +1,9 @@ +( + foo && + bar=$(gobble) && + baz +) && +( + bar=$(gobble blocks) ?!AMP?! + baz +) diff --git a/t/chainlint/command-substitution.test b/t/chainlint/command-substitution.test new file mode 100644 index 0000000..3bbb002 --- /dev/null +++ b/t/chainlint/command-substitution.test @@ -0,0 +1,11 @@ +( + foo && +# LINT: closing ")" of $(...) not misinterpreted as subshell-closing ")" + bar=$(gobble) && + baz +) && +( +# LINT: missing "&&" on $(...) + bar=$(gobble blocks) + baz +) diff --git a/t/chainlint/comment.expect b/t/chainlint/comment.expect new file mode 100644 index 0000000..a68f1f9 --- /dev/null +++ b/t/chainlint/comment.expect @@ -0,0 +1,8 @@ +( + # comment 1 + nothing && + # comment 2 + something + # comment 3 + # comment 4 +) diff --git a/t/chainlint/comment.test b/t/chainlint/comment.test new file mode 100644 index 0000000..113c0c4 --- /dev/null +++ b/t/chainlint/comment.test @@ -0,0 +1,11 @@ +( +# LINT: swallow comment lines + # comment 1 + nothing && + # comment 2 + something +# LINT: swallow comment lines since final _statement_ before subshell end is +# LINT: significant to "&&"-check, not final _line_ (which might be comment) + # comment 3 + # comment 4 +) diff --git a/t/chainlint/complex-if-in-cuddled-loop.expect b/t/chainlint/complex-if-in-cuddled-loop.expect new file mode 100644 index 0000000..dac2d0f --- /dev/null +++ b/t/chainlint/complex-if-in-cuddled-loop.expect @@ -0,0 +1,9 @@ +(for i in a b c; do + if test "$(echo $(waffle bat))" = "eleventeen" && + test "$x" = "$y"; then + : + else + echo >file + fi ?!LOOP?! + done) && +test ! -f file diff --git a/t/chainlint/complex-if-in-cuddled-loop.test b/t/chainlint/complex-if-in-cuddled-loop.test new file mode 100644 index 0000000..5efeda5 --- /dev/null +++ b/t/chainlint/complex-if-in-cuddled-loop.test @@ -0,0 +1,11 @@ +# LINT: "for" loop cuddled with "(" and ")" and nested "if" with complex +# LINT: multi-line condition; indented with spaces, not tabs +(for i in a b c; do + if test "$(echo $(waffle bat))" = "eleventeen" && + test "$x" = "$y"; then + : + else + echo >file + fi + done) && +test ! -f file diff --git a/t/chainlint/cuddled-if-then-else.expect b/t/chainlint/cuddled-if-then-else.expect new file mode 100644 index 0000000..1d8ed58 --- /dev/null +++ b/t/chainlint/cuddled-if-then-else.expect @@ -0,0 +1,6 @@ +(if test -z ""; then + echo empty + else + echo bizzy + fi) && +echo foobar diff --git a/t/chainlint/cuddled-if-then-else.test b/t/chainlint/cuddled-if-then-else.test new file mode 100644 index 0000000..7c53f4e --- /dev/null +++ b/t/chainlint/cuddled-if-then-else.test @@ -0,0 +1,7 @@ +# LINT: "if" cuddled with "(" and ")"; indented with spaces, not tabs +(if test -z ""; then + echo empty + else + echo bizzy + fi) && +echo foobar diff --git a/t/chainlint/cuddled-loop.expect b/t/chainlint/cuddled-loop.expect new file mode 100644 index 0000000..9cf2607 --- /dev/null +++ b/t/chainlint/cuddled-loop.expect @@ -0,0 +1,4 @@ +( while read x + do foobar bop || exit 1 + done <file ) && +outside subshell diff --git a/t/chainlint/cuddled-loop.test b/t/chainlint/cuddled-loop.test new file mode 100644 index 0000000..3c2a62f --- /dev/null +++ b/t/chainlint/cuddled-loop.test @@ -0,0 +1,7 @@ +# LINT: "while" loop cuddled with "(" and ")", with embedded (allowed) +# LINT: "|| exit {n}" to exit loop early, and using redirection "<" to feed +# LINT: loop; indented with spaces, not tabs +( while read x + do foobar bop || exit 1 + done <file ) && +outside subshell diff --git a/t/chainlint/cuddled.expect b/t/chainlint/cuddled.expect new file mode 100644 index 0000000..c3e0be4 --- /dev/null +++ b/t/chainlint/cuddled.expect @@ -0,0 +1,17 @@ +(cd foo && + bar +) && + +(cd foo ?!AMP?! + bar +) && + +( + cd foo && + bar) && + +(cd foo && + bar) && + +(cd foo ?!AMP?! + bar) diff --git a/t/chainlint/cuddled.test b/t/chainlint/cuddled.test new file mode 100644 index 0000000..257b5b5 --- /dev/null +++ b/t/chainlint/cuddled.test @@ -0,0 +1,22 @@ +# LINT: first subshell statement cuddled with opening "(" +(cd foo && + bar +) && + +# LINT: same with missing "&&" +(cd foo + bar +) && + +# LINT: closing ")" cuddled with final subshell statement +( + cd foo && + bar) && + +# LINT: "(" and ")" cuddled with first and final subshell statements +(cd foo && + bar) && + +# LINT: same with missing "&&" +(cd foo + bar) diff --git a/t/chainlint/double-here-doc.expect b/t/chainlint/double-here-doc.expect new file mode 100644 index 0000000..cd584a4 --- /dev/null +++ b/t/chainlint/double-here-doc.expect @@ -0,0 +1,12 @@ +run_sub_test_lib_test_err run-inv-range-start \ + "--run invalid range start" \ + --run="a-5" <<-\EOF && +test_expect_success "passing test #1" "true" +test_done +EOF +check_sub_test_lib_test_err run-inv-range-start \ + <<-\EOF_OUT 3<<-EOF_ERR +> FATAL: Unexpected exit with code 1 +EOF_OUT +> error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ} +EOF_ERR diff --git a/t/chainlint/double-here-doc.test b/t/chainlint/double-here-doc.test new file mode 100644 index 0000000..cd584a4 --- /dev/null +++ b/t/chainlint/double-here-doc.test @@ -0,0 +1,12 @@ +run_sub_test_lib_test_err run-inv-range-start \ + "--run invalid range start" \ + --run="a-5" <<-\EOF && +test_expect_success "passing test #1" "true" +test_done +EOF +check_sub_test_lib_test_err run-inv-range-start \ + <<-\EOF_OUT 3<<-EOF_ERR +> FATAL: Unexpected exit with code 1 +EOF_OUT +> error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ} +EOF_ERR diff --git a/t/chainlint/dqstring-line-splice.expect b/t/chainlint/dqstring-line-splice.expect new file mode 100644 index 0000000..bf9ced6 --- /dev/null +++ b/t/chainlint/dqstring-line-splice.expect @@ -0,0 +1,3 @@ +echo 'fatal: reword option of --fixup is mutually exclusive with' '--patch/--interactive/--all/--include/--only' > expect && +test_must_fail git commit --fixup=reword:HEAD~ $1 2 > actual && +test_cmp expect actual diff --git a/t/chainlint/dqstring-line-splice.test b/t/chainlint/dqstring-line-splice.test new file mode 100644 index 0000000..b407144 --- /dev/null +++ b/t/chainlint/dqstring-line-splice.test @@ -0,0 +1,7 @@ +# LINT: line-splice within DQ-string +'" +echo 'fatal: reword option of --fixup is mutually exclusive with'\ + '--patch/--interactive/--all/--include/--only' >expect && +test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual && +test_cmp expect actual +"' diff --git a/t/chainlint/dqstring-no-interpolate.expect b/t/chainlint/dqstring-no-interpolate.expect new file mode 100644 index 0000000..1072498 --- /dev/null +++ b/t/chainlint/dqstring-no-interpolate.expect @@ -0,0 +1,11 @@ +grep "^ ! [rejected][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" out && + +grep "^\.git$" output.txt && + + +( + cd client$version && + GIT_TEST_PROTOCOL_VERSION=$version git fetch-pack --no-progress .. $(cat ../input) +) > output && + cut -d ' ' -f 2 < output | sort > actual && + test_cmp expect actual diff --git a/t/chainlint/dqstring-no-interpolate.test b/t/chainlint/dqstring-no-interpolate.test new file mode 100644 index 0000000..d2f4219 --- /dev/null +++ b/t/chainlint/dqstring-no-interpolate.test @@ -0,0 +1,15 @@ +# LINT: regex dollar-sign eol anchor in double-quoted string not special +grep "^ ! \[rejected\][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" out && + +# LINT: escaped "$" not mistaken for variable expansion +grep "^\\.git\$" output.txt && + +'" +( + cd client$version && +# LINT: escaped dollar-sign in double-quoted test body + GIT_TEST_PROTOCOL_VERSION=$version git fetch-pack --no-progress .. \$(cat ../input) +) >output && + cut -d ' ' -f 2 <output | sort >actual && + test_cmp expect actual +"' diff --git a/t/chainlint/empty-here-doc.expect b/t/chainlint/empty-here-doc.expect new file mode 100644 index 0000000..e8733c9 --- /dev/null +++ b/t/chainlint/empty-here-doc.expect @@ -0,0 +1,4 @@ +git ls-tree $tree path > current && +cat > expected <<\EOF && +EOF +test_output diff --git a/t/chainlint/empty-here-doc.test b/t/chainlint/empty-here-doc.test new file mode 100644 index 0000000..24fc165 --- /dev/null +++ b/t/chainlint/empty-here-doc.test @@ -0,0 +1,5 @@ +git ls-tree $tree path >current && +# LINT: empty here-doc +cat >expected <<\EOF && +EOF +test_output diff --git a/t/chainlint/exclamation.expect b/t/chainlint/exclamation.expect new file mode 100644 index 0000000..2d961a5 --- /dev/null +++ b/t/chainlint/exclamation.expect @@ -0,0 +1,4 @@ +if ! condition ; then echo nope ; else yep ; fi && +test_prerequisite !MINGW && +mail uucp!address && +echo !whatever! diff --git a/t/chainlint/exclamation.test b/t/chainlint/exclamation.test new file mode 100644 index 0000000..323595b --- /dev/null +++ b/t/chainlint/exclamation.test @@ -0,0 +1,8 @@ +# LINT: "! word" is two tokens +if ! condition; then echo nope; else yep; fi && +# LINT: "!word" is single token, not two tokens "!" and "word" +test_prerequisite !MINGW && +# LINT: "word!word" is single token, not three tokens "word", "!", and "word" +mail uucp!address && +# LINT: "!word!" is single token, not three tokens "!", "word", and "!" +echo !whatever! diff --git a/t/chainlint/exit-loop.expect b/t/chainlint/exit-loop.expect new file mode 100644 index 0000000..f76aa60 --- /dev/null +++ b/t/chainlint/exit-loop.expect @@ -0,0 +1,24 @@ +( + for i in a b c + do + foo || exit 1 + bar && + baz + done +) && +( + while true + do + foo || exit 1 + bar && + baz + done +) && +( + i=0 && + while test $i -lt 10 + do + echo $i || exit + i=$(($i + 1)) + done +) diff --git a/t/chainlint/exit-loop.test b/t/chainlint/exit-loop.test new file mode 100644 index 0000000..2f03820 --- /dev/null +++ b/t/chainlint/exit-loop.test @@ -0,0 +1,27 @@ +( + for i in a b c + do +# LINT: "|| exit {n}" valid for-loop escape in subshell; no "&&" needed + foo || exit 1 + bar && + baz + done +) && +( + while true + do +# LINT: "|| exit {n}" valid while-loop escape in subshell; no "&&" needed + foo || exit 1 + bar && + baz + done +) && +( + i=0 && + while test $i -lt 10 + do +# LINT: "|| exit" (sans exit code) valid escape in subshell; no "&&" needed + echo $i || exit + i=$(($i + 1)) + done +) diff --git a/t/chainlint/exit-subshell.expect b/t/chainlint/exit-subshell.expect new file mode 100644 index 0000000..da80339 --- /dev/null +++ b/t/chainlint/exit-subshell.expect @@ -0,0 +1,5 @@ +( + foo || exit 1 + bar && + baz +) diff --git a/t/chainlint/exit-subshell.test b/t/chainlint/exit-subshell.test new file mode 100644 index 0000000..4e6ab69 --- /dev/null +++ b/t/chainlint/exit-subshell.test @@ -0,0 +1,6 @@ +( +# LINT: "|| exit {n}" valid subshell escape without hurting &&-chain + foo || exit 1 + bar && + baz +) diff --git a/t/chainlint/for-loop-abbreviated.expect b/t/chainlint/for-loop-abbreviated.expect new file mode 100644 index 0000000..a21007a --- /dev/null +++ b/t/chainlint/for-loop-abbreviated.expect @@ -0,0 +1,5 @@ +for it +do + path=$(expr "$it" : ( [^:]*) ) && + git update-index --add "$path" || exit +done diff --git a/t/chainlint/for-loop-abbreviated.test b/t/chainlint/for-loop-abbreviated.test new file mode 100644 index 0000000..1084ecc --- /dev/null +++ b/t/chainlint/for-loop-abbreviated.test @@ -0,0 +1,6 @@ +# LINT: for-loop lacking optional "in [word...]" before "do" +for it +do + path=$(expr "$it" : '\([^:]*\)') && + git update-index --add "$path" || exit +done diff --git a/t/chainlint/for-loop.expect b/t/chainlint/for-loop.expect new file mode 100644 index 0000000..d65c821 --- /dev/null +++ b/t/chainlint/for-loop.expect @@ -0,0 +1,13 @@ +( + for i in a b c + do + echo $i ?!AMP?! + cat <<-\EOF ?!LOOP?! + bar + EOF + done ?!AMP?! + for i in a b c; do + echo $i && + cat $i ?!LOOP?! + done +) diff --git a/t/chainlint/for-loop.test b/t/chainlint/for-loop.test new file mode 100644 index 0000000..6cb3428 --- /dev/null +++ b/t/chainlint/for-loop.test @@ -0,0 +1,19 @@ +( +# LINT: "for", "do", "done" do not need "&&" + for i in a b c + do +# LINT: missing "&&" on "echo" + echo $i +# LINT: last statement of while does not need "&&" + cat <<-\EOF + bar + EOF +# LINT: missing "&&" on "done" + done + +# LINT: "do" on same line as "for" + for i in a b c; do + echo $i && + cat $i + done +) diff --git a/t/chainlint/function.expect b/t/chainlint/function.expect new file mode 100644 index 0000000..a14388e --- /dev/null +++ b/t/chainlint/function.expect @@ -0,0 +1,11 @@ +sha1_file ( ) { + echo "$*" | sed "s#..#.git/objects/&/#" +} && + +remove_object ( ) { + file=$(sha1_file "$*") && + test -e "$file" ?!AMP?! + rm -f "$file" +} ?!AMP?! + +sha1_file arg && remove_object arg diff --git a/t/chainlint/function.test b/t/chainlint/function.test new file mode 100644 index 0000000..5ee5956 --- /dev/null +++ b/t/chainlint/function.test @@ -0,0 +1,13 @@ +# LINT: "()" in function definition not mistaken for subshell +sha1_file() { + echo "$*" | sed "s#..#.git/objects/&/#" +} && + +# LINT: broken &&-chain in function and after function +remove_object() { + file=$(sha1_file "$*") && + test -e "$file" + rm -f "$file" +} + +sha1_file arg && remove_object arg diff --git a/t/chainlint/here-doc-close-subshell.expect b/t/chainlint/here-doc-close-subshell.expect new file mode 100644 index 0000000..7d9c2b5 --- /dev/null +++ b/t/chainlint/here-doc-close-subshell.expect @@ -0,0 +1,4 @@ +( + cat <<-\INPUT) + fizz + INPUT diff --git a/t/chainlint/here-doc-close-subshell.test b/t/chainlint/here-doc-close-subshell.test new file mode 100644 index 0000000..b857ff5 --- /dev/null +++ b/t/chainlint/here-doc-close-subshell.test @@ -0,0 +1,5 @@ +( +# LINT: line contains here-doc and closes nested subshell + cat <<-\INPUT) + fizz + INPUT diff --git a/t/chainlint/here-doc-indent-operator.expect b/t/chainlint/here-doc-indent-operator.expect new file mode 100644 index 0000000..f92a7ce --- /dev/null +++ b/t/chainlint/here-doc-indent-operator.expect @@ -0,0 +1,11 @@ +cat >expect <<- EOF && +header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0 +num_commits: $1 +chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data +EOF + +cat >expect << -EOF ?!AMP?! +this is not indented +-EOF + +cleanup diff --git a/t/chainlint/here-doc-indent-operator.test b/t/chainlint/here-doc-indent-operator.test new file mode 100644 index 0000000..c8a6f18 --- /dev/null +++ b/t/chainlint/here-doc-indent-operator.test @@ -0,0 +1,13 @@ +# LINT: whitespace between operator "<<-" and tag legal +cat >expect <<- EOF && +header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0 +num_commits: $1 +chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data +EOF + +# LINT: not an indented here-doc; just a plain here-doc with tag named "-EOF" +cat >expect << -EOF +this is not indented +-EOF + +cleanup diff --git a/t/chainlint/here-doc-multi-line-command-subst.expect b/t/chainlint/here-doc-multi-line-command-subst.expect new file mode 100644 index 0000000..b7364c8 --- /dev/null +++ b/t/chainlint/here-doc-multi-line-command-subst.expect @@ -0,0 +1,8 @@ +( + x=$(bobble <<-\END && + fossil + vegetable + END + wiffle) ?!AMP?! + echo $x +) diff --git a/t/chainlint/here-doc-multi-line-command-subst.test b/t/chainlint/here-doc-multi-line-command-subst.test new file mode 100644 index 0000000..899bc5d --- /dev/null +++ b/t/chainlint/here-doc-multi-line-command-subst.test @@ -0,0 +1,9 @@ +( +# LINT: line contains here-doc and opens multi-line $(...) + x=$(bobble <<-\END && + fossil + vegetable + END + wiffle) + echo $x +) diff --git a/t/chainlint/here-doc-multi-line-string.expect b/t/chainlint/here-doc-multi-line-string.expect new file mode 100644 index 0000000..6c13bdc --- /dev/null +++ b/t/chainlint/here-doc-multi-line-string.expect @@ -0,0 +1,7 @@ +( + cat <<-\TXT && echo "multi-line + string" ?!AMP?! + fizzle + TXT + bap +) diff --git a/t/chainlint/here-doc-multi-line-string.test b/t/chainlint/here-doc-multi-line-string.test new file mode 100644 index 0000000..a53edbc --- /dev/null +++ b/t/chainlint/here-doc-multi-line-string.test @@ -0,0 +1,8 @@ +( +# LINT: line contains here-doc and opens multi-line string + cat <<-\TXT && echo "multi-line + string" + fizzle + TXT + bap +) diff --git a/t/chainlint/here-doc.expect b/t/chainlint/here-doc.expect new file mode 100644 index 0000000..1df3f78 --- /dev/null +++ b/t/chainlint/here-doc.expect @@ -0,0 +1,25 @@ +boodle wobba \ + gorgo snoot \ + wafta snurb <<EOF && +quoth the raven, +nevermore... +EOF + +cat <<-Arbitrary_Tag_42 >foo && +snoz +boz +woz +Arbitrary_Tag_42 + +cat <<"zump" >boo && +snoz +boz +woz +zump + +horticulture <<\EOF +gomez +morticia +wednesday +pugsly +EOF diff --git a/t/chainlint/here-doc.test b/t/chainlint/here-doc.test new file mode 100644 index 0000000..3f5f92c --- /dev/null +++ b/t/chainlint/here-doc.test @@ -0,0 +1,30 @@ +# LINT: stitch together incomplete \-ending lines +# LINT: swallow here-doc to avoid false positives in content +boodle wobba \ + gorgo snoot \ + wafta snurb <<EOF && +quoth the raven, +nevermore... +EOF + +# LINT: swallow here-doc with arbitrary tag +cat <<-Arbitrary_Tag_42 >foo && +snoz +boz +woz +Arbitrary_Tag_42 + +# LINT: swallow "quoted" here-doc +cat <<"zump" >boo && +snoz +boz +woz +zump + +# LINT: swallow here-doc (EOF is last line of test) +horticulture <<\EOF +gomez +morticia +wednesday +pugsly +EOF diff --git a/t/chainlint/if-condition-split.expect b/t/chainlint/if-condition-split.expect new file mode 100644 index 0000000..ee745ef --- /dev/null +++ b/t/chainlint/if-condition-split.expect @@ -0,0 +1,7 @@ +if bob && + marcia || + kevin +then + echo "nomads" ?!AMP?! + echo "for sure" +fi diff --git a/t/chainlint/if-condition-split.test b/t/chainlint/if-condition-split.test new file mode 100644 index 0000000..240daa9 --- /dev/null +++ b/t/chainlint/if-condition-split.test @@ -0,0 +1,8 @@ +# LINT: "if" condition split across multiple lines at "&&" or "||" +if bob && + marcia || + kevin +then + echo "nomads" + echo "for sure" +fi diff --git a/t/chainlint/if-in-loop.expect b/t/chainlint/if-in-loop.expect new file mode 100644 index 0000000..d6514ae --- /dev/null +++ b/t/chainlint/if-in-loop.expect @@ -0,0 +1,12 @@ +( + for i in a b c + do + if false + then + echo "err" + exit 1 + fi ?!AMP?! + foo + done ?!AMP?! + bar +) diff --git a/t/chainlint/if-in-loop.test b/t/chainlint/if-in-loop.test new file mode 100644 index 0000000..90c2397 --- /dev/null +++ b/t/chainlint/if-in-loop.test @@ -0,0 +1,15 @@ +( + for i in a b c + do + if false + then +# LINT: missing "&&" on "echo" okay since "exit 1" signals error explicitly + echo "err" + exit 1 +# LINT: missing "&&" on "fi" + fi + foo +# LINT: missing "&&" on "done" + done + bar +) diff --git a/t/chainlint/if-then-else.expect b/t/chainlint/if-then-else.expect new file mode 100644 index 0000000..cbaaf85 --- /dev/null +++ b/t/chainlint/if-then-else.expect @@ -0,0 +1,22 @@ +( + if test -n "" + then + echo very ?!AMP?! + echo empty + elif test -z "" + then + echo foo + else + echo foo && + cat <<-\EOF + bar + EOF + fi ?!AMP?! + echo poodle +) && +( + if test -n ""; then + echo very && + echo empty + fi +) diff --git a/t/chainlint/if-then-else.test b/t/chainlint/if-then-else.test new file mode 100644 index 0000000..2055336 --- /dev/null +++ b/t/chainlint/if-then-else.test @@ -0,0 +1,29 @@ +( +# LINT: "if", "then", "elif", "else", "fi" do not need "&&" + if test -n "" + then +# LINT: missing "&&" on "echo" + echo very +# LINT: last statement before "elif" does not need "&&" + echo empty + elif test -z "" + then +# LINT: last statement before "else" does not need "&&" + echo foo + else + echo foo && +# LINT: last statement before "fi" does not need "&&" + cat <<-\EOF + bar + EOF +# LINT: missing "&&" on "fi" + fi + echo poodle +) && +( +# LINT: "then" on same line as "if" + if test -n ""; then + echo very && + echo empty + fi +) diff --git a/t/chainlint/incomplete-line.expect b/t/chainlint/incomplete-line.expect new file mode 100644 index 0000000..134d3a1 --- /dev/null +++ b/t/chainlint/incomplete-line.expect @@ -0,0 +1,10 @@ +line 1 \ +line 2 \ +line 3 \ +line 4 && +( + line 5 \ + line 6 \ + line 7 \ + line 8 +) diff --git a/t/chainlint/incomplete-line.test b/t/chainlint/incomplete-line.test new file mode 100644 index 0000000..d856658 --- /dev/null +++ b/t/chainlint/incomplete-line.test @@ -0,0 +1,12 @@ +# LINT: stitch together all incomplete \-ending lines +line 1 \ +line 2 \ +line 3 \ +line 4 && +( +# LINT: stitch together all incomplete \-ending lines (subshell) + line 5 \ + line 6 \ + line 7 \ + line 8 +) diff --git a/t/chainlint/inline-comment.expect b/t/chainlint/inline-comment.expect new file mode 100644 index 0000000..6bad218 --- /dev/null +++ b/t/chainlint/inline-comment.expect @@ -0,0 +1,8 @@ +( + foobar && # comment 1 + barfoo ?!AMP?! # wrong position for && + flibble "not a # comment" +) && + +(cd foo && + flibble "not a # comment") diff --git a/t/chainlint/inline-comment.test b/t/chainlint/inline-comment.test new file mode 100644 index 0000000..8f26856 --- /dev/null +++ b/t/chainlint/inline-comment.test @@ -0,0 +1,12 @@ +( +# LINT: swallow inline comment (leaving command intact) + foobar && # comment 1 +# LINT: mispositioned "&&" (correctly) swallowed with comment + barfoo # wrong position for && +# LINT: "#" in string not misinterpreted as comment + flibble "not a # comment" +) && + +# LINT: "#" in string in cuddled subshell not misinterpreted as comment +(cd foo && + flibble "not a # comment") diff --git a/t/chainlint/loop-detect-failure.expect b/t/chainlint/loop-detect-failure.expect new file mode 100644 index 0000000..a66025c --- /dev/null +++ b/t/chainlint/loop-detect-failure.expect @@ -0,0 +1,15 @@ +git init r1 && +for n in 1 2 3 4 5 +do + echo "This is file: $n" > r1/file.$n && + git -C r1 add file.$n && + git -C r1 commit -m "$n" || return 1 +done && + +git init r2 && +for n in 1000 10000 +do + printf "%"$n"s" X > r2/large.$n && + git -C r2 add large.$n && + git -C r2 commit -m "$n" ?!LOOP?! +done diff --git a/t/chainlint/loop-detect-failure.test b/t/chainlint/loop-detect-failure.test new file mode 100644 index 0000000..b9791cc --- /dev/null +++ b/t/chainlint/loop-detect-failure.test @@ -0,0 +1,17 @@ +git init r1 && +# LINT: loop handles failure explicitly with "|| return 1" +for n in 1 2 3 4 5 +do + echo "This is file: $n" > r1/file.$n && + git -C r1 add file.$n && + git -C r1 commit -m "$n" || return 1 +done && + +git init r2 && +# LINT: loop fails to handle failure explicitly with "|| return 1" +for n in 1000 10000 +do + printf "%"$n"s" X > r2/large.$n && + git -C r2 add large.$n && + git -C r2 commit -m "$n" +done diff --git a/t/chainlint/loop-detect-status.expect b/t/chainlint/loop-detect-status.expect new file mode 100644 index 0000000..24da9e8 --- /dev/null +++ b/t/chainlint/loop-detect-status.expect @@ -0,0 +1,18 @@ +( while test $i -le $blobcount +do + printf "Generating blob $i/$blobcount\r" >& 2 && + printf "blob\nmark :$i\ndata $blobsize\n" && + #test-tool genrandom $i $blobsize && + printf "%-${blobsize}s" $i && + echo "M 100644 :$i $i" >> commit && + i=$(($i+1)) || + echo $? > exit-status +done && +echo "commit refs/heads/main" && +echo "author A U Thor <author@email.com> 123456789 +0000" && +echo "committer C O Mitter <committer@email.com> 123456789 +0000" && +echo "data 5" && +echo ">2gb" && +cat commit ) | +git fast-import --big-file-threshold=2 && +test ! -f exit-status diff --git a/t/chainlint/loop-detect-status.test b/t/chainlint/loop-detect-status.test new file mode 100644 index 0000000..1c6c23c --- /dev/null +++ b/t/chainlint/loop-detect-status.test @@ -0,0 +1,19 @@ +# LINT: "$?" handled explicitly within loop body +(while test $i -le $blobcount + do + printf "Generating blob $i/$blobcount\r" >&2 && + printf "blob\nmark :$i\ndata $blobsize\n" && + #test-tool genrandom $i $blobsize && + printf "%-${blobsize}s" $i && + echo "M 100644 :$i $i" >> commit && + i=$(($i+1)) || + echo $? > exit-status + done && + echo "commit refs/heads/main" && + echo "author A U Thor <author@email.com> 123456789 +0000" && + echo "committer C O Mitter <committer@email.com> 123456789 +0000" && + echo "data 5" && + echo ">2gb" && + cat commit) | +git fast-import --big-file-threshold=2 && +test ! -f exit-status diff --git a/t/chainlint/loop-in-if.expect b/t/chainlint/loop-in-if.expect new file mode 100644 index 0000000..6c5d6e5 --- /dev/null +++ b/t/chainlint/loop-in-if.expect @@ -0,0 +1,12 @@ +( + if true + then + while true + do + echo "pop" ?!AMP?! + echo "glup" ?!LOOP?! + done ?!AMP?! + foo + fi ?!AMP?! + bar +) diff --git a/t/chainlint/loop-in-if.test b/t/chainlint/loop-in-if.test new file mode 100644 index 0000000..dfcc3f9 --- /dev/null +++ b/t/chainlint/loop-in-if.test @@ -0,0 +1,15 @@ +( + if true + then + while true + do +# LINT: missing "&&" on "echo" + echo "pop" + echo "glup" +# LINT: missing "&&" on "done" + done + foo +# LINT: missing "&&" on "fi" + fi + bar +) diff --git a/t/chainlint/loop-upstream-pipe.expect b/t/chainlint/loop-upstream-pipe.expect new file mode 100644 index 0000000..0b82ecc --- /dev/null +++ b/t/chainlint/loop-upstream-pipe.expect @@ -0,0 +1,10 @@ +( + git rev-list --objects --no-object-names base..loose | + while read oid + do + path="$objdir/$(test_oid_to_path "$oid")" && + printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")" || + echo "object list generation failed for $oid" + done | + sort -k1 +) >expect && diff --git a/t/chainlint/loop-upstream-pipe.test b/t/chainlint/loop-upstream-pipe.test new file mode 100644 index 0000000..efb77da --- /dev/null +++ b/t/chainlint/loop-upstream-pipe.test @@ -0,0 +1,11 @@ +( + git rev-list --objects --no-object-names base..loose | + while read oid + do +# LINT: "|| echo" signals failure in loop upstream of a pipe + path="$objdir/$(test_oid_to_path "$oid")" && + printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")" || + echo "object list generation failed for $oid" + done | + sort -k1 +) >expect && diff --git a/t/chainlint/multi-line-nested-command-substitution.expect b/t/chainlint/multi-line-nested-command-substitution.expect new file mode 100644 index 0000000..3000583 --- /dev/null +++ b/t/chainlint/multi-line-nested-command-substitution.expect @@ -0,0 +1,18 @@ +( + foo && + x=$( + echo bar | + cat + ) && + echo ok +) | +sort && +( + bar && + x=$(echo bar | + cat + ) && + y=$(echo baz | + fip) && + echo fail +) diff --git a/t/chainlint/multi-line-nested-command-substitution.test b/t/chainlint/multi-line-nested-command-substitution.test new file mode 100644 index 0000000..3000583 --- /dev/null +++ b/t/chainlint/multi-line-nested-command-substitution.test @@ -0,0 +1,18 @@ +( + foo && + x=$( + echo bar | + cat + ) && + echo ok +) | +sort && +( + bar && + x=$(echo bar | + cat + ) && + y=$(echo baz | + fip) && + echo fail +) diff --git a/t/chainlint/multi-line-string.expect b/t/chainlint/multi-line-string.expect new file mode 100644 index 0000000..27ff952 --- /dev/null +++ b/t/chainlint/multi-line-string.expect @@ -0,0 +1,14 @@ +( + x="line 1 + line 2 + line 3" && + y="line 1 + line2" ?!AMP?! + foobar +) && +( + echo "xyz" "abc + def + ghi" && + barfoo +) diff --git a/t/chainlint/multi-line-string.test b/t/chainlint/multi-line-string.test new file mode 100644 index 0000000..4a0af21 --- /dev/null +++ b/t/chainlint/multi-line-string.test @@ -0,0 +1,15 @@ +( + x="line 1 + line 2 + line 3" && +# LINT: missing "&&" on assignment + y="line 1 + line2" + foobar +) && +( + echo "xyz" "abc + def + ghi" && + barfoo +) diff --git a/t/chainlint/negated-one-liner.expect b/t/chainlint/negated-one-liner.expect new file mode 100644 index 0000000..ad4c2d9 --- /dev/null +++ b/t/chainlint/negated-one-liner.expect @@ -0,0 +1,5 @@ +! (foo && bar) && +! (foo && bar) >baz && + +! (foo; ?!AMP?! bar) && +! (foo; ?!AMP?! bar) >baz diff --git a/t/chainlint/negated-one-liner.test b/t/chainlint/negated-one-liner.test new file mode 100644 index 0000000..c9598e9 --- /dev/null +++ b/t/chainlint/negated-one-liner.test @@ -0,0 +1,7 @@ +# LINT: top-level one-liner subshell +! (foo && bar) && +! (foo && bar) >baz && + +# LINT: top-level one-liner subshell missing internal "&&" +! (foo; bar) && +! (foo; bar) >baz diff --git a/t/chainlint/nested-cuddled-subshell.expect b/t/chainlint/nested-cuddled-subshell.expect new file mode 100644 index 0000000..2a86885 --- /dev/null +++ b/t/chainlint/nested-cuddled-subshell.expect @@ -0,0 +1,19 @@ +( + (cd foo && + bar + ) && + (cd foo && + bar + ) ?!AMP?! + ( + cd foo && + bar) && + ( + cd foo && + bar) ?!AMP?! + (cd foo && + bar) && + (cd foo && + bar) ?!AMP?! + foobar +) diff --git a/t/chainlint/nested-cuddled-subshell.test b/t/chainlint/nested-cuddled-subshell.test new file mode 100644 index 0000000..8fd656c --- /dev/null +++ b/t/chainlint/nested-cuddled-subshell.test @@ -0,0 +1,31 @@ +( +# LINT: opening "(" cuddled with first nested subshell statement + (cd foo && + bar + ) && + +# LINT: same but "&&" missing + (cd foo && + bar + ) + +# LINT: closing ")" cuddled with final nested subshell statement + ( + cd foo && + bar) && + +# LINT: same but "&&" missing + ( + cd foo && + bar) + +# LINT: "(" and ")" cuddled with first and final subshell statements + (cd foo && + bar) && + +# LINT: same but "&&" missing + (cd foo && + bar) + + foobar +) diff --git a/t/chainlint/nested-here-doc.expect b/t/chainlint/nested-here-doc.expect new file mode 100644 index 0000000..29b3832 --- /dev/null +++ b/t/chainlint/nested-here-doc.expect @@ -0,0 +1,30 @@ +cat <<ARBITRARY >foop && +naddle +fub <<EOF + nozzle + noodle +EOF +formp +ARBITRARY + +( + cat <<-\INPUT_END && + fish are mice + but geese go slow + data <<EOF + perl is lerp + and nothing else + EOF + toink + INPUT_END + + cat <<-\EOT ?!AMP?! + text goes here + data <<EOF + data goes here + EOF + more test here + EOT + + foobar +) diff --git a/t/chainlint/nested-here-doc.test b/t/chainlint/nested-here-doc.test new file mode 100644 index 0000000..f35404b --- /dev/null +++ b/t/chainlint/nested-here-doc.test @@ -0,0 +1,33 @@ +# LINT: inner "EOF" not misintrepreted as closing ARBITRARY here-doc +cat <<ARBITRARY >foop && +naddle +fub <<EOF + nozzle + noodle +EOF +formp +ARBITRARY + +( +# LINT: inner "EOF" not misintrepreted as closing INPUT_END here-doc + cat <<-\INPUT_END && + fish are mice + but geese go slow + data <<EOF + perl is lerp + and nothing else + EOF + toink + INPUT_END + +# LINT: same but missing "&&" + cat <<-\EOT + text goes here + data <<EOF + data goes here + EOF + more test here + EOT + + foobar +) diff --git a/t/chainlint/nested-loop-detect-failure.expect b/t/chainlint/nested-loop-detect-failure.expect new file mode 100644 index 0000000..4793a0e --- /dev/null +++ b/t/chainlint/nested-loop-detect-failure.expect @@ -0,0 +1,31 @@ +for i in 0 1 2 3 4 5 6 7 8 9 ; +do + for j in 0 1 2 3 4 5 6 7 8 9 ; + do + echo "$i$j" > "path$i$j" ?!LOOP?! + done ?!LOOP?! +done && + +for i in 0 1 2 3 4 5 6 7 8 9 ; +do + for j in 0 1 2 3 4 5 6 7 8 9 ; + do + echo "$i$j" > "path$i$j" || return 1 + done +done && + +for i in 0 1 2 3 4 5 6 7 8 9 ; +do + for j in 0 1 2 3 4 5 6 7 8 9 ; + do + echo "$i$j" > "path$i$j" ?!LOOP?! + done || return 1 +done && + +for i in 0 1 2 3 4 5 6 7 8 9 ; +do + for j in 0 1 2 3 4 5 6 7 8 9 ; + do + echo "$i$j" > "path$i$j" || return 1 + done || return 1 +done diff --git a/t/chainlint/nested-loop-detect-failure.test b/t/chainlint/nested-loop-detect-failure.test new file mode 100644 index 0000000..e6f0c1a --- /dev/null +++ b/t/chainlint/nested-loop-detect-failure.test @@ -0,0 +1,35 @@ +# LINT: neither loop handles failure explicitly with "|| return 1" +for i in 0 1 2 3 4 5 6 7 8 9; +do + for j in 0 1 2 3 4 5 6 7 8 9; + do + echo "$i$j" >"path$i$j" + done +done && + +# LINT: inner loop handles failure explicitly with "|| return 1" +for i in 0 1 2 3 4 5 6 7 8 9; +do + for j in 0 1 2 3 4 5 6 7 8 9; + do + echo "$i$j" >"path$i$j" || return 1 + done +done && + +# LINT: outer loop handles failure explicitly with "|| return 1" +for i in 0 1 2 3 4 5 6 7 8 9; +do + for j in 0 1 2 3 4 5 6 7 8 9; + do + echo "$i$j" >"path$i$j" + done || return 1 +done && + +# LINT: inner & outer loops handles failure explicitly with "|| return 1" +for i in 0 1 2 3 4 5 6 7 8 9; +do + for j in 0 1 2 3 4 5 6 7 8 9; + do + echo "$i$j" >"path$i$j" || return 1 + done || return 1 +done diff --git a/t/chainlint/nested-subshell-comment.expect b/t/chainlint/nested-subshell-comment.expect new file mode 100644 index 0000000..9138cf3 --- /dev/null +++ b/t/chainlint/nested-subshell-comment.expect @@ -0,0 +1,11 @@ +( + foo && + ( + bar && + # bottles wobble while fiddles gobble + # minor numbers of cows (or do they?) + baz && + snaff + ) ?!AMP?! + fuzzy +) diff --git a/t/chainlint/nested-subshell-comment.test b/t/chainlint/nested-subshell-comment.test new file mode 100644 index 0000000..0215cdb --- /dev/null +++ b/t/chainlint/nested-subshell-comment.test @@ -0,0 +1,13 @@ +( + foo && + ( + bar && +# LINT: ")" in comment in nested subshell not misinterpreted as closing ")" + # bottles wobble while fiddles gobble + # minor numbers of cows (or do they?) + baz && + snaff +# LINT: missing "&&" on ")" + ) + fuzzy +) diff --git a/t/chainlint/nested-subshell.expect b/t/chainlint/nested-subshell.expect new file mode 100644 index 0000000..02e0a9f --- /dev/null +++ b/t/chainlint/nested-subshell.expect @@ -0,0 +1,12 @@ +( + cd foo && + ( + echo a && + echo b + ) >file && + cd foo && + ( + echo a ?!AMP?! + echo b + ) >file +) diff --git a/t/chainlint/nested-subshell.test b/t/chainlint/nested-subshell.test new file mode 100644 index 0000000..440ee99 --- /dev/null +++ b/t/chainlint/nested-subshell.test @@ -0,0 +1,13 @@ +( + cd foo && + ( + echo a && + echo b + ) >file && + + cd foo && + ( + echo a + echo b + ) >file +) diff --git a/t/chainlint/not-heredoc.expect b/t/chainlint/not-heredoc.expect new file mode 100644 index 0000000..2e9bb13 --- /dev/null +++ b/t/chainlint/not-heredoc.expect @@ -0,0 +1,14 @@ +echo "<<<<<<< ours" && +echo ourside && +echo "=======" && +echo theirside && +echo ">>>>>>> theirs" && + +( + echo "<<<<<<< ours" && + echo ourside && + echo "=======" && + echo theirside && + echo ">>>>>>> theirs" ?!AMP?! + poodle +) >merged diff --git a/t/chainlint/not-heredoc.test b/t/chainlint/not-heredoc.test new file mode 100644 index 0000000..9aa5734 --- /dev/null +++ b/t/chainlint/not-heredoc.test @@ -0,0 +1,16 @@ +# LINT: "<< ours" inside string is not here-doc +echo "<<<<<<< ours" && +echo ourside && +echo "=======" && +echo theirside && +echo ">>>>>>> theirs" && + +( +# LINT: "<< ours" inside string is not here-doc + echo "<<<<<<< ours" && + echo ourside && + echo "=======" && + echo theirside && + echo ">>>>>>> theirs" + poodle +) >merged diff --git a/t/chainlint/one-liner-for-loop.expect b/t/chainlint/one-liner-for-loop.expect new file mode 100644 index 0000000..51a3dc7 --- /dev/null +++ b/t/chainlint/one-liner-for-loop.expect @@ -0,0 +1,9 @@ +git init dir-rename-and-content && +( + cd dir-rename-and-content && + test_write_lines 1 2 3 4 5 >foo && + mkdir olddir && + for i in a b c; do echo $i >olddir/$i; ?!LOOP?! done ?!AMP?! + git add foo olddir && + git commit -m "original" && +) diff --git a/t/chainlint/one-liner-for-loop.test b/t/chainlint/one-liner-for-loop.test new file mode 100644 index 0000000..4bd8c06 --- /dev/null +++ b/t/chainlint/one-liner-for-loop.test @@ -0,0 +1,10 @@ +git init dir-rename-and-content && +( + cd dir-rename-and-content && + test_write_lines 1 2 3 4 5 >foo && + mkdir olddir && +# LINT: one-liner for-loop missing "|| exit"; also broken &&-chain + for i in a b c; do echo $i >olddir/$i; done + git add foo olddir && + git commit -m "original" && +) diff --git a/t/chainlint/one-liner.expect b/t/chainlint/one-liner.expect new file mode 100644 index 0000000..57a7a44 --- /dev/null +++ b/t/chainlint/one-liner.expect @@ -0,0 +1,9 @@ +(foo && bar) && +(foo && bar) | +(foo && bar) >baz && + +(foo; ?!AMP?! bar) && +(foo; ?!AMP?! bar) | +(foo; ?!AMP?! bar) >baz && + +(foo "bar; baz") diff --git a/t/chainlint/one-liner.test b/t/chainlint/one-liner.test new file mode 100644 index 0000000..be9858f --- /dev/null +++ b/t/chainlint/one-liner.test @@ -0,0 +1,12 @@ +# LINT: top-level one-liner subshell +(foo && bar) && +(foo && bar) | +(foo && bar) >baz && + +# LINT: top-level one-liner subshell missing internal "&&" and broken &&-chain +(foo; bar) && +(foo; bar) | +(foo; bar) >baz && + +# LINT: ";" in string not misinterpreted as broken &&-chain +(foo "bar; baz") diff --git a/t/chainlint/p4-filespec.expect b/t/chainlint/p4-filespec.expect new file mode 100644 index 0000000..1290fd1 --- /dev/null +++ b/t/chainlint/p4-filespec.expect @@ -0,0 +1,4 @@ +( + p4 print -1 //depot/fiddle#42 >file && + foobar +) diff --git a/t/chainlint/p4-filespec.test b/t/chainlint/p4-filespec.test new file mode 100644 index 0000000..4fd2d6e --- /dev/null +++ b/t/chainlint/p4-filespec.test @@ -0,0 +1,5 @@ +( +# LINT: Perforce revspec in filespec not misinterpreted as in-line comment + p4 print -1 //depot/fiddle#42 >file && + foobar +) diff --git a/t/chainlint/pipe.expect b/t/chainlint/pipe.expect new file mode 100644 index 0000000..2cfc028 --- /dev/null +++ b/t/chainlint/pipe.expect @@ -0,0 +1,8 @@ +( + foo | + bar | + baz && + fish | + cow ?!AMP?! + sunder +) diff --git a/t/chainlint/pipe.test b/t/chainlint/pipe.test new file mode 100644 index 0000000..dd82534 --- /dev/null +++ b/t/chainlint/pipe.test @@ -0,0 +1,12 @@ +( +# LINT: no "&&" needed on line ending with "|" + foo | + bar | + baz && + +# LINT: final line of pipe sequence ("cow") lacking "&&" + fish | + cow + + sunder +) diff --git a/t/chainlint/return-loop.expect b/t/chainlint/return-loop.expect new file mode 100644 index 0000000..cfc0549 --- /dev/null +++ b/t/chainlint/return-loop.expect @@ -0,0 +1,5 @@ +while test $i -lt $((num - 5)) +do + git notes add -m "notes for commit$i" HEAD~$i || return 1 + i=$((i + 1)) +done diff --git a/t/chainlint/return-loop.test b/t/chainlint/return-loop.test new file mode 100644 index 0000000..f90b171 --- /dev/null +++ b/t/chainlint/return-loop.test @@ -0,0 +1,6 @@ +while test $i -lt $((num - 5)) +do +# LINT: "|| return {n}" valid loop escape outside subshell; no "&&" needed + git notes add -m "notes for commit$i" HEAD~$i || return 1 + i=$((i + 1)) +done diff --git a/t/chainlint/semicolon.expect b/t/chainlint/semicolon.expect new file mode 100644 index 0000000..3aa2259 --- /dev/null +++ b/t/chainlint/semicolon.expect @@ -0,0 +1,19 @@ +( + cat foo ; ?!AMP?! echo bar ?!AMP?! + cat foo ; ?!AMP?! echo bar +) && +( + cat foo ; ?!AMP?! echo bar && + cat foo ; ?!AMP?! echo bar +) && +( + echo "foo; bar" && + cat foo; ?!AMP?! echo bar +) && +( + foo; +) && +(cd foo && + for i in a b c; do + echo; ?!LOOP?! + done) diff --git a/t/chainlint/semicolon.test b/t/chainlint/semicolon.test new file mode 100644 index 0000000..67e1192 --- /dev/null +++ b/t/chainlint/semicolon.test @@ -0,0 +1,25 @@ +( +# LINT: missing internal "&&" and ending "&&" + cat foo ; echo bar +# LINT: final statement before ")" only missing internal "&&" + cat foo ; echo bar +) && +( +# LINT: missing internal "&&" + cat foo ; echo bar && + cat foo ; echo bar +) && +( +# LINT: not fooled by semicolon in string + echo "foo; bar" && + cat foo; echo bar +) && +( +# LINT: semicolon unnecessary but legitimate + foo; +) && +(cd foo && + for i in a b c; do +# LINT: semicolon unnecessary but legitimate + echo; + done) diff --git a/t/chainlint/sqstring-in-sqstring.expect b/t/chainlint/sqstring-in-sqstring.expect new file mode 100644 index 0000000..cf0b591 --- /dev/null +++ b/t/chainlint/sqstring-in-sqstring.expect @@ -0,0 +1,4 @@ +perl -e ' + defined($_ = -s $_) or die for @ARGV; + exit 1 if $ARGV[0] <= $ARGV[1]; +' test-2-$packname_2.pack test-3-$packname_3.pack diff --git a/t/chainlint/sqstring-in-sqstring.test b/t/chainlint/sqstring-in-sqstring.test new file mode 100644 index 0000000..77a425e --- /dev/null +++ b/t/chainlint/sqstring-in-sqstring.test @@ -0,0 +1,5 @@ +# LINT: SQ-string Perl code fragment within SQ-string +perl -e '\'' + defined($_ = -s $_) or die for @ARGV; + exit 1 if $ARGV[0] <= $ARGV[1]; +'\'' test-2-$packname_2.pack test-3-$packname_3.pack diff --git a/t/chainlint/subshell-here-doc.expect b/t/chainlint/subshell-here-doc.expect new file mode 100644 index 0000000..5278927 --- /dev/null +++ b/t/chainlint/subshell-here-doc.expect @@ -0,0 +1,30 @@ +( + echo wobba \ + gorgo snoot \ + wafta snurb <<-EOF && + quoth the raven, + nevermore... + EOF + + cat <<EOF >bip ?!AMP?! + fish fly high +EOF + + echo <<-\EOF >bop + gomez + morticia + wednesday + pugsly + EOF +) && +( + cat <<-\ARBITRARY >bup && + glink + FIZZ + ARBITRARY + cat <<-"ARBITRARY3" >bup3 && + glink + FIZZ + ARBITRARY3 + meep +) diff --git a/t/chainlint/subshell-here-doc.test b/t/chainlint/subshell-here-doc.test new file mode 100644 index 0000000..d40eb65 --- /dev/null +++ b/t/chainlint/subshell-here-doc.test @@ -0,0 +1,35 @@ +( +# LINT: stitch together incomplete \-ending lines +# LINT: swallow here-doc to avoid false positives in content + echo wobba \ + gorgo snoot \ + wafta snurb <<-EOF && + quoth the raven, + nevermore... + EOF + +# LINT: missing "&&" on "cat" + cat <<EOF >bip + fish fly high +EOF + +# LINT: swallow here-doc (EOF is last line of subshell) + echo <<-\EOF >bop + gomez + morticia + wednesday + pugsly + EOF +) && +( +# LINT: swallow here-doc with arbitrary tag + cat <<-\ARBITRARY >bup && + glink + FIZZ + ARBITRARY + cat <<-"ARBITRARY3" >bup3 && + glink + FIZZ + ARBITRARY3 + meep +) diff --git a/t/chainlint/subshell-one-liner.expect b/t/chainlint/subshell-one-liner.expect new file mode 100644 index 0000000..b701536 --- /dev/null +++ b/t/chainlint/subshell-one-liner.expect @@ -0,0 +1,14 @@ +( + (foo && bar) && + (foo && bar) | + (foo && bar) >baz && + (foo; ?!AMP?! bar) && + (foo; ?!AMP?! bar) | + (foo; ?!AMP?! bar) >baz && + (foo || exit 1) && + (foo || exit 1) | + (foo || exit 1) >baz && + (foo && bar) ?!AMP?! + (foo && bar; ?!AMP?! baz) ?!AMP?! + foobar +) diff --git a/t/chainlint/subshell-one-liner.test b/t/chainlint/subshell-one-liner.test new file mode 100644 index 0000000..37fa643 --- /dev/null +++ b/t/chainlint/subshell-one-liner.test @@ -0,0 +1,24 @@ +( +# LINT: nested one-liner subshell + (foo && bar) && + (foo && bar) | + (foo && bar) >baz && + +# LINT: nested one-liner subshell missing internal "&&" + (foo; bar) && + (foo; bar) | + (foo; bar) >baz && + +# LINT: nested one-liner subshell with "|| exit" + (foo || exit 1) && + (foo || exit 1) | + (foo || exit 1) >baz && + +# LINT: nested one-liner subshell lacking ending "&&" + (foo && bar) + +# LINT: nested one-liner subshell missing internal "&&" and lacking ending "&&" + (foo && bar; baz) + + foobar +) diff --git a/t/chainlint/t7900-subtree.expect b/t/chainlint/t7900-subtree.expect new file mode 100644 index 0000000..71b3b3b --- /dev/null +++ b/t/chainlint/t7900-subtree.expect @@ -0,0 +1,21 @@ +( + chks="sub1 +sub2 +sub3 +sub4" && + chks_sub=$(cat <<TXT | sed "s,^,sub dir/," +$chks +TXT +) && + chkms="main-sub1 +main-sub2 +main-sub3 +main-sub4" && + chkms_sub=$(cat <<TXT | sed "s,^,sub dir/," +$chkms +TXT +) && + subfiles=$(git ls-files) && + check_equal "$subfiles" "$chkms +$chks" +) diff --git a/t/chainlint/t7900-subtree.test b/t/chainlint/t7900-subtree.test new file mode 100644 index 0000000..02f3129 --- /dev/null +++ b/t/chainlint/t7900-subtree.test @@ -0,0 +1,22 @@ +( + chks="sub1 +sub2 +sub3 +sub4" && + chks_sub=$(cat <<TXT | sed "s,^,sub dir/," +$chks +TXT +) && + chkms="main-sub1 +main-sub2 +main-sub3 +main-sub4" && + chkms_sub=$(cat <<TXT | sed "s,^,sub dir/," +$chkms +TXT +) && + + subfiles=$(git ls-files) && + check_equal "$subfiles" "$chkms +$chks" +) diff --git a/t/chainlint/token-pasting.expect b/t/chainlint/token-pasting.expect new file mode 100644 index 0000000..342360b --- /dev/null +++ b/t/chainlint/token-pasting.expect @@ -0,0 +1,27 @@ +git config filter.rot13.smudge ./rot13.sh && +git config filter.rot13.clean ./rot13.sh && + +{ + echo "*.t filter=rot13" ?!AMP?! + echo "*.i ident" +} > .gitattributes && + +{ + echo a b c d e f g h i j k l m ?!AMP?! + echo n o p q r s t u v w x y z ?!AMP?! + echo '$Id$' +} > test && +cat test > test.t && +cat test > test.o && +cat test > test.i && +git add test test.t test.i && +rm -f test test.t test.i && +git checkout -- test test.t test.i && + +echo "content-test2" > test2.o && +echo "content-test3 - filename with special characters" > "test3 'sq',$x=.o" ?!AMP?! + +downstream_url_for_sed=$( + printf "%sn" "$downstream_url" | + sed -e 's/\/\\/g' -e 's/[[/.*^$]/\&/g' +) diff --git a/t/chainlint/token-pasting.test b/t/chainlint/token-pasting.test new file mode 100644 index 0000000..b4610ce --- /dev/null +++ b/t/chainlint/token-pasting.test @@ -0,0 +1,32 @@ +# LINT: single token; composite of multiple strings +git config filter.rot13.smudge ./rot13.sh && +git config filter.rot13.clean ./rot13.sh && + +{ + echo "*.t filter=rot13" + echo "*.i ident" +} >.gitattributes && + +{ + echo a b c d e f g h i j k l m + echo n o p q r s t u v w x y z +# LINT: exit/enter string context and escaped-quote outside of string + echo '\''$Id$'\'' +} >test && +cat test >test.t && +cat test >test.o && +cat test >test.i && +git add test test.t test.i && +rm -f test test.t test.i && +git checkout -- test test.t test.i && + +echo "content-test2" >test2.o && +# LINT: exit/enter string context and escaped-quote outside of string +echo "content-test3 - filename with special characters" >"test3 '\''sq'\'',\$x=.o" + +# LINT: single token; composite of multiple strings +downstream_url_for_sed=$( + printf "%s\n" "$downstream_url" | +# LINT: exit/enter string context; "&" inside string not command terminator + sed -e '\''s/\\/\\\\/g'\'' -e '\''s/[[/.*^$]/\\&/g'\'' +) diff --git a/t/chainlint/unclosed-here-doc-indent.expect b/t/chainlint/unclosed-here-doc-indent.expect new file mode 100644 index 0000000..7c30a1a --- /dev/null +++ b/t/chainlint/unclosed-here-doc-indent.expect @@ -0,0 +1,4 @@ +command_which_is_run && +cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! && +we forget to end the here-doc +command_which_is_gobbled diff --git a/t/chainlint/unclosed-here-doc-indent.test b/t/chainlint/unclosed-here-doc-indent.test new file mode 100644 index 0000000..5c841a9 --- /dev/null +++ b/t/chainlint/unclosed-here-doc-indent.test @@ -0,0 +1,4 @@ +command_which_is_run && +cat >expect <<-\EOF && +we forget to end the here-doc +command_which_is_gobbled diff --git a/t/chainlint/unclosed-here-doc.expect b/t/chainlint/unclosed-here-doc.expect new file mode 100644 index 0000000..d65e50f --- /dev/null +++ b/t/chainlint/unclosed-here-doc.expect @@ -0,0 +1,7 @@ +command_which_is_run && +cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! && + we try to end the here-doc below, + but the indentation throws us off + since the operator is not "<<-". + EOF +command_which_is_gobbled diff --git a/t/chainlint/unclosed-here-doc.test b/t/chainlint/unclosed-here-doc.test new file mode 100644 index 0000000..69d3786 --- /dev/null +++ b/t/chainlint/unclosed-here-doc.test @@ -0,0 +1,7 @@ +command_which_is_run && +cat >expect <<\EOF && + we try to end the here-doc below, + but the indentation throws us off + since the operator is not "<<-". + EOF +command_which_is_gobbled diff --git a/t/chainlint/while-loop.expect b/t/chainlint/while-loop.expect new file mode 100644 index 0000000..1f5eaea --- /dev/null +++ b/t/chainlint/while-loop.expect @@ -0,0 +1,13 @@ +( + while true + do + echo foo ?!AMP?! + cat <<-\EOF ?!LOOP?! + bar + EOF + done ?!AMP?! + while true; do + echo foo && + cat bar ?!LOOP?! + done +) diff --git a/t/chainlint/while-loop.test b/t/chainlint/while-loop.test new file mode 100644 index 0000000..d09fb01 --- /dev/null +++ b/t/chainlint/while-loop.test @@ -0,0 +1,19 @@ +( +# LINT: "while", "do", "done" do not need "&&" + while true + do +# LINT: missing "&&" on "echo" + echo foo +# LINT: last statement of while does not need "&&" + cat <<-\EOF + bar + EOF +# LINT: missing "&&" on "done" + done + +# LINT: "do" on same line as "while" + while true; do + echo foo && + cat bar + done +) |