chainlint: make error messages self-explanatory
The annotations emitted by chainlint to indicate detected problems are overly terse, so much so that developers new to the project -- those who should most benefit from the linting -- may find them baffling. For instance, although the author of chainlint and seasoned Git developers may understand that "?!AMP?!" is an abbreviation of "ampersand" and indicates a break in the &&-chain, this may not be obvious to newcomers. The "?!LOOP?!" case is particularly serious because that terse single word does nothing to convey that the loop body should end with "|| return 1" (or "|| exit 1" in a subshell) to ensure that a failing command in the body aborts the loop immediately. Moreover, unlike &&-chaining which is ubiquitous in Git tests, the "|| return 1" idiom is relatively infrequent, thus may be harder for a newcomer to discover by consulting nearby code. Address these shortcomings by emitting human-readable messages which both explain the problem and give a strong hint about how to correct it. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									588ef84ece
								
							
						
					
					
						commit
						e44f15ba3e
					
				|  | @ -9,9 +9,9 @@ | ||||||
| # Input arguments are pathnames of shell scripts containing test definitions, | # Input arguments are pathnames of shell scripts containing test definitions, | ||||||
| # or globs referencing a collection of scripts. For each problem discovered, | # or globs referencing a collection of scripts. For each problem discovered, | ||||||
| # the pathname of the script containing the test is printed along with the test | # the pathname of the script containing the test is printed along with the test | ||||||
| # name and the test body with a `?!FOO?!` annotation at the location of each | # name and the test body with a `?!LINT: ...?!` annotation at the location of | ||||||
| # detected problem, where "FOO" is a tag such as "AMP" which indicates a broken | # each detected problem, where "..." is an explanation of the problem. Returns | ||||||
| # &&-chain. Returns zero if no problems are discovered, otherwise non-zero. | # zero if no problems are discovered, otherwise non-zero. | ||||||
|  |  | ||||||
| use warnings; | use warnings; | ||||||
| use strict; | use strict; | ||||||
|  | @ -181,7 +181,7 @@ sub swallow_heredocs { | ||||||
| 			$self->{lineno} += () = $body =~ /\n/sg; | 			$self->{lineno} += () = $body =~ /\n/sg; | ||||||
| 			next; | 			next; | ||||||
| 		} | 		} | ||||||
| 		push(@{$self->{parser}->{problems}}, ['UNCLOSED-HEREDOC', $tag]); | 		push(@{$self->{parser}->{problems}}, ['HEREDOC', $tag]); | ||||||
| 		$$b =~ /(?:\G|\n).*\z/gc; # consume rest of input | 		$$b =~ /(?:\G|\n).*\z/gc; # consume rest of input | ||||||
| 		my $body = substr($$b, $start, pos($$b) - $start); | 		my $body = substr($$b, $start, pos($$b) - $start); | ||||||
| 		$self->{lineno} += () = $body =~ /\n/sg; | 		$self->{lineno} += () = $body =~ /\n/sg; | ||||||
|  | @ -238,6 +238,7 @@ sub new { | ||||||
| 		stop => [], | 		stop => [], | ||||||
| 		output => [], | 		output => [], | ||||||
| 		heredocs => {}, | 		heredocs => {}, | ||||||
|  | 		insubshell => 0, | ||||||
| 	} => $class; | 	} => $class; | ||||||
| 	$self->{lexer} = Lexer->new($self, $s); | 	$self->{lexer} = Lexer->new($self, $s); | ||||||
| 	return $self; | 	return $self; | ||||||
|  | @ -296,8 +297,11 @@ sub parse_group { | ||||||
|  |  | ||||||
| sub parse_subshell { | sub parse_subshell { | ||||||
| 	my $self = shift @_; | 	my $self = shift @_; | ||||||
| 	return ($self->parse(qr/^\)$/), | 	$self->{insubshell}++; | ||||||
| 		$self->expect(')')); | 	my @tokens = ($self->parse(qr/^\)$/), | ||||||
|  | 		      $self->expect(')')); | ||||||
|  | 	$self->{insubshell}--; | ||||||
|  | 	return @tokens; | ||||||
| } | } | ||||||
|  |  | ||||||
| sub parse_case_pattern { | sub parse_case_pattern { | ||||||
|  | @ -528,7 +532,7 @@ sub parse_loop_body { | ||||||
| 	return @tokens if ends_with(\@tokens, [qr/^\|\|$/, "\n", qr/^echo$/, qr/^.+$/]); | 	return @tokens if ends_with(\@tokens, [qr/^\|\|$/, "\n", qr/^echo$/, qr/^.+$/]); | ||||||
| 	# flag missing "return/exit" handling explicit failure in loop body | 	# flag missing "return/exit" handling explicit failure in loop body | ||||||
| 	my $n = find_non_nl(\@tokens); | 	my $n = find_non_nl(\@tokens); | ||||||
| 	push(@{$self->{problems}}, ['LOOP', $tokens[$n]]); | 	push(@{$self->{problems}}, [$self->{insubshell} ? 'LOOPEXIT' : 'LOOPRETURN', $tokens[$n]]); | ||||||
| 	return @tokens; | 	return @tokens; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -620,6 +624,15 @@ sub unwrap { | ||||||
| 	return $s | 	return $s | ||||||
| } | } | ||||||
|  |  | ||||||
|  | sub format_problem { | ||||||
|  | 	local $_ = shift; | ||||||
|  | 	/^AMP$/ && return "missing '&&'"; | ||||||
|  | 	/^LOOPRETURN$/ && return "missing '|| return 1'"; | ||||||
|  | 	/^LOOPEXIT$/ && return "missing '|| exit 1'"; | ||||||
|  | 	/^HEREDOC$/ && return 'unclosed heredoc'; | ||||||
|  | 	die("unrecognized problem type '$_'\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
| sub check_test { | sub check_test { | ||||||
| 	my $self = shift @_; | 	my $self = shift @_; | ||||||
| 	my $title = unwrap(shift @_); | 	my $title = unwrap(shift @_); | ||||||
|  | @ -643,9 +656,10 @@ sub check_test { | ||||||
| 	for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) { | 	for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) { | ||||||
| 		my ($label, $token) = @$_; | 		my ($label, $token) = @$_; | ||||||
| 		my $pos = $token->[2]; | 		my $pos = $token->[2]; | ||||||
|  | 		my $err = format_problem($label); | ||||||
| 		$checked .= substr($body, $start, $pos - $start); | 		$checked .= substr($body, $start, $pos - $start); | ||||||
| 		$checked .= ' ' unless $checked =~ /\s$/; | 		$checked .= ' ' unless $checked =~ /\s$/; | ||||||
| 		$checked .= "$c->{rev}$c->{red}?!$label?!$c->{reset}"; | 		$checked .= "$c->{rev}$c->{red}?!LINT: $err?!$c->{reset}"; | ||||||
| 		$checked .= ' ' unless $pos >= length($body) || | 		$checked .= ' ' unless $pos >= length($body) || | ||||||
| 		    substr($body, $pos, 1) =~ /^\s/; | 		    substr($body, $pos, 1) =~ /^\s/; | ||||||
| 		$start = $pos; | 		$start = $pos; | ||||||
|  |  | ||||||
|  | @ -4,6 +4,6 @@ | ||||||
| 5 	baz | 5 	baz | ||||||
| 6 ) && | 6 ) && | ||||||
| 7 ( | 7 ( | ||||||
| 8 	bar=$((42 + 1)) ?!AMP?! | 8 	bar=$((42 + 1)) ?!LINT: missing '&&'?! | ||||||
| 9 	baz | 9 	baz | ||||||
| 10 ) | 10 ) | ||||||
|  |  | ||||||
|  | @ -1,20 +1,20 @@ | ||||||
| 2 ( | 2 ( | ||||||
| 3 	foo && | 3 	foo && | ||||||
| 4 	{ | 4 	{ | ||||||
| 5 		echo a ?!AMP?! | 5 		echo a ?!LINT: missing '&&'?! | ||||||
| 6 		echo b | 6 		echo b | ||||||
| 7 	} && | 7 	} && | ||||||
| 8 	bar && | 8 	bar && | ||||||
| 9 	{ | 9 	{ | ||||||
| 10 		echo c | 10 		echo c | ||||||
| 11 	} ?!AMP?! | 11 	} ?!LINT: missing '&&'?! | ||||||
| 12 	baz | 12 	baz | ||||||
| 13 ) && | 13 ) && | ||||||
| 14  | 14  | ||||||
| 15 { | 15 { | ||||||
| 16 	echo a; ?!AMP?! echo b | 16 	echo a; ?!LINT: missing '&&'?! echo b | ||||||
| 17 } && | 17 } && | ||||||
| 18 { echo a; ?!AMP?! echo b; } && | 18 { echo a; ?!LINT: missing '&&'?! echo b; } && | ||||||
| 19  | 19  | ||||||
| 20 { | 20 { | ||||||
| 21 	echo "${var}9" && | 21 	echo "${var}9" && | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| 2 ( | 2 ( | ||||||
| 3 	foo && | 3 	foo && | ||||||
| 4 	bar ?!AMP?! | 4 	bar ?!LINT: missing '&&'?! | ||||||
| 5 	baz && | 5 	baz && | ||||||
| 6 	wop | 6 	wop | ||||||
| 7 ) | 7 ) | ||||||
|  |  | ||||||
|  | @ -9,11 +9,11 @@ | ||||||
| 10 	case "$x" in | 10 	case "$x" in | ||||||
| 11 	x) foo ;; | 11 	x) foo ;; | ||||||
| 12 	*) bar ;; | 12 	*) bar ;; | ||||||
| 13 	esac ?!AMP?! | 13 	esac ?!LINT: missing '&&'?! | ||||||
| 14 	foobar | 14 	foobar | ||||||
| 15 ) && | 15 ) && | ||||||
| 16 ( | 16 ( | ||||||
| 17 	case "$x" in 1) true;; esac && | 17 	case "$x" in 1) true;; esac && | ||||||
| 18 	case "$y" in 2) false;; esac ?!AMP?! | 18 	case "$y" in 2) false;; esac ?!LINT: missing '&&'?! | ||||||
| 19 	foobar | 19 	foobar | ||||||
| 20 ) | 20 ) | ||||||
|  |  | ||||||
|  | @ -4,6 +4,6 @@ | ||||||
| 5 	echo failed! | 5 	echo failed! | ||||||
| 6 	false | 6 	false | ||||||
| 7 else | 7 else | ||||||
| 8 	echo it went okay ?!AMP?! | 8 	echo it went okay ?!LINT: missing '&&'?! | ||||||
| 9 	congratulate user | 9 	congratulate user | ||||||
| 10 fi | 10 fi | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| 2 echo nobody home && { | 2 echo nobody home && { | ||||||
| 3 	test the doohicky ?!AMP?! | 3 	test the doohicky ?!LINT: missing '&&'?! | ||||||
| 4 	right now | 4 	right now | ||||||
| 5 } && | 5 } && | ||||||
| 6  | 6  | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| 2 mkdir sub && ( | 2 mkdir sub && ( | ||||||
| 3 	cd sub && | 3 	cd sub && | ||||||
| 4 	foo the bar ?!AMP?! | 4 	foo the bar ?!LINT: missing '&&'?! | ||||||
| 5 	nuff said | 5 	nuff said | ||||||
| 6 ) && | 6 ) && | ||||||
| 7  | 7  | ||||||
| 8 cut "-d " -f actual | (read s1 s2 s3 && | 8 cut "-d " -f actual | (read s1 s2 s3 && | ||||||
| 9 test -f $s1 ?!AMP?! | 9 test -f $s1 ?!LINT: missing '&&'?! | ||||||
| 10 test $(cat $s2) = tree2path1 && | 10 test $(cat $s2) = tree2path1 && | ||||||
| 11 test $(cat $s3) = tree3path1) | 11 test $(cat $s3) = tree3path1) | ||||||
|  |  | ||||||
|  | @ -4,6 +4,6 @@ | ||||||
| 5 	baz | 5 	baz | ||||||
| 6 ) && | 6 ) && | ||||||
| 7 ( | 7 ( | ||||||
| 8 	bar=$(gobble blocks) ?!AMP?! | 8 	bar=$(gobble blocks) ?!LINT: missing '&&'?! | ||||||
| 9 	baz | 9 	baz | ||||||
| 10 ) | 10 ) | ||||||
|  |  | ||||||
|  | @ -4,6 +4,6 @@ | ||||||
| 5      : | 5      : | ||||||
| 6    else | 6    else | ||||||
| 7      echo >file | 7      echo >file | ||||||
| 8    fi ?!LOOP?! | 8    fi ?!LINT: missing '|| exit 1'?! | ||||||
| 9  done) && | 9  done) && | ||||||
| 10 test ! -f file | 10 test ! -f file | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| 3 	bar | 3 	bar | ||||||
| 4 ) && | 4 ) && | ||||||
| 5  | 5  | ||||||
| 6 (cd foo ?!AMP?! | 6 (cd foo ?!LINT: missing '&&'?! | ||||||
| 7 	bar | 7 	bar | ||||||
| 8 ) && | 8 ) && | ||||||
| 9  | 9  | ||||||
|  | @ -13,5 +13,5 @@ | ||||||
| 14 (cd foo && | 14 (cd foo && | ||||||
| 15 	bar) && | 15 	bar) && | ||||||
| 16  | 16  | ||||||
| 17 (cd foo ?!AMP?! | 17 (cd foo ?!LINT: missing '&&'?! | ||||||
| 18 	bar) | 18 	bar) | ||||||
|  |  | ||||||
|  | @ -1,14 +1,14 @@ | ||||||
| 2 ( | 2 ( | ||||||
| 3 	for i in a b c | 3 	for i in a b c | ||||||
| 4 	do | 4 	do | ||||||
| 5 		echo $i ?!AMP?! | 5 		echo $i ?!LINT: missing '&&'?! | ||||||
| 6 		cat <<-\EOF ?!LOOP?! | 6 		cat <<-\EOF ?!LINT: missing '|| exit 1'?! | ||||||
| 7 		bar | 7 		bar | ||||||
| 8 		EOF | 8 		EOF | ||||||
| 9 	done ?!AMP?! | 9 	done ?!LINT: missing '&&'?! | ||||||
| 10  | 10  | ||||||
| 11 	for i in a b c; do | 11 	for i in a b c; do | ||||||
| 12 		echo $i && | 12 		echo $i && | ||||||
| 13 		cat $i ?!LOOP?! | 13 		cat $i ?!LINT: missing '|| exit 1'?! | ||||||
| 14 	done | 14 	done | ||||||
| 15 ) | 15 ) | ||||||
|  |  | ||||||
|  | @ -4,8 +4,8 @@ | ||||||
| 5  | 5  | ||||||
| 6 remove_object() { | 6 remove_object() { | ||||||
| 7 	file=$(sha1_file "$*") && | 7 	file=$(sha1_file "$*") && | ||||||
| 8 	test -e "$file" ?!AMP?! | 8 	test -e "$file" ?!LINT: missing '&&'?! | ||||||
| 9 	rm -f "$file" | 9 	rm -f "$file" | ||||||
| 10 } ?!AMP?! | 10 } ?!LINT: missing '&&'?! | ||||||
| 11  | 11  | ||||||
| 12 sha1_file arg && remove_object arg | 12 sha1_file arg && remove_object arg | ||||||
|  |  | ||||||
|  | @ -1,2 +1,2 @@ | ||||||
| 2 	echo "we should find this" ?!AMP?! | 2 	echo "we should find this" ?!LINT: missing '&&'?! | ||||||
| 3 	echo "even though our heredoc has its indent stripped" | 3 	echo "even though our heredoc has its indent stripped" | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| 2 	echo "outer here-doc does not allow indented end-tag" ?!AMP?! | 2 	echo "outer here-doc does not allow indented end-tag" ?!LINT: missing '&&'?! | ||||||
| 3 	cat >file <<-\EOF && | 3 	cat >file <<-\EOF && | ||||||
| 4 	but this inner here-doc | 4 	but this inner here-doc | ||||||
| 5 	does allow indented EOF | 5 	does allow indented EOF | ||||||
| 6 	EOF | 6 	EOF | ||||||
| 7 	echo "missing chain after" ?!AMP?! | 7 	echo "missing chain after" ?!LINT: missing '&&'?! | ||||||
| 8 	echo "but this line is OK because it's the end" | 8 	echo "but this line is OK because it's the end" | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| 2 	echo "missing chain before" ?!AMP?! | 2 	echo "missing chain before" ?!LINT: missing '&&'?! | ||||||
| 3 	cat >file <<-\EOF && | 3 	cat >file <<-\EOF && | ||||||
| 4 	inside inner here-doc | 4 	inside inner here-doc | ||||||
| 5 	these are not shell commands | 5 	these are not shell commands | ||||||
| 6 	EOF | 6 	EOF | ||||||
| 7 	echo "missing chain after" ?!AMP?! | 7 	echo "missing chain after" ?!LINT: missing '&&'?! | ||||||
| 8 	echo "but this line is OK because it's the end" | 8 	echo "but this line is OK because it's the end" | ||||||
|  |  | ||||||
|  | @ -1,2 +1,2 @@ | ||||||
| 8 	echo "actual test commands" ?!AMP?! | 8 	echo "actual test commands" ?!LINT: missing '&&'?! | ||||||
| 9 	echo "that should be checked" | 9 	echo "that should be checked" | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| 5 chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data | 5 chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data | ||||||
| 6 EOF | 6 EOF | ||||||
| 7  | 7  | ||||||
| 8 cat >expect << -EOF ?!AMP?! | 8 cat >expect << -EOF ?!LINT: missing '&&'?! | ||||||
| 9 this is not indented | 9 this is not indented | ||||||
| 10 -EOF | 10 -EOF | ||||||
| 11  | 11  | ||||||
|  |  | ||||||
|  | @ -3,6 +3,6 @@ | ||||||
| 4 		fossil | 4 		fossil | ||||||
| 5 		vegetable | 5 		vegetable | ||||||
| 6 		END | 6 		END | ||||||
| 7 		wiffle) ?!AMP?! | 7 		wiffle) ?!LINT: missing '&&'?! | ||||||
| 8 	echo $x | 8 	echo $x | ||||||
| 9 ) | 9 ) | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| 2 ( | 2 ( | ||||||
| 3 	cat <<-\TXT && echo "multi-line | 3 	cat <<-\TXT && echo "multi-line | ||||||
| 4 	string" ?!AMP?! | 4 	string" ?!LINT: missing '&&'?! | ||||||
| 5 	fizzle | 5 	fizzle | ||||||
| 6 	TXT | 6 	TXT | ||||||
| 7 	bap | 7 	bap | ||||||
|  |  | ||||||
|  | @ -2,6 +2,6 @@ | ||||||
| 3    marcia || | 3    marcia || | ||||||
| 4    kevin | 4    kevin | ||||||
| 5 then | 5 then | ||||||
| 6 	echo "nomads" ?!AMP?! | 6 	echo "nomads" ?!LINT: missing '&&'?! | ||||||
| 7 	echo "for sure" | 7 	echo "for sure" | ||||||
| 8 fi | 8 fi | ||||||
|  |  | ||||||
|  | @ -5,8 +5,8 @@ | ||||||
| 6 		then | 6 		then | ||||||
| 7 			echo "err" | 7 			echo "err" | ||||||
| 8 			exit 1 | 8 			exit 1 | ||||||
| 9 		fi ?!AMP?! | 9 		fi ?!LINT: missing '&&'?! | ||||||
| 10 		foo | 10 		foo | ||||||
| 11 	done ?!AMP?! | 11 	done ?!LINT: missing '&&'?! | ||||||
| 12 	bar | 12 	bar | ||||||
| 13 ) | 13 ) | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| 2 ( | 2 ( | ||||||
| 3 	if test -n "" | 3 	if test -n "" | ||||||
| 4 	then | 4 	then | ||||||
| 5 		echo very ?!AMP?! | 5 		echo very ?!LINT: missing '&&'?! | ||||||
| 6 		echo empty | 6 		echo empty | ||||||
| 7 	elif test -z "" | 7 	elif test -z "" | ||||||
| 8 	then | 8 	then | ||||||
|  | @ -11,7 +11,7 @@ | ||||||
| 12 		cat <<-\EOF | 12 		cat <<-\EOF | ||||||
| 13 		bar | 13 		bar | ||||||
| 14 		EOF | 14 		EOF | ||||||
| 15 	fi ?!AMP?! | 15 	fi ?!LINT: missing '&&'?! | ||||||
| 16 	echo poodle | 16 	echo poodle | ||||||
| 17 ) && | 17 ) && | ||||||
| 18 ( | 18 ( | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| 2 ( | 2 ( | ||||||
| 3 	foobar && # comment 1 | 3 	foobar && # comment 1 | ||||||
| 4 	barfoo ?!AMP?! # wrong position for && | 4 	barfoo ?!LINT: missing '&&'?! # wrong position for && | ||||||
| 5 	flibble "not a # comment" | 5 	flibble "not a # comment" | ||||||
| 6 ) && | 6 ) && | ||||||
| 7  | 7  | ||||||
|  |  | ||||||
|  | @ -11,5 +11,5 @@ | ||||||
| 12 do | 12 do | ||||||
| 13 	printf "%"$n"s" X > r2/large.$n && | 13 	printf "%"$n"s" X > r2/large.$n && | ||||||
| 14 	git -C r2 add large.$n && | 14 	git -C r2 add large.$n && | ||||||
| 15 	git -C r2 commit -m "$n" ?!LOOP?! | 15 	git -C r2 commit -m "$n" ?!LINT: missing '|| return 1'?! | ||||||
| 16 done | 16 done | ||||||
|  |  | ||||||
|  | @ -3,10 +3,10 @@ | ||||||
| 4 	then | 4 	then | ||||||
| 5 		while true | 5 		while true | ||||||
| 6 		do | 6 		do | ||||||
| 7 			echo "pop" ?!AMP?! | 7 			echo "pop" ?!LINT: missing '&&'?! | ||||||
| 8 			echo "glup" ?!LOOP?! | 8 			echo "glup" ?!LINT: missing '|| exit 1'?! | ||||||
| 9 		done ?!AMP?! | 9 		done ?!LINT: missing '&&'?! | ||||||
| 10 		foo | 10 		foo | ||||||
| 11 	fi ?!AMP?! | 11 	fi ?!LINT: missing '&&'?! | ||||||
| 12 	bar | 12 	bar | ||||||
| 13 ) | 13 ) | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| 4 		line 2 | 4 		line 2 | ||||||
| 5 		line 3" && | 5 		line 3" && | ||||||
| 6 	y="line 1 | 6 	y="line 1 | ||||||
| 7 		line2" ?!AMP?! | 7 		line2" ?!LINT: missing '&&'?! | ||||||
| 8 	foobar | 8 	foobar | ||||||
| 9 ) && | 9 ) && | ||||||
| 10 ( | 10 ( | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| 2 ! (foo && bar) && | 2 ! (foo && bar) && | ||||||
| 3 ! (foo && bar) >baz && | 3 ! (foo && bar) >baz && | ||||||
| 4  | 4  | ||||||
| 5 ! (foo; ?!AMP?! bar) && | 5 ! (foo; ?!LINT: missing '&&'?! bar) && | ||||||
| 6 ! (foo; ?!AMP?! bar) >baz | 6 ! (foo; ?!LINT: missing '&&'?! bar) >baz | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ | ||||||
| 6  | 6  | ||||||
| 7 	(cd foo && | 7 	(cd foo && | ||||||
| 8 		bar | 8 		bar | ||||||
| 9 	) ?!AMP?! | 9 	) ?!LINT: missing '&&'?! | ||||||
| 10  | 10  | ||||||
| 11 	( | 11 	( | ||||||
| 12 		cd foo && | 12 		cd foo && | ||||||
|  | @ -13,13 +13,13 @@ | ||||||
| 14  | 14  | ||||||
| 15 	( | 15 	( | ||||||
| 16 		cd foo && | 16 		cd foo && | ||||||
| 17 		bar) ?!AMP?! | 17 		bar) ?!LINT: missing '&&'?! | ||||||
| 18  | 18  | ||||||
| 19 	(cd foo && | 19 	(cd foo && | ||||||
| 20 		bar) && | 20 		bar) && | ||||||
| 21  | 21  | ||||||
| 22 	(cd foo && | 22 	(cd foo && | ||||||
| 23 		bar) ?!AMP?! | 23 		bar) ?!LINT: missing '&&'?! | ||||||
| 24  | 24  | ||||||
| 25 	foobar | 25 	foobar | ||||||
| 26 ) | 26 ) | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ | ||||||
| 19 	toink | 19 	toink | ||||||
| 20 	INPUT_END | 20 	INPUT_END | ||||||
| 21  | 21  | ||||||
| 22 	cat <<-\EOT ?!AMP?! | 22 	cat <<-\EOT ?!LINT: missing '&&'?! | ||||||
| 23 	text goes here | 23 	text goes here | ||||||
| 24 	data <<EOF | 24 	data <<EOF | ||||||
| 25 		data goes here | 25 		data goes here | ||||||
|  |  | ||||||
|  | @ -2,8 +2,8 @@ | ||||||
| 3 do | 3 do | ||||||
| 4 	for j in 0 1 2 3 4 5 6 7 8 9; | 4 	for j in 0 1 2 3 4 5 6 7 8 9; | ||||||
| 5 	do | 5 	do | ||||||
| 6 		echo "$i$j" >"path$i$j" ?!LOOP?! | 6 		echo "$i$j" >"path$i$j" ?!LINT: missing '|| return 1'?! | ||||||
| 7 	done ?!LOOP?! | 7 	done ?!LINT: missing '|| return 1'?! | ||||||
| 8 done && | 8 done && | ||||||
| 9  | 9  | ||||||
| 10 for i in 0 1 2 3 4 5 6 7 8 9; | 10 for i in 0 1 2 3 4 5 6 7 8 9; | ||||||
|  | @ -18,7 +18,7 @@ | ||||||
| 19 do | 19 do | ||||||
| 20 	for j in 0 1 2 3 4 5 6 7 8 9; | 20 	for j in 0 1 2 3 4 5 6 7 8 9; | ||||||
| 21 	do | 21 	do | ||||||
| 22 		echo "$i$j" >"path$i$j" ?!LOOP?! | 22 		echo "$i$j" >"path$i$j" ?!LINT: missing '|| return 1'?! | ||||||
| 23 	done || return 1 | 23 	done || return 1 | ||||||
| 24 done && | 24 done && | ||||||
| 25  | 25  | ||||||
|  |  | ||||||
|  | @ -6,6 +6,6 @@ | ||||||
| 7 		# minor numbers of cows (or do they?) | 7 		# minor numbers of cows (or do they?) | ||||||
| 8 		baz && | 8 		baz && | ||||||
| 9 		snaff | 9 		snaff | ||||||
| 10 	) ?!AMP?! | 10 	) ?!LINT: missing '&&'?! | ||||||
| 11 	fuzzy | 11 	fuzzy | ||||||
| 12 ) | 12 ) | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| 8  | 8  | ||||||
| 9 	cd foo && | 9 	cd foo && | ||||||
| 10 	( | 10 	( | ||||||
| 11 		echo a ?!AMP?! | 11 		echo a ?!LINT: missing '&&'?! | ||||||
| 12 		echo b | 12 		echo b | ||||||
| 13 	) >file | 13 	) >file | ||||||
| 14 ) | 14 ) | ||||||
|  |  | ||||||
|  | @ -9,6 +9,6 @@ | ||||||
| 10 	echo ourside && | 10 	echo ourside && | ||||||
| 11 	echo "=======" && | 11 	echo "=======" && | ||||||
| 12 	echo theirside && | 12 	echo theirside && | ||||||
| 13 	echo ">>>>>>> theirs" ?!AMP?! | 13 	echo ">>>>>>> theirs" ?!LINT: missing '&&'?! | ||||||
| 14 	poodle | 14 	poodle | ||||||
| 15 ) >merged | 15 ) >merged | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| 4 	cd dir-rename-and-content && | 4 	cd dir-rename-and-content && | ||||||
| 5 	test_write_lines 1 2 3 4 5 >foo && | 5 	test_write_lines 1 2 3 4 5 >foo && | ||||||
| 6 	mkdir olddir && | 6 	mkdir olddir && | ||||||
| 7 	for i in a b c; do echo $i >olddir/$i; ?!LOOP?! done ?!AMP?! | 7 	for i in a b c; do echo $i >olddir/$i; ?!LINT: missing '|| exit 1'?! done ?!LINT: missing '&&'?! | ||||||
| 8 	git add foo olddir && | 8 	git add foo olddir && | ||||||
| 9 	git commit -m "original" && | 9 	git commit -m "original" && | ||||||
| 10 ) | 10 ) | ||||||
|  |  | ||||||
|  | @ -2,8 +2,8 @@ | ||||||
| 3 (foo && bar) | | 3 (foo && bar) | | ||||||
| 4 (foo && bar) >baz && | 4 (foo && bar) >baz && | ||||||
| 5  | 5  | ||||||
| 6 (foo; ?!AMP?! bar) && | 6 (foo; ?!LINT: missing '&&'?! bar) && | ||||||
| 7 (foo; ?!AMP?! bar) | | 7 (foo; ?!LINT: missing '&&'?! bar) | | ||||||
| 8 (foo; ?!AMP?! bar) >baz && | 8 (foo; ?!LINT: missing '&&'?! bar) >baz && | ||||||
| 9  | 9  | ||||||
| 10 (foo "bar; baz") | 10 (foo "bar; baz") | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| 5 	baz && | 5 	baz && | ||||||
| 6  | 6  | ||||||
| 7 	fish | | 7 	fish | | ||||||
| 8 	cow ?!AMP?! | 8 	cow ?!LINT: missing '&&'?! | ||||||
| 9  | 9  | ||||||
| 10 	sunder | 10 	sunder | ||||||
| 11 ) | 11 ) | ||||||
|  |  | ||||||
|  | @ -1,19 +1,19 @@ | ||||||
| 2 ( | 2 ( | ||||||
| 3 	cat foo ; ?!AMP?! echo bar ?!AMP?! | 3 	cat foo ; ?!LINT: missing '&&'?! echo bar ?!LINT: missing '&&'?! | ||||||
| 4 	cat foo ; ?!AMP?! echo bar | 4 	cat foo ; ?!LINT: missing '&&'?! echo bar | ||||||
| 5 ) && | 5 ) && | ||||||
| 6 ( | 6 ( | ||||||
| 7 	cat foo ; ?!AMP?! echo bar && | 7 	cat foo ; ?!LINT: missing '&&'?! echo bar && | ||||||
| 8 	cat foo ; ?!AMP?! echo bar | 8 	cat foo ; ?!LINT: missing '&&'?! echo bar | ||||||
| 9 ) && | 9 ) && | ||||||
| 10 ( | 10 ( | ||||||
| 11 	echo "foo; bar" && | 11 	echo "foo; bar" && | ||||||
| 12 	cat foo; ?!AMP?! echo bar | 12 	cat foo; ?!LINT: missing '&&'?! echo bar | ||||||
| 13 ) && | 13 ) && | ||||||
| 14 ( | 14 ( | ||||||
| 15 	foo; | 15 	foo; | ||||||
| 16 ) && | 16 ) && | ||||||
| 17 (cd foo && | 17 (cd foo && | ||||||
| 18 	for i in a b c; do | 18 	for i in a b c; do | ||||||
| 19 		echo; ?!LOOP?! | 19 		echo; ?!LINT: missing '|| exit 1'?! | ||||||
| 20 	done) | 20 	done) | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ | ||||||
| 7 	nevermore... | 7 	nevermore... | ||||||
| 8 	EOF | 8 	EOF | ||||||
| 9  | 9  | ||||||
| 10 	cat <<EOF >bip ?!AMP?! | 10 	cat <<EOF >bip ?!LINT: missing '&&'?! | ||||||
| 11 	fish fly high | 11 	fish fly high | ||||||
| 12 EOF | 12 EOF | ||||||
| 13  | 13  | ||||||
|  |  | ||||||
|  | @ -3,17 +3,17 @@ | ||||||
| 4 	(foo && bar) | | 4 	(foo && bar) | | ||||||
| 5 	(foo && bar) >baz && | 5 	(foo && bar) >baz && | ||||||
| 6  | 6  | ||||||
| 7 	(foo; ?!AMP?! bar) && | 7 	(foo; ?!LINT: missing '&&'?! bar) && | ||||||
| 8 	(foo; ?!AMP?! bar) | | 8 	(foo; ?!LINT: missing '&&'?! bar) | | ||||||
| 9 	(foo; ?!AMP?! bar) >baz && | 9 	(foo; ?!LINT: missing '&&'?! bar) >baz && | ||||||
| 10  | 10  | ||||||
| 11 	(foo || exit 1) && | 11 	(foo || exit 1) && | ||||||
| 12 	(foo || exit 1) | | 12 	(foo || exit 1) | | ||||||
| 13 	(foo || exit 1) >baz && | 13 	(foo || exit 1) >baz && | ||||||
| 14  | 14  | ||||||
| 15 	(foo && bar) ?!AMP?! | 15 	(foo && bar) ?!LINT: missing '&&'?! | ||||||
| 16  | 16  | ||||||
| 17 	(foo && bar; ?!AMP?! baz) ?!AMP?! | 17 	(foo && bar; ?!LINT: missing '&&'?! baz) ?!LINT: missing '&&'?! | ||||||
| 18  | 18  | ||||||
| 19 	foobar | 19 	foobar | ||||||
| 20 ) | 20 ) | ||||||
|  |  | ||||||
|  | @ -2,13 +2,13 @@ | ||||||
| 3 git config filter.rot13.clean ./rot13.sh && | 3 git config filter.rot13.clean ./rot13.sh && | ||||||
| 4  | 4  | ||||||
| 5 { | 5 { | ||||||
| 6     echo "*.t filter=rot13" ?!AMP?! | 6     echo "*.t filter=rot13" ?!LINT: missing '&&'?! | ||||||
| 7     echo "*.i ident" | 7     echo "*.i ident" | ||||||
| 8 } >.gitattributes && | 8 } >.gitattributes && | ||||||
| 9  | 9  | ||||||
| 10 { | 10 { | ||||||
| 11     echo a b c d e f g h i j k l m ?!AMP?! | 11     echo a b c d e f g h i j k l m ?!LINT: missing '&&'?! | ||||||
| 12     echo n o p q r s t u v w x y z ?!AMP?! | 12     echo n o p q r s t u v w x y z ?!LINT: missing '&&'?! | ||||||
| 13     echo '$Id$' | 13     echo '$Id$' | ||||||
| 14 } >test && | 14 } >test && | ||||||
| 15 cat test >test.t && | 15 cat test >test.t && | ||||||
|  | @ -19,7 +19,7 @@ | ||||||
| 20 git checkout -- test test.t test.i && | 20 git checkout -- test test.t test.i && | ||||||
| 21  | 21  | ||||||
| 22 echo "content-test2" >test2.o && | 22 echo "content-test2" >test2.o && | ||||||
| 23 echo "content-test3 - filename with special characters" >"test3 'sq',$x=.o" ?!AMP?! | 23 echo "content-test3 - filename with special characters" >"test3 'sq',$x=.o" ?!LINT: missing '&&'?! | ||||||
| 24  | 24  | ||||||
| 25 downstream_url_for_sed=$( | 25 downstream_url_for_sed=$( | ||||||
| 26 	printf "%sn" "$downstream_url" | | 26 	printf "%sn" "$downstream_url" | | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| 2 command_which_is_run && | 2 command_which_is_run && | ||||||
| 3 cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! && | 3 cat >expect <<-\EOF ?!LINT: unclosed heredoc?! && | ||||||
| 4 we forget to end the here-doc | 4 we forget to end the here-doc | ||||||
| 5 command_which_is_gobbled | 5 command_which_is_gobbled | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| 2 command_which_is_run && | 2 command_which_is_run && | ||||||
| 3 cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! && | 3 cat >expect <<\EOF ?!LINT: unclosed heredoc?! && | ||||||
| 4 	we try to end the here-doc below, | 4 	we try to end the here-doc below, | ||||||
| 5 	but the indentation throws us off | 5 	but the indentation throws us off | ||||||
| 6 	since the operator is not "<<-". | 6 	since the operator is not "<<-". | ||||||
|  |  | ||||||
|  | @ -1,14 +1,14 @@ | ||||||
| 2 ( | 2 ( | ||||||
| 3 	while true | 3 	while true | ||||||
| 4 	do | 4 	do | ||||||
| 5 		echo foo ?!AMP?! | 5 		echo foo ?!LINT: missing '&&'?! | ||||||
| 6 		cat <<-\EOF ?!LOOP?! | 6 		cat <<-\EOF ?!LINT: missing '|| exit 1'?! | ||||||
| 7 		bar | 7 		bar | ||||||
| 8 		EOF | 8 		EOF | ||||||
| 9 	done ?!AMP?! | 9 	done ?!LINT: missing '&&'?! | ||||||
| 10  | 10  | ||||||
| 11 	while true; do | 11 	while true; do | ||||||
| 12 		echo foo && | 12 		echo foo && | ||||||
| 13 		cat bar ?!LOOP?! | 13 		cat bar ?!LINT: missing '|| exit 1'?! | ||||||
| 14 	done | 14 	done | ||||||
| 15 ) | 15 ) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Eric Sunshine
						Eric Sunshine