Browse Source

chainlint: recognize multi-line quoted strings more robustly

chainlint.sed recognizes multi-line quoted strings within subshells:

    echo "abc
        def" >out &&

so it can avoid incorrectly classifying lines internal to the string as
breaking the &&-chain. To identify the first line of a multi-line
string, it checks if the line contains a single quote. However, this is
fragile and can be easily fooled by a line containing multiple strings:

    echo "xyz" "abc
        def" >out &&

Make detection more robust by checking for an odd number of quotes
rather than only a single one.

(Escaped quotes are not handled, but support may be added later.)

The original multi-line string recognizer rather cavalierly threw away
all but the final quote, whereas the new one is careful to retain all
quotes, so the "expected" output of a couple existing chainlint tests is
updated to account for this new behavior.

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Eric Sunshine 7 years ago committed by Junio C Hamano
parent
commit
22e3e0241a
  1. 32
      t/chainlint.sed
  2. 2
      t/chainlint/here-doc-multi-line-string.expect
  3. 10
      t/chainlint/multi-line-string.expect
  4. 12
      t/chainlint/multi-line-string.test

32
t/chainlint.sed

@ -151,10 +151,10 @@ s/.*\n//
:slurp :slurp
# incomplete line "...\" # incomplete line "...\"
/\\$/bincomplete /\\$/bincomplete
# multi-line quoted string "...\n..." # multi-line quoted string "...\n..."?
/^[^"]*"[^"]*$/bdqstring /"/bdqstring
# multi-line quoted string '...\n...' (but not contraction in string "it's so") # multi-line quoted string '...\n...'? (but not contraction in string "it's")
/^[^']*'[^']*$/{ /'/{
/"[^'"]*'[^'"]*"/!bsqstring /"[^'"]*'[^'"]*"/!bsqstring
} }
:folded :folded
@ -250,20 +250,32 @@ N
s/\\\n// s/\\\n//
bslurp bslurp


# found multi-line double-quoted string "...\n..." -- slurp until end of string # check for multi-line double-quoted string "...\n..." -- fold to one line
:dqstring :dqstring
s/"//g # remove all quote pairs
s/"\([^"]*\)"/@!\1@!/g
# done if no dangling quote
/"/!bdqdone
# otherwise, slurp next line and try again
N N
s/\n// s/\n//
/"/!bdqstring bdqstring
:dqdone
s/@!/"/g
bfolded bfolded


# found multi-line single-quoted string '...\n...' -- slurp until end of string # check for multi-line single-quoted string '...\n...' -- fold to one line
:sqstring :sqstring
s/'//g # remove all quote pairs
s/'\([^']*\)'/@!\1@!/g
# done if no dangling quote
/'/!bsqdone
# otherwise, slurp next line and try again
N N
s/\n// s/\n//
/'/!bsqstring bsqstring
:sqdone
s/@!/'/g
bfolded bfolded


# found here-doc -- swallow it to avoid false hits within its body (but keep # found here-doc -- swallow it to avoid false hits within its body (but keep

2
t/chainlint/here-doc-multi-line-string.expect

@ -1,4 +1,4 @@
( (
?!AMP?! cat && echo multi-line string" ?!AMP?! cat && echo "multi-line string"
bap bap
>) >)

10
t/chainlint/multi-line-string.expect

@ -1,9 +1,15 @@
( (
x=line 1 line 2 line 3" && x="line 1 line 2 line 3" &&
?!AMP?! y=line 1 line2' ?!AMP?! y='line 1 line2'
foobar foobar
>) && >) &&
( (
echo "there's nothing to see here" && echo "there's nothing to see here" &&
exit exit
>) &&
(
echo "xyz" "abc def ghi" &&
echo 'xyz' 'abc def ghi' &&
echo 'xyz' "abc def ghi" &&
barfoo
>) >)

12
t/chainlint/multi-line-string.test

@ -12,4 +12,16 @@
# LINT: starting multi-line single-quoted string # LINT: starting multi-line single-quoted string
echo "there's nothing to see here" && echo "there's nothing to see here" &&
exit exit
) &&
(
echo "xyz" "abc
def
ghi" &&
echo 'xyz' 'abc
def
ghi' &&
echo 'xyz' "abc
def
ghi" &&
barfoo
) )

Loading…
Cancel
Save