Squashed 'third_party/git/' content from commit cb71568594
git-subtree-dir: third_party/git git-subtree-split: cb715685942260375e1eb8153b0768a376e4ece7
This commit is contained in:
commit
1b593e1ea4
3629 changed files with 1139935 additions and 0 deletions
25
t/.gitattributes
vendored
Normal file
25
t/.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
t[0-9][0-9][0-9][0-9]/* -whitespace
|
||||
/chainlint/*.expect eol=lf
|
||||
/diff-lib/* eol=lf
|
||||
/t0110/url-* binary
|
||||
/t3206/* eol=lf
|
||||
/t3900/*.txt eol=lf
|
||||
/t3901/*.txt eol=lf
|
||||
/t4034/*/* eol=lf
|
||||
/t4013/* eol=lf
|
||||
/t4018/* eol=lf
|
||||
/t4051/* eol=lf
|
||||
/t4100/* eol=lf
|
||||
/t4101/* eol=lf
|
||||
/t4109/* eol=lf
|
||||
/t4110/* eol=lf
|
||||
/t4135/* eol=lf
|
||||
/t4211/* eol=lf
|
||||
/t4252/* eol=lf
|
||||
/t4256/1/* eol=lf
|
||||
/t5100/* eol=lf
|
||||
/t5515/* eol=lf
|
||||
/t556x_common eol=lf
|
||||
/t7500/* eol=lf
|
||||
/t8005/*.txt eol=lf
|
||||
/t9*/*.dump eol=lf
|
||||
5
t/.gitignore
vendored
Normal file
5
t/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/trash directory*
|
||||
/test-results
|
||||
/.prove
|
||||
/chainlinttmp
|
||||
/out/
|
||||
14
t/Git-SVN/00compile.t
Executable file
14
t/Git-SVN/00compile.t
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More tests => 7;
|
||||
|
||||
require_ok 'Git::SVN';
|
||||
require_ok 'Git::SVN::Utils';
|
||||
require_ok 'Git::SVN::Ra';
|
||||
require_ok 'Git::SVN::Log';
|
||||
require_ok 'Git::SVN::Migration';
|
||||
require_ok 'Git::IndexInfo';
|
||||
require_ok 'Git::SVN::GlobSpec';
|
||||
27
t/Git-SVN/Utils/add_path_to_url.t
Executable file
27
t/Git-SVN/Utils/add_path_to_url.t
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More 'no_plan';
|
||||
|
||||
use Git::SVN::Utils qw(
|
||||
add_path_to_url
|
||||
);
|
||||
|
||||
# A reference cannot be a hash key, so we use an array.
|
||||
my @tests = (
|
||||
["http://x.com", "bar"] => 'http://x.com/bar',
|
||||
["http://x.com", ""] => 'http://x.com',
|
||||
["http://x.com/foo/", undef] => 'http://x.com/foo/',
|
||||
["http://x.com/foo/", "/bar/baz/"] => 'http://x.com/foo/bar/baz/',
|
||||
["http://x.com", 'per%cent'] => 'http://x.com/per%25cent',
|
||||
);
|
||||
|
||||
while(@tests) {
|
||||
my($have, $want) = splice @tests, 0, 2;
|
||||
|
||||
my $args = join ", ", map { qq['$_'] } map { defined($_) ? $_ : 'undef' } @$have;
|
||||
my $name = "add_path_to_url($args) eq $want";
|
||||
is add_path_to_url(@$have), $want, $name;
|
||||
}
|
||||
11
t/Git-SVN/Utils/can_compress.t
Executable file
11
t/Git-SVN/Utils/can_compress.t
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More 'no_plan';
|
||||
|
||||
use Git::SVN::Utils qw(can_compress);
|
||||
|
||||
# !! is the "convert this to boolean" operator.
|
||||
is !!can_compress(), !!eval { require Compress::Zlib };
|
||||
26
t/Git-SVN/Utils/canonicalize_url.t
Executable file
26
t/Git-SVN/Utils/canonicalize_url.t
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
# Test our own home rolled URL canonicalizer. Test the private one
|
||||
# directly because we can't predict what the SVN API is doing to do.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More 'no_plan';
|
||||
|
||||
use Git::SVN::Utils;
|
||||
my $canonicalize_url = \&Git::SVN::Utils::_canonicalize_url_ourselves;
|
||||
|
||||
my %tests = (
|
||||
"http://x.com" => "http://x.com",
|
||||
"http://x.com/" => "http://x.com",
|
||||
"http://x.com/foo/bar" => "http://x.com/foo/bar",
|
||||
"http://x.com//foo//bar//" => "http://x.com/foo/bar",
|
||||
"http://x.com/ /%/" => "http://x.com/%20%20/%25",
|
||||
);
|
||||
|
||||
for my $arg (keys %tests) {
|
||||
my $want = $tests{$arg};
|
||||
|
||||
is $canonicalize_url->($arg), $want, "canonicalize_url('$arg') => $want";
|
||||
}
|
||||
23
t/Git-SVN/Utils/collapse_dotdot.t
Executable file
23
t/Git-SVN/Utils/collapse_dotdot.t
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More 'no_plan';
|
||||
|
||||
use Git::SVN::Utils;
|
||||
my $collapse_dotdot = \&Git::SVN::Utils::_collapse_dotdot;
|
||||
|
||||
my %tests = (
|
||||
"foo/bar/baz" => "foo/bar/baz",
|
||||
".." => "..",
|
||||
"foo/.." => "",
|
||||
"/foo/bar/../../baz" => "/baz",
|
||||
"deeply/.././deeply/nested" => "./deeply/nested",
|
||||
);
|
||||
|
||||
for my $arg (keys %tests) {
|
||||
my $want = $tests{$arg};
|
||||
|
||||
is $collapse_dotdot->($arg), $want, "_collapse_dotdot('$arg') => $want";
|
||||
}
|
||||
34
t/Git-SVN/Utils/fatal.t
Executable file
34
t/Git-SVN/Utils/fatal.t
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More 'no_plan';
|
||||
|
||||
BEGIN {
|
||||
# Override exit at BEGIN time before Git::SVN::Utils is loaded
|
||||
# so it will see our local exit later.
|
||||
*CORE::GLOBAL::exit = sub(;$) {
|
||||
return @_ ? CORE::exit($_[0]) : CORE::exit();
|
||||
};
|
||||
}
|
||||
|
||||
use Git::SVN::Utils qw(fatal);
|
||||
|
||||
# fatal()
|
||||
{
|
||||
# Capture the exit code and prevent exit.
|
||||
my $exit_status;
|
||||
no warnings 'redefine';
|
||||
local *CORE::GLOBAL::exit = sub { $exit_status = $_[0] || 0 };
|
||||
|
||||
# Trap fatal's message to STDERR
|
||||
my $stderr;
|
||||
close STDERR;
|
||||
ok open STDERR, ">", \$stderr;
|
||||
|
||||
fatal "Some", "Stuff", "Happened";
|
||||
|
||||
is $stderr, "Some Stuff Happened\n";
|
||||
is $exit_status, 1;
|
||||
}
|
||||
32
t/Git-SVN/Utils/join_paths.t
Executable file
32
t/Git-SVN/Utils/join_paths.t
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More 'no_plan';
|
||||
|
||||
use Git::SVN::Utils qw(
|
||||
join_paths
|
||||
);
|
||||
|
||||
# A reference cannot be a hash key, so we use an array.
|
||||
my @tests = (
|
||||
[] => '',
|
||||
["/x.com", "bar"] => '/x.com/bar',
|
||||
["x.com", ""] => 'x.com',
|
||||
["/x.com/foo/", undef, "bar"] => '/x.com/foo/bar',
|
||||
["x.com/foo/", "/bar/baz/"] => 'x.com/foo/bar/baz/',
|
||||
["foo", "bar"] => 'foo/bar',
|
||||
["/foo/bar", "baz", "/biff"] => '/foo/bar/baz/biff',
|
||||
["", undef, "."] => '.',
|
||||
[] => '',
|
||||
|
||||
);
|
||||
|
||||
while(@tests) {
|
||||
my($have, $want) = splice @tests, 0, 2;
|
||||
|
||||
my $args = join ", ", map { qq['$_'] } map { defined($_) ? $_ : 'undef' } @$have;
|
||||
my $name = "join_paths($args) eq '$want'";
|
||||
is join_paths(@$have), $want, $name;
|
||||
}
|
||||
122
t/Makefile
Normal file
122
t/Makefile
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# Run tests
|
||||
#
|
||||
# Copyright (c) 2005 Junio C Hamano
|
||||
#
|
||||
|
||||
-include ../config.mak.autogen
|
||||
-include ../config.mak
|
||||
|
||||
#GIT_TEST_OPTS = --verbose --debug
|
||||
SHELL_PATH ?= $(SHELL)
|
||||
TEST_SHELL_PATH ?= $(SHELL_PATH)
|
||||
PERL_PATH ?= /usr/bin/perl
|
||||
TAR ?= $(TAR)
|
||||
RM ?= rm -f
|
||||
PROVE ?= prove
|
||||
DEFAULT_TEST_TARGET ?= test
|
||||
TEST_LINT ?= test-lint
|
||||
|
||||
ifdef TEST_OUTPUT_DIRECTORY
|
||||
TEST_RESULTS_DIRECTORY = $(TEST_OUTPUT_DIRECTORY)/test-results
|
||||
CHAINLINTTMP = $(TEST_OUTPUT_DIRECTORY)/chainlinttmp
|
||||
else
|
||||
TEST_RESULTS_DIRECTORY = test-results
|
||||
CHAINLINTTMP = chainlinttmp
|
||||
endif
|
||||
|
||||
# Shell quote;
|
||||
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
|
||||
TEST_SHELL_PATH_SQ = $(subst ','\'',$(TEST_SHELL_PATH))
|
||||
PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
|
||||
TEST_RESULTS_DIRECTORY_SQ = $(subst ','\'',$(TEST_RESULTS_DIRECTORY))
|
||||
CHAINLINTTMP_SQ = $(subst ','\'',$(CHAINLINTTMP))
|
||||
|
||||
T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
|
||||
TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh))
|
||||
THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
|
||||
CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.test)))
|
||||
CHAINLINT = sed -f chainlint.sed
|
||||
|
||||
all: $(DEFAULT_TEST_TARGET)
|
||||
|
||||
test: pre-clean check-chainlint $(TEST_LINT)
|
||||
$(MAKE) aggregate-results-and-cleanup
|
||||
|
||||
failed:
|
||||
@failed=$$(cd '$(TEST_RESULTS_DIRECTORY_SQ)' && \
|
||||
grep -l '^failed [1-9]' *.counts | \
|
||||
sed -n 's/\.counts$$/.sh/p') && \
|
||||
test -z "$$failed" || $(MAKE) $$failed
|
||||
|
||||
prove: pre-clean check-chainlint $(TEST_LINT)
|
||||
@echo "*** prove ***"; $(PROVE) --exec '$(TEST_SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
|
||||
$(MAKE) clean-except-prove-cache
|
||||
|
||||
$(T):
|
||||
@echo "*** $@ ***"; '$(TEST_SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
|
||||
|
||||
pre-clean:
|
||||
$(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)'
|
||||
|
||||
clean-except-prove-cache: clean-chainlint
|
||||
$(RM) -r 'trash directory'.* '$(TEST_RESULTS_DIRECTORY_SQ)'
|
||||
$(RM) -r valgrind/bin
|
||||
|
||||
clean: clean-except-prove-cache
|
||||
$(RM) .prove
|
||||
|
||||
clean-chainlint:
|
||||
$(RM) -r '$(CHAINLINTTMP_SQ)'
|
||||
|
||||
check-chainlint:
|
||||
@mkdir -p '$(CHAINLINTTMP_SQ)' && \
|
||||
err=0 && \
|
||||
for i in $(CHAINLINTTESTS); do \
|
||||
$(CHAINLINT) <chainlint/$$i.test | \
|
||||
sed -e '/^# LINT: /d' >'$(CHAINLINTTMP_SQ)'/$$i.actual && \
|
||||
diff -u chainlint/$$i.expect '$(CHAINLINTTMP_SQ)'/$$i.actual || err=1; \
|
||||
done && exit $$err
|
||||
|
||||
test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax \
|
||||
test-lint-filenames
|
||||
|
||||
test-lint-duplicates:
|
||||
@dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
|
||||
test -z "$$dups" || { \
|
||||
echo >&2 "duplicate test numbers:" $$dups; exit 1; }
|
||||
|
||||
test-lint-executable:
|
||||
@bad=`for i in $(T); do test -x "$$i" || echo $$i; done` && \
|
||||
test -z "$$bad" || { \
|
||||
echo >&2 "non-executable tests:" $$bad; exit 1; }
|
||||
|
||||
test-lint-shell-syntax:
|
||||
@'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T) $(THELPERS)
|
||||
|
||||
test-lint-filenames:
|
||||
@# We do *not* pass a glob to ls-files but use grep instead, to catch
|
||||
@# non-ASCII characters (which are quoted within double-quotes)
|
||||
@bad="$$(git -c core.quotepath=true ls-files 2>/dev/null | \
|
||||
grep '["*:<>?\\|]')"; \
|
||||
test -z "$$bad" || { \
|
||||
echo >&2 "non-portable file name(s): $$bad"; exit 1; }
|
||||
|
||||
aggregate-results-and-cleanup: $(T)
|
||||
$(MAKE) aggregate-results
|
||||
$(MAKE) clean
|
||||
|
||||
aggregate-results:
|
||||
for f in '$(TEST_RESULTS_DIRECTORY_SQ)'/t*-*.counts; do \
|
||||
echo "$$f"; \
|
||||
done | '$(SHELL_PATH_SQ)' ./aggregate-results.sh
|
||||
|
||||
gitweb-test:
|
||||
$(MAKE) $(TGITWEB)
|
||||
|
||||
valgrind:
|
||||
$(MAKE) GIT_TEST_OPTS="$(GIT_TEST_OPTS) --valgrind"
|
||||
|
||||
perf:
|
||||
$(MAKE) -C perf/ all
|
||||
|
||||
.PHONY: pre-clean $(T) aggregate-results clean valgrind perf check-chainlint clean-chainlint
|
||||
46
t/aggregate-results.sh
Executable file
46
t/aggregate-results.sh
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
#!/bin/sh
|
||||
|
||||
failed_tests=
|
||||
fixed=0
|
||||
success=0
|
||||
failed=0
|
||||
broken=0
|
||||
total=0
|
||||
|
||||
while read file
|
||||
do
|
||||
while read type value
|
||||
do
|
||||
case $type in
|
||||
'')
|
||||
continue ;;
|
||||
fixed)
|
||||
fixed=$(($fixed + $value)) ;;
|
||||
success)
|
||||
success=$(($success + $value)) ;;
|
||||
failed)
|
||||
failed=$(($failed + $value))
|
||||
if test $value != 0
|
||||
then
|
||||
testnum=$(expr "$file" : 'test-results/\(t[0-9]*\)-')
|
||||
failed_tests="$failed_tests $testnum"
|
||||
fi
|
||||
;;
|
||||
broken)
|
||||
broken=$(($broken + $value)) ;;
|
||||
total)
|
||||
total=$(($total + $value)) ;;
|
||||
esac
|
||||
done <"$file"
|
||||
done
|
||||
|
||||
if test -n "$failed_tests"
|
||||
then
|
||||
printf "\nfailed test(s):$failed_tests\n\n"
|
||||
fi
|
||||
|
||||
printf "%-8s%d\n" fixed $fixed
|
||||
printf "%-8s%d\n" success $success
|
||||
printf "%-8s%d\n" failed $failed
|
||||
printf "%-8s%d\n" broken $broken
|
||||
printf "%-8s%d\n" total $total
|
||||
584
t/annotate-tests.sh
Normal file
584
t/annotate-tests.sh
Normal file
|
|
@ -0,0 +1,584 @@
|
|||
# This file isn't used as a test script directly, instead it is
|
||||
# sourced from t8001-annotate.sh and t8002-blame.sh.
|
||||
|
||||
if test_have_prereq MINGW
|
||||
then
|
||||
sanitize_L () {
|
||||
echo "$1" | sed 'sX\(^-L\|,\)\^\?/X&\\;*Xg'
|
||||
}
|
||||
else
|
||||
sanitize_L () {
|
||||
echo "$1"
|
||||
}
|
||||
fi
|
||||
|
||||
check_count () {
|
||||
head= &&
|
||||
file='file' &&
|
||||
options= &&
|
||||
while :
|
||||
do
|
||||
case "$1" in
|
||||
-h) head="$2"; shift; shift ;;
|
||||
-f) file="$2"; shift; shift ;;
|
||||
-L*) options="$options $(sanitize_L "$1")"; shift ;;
|
||||
-*) options="$options $1"; shift ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done &&
|
||||
echo "$PROG $options $file $head" >&4 &&
|
||||
$PROG $options $file $head >actual &&
|
||||
perl -e '
|
||||
my %expect = (@ARGV);
|
||||
my %count = map { $_ => 0 } keys %expect;
|
||||
while (<STDIN>) {
|
||||
if (/^[0-9a-f]+\t\(([^\t]+)\t/) {
|
||||
my $author = $1;
|
||||
for ($author) { s/^\s*//; s/\s*$//; }
|
||||
$count{$author}++;
|
||||
}
|
||||
}
|
||||
my $bad = 0;
|
||||
while (my ($author, $count) = each %count) {
|
||||
my $ok;
|
||||
my $value = 0;
|
||||
$value = $expect{$author} if defined $expect{$author};
|
||||
if ($value != $count) {
|
||||
$bad = 1;
|
||||
$ok = "bad";
|
||||
}
|
||||
else {
|
||||
$ok = "good";
|
||||
}
|
||||
print STDERR "Author $author (expected $value, attributed $count) $ok\n";
|
||||
}
|
||||
exit($bad);
|
||||
' "$@" <actual
|
||||
}
|
||||
|
||||
test_expect_success 'setup A lines' '
|
||||
echo "1A quick brown fox jumps over the" >file &&
|
||||
echo "lazy dog" >>file &&
|
||||
git add file &&
|
||||
GIT_AUTHOR_NAME="A" GIT_AUTHOR_EMAIL="A@test.git" \
|
||||
git commit -a -m "Initial."
|
||||
'
|
||||
|
||||
test_expect_success 'blame 1 author' '
|
||||
check_count A 2
|
||||
'
|
||||
|
||||
test_expect_success 'blame in a bare repo without starting commit' '
|
||||
git clone --bare . bare.git &&
|
||||
(
|
||||
cd bare.git &&
|
||||
check_count A 2
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'blame by tag objects' '
|
||||
git tag -m "test tag" testTag &&
|
||||
git tag -m "test tag #2" testTag2 testTag &&
|
||||
check_count -h testTag A 2 &&
|
||||
check_count -h testTag2 A 2
|
||||
'
|
||||
|
||||
test_expect_success 'setup B lines' '
|
||||
echo "2A quick brown fox jumps over the" >>file &&
|
||||
echo "lazy dog" >>file &&
|
||||
GIT_AUTHOR_NAME="B" GIT_AUTHOR_EMAIL="B@test.git" \
|
||||
git commit -a -m "Second."
|
||||
'
|
||||
|
||||
test_expect_success 'blame 2 authors' '
|
||||
check_count A 2 B 2
|
||||
'
|
||||
|
||||
test_expect_success 'setup B1 lines (branch1)' '
|
||||
git checkout -b branch1 master &&
|
||||
echo "3A slow green fox jumps into the" >>file &&
|
||||
echo "well." >>file &&
|
||||
GIT_AUTHOR_NAME="B1" GIT_AUTHOR_EMAIL="B1@test.git" \
|
||||
git commit -a -m "Branch1-1"
|
||||
'
|
||||
|
||||
test_expect_success 'blame 2 authors + 1 branch1 author' '
|
||||
check_count A 2 B 2 B1 2
|
||||
'
|
||||
|
||||
test_expect_success 'setup B2 lines (branch2)' '
|
||||
git checkout -b branch2 master &&
|
||||
sed -e "s/2A quick brown/4A quick brown lazy dog/" <file >file.new &&
|
||||
mv file.new file &&
|
||||
GIT_AUTHOR_NAME="B2" GIT_AUTHOR_EMAIL="B2@test.git" \
|
||||
git commit -a -m "Branch2-1"
|
||||
'
|
||||
|
||||
test_expect_success 'blame 2 authors + 1 branch2 author' '
|
||||
check_count A 2 B 1 B2 1
|
||||
'
|
||||
|
||||
test_expect_success 'merge branch1 & branch2' '
|
||||
git merge branch1
|
||||
'
|
||||
|
||||
test_expect_success 'blame 2 authors + 2 merged-in authors' '
|
||||
check_count A 2 B 1 B1 2 B2 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame --first-parent blames merge for branch1' '
|
||||
check_count --first-parent A 2 B 1 "A U Thor" 2 B2 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame ancestor' '
|
||||
check_count -h master A 2 B 2
|
||||
'
|
||||
|
||||
test_expect_success 'blame great-ancestor' '
|
||||
check_count -h master^ A 2
|
||||
'
|
||||
|
||||
test_expect_success 'setup evil merge' '
|
||||
echo "evil merge." >>file &&
|
||||
git commit -a --amend
|
||||
'
|
||||
|
||||
test_expect_success 'blame evil merge' '
|
||||
check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame huge graft' '
|
||||
test_when_finished "git checkout branch2" &&
|
||||
test_when_finished "rm -f .git/info/grafts" &&
|
||||
graft= &&
|
||||
for i in 0 1 2
|
||||
do
|
||||
for j in 0 1 2 3 4 5 6 7 8 9
|
||||
do
|
||||
git checkout --orphan "$i$j" &&
|
||||
printf "%s\n" "$i" "$j" >file &&
|
||||
test_tick &&
|
||||
GIT_AUTHOR_NAME=$i$j GIT_AUTHOR_EMAIL=$i$j@test.git \
|
||||
git commit -a -m "$i$j" &&
|
||||
commit=$(git rev-parse --verify HEAD) &&
|
||||
graft="$graft$commit "
|
||||
done
|
||||
done &&
|
||||
printf "%s " $graft >.git/info/grafts &&
|
||||
check_count -h 00 01 1 10 1
|
||||
'
|
||||
|
||||
test_expect_success 'setup incomplete line' '
|
||||
echo "incomplete" | tr -d "\\012" >>file &&
|
||||
GIT_AUTHOR_NAME="C" GIT_AUTHOR_EMAIL="C@test.git" \
|
||||
git commit -a -m "Incomplete"
|
||||
'
|
||||
|
||||
test_expect_success 'blame incomplete line' '
|
||||
check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1 C 1
|
||||
'
|
||||
|
||||
test_expect_success 'setup edits' '
|
||||
mv file file.orig &&
|
||||
{
|
||||
cat file.orig &&
|
||||
echo
|
||||
} | sed -e "s/^3A/99/" -e "/^1A/d" -e "/^incomplete/d" >file &&
|
||||
echo "incomplete" | tr -d "\\012" >>file &&
|
||||
GIT_AUTHOR_NAME="D" GIT_AUTHOR_EMAIL="D@test.git" \
|
||||
git commit -a -m "edit"
|
||||
'
|
||||
|
||||
test_expect_success 'blame edits' '
|
||||
check_count A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1
|
||||
'
|
||||
|
||||
test_expect_success 'setup obfuscated email' '
|
||||
echo "No robots allowed" >file.new &&
|
||||
cat file >>file.new &&
|
||||
mv file.new file &&
|
||||
GIT_AUTHOR_NAME="E" GIT_AUTHOR_EMAIL="E at test dot git" \
|
||||
git commit -a -m "norobots"
|
||||
'
|
||||
|
||||
test_expect_success 'blame obfuscated email' '
|
||||
check_count A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 1 (all)' '
|
||||
check_count -L1 A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L , (all)' '
|
||||
check_count -L, A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X (X to end)' '
|
||||
check_count -L5 B1 1 C 1 D 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X, (X to end)' '
|
||||
check_count -L5, B1 1 C 1 D 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ,Y (up to Y)' '
|
||||
check_count -L,3 A 1 B2 1 E 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,X' '
|
||||
check_count -L3,3 B2 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,Y' '
|
||||
check_count -L3,6 B 1 B1 1 B2 1 D 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L Y,X (undocumented)' '
|
||||
check_count -L6,3 B 1 B1 1 B2 1 D 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L -X' '
|
||||
test_must_fail $PROG -L-1 file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 0' '
|
||||
test_must_fail $PROG -L0 file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ,0' '
|
||||
test_must_fail $PROG -L,0 file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ,+0' '
|
||||
test_must_fail $PROG -L,+0 file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,+0' '
|
||||
test_must_fail $PROG -L1,+0 file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,+1' '
|
||||
check_count -L3,+1 B2 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,+N' '
|
||||
check_count -L3,+4 B 1 B1 1 B2 1 D 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ,-0' '
|
||||
test_must_fail $PROG -L,-0 file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,-0' '
|
||||
test_must_fail $PROG -L1,-0 file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,-1' '
|
||||
check_count -L3,-1 B2 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,-N' '
|
||||
check_count -L6,-4 B 1 B1 1 B2 1 D 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L /RE/ (RE to end)' '
|
||||
check_count -L/evil/ C 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L /RE/,/RE2/' '
|
||||
check_count -L/robot/,/green/ A 1 B 1 B2 1 D 1 E 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,/RE/' '
|
||||
check_count -L5,/evil/ B1 1 D 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L /RE/,Y' '
|
||||
check_count -L/99/,7 B1 1 D 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L /RE/,+N' '
|
||||
check_count -L/99/,+3 B1 1 D 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L /RE/,-N' '
|
||||
check_count -L/99/,-3 B 1 B2 1 D 1
|
||||
'
|
||||
|
||||
# 'file' ends with an incomplete line, so 'wc' reports one fewer lines than
|
||||
# git-blame sees, hence the last line is actually $(wc...)+1.
|
||||
test_expect_success 'blame -L X (X == nlines)' '
|
||||
n=$(expr $(wc -l <file) + 1) &&
|
||||
check_count -L$n C 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X (X == nlines + 1)' '
|
||||
n=$(expr $(wc -l <file) + 2) &&
|
||||
test_must_fail $PROG -L$n file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X (X > nlines)' '
|
||||
test_must_fail $PROG -L12345 file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ,Y (Y == nlines)' '
|
||||
n=$(expr $(wc -l <file) + 1) &&
|
||||
check_count -L,$n A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ,Y (Y == nlines + 1)' '
|
||||
n=$(expr $(wc -l <file) + 2) &&
|
||||
check_count -L,$n A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ,Y (Y > nlines)' '
|
||||
check_count -L,12345 A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L multiple (disjoint)' '
|
||||
check_count -L2,3 -L6,7 A 1 B1 1 B2 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L multiple (disjoint: unordered)' '
|
||||
check_count -L6,7 -L2,3 A 1 B1 1 B2 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L multiple (adjacent)' '
|
||||
check_count -L2,3 -L4,5 A 1 B 1 B2 1 D 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L multiple (adjacent: unordered)' '
|
||||
check_count -L4,5 -L2,3 A 1 B 1 B2 1 D 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L multiple (overlapping)' '
|
||||
check_count -L2,4 -L3,5 A 1 B 1 B2 1 D 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L multiple (overlapping: unordered)' '
|
||||
check_count -L3,5 -L2,4 A 1 B 1 B2 1 D 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L multiple (superset/subset)' '
|
||||
check_count -L2,8 -L3,5 A 1 B 1 B1 1 B2 1 C 1 D 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L multiple (superset/subset: unordered)' '
|
||||
check_count -L3,5 -L2,8 A 1 B 1 B1 1 B2 1 C 1 D 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L /RE/ (relative)' '
|
||||
check_count -L3,3 -L/fox/ B1 1 B2 1 C 1 D 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L /RE/ (relative: no preceding range)' '
|
||||
check_count -L/dog/ A 1 B 1 B1 1 B2 1 C 1 D 1 "A U Thor" 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L /RE/ (relative: adjacent)' '
|
||||
check_count -L1,1 -L/dog/,+1 A 1 E 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L /RE/ (relative: not found)' '
|
||||
test_must_fail $PROG -L4,4 -L/dog/ file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L /RE/ (relative: end-of-file)' '
|
||||
test_must_fail $PROG -L, -L/$/ file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ^/RE/ (absolute)' '
|
||||
check_count -L3,3 -L^/dog/,+2 A 1 B2 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ^/RE/ (absolute: no preceding range)' '
|
||||
check_count -L^/dog/,+2 A 1 B2 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ^/RE/ (absolute: not found)' '
|
||||
test_must_fail $PROG -L4,4 -L^/tambourine/ file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ^/RE/ (absolute: end-of-file)' '
|
||||
n=$(expr $(wc -l <file) + 1) &&
|
||||
check_count -L$n -L^/$/,+2 A 1 C 1 E 1
|
||||
'
|
||||
|
||||
test_expect_success 'setup -L :regex' '
|
||||
tr Q "\\t" >hello.c <<-\EOF &&
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
Qputs("hello");
|
||||
}
|
||||
EOF
|
||||
git add hello.c &&
|
||||
GIT_AUTHOR_NAME="F" GIT_AUTHOR_EMAIL="F@test.git" \
|
||||
git commit -m "hello" &&
|
||||
|
||||
mv hello.c hello.orig &&
|
||||
sed -e "/}/ {x; s/$/Qputs(\"goodbye\");/; G;}" <hello.orig |
|
||||
tr Q "\\t" >hello.c &&
|
||||
GIT_AUTHOR_NAME="G" GIT_AUTHOR_EMAIL="G@test.git" \
|
||||
git commit -a -m "goodbye" &&
|
||||
|
||||
mv hello.c hello.orig &&
|
||||
echo "#include <stdio.h>" >hello.c &&
|
||||
cat hello.orig >>hello.c &&
|
||||
tr Q "\\t" >>hello.c <<-\EOF &&
|
||||
void mail()
|
||||
{
|
||||
Qputs("mail");
|
||||
}
|
||||
EOF
|
||||
GIT_AUTHOR_NAME="H" GIT_AUTHOR_EMAIL="H@test.git" \
|
||||
git commit -a -m "mail"
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L :literal' '
|
||||
check_count -f hello.c -L:main F 4 G 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L :regex' '
|
||||
check_count -f hello.c "-L:m[a-z][a-z]l" H 4
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L :nomatch' '
|
||||
test_must_fail $PROG -L:nomatch hello.c
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L :RE (relative)' '
|
||||
check_count -f hello.c -L3,3 -L:ma.. F 1 H 4
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L :RE (relative: no preceding range)' '
|
||||
check_count -f hello.c -L:ma.. F 4 G 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L :RE (relative: not found)' '
|
||||
test_must_fail $PROG -L3,3 -L:tambourine hello.c
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L :RE (relative: end-of-file)' '
|
||||
test_must_fail $PROG -L, -L:main hello.c
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ^:RE (absolute)' '
|
||||
check_count -f hello.c -L3,3 -L^:ma.. F 4 G 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ^:RE (absolute: no preceding range)' '
|
||||
check_count -f hello.c -L^:ma.. F 4 G 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ^:RE (absolute: not found)' '
|
||||
test_must_fail $PROG -L4,4 -L^:tambourine hello.c
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ^:RE (absolute: end-of-file)' '
|
||||
n=$(printf "%d" $(wc -l <hello.c)) &&
|
||||
check_count -f hello.c -L$n -L^:ma.. F 4 G 1 H 1
|
||||
'
|
||||
|
||||
test_expect_success 'setup incremental' '
|
||||
(
|
||||
GIT_AUTHOR_NAME=I &&
|
||||
export GIT_AUTHOR_NAME &&
|
||||
GIT_AUTHOR_EMAIL=I@test.git &&
|
||||
export GIT_AUTHOR_EMAIL &&
|
||||
>incremental &&
|
||||
git add incremental &&
|
||||
git commit -m "step 0" &&
|
||||
printf "partial" >>incremental &&
|
||||
git commit -a -m "step 0.5" &&
|
||||
echo >>incremental &&
|
||||
git commit -a -m "step 1"
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'blame empty' '
|
||||
check_count -h HEAD^^ -f incremental
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 0 empty' '
|
||||
test_must_fail $PROG -L0 incremental HEAD^^
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 1 empty' '
|
||||
test_must_fail $PROG -L1 incremental HEAD^^
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 2 empty' '
|
||||
test_must_fail $PROG -L2 incremental HEAD^^
|
||||
'
|
||||
|
||||
test_expect_success 'blame half' '
|
||||
check_count -h HEAD^ -f incremental I 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 0 half' '
|
||||
test_must_fail $PROG -L0 incremental HEAD^
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 1 half' '
|
||||
check_count -h HEAD^ -f incremental -L1 I 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 2 half' '
|
||||
test_must_fail $PROG -L2 incremental HEAD^
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 3 half' '
|
||||
test_must_fail $PROG -L3 incremental HEAD^
|
||||
'
|
||||
|
||||
test_expect_success 'blame full' '
|
||||
check_count -f incremental I 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 0 full' '
|
||||
test_must_fail $PROG -L0 incremental
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 1 full' '
|
||||
check_count -f incremental -L1 I 1
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 2 full' '
|
||||
test_must_fail $PROG -L2 incremental
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L 3 full' '
|
||||
test_must_fail $PROG -L3 incremental
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L' '
|
||||
test_must_fail $PROG -L file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,+' '
|
||||
test_must_fail $PROG -L1,+ file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,-' '
|
||||
test_must_fail $PROG -L1,- file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X (non-numeric X)' '
|
||||
test_must_fail $PROG -LX file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,Y (non-numeric Y)' '
|
||||
test_must_fail $PROG -L1,Y file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,+N (non-numeric N)' '
|
||||
test_must_fail $PROG -L1,+N file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L X,-N (non-numeric N)' '
|
||||
test_must_fail $PROG -L1,-N file
|
||||
'
|
||||
|
||||
test_expect_success 'blame -L ,^/RE/' '
|
||||
test_must_fail $PROG -L1,^/99/ file
|
||||
'
|
||||
369
t/chainlint.sed
Normal file
369
t/chainlint.sed
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
#------------------------------------------------------------------------------
|
||||
# Detect broken &&-chains in tests.
|
||||
#
|
||||
# At present, only &&-chains in subshells are examined by this linter;
|
||||
# top-level &&-chains are instead checked directly by the test framework. Like
|
||||
# the top-level &&-chain linter, the subshell linter (intentionally) does not
|
||||
# check &&-chains within {...} blocks.
|
||||
#
|
||||
# Checking for &&-chain breakage is done line-by-line by pure textual
|
||||
# inspection.
|
||||
#
|
||||
# Incomplete lines (those ending with "\") are stitched together with following
|
||||
# lines to simplify processing, particularly of "one-liner" statements.
|
||||
# Top-level here-docs are swallowed to avoid false positives within the
|
||||
# here-doc body, although the statement to which the here-doc is attached is
|
||||
# retained.
|
||||
#
|
||||
# Heuristics are used to detect end-of-subshell when the closing ")" is cuddled
|
||||
# with the final subshell statement on the same line:
|
||||
#
|
||||
# (cd foo &&
|
||||
# bar)
|
||||
#
|
||||
# in order to avoid misinterpreting the ")" in constructs such as "x=$(...)"
|
||||
# and "case $x in *)" as ending the subshell.
|
||||
#
|
||||
# Lines missing a final "&&" are flagged with "?!AMP?!", and lines which chain
|
||||
# commands with ";" internally rather than "&&" are flagged "?!SEMI?!". A line
|
||||
# may be flagged for both violations.
|
||||
#
|
||||
# Detection of a missing &&-link in a multi-line subshell is complicated by the
|
||||
# fact that the last statement before the closing ")" must not end with "&&".
|
||||
# Since processing is line-by-line, it is not known whether a missing "&&" is
|
||||
# legitimate or not until the _next_ line is seen. To accommodate this, within
|
||||
# multi-line subshells, each line is stored in sed's "hold" area until after
|
||||
# the next line is seen and processed. If the next line is a stand-alone ")",
|
||||
# then a missing "&&" on the previous line is legitimate; otherwise a missing
|
||||
# "&&" is a break in the &&-chain.
|
||||
#
|
||||
# (
|
||||
# cd foo &&
|
||||
# bar
|
||||
# )
|
||||
#
|
||||
# In practical terms, when "bar" is encountered, it is flagged with "?!AMP?!",
|
||||
# but when the stand-alone ")" line is seen which closes the subshell, the
|
||||
# "?!AMP?!" violation is removed from the "bar" line (retrieved from the "hold"
|
||||
# area) since the final statement of a subshell must not end with "&&". The
|
||||
# final line of a subshell may still break the &&-chain by using ";" internally
|
||||
# to chain commands together rather than "&&", so "?!SEMI?!" is never removed
|
||||
# from a line (even though "?!AMP?!" might be).
|
||||
#
|
||||
# Care is taken to recognize the last _statement_ of a multi-line subshell, not
|
||||
# necessarily the last textual _line_ within the subshell, since &&-chaining
|
||||
# applies to statements, not to lines. Consequently, blank lines, comment
|
||||
# lines, and here-docs are swallowed (but not the command to which the here-doc
|
||||
# is attached), leaving the last statement in the "hold" area, not the last
|
||||
# line, thus simplifying &&-link checking.
|
||||
#
|
||||
# The final statement before "done" in for- and while-loops, and before "elif",
|
||||
# "else", and "fi" in if-then-else likewise must not end with "&&", thus
|
||||
# receives similar treatment.
|
||||
#
|
||||
# Swallowing here-docs with arbitrary tags requires a bit of finesse. When a
|
||||
# line such as "cat <<EOF >out" is seen, the here-doc tag is moved to the front
|
||||
# of the line enclosed in angle brackets as a sentinel, giving "<EOF>cat >out".
|
||||
# As each subsequent line is read, it is appended to the target line and a
|
||||
# (whitespace-loose) back-reference match /^<(.*)>\n\1$/ is attempted to see if
|
||||
# the content inside "<...>" matches the entirety of the newly-read line. For
|
||||
# instance, if the next line read is "some data", when concatenated with the
|
||||
# target line, it becomes "<EOF>cat >out\nsome data", and a match is attempted
|
||||
# to see if "EOF" matches "some data". Since it doesn't, the next line is
|
||||
# attempted. When a line consisting of only "EOF" (and possible whitespace) is
|
||||
# encountered, it is appended to the target line giving "<EOF>cat >out\nEOF",
|
||||
# in which case the "EOF" inside "<...>" does match the text following the
|
||||
# newline, thus the closing here-doc tag has been found. The closing tag line
|
||||
# and the "<...>" prefix on the target line are then discarded, leaving just
|
||||
# the target line "cat >out".
|
||||
#
|
||||
# To facilitate regression testing (and manual debugging), a ">" annotation is
|
||||
# applied to the line containing ")" which closes a subshell, ">>" to a line
|
||||
# closing a nested subshell, and ">>>" to a line closing both at once. This
|
||||
# makes it easy to detect whether the heuristics correctly identify
|
||||
# end-of-subshell.
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# incomplete line -- slurp up next line
|
||||
:squash
|
||||
/\\$/ {
|
||||
N
|
||||
s/\\\n//
|
||||
bsquash
|
||||
}
|
||||
|
||||
# here-doc -- swallow it to avoid false hits within its body (but keep the
|
||||
# command to which it was attached)
|
||||
/<<[ ]*[-\\'"]*[A-Za-z0-9_]/ {
|
||||
s/^\(.*\)<<[ ]*[-\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\2>\1<</
|
||||
s/[ ]*<<//
|
||||
:hered
|
||||
N
|
||||
/^<\([^>]*\)>.*\n[ ]*\1[ ]*$/!{
|
||||
s/\n.*$//
|
||||
bhered
|
||||
}
|
||||
s/^<[^>]*>//
|
||||
s/\n.*$//
|
||||
}
|
||||
|
||||
# one-liner "(...) &&"
|
||||
/^[ ]*!*[ ]*(..*)[ ]*&&[ ]*$/boneline
|
||||
|
||||
# same as above but without trailing "&&"
|
||||
/^[ ]*!*[ ]*(..*)[ ]*$/boneline
|
||||
|
||||
# one-liner "(...) >x" (or "2>x" or "<x" or "|x" or "&"
|
||||
/^[ ]*!*[ ]*(..*)[ ]*[0-9]*[<>|&]/boneline
|
||||
|
||||
# multi-line "(...\n...)"
|
||||
/^[ ]*(/bsubshell
|
||||
|
||||
# innocuous line -- print it and advance to next line
|
||||
b
|
||||
|
||||
# found one-liner "(...)" -- mark suspect if it uses ";" internally rather than
|
||||
# "&&" (but not ";" in a string)
|
||||
:oneline
|
||||
/;/{
|
||||
/"[^"]*;[^"]*"/!s/^/?!SEMI?!/
|
||||
}
|
||||
b
|
||||
|
||||
:subshell
|
||||
# bare "(" line? -- stash for later printing
|
||||
/^[ ]*([ ]*$/ {
|
||||
h
|
||||
bnextline
|
||||
}
|
||||
# "(..." line -- split off and stash "(", then process "..." as its own line
|
||||
x
|
||||
s/.*/(/
|
||||
x
|
||||
s/(//
|
||||
bslurp
|
||||
|
||||
:nextline
|
||||
N
|
||||
s/.*\n//
|
||||
|
||||
:slurp
|
||||
# incomplete line "...\"
|
||||
/\\$/bicmplte
|
||||
# multi-line quoted string "...\n..."?
|
||||
/"/bdqstring
|
||||
# multi-line quoted string '...\n...'? (but not contraction in string "it's")
|
||||
/'/{
|
||||
/"[^'"]*'[^'"]*"/!bsqstring
|
||||
}
|
||||
:folded
|
||||
# here-doc -- swallow it
|
||||
/<<[ ]*[-\\'"]*[A-Za-z0-9_]/bheredoc
|
||||
# comment or empty line -- discard since final non-comment, non-empty line
|
||||
# before closing ")", "done", "elsif", "else", or "fi" will need to be
|
||||
# re-visited to drop "suspect" marking since final line of those constructs
|
||||
# legitimately lacks "&&", so "suspect" mark must be removed
|
||||
/^[ ]*#/bnextline
|
||||
/^[ ]*$/bnextline
|
||||
# in-line comment -- strip it (but not "#" in a string, Bash ${#...} array
|
||||
# length, or Perforce "//depot/path#42" revision in filespec)
|
||||
/[ ]#/{
|
||||
/"[^"]*#[^"]*"/!s/[ ]#.*$//
|
||||
}
|
||||
# one-liner "case ... esac"
|
||||
/^[ ]*case[ ]*..*esac/bchkchn
|
||||
# multi-line "case ... esac"
|
||||
/^[ ]*case[ ]..*[ ]in/bcase
|
||||
# multi-line "for ... done" or "while ... done"
|
||||
/^[ ]*for[ ]..*[ ]in/bcontinue
|
||||
/^[ ]*while[ ]/bcontinue
|
||||
/^[ ]*do[ ]/bcontinue
|
||||
/^[ ]*do[ ]*$/bcontinue
|
||||
/;[ ]*do/bcontinue
|
||||
/^[ ]*done[ ]*&&[ ]*$/bdone
|
||||
/^[ ]*done[ ]*$/bdone
|
||||
/^[ ]*done[ ]*[<>|]/bdone
|
||||
/^[ ]*done[ ]*)/bdone
|
||||
/||[ ]*exit[ ]/bcontinue
|
||||
/||[ ]*exit[ ]*$/bcontinue
|
||||
# multi-line "if...elsif...else...fi"
|
||||
/^[ ]*if[ ]/bcontinue
|
||||
/^[ ]*then[ ]/bcontinue
|
||||
/^[ ]*then[ ]*$/bcontinue
|
||||
/;[ ]*then/bcontinue
|
||||
/^[ ]*elif[ ]/belse
|
||||
/^[ ]*elif[ ]*$/belse
|
||||
/^[ ]*else[ ]/belse
|
||||
/^[ ]*else[ ]*$/belse
|
||||
/^[ ]*fi[ ]*&&[ ]*$/bdone
|
||||
/^[ ]*fi[ ]*$/bdone
|
||||
/^[ ]*fi[ ]*[<>|]/bdone
|
||||
/^[ ]*fi[ ]*)/bdone
|
||||
# nested one-liner "(...) &&"
|
||||
/^[ ]*(.*)[ ]*&&[ ]*$/bchkchn
|
||||
# nested one-liner "(...)"
|
||||
/^[ ]*(.*)[ ]*$/bchkchn
|
||||
# nested one-liner "(...) >x" (or "2>x" or "<x" or "|x")
|
||||
/^[ ]*(.*)[ ]*[0-9]*[<>|]/bchkchn
|
||||
# nested multi-line "(...\n...)"
|
||||
/^[ ]*(/bnest
|
||||
# multi-line "{...\n...}"
|
||||
/^[ ]*{/bblock
|
||||
# closing ")" on own line -- exit subshell
|
||||
/^[ ]*)/bclssolo
|
||||
# "$((...))" -- arithmetic expansion; not closing ")"
|
||||
/\$(([^)][^)]*))[^)]*$/bchkchn
|
||||
# "$(...)" -- command substitution; not closing ")"
|
||||
/\$([^)][^)]*)[^)]*$/bchkchn
|
||||
# multi-line "$(...\n...)" -- command substitution; treat as nested subshell
|
||||
/\$([^)]*$/bnest
|
||||
# "=(...)" -- Bash array assignment; not closing ")"
|
||||
/=(/bchkchn
|
||||
# closing "...) &&"
|
||||
/)[ ]*&&[ ]*$/bclose
|
||||
# closing "...)"
|
||||
/)[ ]*$/bclose
|
||||
# closing "...) >x" (or "2>x" or "<x" or "|x")
|
||||
/)[ ]*[<>|]/bclose
|
||||
:chkchn
|
||||
# mark suspect if line uses ";" internally rather than "&&" (but not ";" in a
|
||||
# string and not ";;" in one-liner "case...esac")
|
||||
/;/{
|
||||
/;;/!{
|
||||
/"[^"]*;[^"]*"/!s/^/?!SEMI?!/
|
||||
}
|
||||
}
|
||||
# line ends with pipe "...|" -- valid; not missing "&&"
|
||||
/|[ ]*$/bcontinue
|
||||
# missing end-of-line "&&" -- mark suspect
|
||||
/&&[ ]*$/!s/^/?!AMP?!/
|
||||
:continue
|
||||
# retrieve and print previous line
|
||||
x
|
||||
n
|
||||
bslurp
|
||||
|
||||
# found incomplete line "...\" -- slurp up next line
|
||||
:icmplte
|
||||
N
|
||||
s/\\\n//
|
||||
bslurp
|
||||
|
||||
# check for multi-line double-quoted string "...\n..." -- fold to one line
|
||||
:dqstring
|
||||
# remove all quote pairs
|
||||
s/"\([^"]*\)"/@!\1@!/g
|
||||
# done if no dangling quote
|
||||
/"/!bdqdone
|
||||
# otherwise, slurp next line and try again
|
||||
N
|
||||
s/\n//
|
||||
bdqstring
|
||||
:dqdone
|
||||
s/@!/"/g
|
||||
bfolded
|
||||
|
||||
# check for multi-line single-quoted string '...\n...' -- fold to one line
|
||||
:sqstring
|
||||
# remove all quote pairs
|
||||
s/'\([^']*\)'/@!\1@!/g
|
||||
# done if no dangling quote
|
||||
/'/!bsqdone
|
||||
# otherwise, slurp next line and try again
|
||||
N
|
||||
s/\n//
|
||||
bsqstring
|
||||
:sqdone
|
||||
s/@!/'/g
|
||||
bfolded
|
||||
|
||||
# found here-doc -- swallow it to avoid false hits within its body (but keep
|
||||
# the command to which it was attached)
|
||||
:heredoc
|
||||
s/^\(.*\)<<[ ]*[-\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\2>\1<</
|
||||
s/[ ]*<<//
|
||||
:heredsub
|
||||
N
|
||||
/^<\([^>]*\)>.*\n[ ]*\1[ ]*$/!{
|
||||
s/\n.*$//
|
||||
bheredsub
|
||||
}
|
||||
s/^<[^>]*>//
|
||||
s/\n.*$//
|
||||
bfolded
|
||||
|
||||
# found "case ... in" -- pass through untouched
|
||||
:case
|
||||
x
|
||||
n
|
||||
/^[ ]*esac/bslurp
|
||||
bcase
|
||||
|
||||
# found "else" or "elif" -- drop "suspect" from final line before "else" since
|
||||
# that line legitimately lacks "&&"
|
||||
:else
|
||||
x
|
||||
s/?!AMP?!//
|
||||
x
|
||||
bcontinue
|
||||
|
||||
# found "done" closing for-loop or while-loop, or "fi" closing if-then -- drop
|
||||
# "suspect" from final contained line since that line legitimately lacks "&&"
|
||||
:done
|
||||
x
|
||||
s/?!AMP?!//
|
||||
x
|
||||
# is 'done' or 'fi' cuddled with ")" to close subshell?
|
||||
/done.*)/bclose
|
||||
/fi.*)/bclose
|
||||
bchkchn
|
||||
|
||||
# found nested multi-line "(...\n...)" -- pass through untouched
|
||||
:nest
|
||||
x
|
||||
:nstslurp
|
||||
n
|
||||
# closing ")" on own line -- stop nested slurp
|
||||
/^[ ]*)/bnstclose
|
||||
# comment -- not closing ")" if in comment
|
||||
/^[ ]*#/bnstcnt
|
||||
# "$((...))" -- arithmetic expansion; not closing ")"
|
||||
/\$(([^)][^)]*))[^)]*$/bnstcnt
|
||||
# "$(...)" -- command substitution; not closing ")"
|
||||
/\$([^)][^)]*)[^)]*$/bnstcnt
|
||||
# closing "...)" -- stop nested slurp
|
||||
/)/bnstclose
|
||||
:nstcnt
|
||||
x
|
||||
bnstslurp
|
||||
:nstclose
|
||||
s/^/>>/
|
||||
# is it "))" which closes nested and parent subshells?
|
||||
/)[ ]*)/bslurp
|
||||
bchkchn
|
||||
|
||||
# found multi-line "{...\n...}" block -- pass through untouched
|
||||
:block
|
||||
x
|
||||
n
|
||||
# closing "}" -- stop block slurp
|
||||
/}/bchkchn
|
||||
bblock
|
||||
|
||||
# found closing ")" on own line -- drop "suspect" from final line of subshell
|
||||
# since that line legitimately lacks "&&" and exit subshell loop
|
||||
:clssolo
|
||||
x
|
||||
s/?!AMP?!//
|
||||
p
|
||||
x
|
||||
s/^/>/
|
||||
b
|
||||
|
||||
# found closing "...)" -- exit subshell loop
|
||||
:close
|
||||
x
|
||||
p
|
||||
x
|
||||
s/^/>/
|
||||
b
|
||||
9
t/chainlint/arithmetic-expansion.expect
Normal file
9
t/chainlint/arithmetic-expansion.expect
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(
|
||||
foo &&
|
||||
bar=$((42 + 1)) &&
|
||||
baz
|
||||
>) &&
|
||||
(
|
||||
?!AMP?! bar=$((42 + 1))
|
||||
baz
|
||||
>)
|
||||
11
t/chainlint/arithmetic-expansion.test
Normal file
11
t/chainlint/arithmetic-expansion.test
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
(
|
||||
foo &&
|
||||
# LINT: closing ")" of $((...)) not misinterpreted as subshell-closing ")"
|
||||
bar=$((42 + 1)) &&
|
||||
baz
|
||||
) &&
|
||||
(
|
||||
# LINT: missing "&&" on $((...))
|
||||
bar=$((42 + 1))
|
||||
baz
|
||||
)
|
||||
10
t/chainlint/bash-array.expect
Normal file
10
t/chainlint/bash-array.expect
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
(
|
||||
foo &&
|
||||
bar=(gumbo stumbo wumbo) &&
|
||||
baz
|
||||
>) &&
|
||||
(
|
||||
foo &&
|
||||
bar=${#bar[@]} &&
|
||||
baz
|
||||
>)
|
||||
12
t/chainlint/bash-array.test
Normal file
12
t/chainlint/bash-array.test
Normal file
|
|
@ -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
|
||||
)
|
||||
4
t/chainlint/blank-line.expect
Normal file
4
t/chainlint/blank-line.expect
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(
|
||||
nothing &&
|
||||
something
|
||||
>)
|
||||
10
t/chainlint/blank-line.test
Normal file
10
t/chainlint/blank-line.test
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
(
|
||||
|
||||
nothing &&
|
||||
|
||||
something
|
||||
# LINT: swallow blank lines since final _statement_ before subshell end is
|
||||
# LINT: significant to "&&"-check, not final _line_ (which might be blank)
|
||||
|
||||
|
||||
)
|
||||
12
t/chainlint/block.expect
Normal file
12
t/chainlint/block.expect
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
(
|
||||
foo &&
|
||||
{
|
||||
echo a
|
||||
echo b
|
||||
} &&
|
||||
bar &&
|
||||
{
|
||||
echo c
|
||||
?!AMP?! }
|
||||
baz
|
||||
>)
|
||||
15
t/chainlint/block.test
Normal file
15
t/chainlint/block.test
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
(
|
||||
# LINT: missing "&&" in block not currently detected (for consistency with
|
||||
# LINT: --chain-lint at top level and to provide escape hatch if needed)
|
||||
foo &&
|
||||
{
|
||||
echo a
|
||||
echo b
|
||||
} &&
|
||||
bar &&
|
||||
# LINT: missing "&&" at closing "}"
|
||||
{
|
||||
echo c
|
||||
}
|
||||
baz
|
||||
)
|
||||
6
t/chainlint/broken-chain.expect
Normal file
6
t/chainlint/broken-chain.expect
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
(
|
||||
foo &&
|
||||
?!AMP?! bar
|
||||
baz &&
|
||||
wop
|
||||
>)
|
||||
8
t/chainlint/broken-chain.test
Normal file
8
t/chainlint/broken-chain.test
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
(
|
||||
foo &&
|
||||
# LINT: missing "&&" from 'bar'
|
||||
bar
|
||||
baz &&
|
||||
# LINT: final statement before closing ")" legitimately lacks "&&"
|
||||
wop
|
||||
)
|
||||
19
t/chainlint/case.expect
Normal file
19
t/chainlint/case.expect
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
(
|
||||
case "$x" in
|
||||
x) foo ;;
|
||||
*) bar ;;
|
||||
esac &&
|
||||
foobar
|
||||
>) &&
|
||||
(
|
||||
case "$x" in
|
||||
x) foo ;;
|
||||
*) bar ;;
|
||||
?!AMP?! esac
|
||||
foobar
|
||||
>) &&
|
||||
(
|
||||
case "$x" in 1) true;; esac &&
|
||||
?!AMP?! case "$y" in 2) false;; esac
|
||||
foobar
|
||||
>)
|
||||
23
t/chainlint/case.test
Normal file
23
t/chainlint/case.test
Normal file
|
|
@ -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
|
||||
)
|
||||
4
t/chainlint/close-nested-and-parent-together.expect
Normal file
4
t/chainlint/close-nested-and-parent-together.expect
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(
|
||||
cd foo &&
|
||||
(bar &&
|
||||
>>> baz))
|
||||
3
t/chainlint/close-nested-and-parent-together.test
Normal file
3
t/chainlint/close-nested-and-parent-together.test
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
(cd foo &&
|
||||
(bar &&
|
||||
baz))
|
||||
25
t/chainlint/close-subshell.expect
Normal file
25
t/chainlint/close-subshell.expect
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
(
|
||||
foo
|
||||
>) &&
|
||||
(
|
||||
bar
|
||||
>) >out &&
|
||||
(
|
||||
baz
|
||||
>) 2>err &&
|
||||
(
|
||||
boo
|
||||
>) <input &&
|
||||
(
|
||||
bip
|
||||
>) | wuzzle &&
|
||||
(
|
||||
bop
|
||||
>) | fazz fozz &&
|
||||
(
|
||||
bup
|
||||
>) |
|
||||
fuzzle &&
|
||||
(
|
||||
yop
|
||||
>)
|
||||
27
t/chainlint/close-subshell.test
Normal file
27
t/chainlint/close-subshell.test
Normal file
|
|
@ -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
|
||||
)
|
||||
9
t/chainlint/command-substitution.expect
Normal file
9
t/chainlint/command-substitution.expect
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(
|
||||
foo &&
|
||||
bar=$(gobble) &&
|
||||
baz
|
||||
>) &&
|
||||
(
|
||||
?!AMP?! bar=$(gobble blocks)
|
||||
baz
|
||||
>)
|
||||
11
t/chainlint/command-substitution.test
Normal file
11
t/chainlint/command-substitution.test
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
(
|
||||
foo &&
|
||||
# LINT: closing ")" of $(...) not misinterpreted as subshell-closing ")"
|
||||
bar=$(gobble) &&
|
||||
baz
|
||||
) &&
|
||||
(
|
||||
# LINT: missing "&&" on $(...)
|
||||
bar=$(gobble blocks)
|
||||
baz
|
||||
)
|
||||
4
t/chainlint/comment.expect
Normal file
4
t/chainlint/comment.expect
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(
|
||||
nothing &&
|
||||
something
|
||||
>)
|
||||
11
t/chainlint/comment.test
Normal file
11
t/chainlint/comment.test
Normal file
|
|
@ -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
|
||||
)
|
||||
10
t/chainlint/complex-if-in-cuddled-loop.expect
Normal file
10
t/chainlint/complex-if-in-cuddled-loop.expect
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
(
|
||||
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
|
||||
11
t/chainlint/complex-if-in-cuddled-loop.test
Normal file
11
t/chainlint/complex-if-in-cuddled-loop.test
Normal file
|
|
@ -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
|
||||
7
t/chainlint/cuddled-if-then-else.expect
Normal file
7
t/chainlint/cuddled-if-then-else.expect
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
(
|
||||
if test -z ""; then
|
||||
echo empty
|
||||
else
|
||||
echo bizzy
|
||||
> fi) &&
|
||||
echo foobar
|
||||
7
t/chainlint/cuddled-if-then-else.test
Normal file
7
t/chainlint/cuddled-if-then-else.test
Normal file
|
|
@ -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
|
||||
5
t/chainlint/cuddled-loop.expect
Normal file
5
t/chainlint/cuddled-loop.expect
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
(
|
||||
while read x
|
||||
do foobar bop || exit 1
|
||||
> done <file ) &&
|
||||
outside subshell
|
||||
7
t/chainlint/cuddled-loop.test
Normal file
7
t/chainlint/cuddled-loop.test
Normal file
|
|
@ -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
|
||||
21
t/chainlint/cuddled.expect
Normal file
21
t/chainlint/cuddled.expect
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
(
|
||||
cd foo &&
|
||||
bar
|
||||
>) &&
|
||||
|
||||
(
|
||||
?!AMP?!cd foo
|
||||
bar
|
||||
>) &&
|
||||
|
||||
(
|
||||
cd foo &&
|
||||
> bar) &&
|
||||
|
||||
(
|
||||
cd foo &&
|
||||
> bar) &&
|
||||
|
||||
(
|
||||
?!AMP?!cd foo
|
||||
> bar)
|
||||
23
t/chainlint/cuddled.test
Normal file
23
t/chainlint/cuddled.test
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# LINT: first subshell statement cuddled with opening "("; for implementation
|
||||
# LINT: simplicity, "(..." is split into two lines, "(" and "..."
|
||||
(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)
|
||||
24
t/chainlint/exit-loop.expect
Normal file
24
t/chainlint/exit-loop.expect
Normal file
|
|
@ -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
|
||||
>)
|
||||
27
t/chainlint/exit-loop.test
Normal file
27
t/chainlint/exit-loop.test
Normal file
|
|
@ -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
|
||||
)
|
||||
5
t/chainlint/exit-subshell.expect
Normal file
5
t/chainlint/exit-subshell.expect
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
(
|
||||
foo || exit 1
|
||||
bar &&
|
||||
baz
|
||||
>)
|
||||
6
t/chainlint/exit-subshell.test
Normal file
6
t/chainlint/exit-subshell.test
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
(
|
||||
# LINT: "|| exit {n}" valid subshell escape without hurting &&-chain
|
||||
foo || exit 1
|
||||
bar &&
|
||||
baz
|
||||
)
|
||||
11
t/chainlint/for-loop.expect
Normal file
11
t/chainlint/for-loop.expect
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
(
|
||||
for i in a b c
|
||||
do
|
||||
?!AMP?! echo $i
|
||||
cat
|
||||
?!AMP?! done
|
||||
for i in a b c; do
|
||||
echo $i &&
|
||||
cat $i
|
||||
done
|
||||
>)
|
||||
19
t/chainlint/for-loop.test
Normal file
19
t/chainlint/for-loop.test
Normal file
|
|
@ -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
|
||||
)
|
||||
2
t/chainlint/here-doc-close-subshell.expect
Normal file
2
t/chainlint/here-doc-close-subshell.expect
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(
|
||||
> cat)
|
||||
5
t/chainlint/here-doc-close-subshell.test
Normal file
5
t/chainlint/here-doc-close-subshell.test
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
(
|
||||
# LINT: line contains here-doc and closes nested subshell
|
||||
cat <<-\INPUT)
|
||||
fizz
|
||||
INPUT
|
||||
5
t/chainlint/here-doc-multi-line-command-subst.expect
Normal file
5
t/chainlint/here-doc-multi-line-command-subst.expect
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
(
|
||||
x=$(bobble &&
|
||||
?!AMP?!>> wiffle)
|
||||
echo $x
|
||||
>)
|
||||
9
t/chainlint/here-doc-multi-line-command-subst.test
Normal file
9
t/chainlint/here-doc-multi-line-command-subst.test
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(
|
||||
# LINT: line contains here-doc and opens multi-line $(...)
|
||||
x=$(bobble <<-\END &&
|
||||
fossil
|
||||
vegetable
|
||||
END
|
||||
wiffle)
|
||||
echo $x
|
||||
)
|
||||
4
t/chainlint/here-doc-multi-line-string.expect
Normal file
4
t/chainlint/here-doc-multi-line-string.expect
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(
|
||||
?!AMP?! cat && echo "multi-line string"
|
||||
bap
|
||||
>)
|
||||
8
t/chainlint/here-doc-multi-line-string.test
Normal file
8
t/chainlint/here-doc-multi-line-string.test
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
(
|
||||
# LINT: line contains here-doc and opens multi-line string
|
||||
cat <<-\TXT && echo "multi-line
|
||||
string"
|
||||
fizzle
|
||||
TXT
|
||||
bap
|
||||
)
|
||||
9
t/chainlint/here-doc.expect
Normal file
9
t/chainlint/here-doc.expect
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
boodle wobba gorgo snoot wafta snurb &&
|
||||
|
||||
cat >foo &&
|
||||
|
||||
cat >bar &&
|
||||
|
||||
cat >boo &&
|
||||
|
||||
horticulture
|
||||
37
t/chainlint/here-doc.test
Normal file
37
t/chainlint/here-doc.test
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# 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 <<'FUMP' >bar &&
|
||||
snoz
|
||||
boz
|
||||
woz
|
||||
FUMP
|
||||
|
||||
# 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
|
||||
12
t/chainlint/if-in-loop.expect
Normal file
12
t/chainlint/if-in-loop.expect
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
(
|
||||
for i in a b c
|
||||
do
|
||||
if false
|
||||
then
|
||||
?!AMP?! echo "err"
|
||||
exit 1
|
||||
?!AMP?! fi
|
||||
foo
|
||||
?!AMP?! done
|
||||
bar
|
||||
>)
|
||||
15
t/chainlint/if-in-loop.test
Normal file
15
t/chainlint/if-in-loop.test
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
(
|
||||
for i in a b c
|
||||
do
|
||||
if false
|
||||
then
|
||||
# LINT: missing "&&" on 'echo'
|
||||
echo "err"
|
||||
exit 1
|
||||
# LINT: missing "&&" on 'fi'
|
||||
fi
|
||||
foo
|
||||
# LINT: missing "&&" on 'done'
|
||||
done
|
||||
bar
|
||||
)
|
||||
19
t/chainlint/if-then-else.expect
Normal file
19
t/chainlint/if-then-else.expect
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
(
|
||||
if test -n ""
|
||||
then
|
||||
?!AMP?! echo very
|
||||
echo empty
|
||||
elif test -z ""
|
||||
echo foo
|
||||
else
|
||||
echo foo &&
|
||||
cat
|
||||
?!AMP?! fi
|
||||
echo poodle
|
||||
>) &&
|
||||
(
|
||||
if test -n ""; then
|
||||
echo very &&
|
||||
?!AMP?! echo empty
|
||||
if
|
||||
>)
|
||||
28
t/chainlint/if-then-else.test
Normal file
28
t/chainlint/if-then-else.test
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
(
|
||||
# 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 ""
|
||||
# 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
|
||||
if
|
||||
)
|
||||
4
t/chainlint/incomplete-line.expect
Normal file
4
t/chainlint/incomplete-line.expect
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
line 1 line 2 line 3 line 4 &&
|
||||
(
|
||||
line 5 line 6 line 7 line 8
|
||||
>)
|
||||
12
t/chainlint/incomplete-line.test
Normal file
12
t/chainlint/incomplete-line.test
Normal file
|
|
@ -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
|
||||
)
|
||||
9
t/chainlint/inline-comment.expect
Normal file
9
t/chainlint/inline-comment.expect
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(
|
||||
foobar &&
|
||||
?!AMP?! barfoo
|
||||
flibble "not a # comment"
|
||||
>) &&
|
||||
|
||||
(
|
||||
cd foo &&
|
||||
> flibble "not a # comment")
|
||||
12
t/chainlint/inline-comment.test
Normal file
12
t/chainlint/inline-comment.test
Normal file
|
|
@ -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")
|
||||
12
t/chainlint/loop-in-if.expect
Normal file
12
t/chainlint/loop-in-if.expect
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
(
|
||||
if true
|
||||
then
|
||||
while true
|
||||
do
|
||||
?!AMP?! echo "pop"
|
||||
echo "glup"
|
||||
?!AMP?! done
|
||||
foo
|
||||
?!AMP?! fi
|
||||
bar
|
||||
>)
|
||||
15
t/chainlint/loop-in-if.test
Normal file
15
t/chainlint/loop-in-if.test
Normal file
|
|
@ -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
|
||||
)
|
||||
18
t/chainlint/multi-line-nested-command-substitution.expect
Normal file
18
t/chainlint/multi-line-nested-command-substitution.expect
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
(
|
||||
foo &&
|
||||
x=$(
|
||||
echo bar |
|
||||
cat
|
||||
>> ) &&
|
||||
echo ok
|
||||
>) |
|
||||
sort &&
|
||||
(
|
||||
bar &&
|
||||
x=$(echo bar |
|
||||
cat
|
||||
>> ) &&
|
||||
y=$(echo baz |
|
||||
>> fip) &&
|
||||
echo fail
|
||||
>)
|
||||
18
t/chainlint/multi-line-nested-command-substitution.test
Normal file
18
t/chainlint/multi-line-nested-command-substitution.test
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
(
|
||||
foo &&
|
||||
x=$(
|
||||
echo bar |
|
||||
cat
|
||||
) &&
|
||||
echo ok
|
||||
) |
|
||||
sort &&
|
||||
(
|
||||
bar &&
|
||||
x=$(echo bar |
|
||||
cat
|
||||
) &&
|
||||
y=$(echo baz |
|
||||
fip) &&
|
||||
echo fail
|
||||
)
|
||||
15
t/chainlint/multi-line-string.expect
Normal file
15
t/chainlint/multi-line-string.expect
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
(
|
||||
x="line 1 line 2 line 3" &&
|
||||
?!AMP?! y='line 1 line2'
|
||||
foobar
|
||||
>) &&
|
||||
(
|
||||
echo "there's nothing to see here" &&
|
||||
exit
|
||||
>) &&
|
||||
(
|
||||
echo "xyz" "abc def ghi" &&
|
||||
echo 'xyz' 'abc def ghi' &&
|
||||
echo 'xyz' "abc def ghi" &&
|
||||
barfoo
|
||||
>)
|
||||
27
t/chainlint/multi-line-string.test
Normal file
27
t/chainlint/multi-line-string.test
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
(
|
||||
x="line 1
|
||||
line 2
|
||||
line 3" &&
|
||||
# LINT: missing "&&" on assignment
|
||||
y='line 1
|
||||
line2'
|
||||
foobar
|
||||
) &&
|
||||
(
|
||||
# LINT: apostrophe (in a contraction) within string not misinterpreted as
|
||||
# LINT: starting multi-line single-quoted string
|
||||
echo "there's nothing to see here" &&
|
||||
exit
|
||||
) &&
|
||||
(
|
||||
echo "xyz" "abc
|
||||
def
|
||||
ghi" &&
|
||||
echo 'xyz' 'abc
|
||||
def
|
||||
ghi' &&
|
||||
echo 'xyz' "abc
|
||||
def
|
||||
ghi" &&
|
||||
barfoo
|
||||
)
|
||||
5
t/chainlint/negated-one-liner.expect
Normal file
5
t/chainlint/negated-one-liner.expect
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
! (foo && bar) &&
|
||||
! (foo && bar) >baz &&
|
||||
|
||||
?!SEMI?!! (foo; bar) &&
|
||||
?!SEMI?!! (foo; bar) >baz
|
||||
7
t/chainlint/negated-one-liner.test
Normal file
7
t/chainlint/negated-one-liner.test
Normal file
|
|
@ -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
|
||||
19
t/chainlint/nested-cuddled-subshell.expect
Normal file
19
t/chainlint/nested-cuddled-subshell.expect
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
(
|
||||
(cd foo &&
|
||||
bar
|
||||
>> ) &&
|
||||
(cd foo &&
|
||||
bar
|
||||
?!AMP?!>> )
|
||||
(
|
||||
cd foo &&
|
||||
>> bar) &&
|
||||
(
|
||||
cd foo &&
|
||||
?!AMP?!>> bar)
|
||||
(cd foo &&
|
||||
>> bar) &&
|
||||
(cd foo &&
|
||||
?!AMP?!>> bar)
|
||||
foobar
|
||||
>)
|
||||
31
t/chainlint/nested-cuddled-subshell.test
Normal file
31
t/chainlint/nested-cuddled-subshell.test
Normal file
|
|
@ -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
|
||||
)
|
||||
7
t/chainlint/nested-here-doc.expect
Normal file
7
t/chainlint/nested-here-doc.expect
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
cat >foop &&
|
||||
|
||||
(
|
||||
cat &&
|
||||
?!AMP?! cat
|
||||
foobar
|
||||
>)
|
||||
33
t/chainlint/nested-here-doc.test
Normal file
33
t/chainlint/nested-here-doc.test
Normal file
|
|
@ -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
|
||||
)
|
||||
11
t/chainlint/nested-subshell-comment.expect
Normal file
11
t/chainlint/nested-subshell-comment.expect
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
(
|
||||
foo &&
|
||||
(
|
||||
bar &&
|
||||
# bottles wobble while fiddles gobble
|
||||
# minor numbers of cows (or do they?)
|
||||
baz &&
|
||||
snaff
|
||||
?!AMP?!>> )
|
||||
fuzzy
|
||||
>)
|
||||
13
t/chainlint/nested-subshell-comment.test
Normal file
13
t/chainlint/nested-subshell-comment.test
Normal file
|
|
@ -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
|
||||
)
|
||||
12
t/chainlint/nested-subshell.expect
Normal file
12
t/chainlint/nested-subshell.expect
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
(
|
||||
cd foo &&
|
||||
(
|
||||
echo a &&
|
||||
echo b
|
||||
>> ) >file &&
|
||||
cd foo &&
|
||||
(
|
||||
echo a
|
||||
echo b
|
||||
>> ) >file
|
||||
>)
|
||||
14
t/chainlint/nested-subshell.test
Normal file
14
t/chainlint/nested-subshell.test
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
(
|
||||
cd foo &&
|
||||
(
|
||||
echo a &&
|
||||
echo b
|
||||
) >file &&
|
||||
|
||||
cd foo &&
|
||||
(
|
||||
# LINT: nested multi-line subshell not presently checked for missing "&&"
|
||||
echo a
|
||||
echo b
|
||||
) >file
|
||||
)
|
||||
9
t/chainlint/one-liner.expect
Normal file
9
t/chainlint/one-liner.expect
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(foo && bar) &&
|
||||
(foo && bar) |
|
||||
(foo && bar) >baz &&
|
||||
|
||||
?!SEMI?!(foo; bar) &&
|
||||
?!SEMI?!(foo; bar) |
|
||||
?!SEMI?!(foo; bar) >baz
|
||||
|
||||
(foo "bar; baz")
|
||||
12
t/chainlint/one-liner.test
Normal file
12
t/chainlint/one-liner.test
Normal file
|
|
@ -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 "&&"
|
||||
(foo; bar) &&
|
||||
(foo; bar) |
|
||||
(foo; bar) >baz
|
||||
|
||||
# LINT: ";" in string not misinterpreted as broken &&-chain
|
||||
(foo "bar; baz")
|
||||
4
t/chainlint/p4-filespec.expect
Normal file
4
t/chainlint/p4-filespec.expect
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(
|
||||
p4 print -1 //depot/fiddle#42 >file &&
|
||||
foobar
|
||||
>)
|
||||
5
t/chainlint/p4-filespec.test
Normal file
5
t/chainlint/p4-filespec.test
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
(
|
||||
# LINT: Perforce revspec in filespec not misinterpreted as in-line comment
|
||||
p4 print -1 //depot/fiddle#42 >file &&
|
||||
foobar
|
||||
)
|
||||
8
t/chainlint/pipe.expect
Normal file
8
t/chainlint/pipe.expect
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
(
|
||||
foo |
|
||||
bar |
|
||||
baz &&
|
||||
fish |
|
||||
?!AMP?! cow
|
||||
sunder
|
||||
>)
|
||||
12
t/chainlint/pipe.test
Normal file
12
t/chainlint/pipe.test
Normal file
|
|
@ -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
|
||||
)
|
||||
20
t/chainlint/semicolon.expect
Normal file
20
t/chainlint/semicolon.expect
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
(
|
||||
?!AMP?!?!SEMI?! cat foo ; echo bar
|
||||
?!SEMI?! cat foo ; echo bar
|
||||
>) &&
|
||||
(
|
||||
?!SEMI?! cat foo ; echo bar &&
|
||||
?!SEMI?! cat foo ; echo bar
|
||||
>) &&
|
||||
(
|
||||
echo "foo; bar" &&
|
||||
?!SEMI?! cat foo; echo bar
|
||||
>) &&
|
||||
(
|
||||
?!SEMI?! foo;
|
||||
>) &&
|
||||
(
|
||||
cd foo &&
|
||||
for i in a b c; do
|
||||
?!SEMI?! echo;
|
||||
> done)
|
||||
25
t/chainlint/semicolon.test
Normal file
25
t/chainlint/semicolon.test
Normal file
|
|
@ -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: unnecessary terminating semicolon
|
||||
foo;
|
||||
) &&
|
||||
(cd foo &&
|
||||
for i in a b c; do
|
||||
# LINT: unnecessary terminating semicolon
|
||||
echo;
|
||||
done)
|
||||
11
t/chainlint/subshell-here-doc.expect
Normal file
11
t/chainlint/subshell-here-doc.expect
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
(
|
||||
echo wobba gorgo snoot wafta snurb &&
|
||||
?!AMP?! cat >bip
|
||||
echo >bop
|
||||
>) &&
|
||||
(
|
||||
cat >bup &&
|
||||
cat >bup2 &&
|
||||
cat >bup3 &&
|
||||
meep
|
||||
>)
|
||||
39
t/chainlint/subshell-here-doc.test
Normal file
39
t/chainlint/subshell-here-doc.test
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
(
|
||||
# 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 <<-'ARBITRARY2' >bup2 &&
|
||||
glink
|
||||
FIZZ
|
||||
ARBITRARY2
|
||||
cat <<-"ARBITRARY3" >bup3 &&
|
||||
glink
|
||||
FIZZ
|
||||
ARBITRARY3
|
||||
meep
|
||||
)
|
||||
14
t/chainlint/subshell-one-liner.expect
Normal file
14
t/chainlint/subshell-one-liner.expect
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
(
|
||||
(foo && bar) &&
|
||||
(foo && bar) |
|
||||
(foo && bar) >baz &&
|
||||
?!SEMI?! (foo; bar) &&
|
||||
?!SEMI?! (foo; bar) |
|
||||
?!SEMI?! (foo; bar) >baz &&
|
||||
(foo || exit 1) &&
|
||||
(foo || exit 1) |
|
||||
(foo || exit 1) >baz &&
|
||||
?!AMP?! (foo && bar)
|
||||
?!AMP?!?!SEMI?! (foo && bar; baz)
|
||||
foobar
|
||||
>)
|
||||
24
t/chainlint/subshell-one-liner.test
Normal file
24
t/chainlint/subshell-one-liner.test
Normal file
|
|
@ -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
|
||||
)
|
||||
10
t/chainlint/t7900-subtree.expect
Normal file
10
t/chainlint/t7900-subtree.expect
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
(
|
||||
chks="sub1sub2sub3sub4" &&
|
||||
chks_sub=$(cat | sed 's,^,sub dir/,'
|
||||
>>) &&
|
||||
chkms="main-sub1main-sub2main-sub3main-sub4" &&
|
||||
chkms_sub=$(cat | sed 's,^,sub dir/,'
|
||||
>>) &&
|
||||
subfiles=$(git ls-files) &&
|
||||
check_equal "$subfiles" "$chkms$chks"
|
||||
>)
|
||||
22
t/chainlint/t7900-subtree.test
Normal file
22
t/chainlint/t7900-subtree.test
Normal file
|
|
@ -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"
|
||||
)
|
||||
11
t/chainlint/while-loop.expect
Normal file
11
t/chainlint/while-loop.expect
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
(
|
||||
while true
|
||||
do
|
||||
?!AMP?! echo foo
|
||||
cat
|
||||
?!AMP?! done
|
||||
while true; do
|
||||
echo foo &&
|
||||
cat bar
|
||||
done
|
||||
>)
|
||||
19
t/chainlint/while-loop.test
Normal file
19
t/chainlint/while-loop.test
Normal file
|
|
@ -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
|
||||
)
|
||||
55
t/check-non-portable-shell.pl
Executable file
55
t/check-non-portable-shell.pl
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# Test t0000..t9999.sh for non portable shell scripts
|
||||
# This script can be called with one or more filenames as parameters
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $exit_code=0;
|
||||
my %func;
|
||||
|
||||
sub err {
|
||||
my $msg = shift;
|
||||
s/^\s+//;
|
||||
s/\s+$//;
|
||||
s/\s+/ /g;
|
||||
print "$ARGV:$.: error: $msg: $_\n";
|
||||
$exit_code = 1;
|
||||
}
|
||||
|
||||
# glean names of shell functions
|
||||
for my $i (@ARGV) {
|
||||
open(my $f, '<', $i) or die "$0: $i: $!\n";
|
||||
while (<$f>) {
|
||||
$func{$1} = 1 if /^\s*(\w+)\s*\(\)\s*{\s*$/;
|
||||
}
|
||||
close $f;
|
||||
}
|
||||
|
||||
my $line = '';
|
||||
while (<>) {
|
||||
chomp;
|
||||
$line .= $_;
|
||||
# stitch together incomplete lines (those ending with "\")
|
||||
next if $line =~ s/\\$//;
|
||||
|
||||
$_ = $line;
|
||||
/\bcp\s+-a/ and err 'cp -a is not portable';
|
||||
/\bsed\s+-[^efn]\s+/ and err 'sed option not portable (use only -n, -e, -f)';
|
||||
/\becho\s+-[neE]/ and err 'echo with option is not portable (use printf)';
|
||||
/^\s*declare\s+/ and err 'arrays/declare not portable';
|
||||
/^\s*[^#]\s*which\s/ and err 'which is not portable (use type)';
|
||||
/\btest\s+[^=]*==/ and err '"test a == b" is not portable (use =)';
|
||||
/\bwc -l.*"\s*=/ and err '`"$(wc -l)"` is not portable (use test_line_count)';
|
||||
/\bhead\s+-c\b/ and err 'head -c is not portable (use test_copy_bytes BYTES <file >out)';
|
||||
/(?:\$\(seq|^\s*seq\b)/ and err 'seq is not portable (use test_seq)';
|
||||
/\bgrep\b.*--file\b/ and err 'grep --file FILE is not portable (use grep -f FILE)';
|
||||
/\bexport\s+[A-Za-z0-9_]*=/ and err '"export FOO=bar" is not portable (use FOO=bar && export FOO)';
|
||||
/^\s*([A-Z0-9_]+=(\w+|(["']).*?\3)\s+)+(\w+)/ and exists($func{$4}) and
|
||||
err '"FOO=bar shell_func" assignment extends beyond "shell_func"';
|
||||
$line = '';
|
||||
# this resets our $. for each file
|
||||
close ARGV if eof;
|
||||
}
|
||||
exit $exit_code;
|
||||
39
t/diff-lib.sh
Normal file
39
t/diff-lib.sh
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
:
|
||||
|
||||
sanitize_diff_raw='/^:/s/ '"\($OID_REGEX\)"' '"\($OID_REGEX\)"' \([A-Z]\)[0-9]* / \1 \2 \3# /'
|
||||
compare_diff_raw () {
|
||||
# When heuristics are improved, the score numbers would change.
|
||||
# Ignore them while comparing.
|
||||
# Also we do not check SHA1 hash generation in this test, which
|
||||
# is a job for t0000-basic.sh
|
||||
|
||||
sed -e "$sanitize_diff_raw" <"$1" >.tmp-1
|
||||
sed -e "$sanitize_diff_raw" <"$2" >.tmp-2
|
||||
test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
|
||||
}
|
||||
|
||||
sanitize_diff_raw_z='/^:/s/ '"$OID_REGEX"' '"$OID_REGEX"' \([A-Z]\)[0-9]*$/ X X \1#/'
|
||||
compare_diff_raw_z () {
|
||||
# When heuristics are improved, the score numbers would change.
|
||||
# Ignore them while comparing.
|
||||
# Also we do not check SHA1 hash generation in this test, which
|
||||
# is a job for t0000-basic.sh
|
||||
|
||||
perl -pe 'y/\000/\012/' <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1
|
||||
perl -pe 'y/\000/\012/' <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2
|
||||
test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
|
||||
}
|
||||
|
||||
compare_diff_patch () {
|
||||
# When heuristics are improved, the score numbers would change.
|
||||
# Ignore them while comparing.
|
||||
sed -e '
|
||||
/^[dis]*imilarity index [0-9]*%$/d
|
||||
/^index [0-9a-f]*\.\.[0-9a-f]/d
|
||||
' <"$1" >.tmp-1
|
||||
sed -e '
|
||||
/^[dis]*imilarity index [0-9]*%$/d
|
||||
/^index [0-9a-f]*\.\.[0-9a-f]/d
|
||||
' <"$2" >.tmp-2
|
||||
test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
|
||||
}
|
||||
361
t/diff-lib/COPYING
Normal file
361
t/diff-lib/COPYING
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
|
||||
Note that the only valid version of the GPL as far as this project
|
||||
is concerned is _this_ particular version of the license (ie v2, not
|
||||
v2.2 or v3.x or whatever), unless explicitly otherwise stated.
|
||||
|
||||
HOWEVER, in order to allow a migration to GPLv3 if that seems like
|
||||
a good idea, I also ask that people involved with the project make
|
||||
their preferences known. In particular, if you trust me to make that
|
||||
decision, you might note so in your copyright message, ie something
|
||||
like
|
||||
|
||||
This file is licensed under the GPL v2, or a later version
|
||||
at the discretion of Linus.
|
||||
|
||||
might avoid issues. But we can also just decide to synchronize and
|
||||
contact all copyright holders on record if/when the occasion arises.
|
||||
|
||||
Linus Torvalds
|
||||
|
||||
----------------------------------------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
46
t/diff-lib/README
Normal file
46
t/diff-lib/README
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
////////////////////////////////////////////////////////////////
|
||||
|
||||
GIT - the stupid content tracker
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
"git" can mean anything, depending on your mood.
|
||||
|
||||
- random three-letter combination that is pronounceable, and not
|
||||
actually used by any common UNIX command. The fact that it is a
|
||||
mispronunciation of "get" may or may not be relevant.
|
||||
- stupid. contemptible and despicable. simple. Take your pick from the
|
||||
dictionary of slang.
|
||||
- "global information tracker": you're in a good mood, and it actually
|
||||
works for you. Angels sing, and a light suddenly fills the room.
|
||||
- "goddamn idiotic truckload of sh*t": when it breaks
|
||||
|
||||
Git is a fast, scalable, distributed revision control system with an
|
||||
unusually rich command set that provides both high-level operations
|
||||
and full access to internals.
|
||||
|
||||
Git is an Open Source project covered by the GNU General Public License.
|
||||
It was originally written by Linus Torvalds with help of a group of
|
||||
hackers around the net. It is currently maintained by Junio C Hamano.
|
||||
|
||||
Please read the file INSTALL for installation instructions.
|
||||
See Documentation/tutorial.txt to get started, then see
|
||||
Documentation/everyday.txt for a useful minimum set of commands,
|
||||
and "man git-commandname" for documentation of each command.
|
||||
CVS users may also want to read Documentation/cvs-migration.txt.
|
||||
|
||||
Many Git online resources are accessible from http://git.or.cz/
|
||||
including full documentation and Git related tools.
|
||||
|
||||
The user discussion and development of Git take place on the Git
|
||||
mailing list -- everyone is welcome to post bug reports, feature
|
||||
requests, comments and patches to git@vger.kernel.org. To subscribe
|
||||
to the list, send an email with just "subscribe git" in the body to
|
||||
majordomo@vger.kernel.org. The mailing list archives are available at
|
||||
http://marc.theaimsgroup.com/?l=git and other archival sites.
|
||||
|
||||
The messages titled "A note from the maintainer", "What's in
|
||||
git.git (stable)" and "What's cooking in git.git (topics)" and
|
||||
the discussion following them on the mailing list give a good
|
||||
reference for project status, development direction and
|
||||
remaining tasks.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue