summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/Makefile2
-rw-r--r--t/README3
-rwxr-xr-xt/chainlint.pl171
-rw-r--r--t/chainlint/block-comment.expect2
-rw-r--r--t/chainlint/case-comment.expect3
-rw-r--r--t/chainlint/close-subshell.expect3
-rw-r--r--t/chainlint/comment.expect4
-rw-r--r--t/chainlint/double-here-doc.expect14
-rw-r--r--t/chainlint/empty-here-doc.expect3
-rw-r--r--t/chainlint/for-loop.expect4
-rw-r--r--t/chainlint/here-doc-close-subshell.expect4
-rw-r--r--t/chainlint/here-doc-indent-operator.expect10
-rw-r--r--t/chainlint/here-doc-multi-line-command-subst.expect5
-rw-r--r--t/chainlint/here-doc-multi-line-string.expect4
-rw-r--r--t/chainlint/here-doc.expect24
-rw-r--r--t/chainlint/if-then-else.expect4
-rw-r--r--t/chainlint/incomplete-line.expect10
-rw-r--r--t/chainlint/inline-comment.expect4
-rw-r--r--t/chainlint/loop-detect-status.expect2
-rw-r--r--t/chainlint/nested-here-doc.expect27
-rw-r--r--t/chainlint/nested-subshell-comment.expect2
-rw-r--r--t/chainlint/subshell-here-doc.expect28
-rw-r--r--t/chainlint/t7900-subtree.expect4
-rw-r--r--t/chainlint/while-loop.expect4
-rw-r--r--t/helper/test-cache-tree.c64
-rw-r--r--t/helper/test-fake-ssh.c1
-rw-r--r--t/helper/test-run-command.c21
-rw-r--r--t/helper/test-sha1.c8
-rw-r--r--t/helper/test-submodule.c84
-rw-r--r--t/helper/test-tool.c2
-rw-r--r--t/helper/test-tool.h2
-rw-r--r--t/lib-gettext.sh2
-rw-r--r--t/lib-gitweb.sh2
-rw-r--r--t/lib-httpd.sh5
-rw-r--r--t/lib-httpd/apache.conf19
-rwxr-xr-xt/perf/p0006-read-tree-checkout.sh8
-rwxr-xr-xt/perf/p0090-cache-tree.sh36
-rwxr-xr-xt/perf/p1401-ref-operations.sh52
-rwxr-xr-xt/perf/p7102-reset.sh21
-rwxr-xr-xt/t0013-sha1dc.sh6
-rwxr-xr-xt/t0021-conversion.sh4
-rwxr-xr-xt/t0040-parse-options.sh12
-rwxr-xr-xt/t0061-run-command.sh54
-rwxr-xr-xt/t0068-for-each-repo.sh7
-rwxr-xr-xt/t0070-fundamental.sh1
-rwxr-xr-xt/t1011-read-tree-sparse-checkout.sh1
-rwxr-xr-xt/t1022-read-tree-partial-clone.sh4
-rwxr-xr-xt/t1050-large.sh6
-rwxr-xr-xt/t1300-config.sh6
-rwxr-xr-xt/t1404-update-ref-errors.sh2
-rwxr-xr-xt/t1409-avoid-packing-refs.sh23
-rwxr-xr-xt/t1413-reflog-detach.sh1
-rwxr-xr-xt/t1501-work-tree.sh2
-rwxr-xr-xt/t1600-index.sh8
-rwxr-xr-xt/t1800-hook.sh2
-rwxr-xr-xt/t2012-checkout-last.sh1
-rwxr-xr-xt/t2018-checkout-branch.sh1
-rwxr-xr-xt/t2025-checkout-no-overlay.sh1
-rwxr-xr-xt/t2400-worktree-add.sh45
-rwxr-xr-xt/t3009-ls-files-others-nonsubmodule.sh1
-rwxr-xr-xt/t3010-ls-files-killed-modified.sh2
-rwxr-xr-xt/t3050-subprojects-fetch.sh1
-rwxr-xr-xt/t3060-ls-files-with-tree.sh2
-rwxr-xr-xt/t3200-branch.sh36
-rwxr-xr-xt/t3210-pack-refs.sh8
-rwxr-xr-xt/t3212-ref-formats.sh100
-rwxr-xr-xt/t3301-notes.sh18
-rwxr-xr-xt/t3404-rebase-interactive.sh107
-rwxr-xr-xt/t3409-rebase-environ.sh1
-rwxr-xr-xt/t3413-rebase-hook.sh1
-rwxr-xr-xt/t3428-rebase-signoff.sh1
-rwxr-xr-xt/t3429-rebase-edit-todo.sh1
-rwxr-xr-xt/t3430-rebase-merges.sh17
-rwxr-xr-xt/t3433-rebase-across-mode-change.sh1
-rwxr-xr-xt/t4015-diff-whitespace.sh4
-rwxr-xr-xt/t4027-diff-submodule.sh19
-rwxr-xr-xt/t4045-diff-relative.sh2
-rwxr-xr-xt/t4052-stat-output.sh1
-rwxr-xr-xt/t4053-diff-no-index.sh1
-rwxr-xr-xt/t4067-diff-partial-clone.sh1
-rwxr-xr-xt/t4111-apply-subdir.sh1
-rwxr-xr-xt/t4135-apply-weird-filenames.sh1
-rwxr-xr-xt/t4213-log-tabexpand.sh1
-rwxr-xr-xt/t4301-merge-tree-write-tree.sh62
-rwxr-xr-xt/t5310-pack-bitmaps.sh5
-rwxr-xr-xt/t5317-pack-objects-filter-objects.sh19
-rwxr-xr-xt/t5502-quickfetch.sh2
-rwxr-xr-xt/t5526-fetch-submodules.sh8
-rwxr-xr-xt/t5531-deep-submodule-push.sh50
-rwxr-xr-xt/t5539-fetch-http-shallow.sh7
-rwxr-xr-xt/t5541-http-push-smart.sh7
-rwxr-xr-xt/t5542-push-http-shallow.sh7
-rwxr-xr-xt/t5544-pack-objects-hook.sh2
-rwxr-xr-xt/t5551-http-fetch-smart.sh20
-rwxr-xr-xt/t5554-noop-fetch-negotiator.sh2
-rwxr-xr-xt/t5558-clone-bundle-uri.sh7
-rwxr-xr-xt/t5559-http-fetch-smart-http2.sh4
-rwxr-xr-xt/t5601-clone.sh22
-rwxr-xr-xt/t5610-clone-detached.sh1
-rwxr-xr-xt/t5611-clone-config.sh1
-rwxr-xr-xt/t5614-clone-submodules-shallow.sh1
-rwxr-xr-xt/t5617-clone-submodules.sh (renamed from t/t5617-clone-submodules-remote.sh)41
-rwxr-xr-xt/t5618-alternate-refs.sh2
-rwxr-xr-xt/t6018-rev-list-glob.sh40
-rwxr-xr-xt/t6021-rev-list-exclude-hidden.sh163
-rwxr-xr-xt/t6030-bisect-porcelain.sh158
-rwxr-xr-xt/t6060-merge-index.sh2
-rwxr-xr-xt/t6102-rev-list-unexpected-objects.sh4
-rwxr-xr-xt/t6301-for-each-ref-errors.sh1
-rwxr-xr-xt/t6401-merge-criss-cross.sh2
-rwxr-xr-xt/t6406-merge-attr.sh1
-rwxr-xr-xt/t6407-merge-binary.sh1
-rwxr-xr-xt/t6415-merge-dir-to-symlink.sh1
-rwxr-xr-xt/t6435-merge-sparse.sh1
-rwxr-xr-xt/t7001-mv.sh62
-rwxr-xr-xt/t7065-wtstatus-slow.sh70
-rwxr-xr-xt/t7103-reset-bare.sh2
-rwxr-xr-xt/t7400-submodule-basic.sh10
-rwxr-xr-xt/t7406-submodule-update.sh156
-rwxr-xr-xt/t7407-submodule-foreach.sh5
-rwxr-xr-xt/t7411-submodule-config.sh36
-rwxr-xr-xt/t7412-submodule-absorbgitdirs.sh36
-rwxr-xr-xt/t7418-submodule-sparse-gitmodules.sh4
-rwxr-xr-xt/t7422-submodule-output.sh170
-rwxr-xr-xt/t7504-commit-msg-hook.sh1
-rwxr-xr-xt/t7506-status-submodule.sh19
-rwxr-xr-xt/t7517-per-repo-email.sh1
-rwxr-xr-xt/t7520-ignored-hook-warning.sh1
-rwxr-xr-xt/t7605-merge-resolve.sh1
-rwxr-xr-xt/t7609-mergetool--lib.sh2
-rwxr-xr-xt/t7610-mergetool.sh4
-rwxr-xr-xt/t7614-merge-signoff.sh1
-rwxr-xr-xt/t7700-repack.sh121
-rwxr-xr-xt/t7900-maintenance.sh21
-rwxr-xr-xt/t9003-help-autocorrect.sh2
-rwxr-xr-xt/t9115-git-svn-dcommit-funky-renames.sh1
-rwxr-xr-xt/t9146-git-svn-empty-dirs.sh1
-rwxr-xr-xt/t9148-git-svn-propset.sh1
-rwxr-xr-xt/t9160-git-svn-preserve-empty-dirs.sh1
-rwxr-xr-xt/t9210-scalar.sh14
-rwxr-xr-xt/t9902-completion.sh46
-rwxr-xr-xt/t9903-bash-prompt.sh2
-rw-r--r--t/test-lib-functions.sh66
-rw-r--r--t/test-lib.sh33
144 files changed, 2450 insertions, 267 deletions
diff --git a/t/Makefile b/t/Makefile
index 882782a519..2c2b252240 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -94,7 +94,7 @@ check-chainlint:
done \
} >'$(CHAINLINTTMP_SQ)'/expect && \
$(CHAINLINT) --emit-all '$(CHAINLINTTMP_SQ)'/tests | \
- grep -v '^[ ]*$$' >'$(CHAINLINTTMP_SQ)'/actual && \
+ sed -e 's/^[1-9][0-9]* //;/^[ ]*$$/d' >'$(CHAINLINTTMP_SQ)'/actual && \
if test -f ../GIT-BUILD-OPTIONS; then \
. ../GIT-BUILD-OPTIONS; \
fi && \
diff --git a/t/README b/t/README
index 979b2d4833..fc0daef2e4 100644
--- a/t/README
+++ b/t/README
@@ -231,6 +231,9 @@ override the location of the dashed-form subcommands (what
GIT_EXEC_PATH would be used for during normal operation).
GIT_TEST_EXEC_PATH defaults to `$GIT_TEST_INSTALLED/git --exec-path`.
+Similar to GIT_TEST_INSTALLED, GIT_TEST_BUILD_DIR can be pointed to
+another git.git checkout's build directory, to test its built binaries
+against the tests in this checkout.
Skipping Tests
--------------
diff --git a/t/chainlint.pl b/t/chainlint.pl
index 976db4b8a0..4e47e808d0 100755
--- a/t/chainlint.pl
+++ b/t/chainlint.pl
@@ -67,6 +67,7 @@ sub new {
bless {
parser => $parser,
buff => $s,
+ lineno => 1,
heretags => []
} => $class;
}
@@ -75,7 +76,9 @@ sub scan_heredoc_tag {
my $self = shift @_;
${$self->{buff}} =~ /\G(-?)/gc;
my $indented = $1;
- my $tag = $self->scan_token();
+ my $token = $self->scan_token();
+ return "<<$indented" unless $token;
+ my $tag = $token->[0];
$tag =~ s/['"\\]//g;
push(@{$self->{heretags}}, $indented ? "\t$tag" : "$tag");
return "<<$indented$tag";
@@ -95,7 +98,9 @@ sub scan_op {
sub scan_sqstring {
my $self = shift @_;
${$self->{buff}} =~ /\G([^']*'|.*\z)/sgc;
- return "'" . $1;
+ my $s = $1;
+ $self->{lineno} += () = $s =~ /\n/sg;
+ return "'" . $s;
}
sub scan_dqstring {
@@ -113,7 +118,7 @@ sub scan_dqstring {
if ($c eq '\\') {
$s .= '\\', last unless $$b =~ /\G(.)/sgc;
$c = $1;
- next if $c eq "\n"; # line splice
+ $self->{lineno}++, next if $c eq "\n"; # line splice
# backslash escapes only $, `, ", \ in dq-string
$s .= '\\' unless $c =~ /^[\$`"\\]$/;
$s .= $c;
@@ -121,6 +126,7 @@ sub scan_dqstring {
}
die("internal error scanning dq-string '$c'\n");
}
+ $self->{lineno} += () = $s =~ /\n/sg;
return $s;
}
@@ -135,6 +141,7 @@ sub scan_balanced {
$depth--;
last if $depth == 0;
}
+ $self->{lineno} += () = $s =~ /\n/sg;
return $s;
}
@@ -149,7 +156,7 @@ sub scan_dollar {
my $self = shift @_;
my $b = $self->{buff};
return $self->scan_balanced('(', ')') if $$b =~ /\G\((?=\()/gc; # $((...))
- return '(' . join(' ', $self->scan_subst()) . ')' if $$b =~ /\G\(/gc; # $(...)
+ return '(' . join(' ', map {$_->[0]} $self->scan_subst()) . ')' if $$b =~ /\G\(/gc; # $(...)
return $self->scan_balanced('{', '}') if $$b =~ /\G\{/gc; # ${...}
return $1 if $$b =~ /\G(\w+)/gc; # $var
return $1 if $$b =~ /\G([@*#?$!0-9-])/gc; # $*, $1, $$, etc.
@@ -161,8 +168,11 @@ sub swallow_heredocs {
my $b = $self->{buff};
my $tags = $self->{heretags};
while (my $tag = shift @$tags) {
+ my $start = pos($$b);
my $indent = $tag =~ s/^\t// ? '\\s*' : '';
$$b =~ /(?:\G|\n)$indent\Q$tag\E(?:\n|\z)/gc;
+ my $body = substr($$b, $start, pos($$b) - $start);
+ $self->{lineno} += () = $body =~ /\n/sg;
}
}
@@ -170,34 +180,37 @@ sub scan_token {
my $self = shift @_;
my $b = $self->{buff};
my $token = '';
+ my ($start, $startln);
RESTART:
+ $startln = $self->{lineno};
$$b =~ /\G[ \t]+/gc; # skip whitespace (but not newline)
- return "\n" if $$b =~ /\G#[^\n]*(?:\n|\z)/gc; # comment
+ $start = pos($$b) || 0;
+ $self->{lineno}++, return ["\n", $start, pos($$b), $startln, $startln] if $$b =~ /\G#[^\n]*(?:\n|\z)/gc; # comment
while (1) {
# slurp up non-special characters
$token .= $1 if $$b =~ /\G([^\\;&|<>(){}'"\$\s]+)/gc;
# handle special characters
last unless $$b =~ /\G(.)/sgc;
my $c = $1;
- last if $c =~ /^[ \t]$/; # whitespace ends token
+ pos($$b)--, last if $c =~ /^[ \t]$/; # whitespace ends token
pos($$b)--, last if length($token) && $c =~ /^[;&|<>(){}\n]$/;
$token .= $self->scan_sqstring(), next if $c eq "'";
$token .= $self->scan_dqstring(), next if $c eq '"';
$token .= $c . $self->scan_dollar(), next if $c eq '$';
- $self->swallow_heredocs(), $token = $c, last if $c eq "\n";
+ $self->{lineno}++, $self->swallow_heredocs(), $token = $c, last if $c eq "\n";
$token = $self->scan_op($c), last if $c =~ /^[;&|<>]$/;
$token = $c, last if $c =~ /^[(){}]$/;
if ($c eq '\\') {
$token .= '\\', last unless $$b =~ /\G(.)/sgc;
$c = $1;
- next if $c eq "\n" && length($token); # line splice
- goto RESTART if $c eq "\n"; # line splice
+ $self->{lineno}++, next if $c eq "\n" && length($token); # line splice
+ $self->{lineno}++, goto RESTART if $c eq "\n"; # line splice
$token .= '\\' . $c;
next;
}
die("internal error scanning character '$c'\n");
}
- return length($token) ? $token : undef;
+ return length($token) ? [$token, $start, pos($$b), $startln, $self->{lineno}] : undef;
}
# ShellParser parses POSIX shell scripts (with minor extensions for Bash). It
@@ -239,14 +252,14 @@ sub stop_at {
my ($self, $token) = @_;
return 1 unless defined($token);
my $stop = ${$self->{stop}}[-1] if @{$self->{stop}};
- return defined($stop) && $token =~ $stop;
+ return defined($stop) && $token->[0] =~ $stop;
}
sub expect {
my ($self, $expect) = @_;
my $token = $self->next_token();
- return $token if defined($token) && $token eq $expect;
- push(@{$self->{output}}, "?!ERR?! expected '$expect' but found '" . (defined($token) ? $token : "<end-of-input>") . "'\n");
+ return $token if defined($token) && $token->[0] eq $expect;
+ push(@{$self->{output}}, "?!ERR?! expected '$expect' but found '" . (defined($token) ? $token->[0] : "<end-of-input>") . "'\n");
$self->untoken($token) if defined($token);
return ();
}
@@ -255,7 +268,7 @@ sub optional_newlines {
my $self = shift @_;
my @tokens;
while (my $token = $self->peek()) {
- last unless $token eq "\n";
+ last unless $token->[0] eq "\n";
push(@tokens, $self->next_token());
}
return @tokens;
@@ -278,7 +291,7 @@ sub parse_case_pattern {
my @tokens;
while (defined(my $token = $self->next_token())) {
push(@tokens, $token);
- last if $token eq ')';
+ last if $token->[0] eq ')';
}
return @tokens;
}
@@ -293,13 +306,13 @@ sub parse_case {
$self->optional_newlines());
while (1) {
my $token = $self->peek();
- last unless defined($token) && $token ne 'esac';
+ last unless defined($token) && $token->[0] ne 'esac';
push(@tokens,
$self->parse_case_pattern(),
$self->optional_newlines(),
$self->parse(qr/^(?:;;|esac)$/)); # item body
$token = $self->peek();
- last unless defined($token) && $token ne 'esac';
+ last unless defined($token) && $token->[0] ne 'esac';
push(@tokens,
$self->expect(';;'),
$self->optional_newlines());
@@ -315,7 +328,7 @@ sub parse_for {
$self->next_token(), # variable
$self->optional_newlines());
my $token = $self->peek();
- if (defined($token) && $token eq 'in') {
+ if (defined($token) && $token->[0] eq 'in') {
push(@tokens,
$self->expect('in'),
$self->optional_newlines());
@@ -339,11 +352,11 @@ sub parse_if {
$self->optional_newlines(),
$self->parse(qr/^(?:elif|else|fi)$/)); # if/elif body
my $token = $self->peek();
- last unless defined($token) && $token eq 'elif';
+ last unless defined($token) && $token->[0] eq 'elif';
push(@tokens, $self->expect('elif'));
}
my $token = $self->peek();
- if (defined($token) && $token eq 'else') {
+ if (defined($token) && $token->[0] eq 'else') {
push(@tokens,
$self->expect('else'),
$self->optional_newlines(),
@@ -380,7 +393,7 @@ sub parse_bash_array_assignment {
my @tokens = $self->expect('(');
while (defined(my $token = $self->next_token())) {
push(@tokens, $token);
- last if $token eq ')';
+ last if $token->[0] eq ')';
}
return @tokens;
}
@@ -398,29 +411,31 @@ sub parse_cmd {
my $self = shift @_;
my $cmd = $self->next_token();
return () unless defined($cmd);
- return $cmd if $cmd eq "\n";
+ return $cmd if $cmd->[0] eq "\n";
my $token;
my @tokens = $cmd;
- if ($cmd eq '!') {
+ if ($cmd->[0] eq '!') {
push(@tokens, $self->parse_cmd());
return @tokens;
- } elsif (my $f = $compound{$cmd}) {
+ } elsif (my $f = $compound{$cmd->[0]}) {
push(@tokens, $self->$f());
- } elsif (defined($token = $self->peek()) && $token eq '(') {
- if ($cmd !~ /\w=$/) {
+ } elsif (defined($token = $self->peek()) && $token->[0] eq '(') {
+ if ($cmd->[0] !~ /\w=$/) {
push(@tokens, $self->parse_func());
return @tokens;
}
- $tokens[-1] .= join(' ', $self->parse_bash_array_assignment());
+ my @array = $self->parse_bash_array_assignment();
+ $tokens[-1]->[0] .= join(' ', map {$_->[0]} @array);
+ $tokens[-1]->[2] = $array[$#array][2] if @array;
}
while (defined(my $token = $self->next_token())) {
$self->untoken($token), last if $self->stop_at($token);
push(@tokens, $token);
- last if $token =~ /^(?:[;&\n|]|&&|\|\|)$/;
+ last if $token->[0] =~ /^(?:[;&\n|]|&&|\|\|)$/;
}
- push(@tokens, $self->next_token()) if $tokens[-1] ne "\n" && defined($token = $self->peek()) && $token eq "\n";
+ push(@tokens, $self->next_token()) if $tokens[-1]->[0] ne "\n" && defined($token = $self->peek()) && $token->[0] eq "\n";
return @tokens;
}
@@ -453,11 +468,18 @@ package TestParser;
use base 'ShellParser';
+sub new {
+ my $class = shift @_;
+ my $self = $class->SUPER::new(@_);
+ $self->{problems} = [];
+ return $self;
+}
+
sub find_non_nl {
my $tokens = shift @_;
my $n = shift @_;
$n = $#$tokens if !defined($n);
- $n-- while $n >= 0 && $$tokens[$n] eq "\n";
+ $n-- while $n >= 0 && $$tokens[$n]->[0] eq "\n";
return $n;
}
@@ -467,7 +489,7 @@ sub ends_with {
for my $needle (reverse(@$needles)) {
return undef if $n < 0;
$n = find_non_nl($tokens, $n), next if $needle eq "\n";
- return undef if $$tokens[$n] !~ $needle;
+ return undef if $$tokens[$n]->[0] !~ $needle;
$n--;
}
return 1;
@@ -486,13 +508,13 @@ sub parse_loop_body {
my $self = shift @_;
my @tokens = $self->SUPER::parse_loop_body(@_);
# did loop signal failure via "|| return" or "|| exit"?
- return @tokens if !@tokens || grep(/^(?:return|exit|\$\?)$/, @tokens);
+ return @tokens if !@tokens || grep {$_->[0] =~ /^(?:return|exit|\$\?)$/} @tokens;
# did loop upstream of a pipe signal failure via "|| echo 'impossible
# text'" as the final command in the loop body?
return @tokens if ends_with(\@tokens, [qr/^\|\|$/, "\n", qr/^echo$/, qr/^.+$/]);
# flag missing "return/exit" handling explicit failure in loop body
my $n = find_non_nl(\@tokens);
- splice(@tokens, $n + 1, 0, '?!LOOP?!');
+ push(@{$self->{problems}}, ['LOOP', $tokens[$n]]);
return @tokens;
}
@@ -505,8 +527,13 @@ my @safe_endings = (
sub accumulate {
my ($self, $tokens, $cmd) = @_;
+ my $problems = $self->{problems};
+
+ # no previous command to check for missing "&&"
goto DONE unless @$tokens;
- goto DONE if @$cmd == 1 && $$cmd[0] eq "\n";
+
+ # new command is empty line; can't yet check if previous is missing "&&"
+ goto DONE if @$cmd == 1 && $$cmd[0]->[0] eq "\n";
# did previous command end with "&&", "|", "|| return" or similar?
goto DONE if match_ending($tokens, \@safe_endings);
@@ -514,20 +541,20 @@ sub accumulate {
# if this command handles "$?" specially, then okay for previous
# command to be missing "&&"
for my $token (@$cmd) {
- goto DONE if $token =~ /\$\?/;
+ goto DONE if $token->[0] =~ /\$\?/;
}
# if this command is "false", "return 1", or "exit 1" (which signal
# failure explicitly), then okay for all preceding commands to be
# missing "&&"
- if ($$cmd[0] =~ /^(?:false|return|exit)$/) {
- @$tokens = grep(!/^\?!AMP\?!$/, @$tokens);
+ if ($$cmd[0]->[0] =~ /^(?:false|return|exit)$/) {
+ @$problems = grep {$_->[0] ne 'AMP'} @$problems;
goto DONE;
}
# flag missing "&&" at end of previous command
my $n = find_non_nl($tokens);
- splice(@$tokens, $n + 1, 0, '?!AMP?!') unless $n < 0;
+ push(@$problems, ['AMP', $tokens->[$n]]) unless $n < 0;
DONE:
$self->SUPER::accumulate($tokens, $cmd);
@@ -553,7 +580,7 @@ sub new {
# composition of multiple strings and non-string character runs; for instance,
# `"test body"` unwraps to `test body`; `word"a b"42'c d'` to `worda b42c d`
sub unwrap {
- my $token = @_ ? shift @_ : $_;
+ my $token = (@_ ? shift @_ : $_)->[0];
# simple case: 'sqstring' or "dqstring"
return $token if $token =~ s/^'([^']*)'$/$1/;
return $token if $token =~ s/^"([^"]*)"$/$1/;
@@ -584,13 +611,25 @@ sub check_test {
$self->{ntests}++;
my $parser = TestParser->new(\$body);
my @tokens = $parser->parse();
- return unless $emit_all || grep(/\?![^?]+\?!/, @tokens);
+ my $problems = $parser->{problems};
+ return unless $emit_all || @$problems;
my $c = main::fd_colors(1);
- my $checked = join(' ', @tokens);
- $checked =~ s/^\n//;
- $checked =~ s/^ //mg;
- $checked =~ s/ $//mg;
+ my $lineno = $_[1]->[3];
+ my $start = 0;
+ my $checked = '';
+ for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) {
+ my ($label, $token) = @$_;
+ my $pos = $token->[2];
+ $checked .= substr($body, $start, $pos - $start) . " ?!$label?! ";
+ $start = $pos;
+ }
+ $checked .= substr($body, $start);
+ $checked =~ s/^/$lineno++ . ' '/mge;
+ $checked =~ s/^\d+ \n//;
+ $checked =~ s/(\s) \?!/$1?!/mg;
+ $checked =~ s/\?! (\s)/?!$1/mg;
$checked =~ s/(\?![^?]+\?!)/$c->{rev}$c->{red}$1$c->{reset}/mg;
+ $checked =~ s/^\d+/$c->{dim}$&$c->{reset}/mg;
$checked .= "\n" unless $checked =~ /\n$/;
push(@{$self->{output}}, "$c->{blue}# chainlint: $title$c->{reset}\n$checked");
}
@@ -598,9 +637,9 @@ sub check_test {
sub parse_cmd {
my $self = shift @_;
my @tokens = $self->SUPER::parse_cmd();
- return @tokens unless @tokens && $tokens[0] =~ /^test_expect_(?:success|failure)$/;
+ return @tokens unless @tokens && $tokens[0]->[0] =~ /^test_expect_(?:success|failure)$/;
my $n = $#tokens;
- $n-- while $n >= 0 && $tokens[$n] =~ /^(?:[;&\n|]|&&|\|\|)$/;
+ $n-- while $n >= 0 && $tokens[$n]->[0] =~ /^(?:[;&\n|]|&&|\|\|)$/;
$self->check_test($tokens[1], $tokens[2]) if $n == 2; # title body
$self->check_test($tokens[2], $tokens[3]) if $n > 2; # prereq title body
return @tokens;
@@ -622,25 +661,39 @@ if (eval {require Time::HiRes; Time::HiRes->import(); 1;}) {
# thread and ignore %ENV changes in subthreads.
$ENV{TERM} = $ENV{USER_TERM} if $ENV{USER_TERM};
-my @NOCOLORS = (bold => '', rev => '', reset => '', blue => '', green => '', red => '');
+my @NOCOLORS = (bold => '', rev => '', dim => '', reset => '', blue => '', green => '', red => '');
my %COLORS = ();
sub get_colors {
return \%COLORS if %COLORS;
- if (exists($ENV{NO_COLOR}) ||
- system("tput sgr0 >/dev/null 2>&1") != 0 ||
- system("tput bold >/dev/null 2>&1") != 0 ||
- system("tput rev >/dev/null 2>&1") != 0 ||
- system("tput setaf 1 >/dev/null 2>&1") != 0) {
+ if (exists($ENV{NO_COLOR})) {
%COLORS = @NOCOLORS;
return \%COLORS;
}
- %COLORS = (bold => `tput bold`,
- rev => `tput rev`,
- reset => `tput sgr0`,
- blue => `tput setaf 4`,
- green => `tput setaf 2`,
- red => `tput setaf 1`);
- chomp(%COLORS);
+ if ($ENV{TERM} =~ /xterm|xterm-\d+color|xterm-new|xterm-direct|nsterm|nsterm-\d+color|nsterm-direct/) {
+ %COLORS = (bold => "\e[1m",
+ rev => "\e[7m",
+ dim => "\e[2m",
+ reset => "\e[0m",
+ blue => "\e[34m",
+ green => "\e[32m",
+ red => "\e[31m");
+ return \%COLORS;
+ }
+ if (system("tput sgr0 >/dev/null 2>&1") == 0 &&
+ system("tput bold >/dev/null 2>&1") == 0 &&
+ system("tput rev >/dev/null 2>&1") == 0 &&
+ system("tput dim >/dev/null 2>&1") == 0 &&
+ system("tput setaf 1 >/dev/null 2>&1") == 0) {
+ %COLORS = (bold => `tput bold`,
+ rev => `tput rev`,
+ dim => `tput dim`,
+ reset => `tput sgr0`,
+ blue => `tput setaf 4`,
+ green => `tput setaf 2`,
+ red => `tput setaf 1`);
+ return \%COLORS;
+ }
+ %COLORS = @NOCOLORS;
return \%COLORS;
}
diff --git a/t/chainlint/block-comment.expect b/t/chainlint/block-comment.expect
index d10b2eeaf2..df2beea888 100644
--- a/t/chainlint/block-comment.expect
+++ b/t/chainlint/block-comment.expect
@@ -1,6 +1,8 @@
(
{
+ # show a
echo a &&
+ # show b
echo b
}
)
diff --git a/t/chainlint/case-comment.expect b/t/chainlint/case-comment.expect
index 1e4b054bda..641c157b98 100644
--- a/t/chainlint/case-comment.expect
+++ b/t/chainlint/case-comment.expect
@@ -1,7 +1,10 @@
(
case "$x" in
+ # found foo
x) foo ;;
+ # found other
*)
+ # treat it as bar
bar
;;
esac
diff --git a/t/chainlint/close-subshell.expect b/t/chainlint/close-subshell.expect
index 0f87db9ae6..2192a2870a 100644
--- a/t/chainlint/close-subshell.expect
+++ b/t/chainlint/close-subshell.expect
@@ -15,7 +15,8 @@
) | wuzzle &&
(
bop
-) | fazz fozz &&
+) | fazz \
+ fozz &&
(
bup
) |
diff --git a/t/chainlint/comment.expect b/t/chainlint/comment.expect
index f76fde1ffb..a68f1f9d7c 100644
--- a/t/chainlint/comment.expect
+++ b/t/chainlint/comment.expect
@@ -1,4 +1,8 @@
(
+ # comment 1
nothing &&
+ # comment 2
something
+ # comment 3
+ # comment 4
)
diff --git a/t/chainlint/double-here-doc.expect b/t/chainlint/double-here-doc.expect
index 75477bb1ad..cd584a4357 100644
--- a/t/chainlint/double-here-doc.expect
+++ b/t/chainlint/double-here-doc.expect
@@ -1,2 +1,12 @@
-run_sub_test_lib_test_err run-inv-range-start "--run invalid range start" --run="a-5" <<-EOF &&
-check_sub_test_lib_test_err run-inv-range-start <<-EOF_OUT 3 <<-EOF_ERR
+run_sub_test_lib_test_err run-inv-range-start \
+ "--run invalid range start" \
+ --run="a-5" <<-\EOF &&
+test_expect_success "passing test #1" "true"
+test_done
+EOF
+check_sub_test_lib_test_err run-inv-range-start \
+ <<-\EOF_OUT 3<<-EOF_ERR
+> FATAL: Unexpected exit with code 1
+EOF_OUT
+> error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ}
+EOF_ERR
diff --git a/t/chainlint/empty-here-doc.expect b/t/chainlint/empty-here-doc.expect
index f42f2d41ba..e8733c97c6 100644
--- a/t/chainlint/empty-here-doc.expect
+++ b/t/chainlint/empty-here-doc.expect
@@ -1,3 +1,4 @@
git ls-tree $tree path > current &&
-cat > expected <<EOF &&
+cat > expected <<\EOF &&
+EOF
test_output
diff --git a/t/chainlint/for-loop.expect b/t/chainlint/for-loop.expect
index a5810c9bdd..d65c82129a 100644
--- a/t/chainlint/for-loop.expect
+++ b/t/chainlint/for-loop.expect
@@ -2,7 +2,9 @@
for i in a b c
do
echo $i ?!AMP?!
- cat <<-EOF ?!LOOP?!
+ cat <<-\EOF ?!LOOP?!
+ bar
+ EOF
done ?!AMP?!
for i in a b c; do
echo $i &&
diff --git a/t/chainlint/here-doc-close-subshell.expect b/t/chainlint/here-doc-close-subshell.expect
index 2af9ced71c..7d9c2b5607 100644
--- a/t/chainlint/here-doc-close-subshell.expect
+++ b/t/chainlint/here-doc-close-subshell.expect
@@ -1,2 +1,4 @@
(
- cat <<-INPUT)
+ cat <<-\INPUT)
+ fizz
+ INPUT
diff --git a/t/chainlint/here-doc-indent-operator.expect b/t/chainlint/here-doc-indent-operator.expect
index fb6cf7285d..f92a7ce999 100644
--- a/t/chainlint/here-doc-indent-operator.expect
+++ b/t/chainlint/here-doc-indent-operator.expect
@@ -1,5 +1,11 @@
-cat > expect <<-EOF &&
+cat >expect <<- EOF &&
+header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
+num_commits: $1
+chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data
+EOF
-cat > expect <<-EOF ?!AMP?!
+cat >expect << -EOF ?!AMP?!
+this is not indented
+-EOF
cleanup
diff --git a/t/chainlint/here-doc-multi-line-command-subst.expect b/t/chainlint/here-doc-multi-line-command-subst.expect
index f8b3aa73c4..b7364c82c8 100644
--- a/t/chainlint/here-doc-multi-line-command-subst.expect
+++ b/t/chainlint/here-doc-multi-line-command-subst.expect
@@ -1,5 +1,8 @@
(
- x=$(bobble <<-END &&
+ x=$(bobble <<-\END &&
+ fossil
+ vegetable
+ END
wiffle) ?!AMP?!
echo $x
)
diff --git a/t/chainlint/here-doc-multi-line-string.expect b/t/chainlint/here-doc-multi-line-string.expect
index be64b26869..6c13bdcbfb 100644
--- a/t/chainlint/here-doc-multi-line-string.expect
+++ b/t/chainlint/here-doc-multi-line-string.expect
@@ -1,5 +1,7 @@
(
- cat <<-TXT && echo "multi-line
+ cat <<-\TXT && echo "multi-line
string" ?!AMP?!
+ fizzle
+ TXT
bap
)
diff --git a/t/chainlint/here-doc.expect b/t/chainlint/here-doc.expect
index 110059ba58..1df3f78282 100644
--- a/t/chainlint/here-doc.expect
+++ b/t/chainlint/here-doc.expect
@@ -1,7 +1,25 @@
-boodle wobba gorgo snoot wafta snurb <<EOF &&
+boodle wobba \
+ gorgo snoot \
+ wafta snurb <<EOF &&
+quoth the raven,
+nevermore...
+EOF
cat <<-Arbitrary_Tag_42 >foo &&
+snoz
+boz
+woz
+Arbitrary_Tag_42
-cat <<zump >boo &&
+cat <<"zump" >boo &&
+snoz
+boz
+woz
+zump
-horticulture <<EOF
+horticulture <<\EOF
+gomez
+morticia
+wednesday
+pugsly
+EOF
diff --git a/t/chainlint/if-then-else.expect b/t/chainlint/if-then-else.expect
index 44d86c3597..cbaaf857d4 100644
--- a/t/chainlint/if-then-else.expect
+++ b/t/chainlint/if-then-else.expect
@@ -8,7 +8,9 @@
echo foo
else
echo foo &&
- cat <<-EOF
+ cat <<-\EOF
+ bar
+ EOF
fi ?!AMP?!
echo poodle
) &&
diff --git a/t/chainlint/incomplete-line.expect b/t/chainlint/incomplete-line.expect
index ffac8f9018..134d3a14f5 100644
--- a/t/chainlint/incomplete-line.expect
+++ b/t/chainlint/incomplete-line.expect
@@ -1,4 +1,10 @@
-line 1 line 2 line 3 line 4 &&
+line 1 \
+line 2 \
+line 3 \
+line 4 &&
(
- line 5 line 6 line 7 line 8
+ line 5 \
+ line 6 \
+ line 7 \
+ line 8
)
diff --git a/t/chainlint/inline-comment.expect b/t/chainlint/inline-comment.expect
index dd0dace077..6bad218530 100644
--- a/t/chainlint/inline-comment.expect
+++ b/t/chainlint/inline-comment.expect
@@ -1,6 +1,6 @@
(
- foobar &&
- barfoo ?!AMP?!
+ foobar && # comment 1
+ barfoo ?!AMP?! # wrong position for &&
flibble "not a # comment"
) &&
diff --git a/t/chainlint/loop-detect-status.expect b/t/chainlint/loop-detect-status.expect
index 0ad23bb35e..24da9e86d5 100644
--- a/t/chainlint/loop-detect-status.expect
+++ b/t/chainlint/loop-detect-status.expect
@@ -2,7 +2,7 @@
do
printf "Generating blob $i/$blobcount\r" >& 2 &&
printf "blob\nmark :$i\ndata $blobsize\n" &&
-
+ #test-tool genrandom $i $blobsize &&
printf "%-${blobsize}s" $i &&
echo "M 100644 :$i $i" >> commit &&
i=$(($i+1)) ||
diff --git a/t/chainlint/nested-here-doc.expect b/t/chainlint/nested-here-doc.expect
index e3bef63f75..29b3832a98 100644
--- a/t/chainlint/nested-here-doc.expect
+++ b/t/chainlint/nested-here-doc.expect
@@ -1,7 +1,30 @@
cat <<ARBITRARY >foop &&
+naddle
+fub <<EOF
+ nozzle
+ noodle
+EOF
+formp
+ARBITRARY
(
- cat <<-INPUT_END &&
- cat <<-EOT ?!AMP?!
+ cat <<-\INPUT_END &&
+ fish are mice
+ but geese go slow
+ data <<EOF
+ perl is lerp
+ and nothing else
+ EOF
+ toink
+ INPUT_END
+
+ cat <<-\EOT ?!AMP?!
+ text goes here
+ data <<EOF
+ data goes here
+ EOF
+ more test here
+ EOT
+
foobar
)
diff --git a/t/chainlint/nested-subshell-comment.expect b/t/chainlint/nested-subshell-comment.expect
index be4b27a305..9138cf386d 100644
--- a/t/chainlint/nested-subshell-comment.expect
+++ b/t/chainlint/nested-subshell-comment.expect
@@ -2,6 +2,8 @@
foo &&
(
bar &&
+ # bottles wobble while fiddles gobble
+ # minor numbers of cows (or do they?)
baz &&
snaff
) ?!AMP?!
diff --git a/t/chainlint/subshell-here-doc.expect b/t/chainlint/subshell-here-doc.expect
index 029d129299..52789278d1 100644
--- a/t/chainlint/subshell-here-doc.expect
+++ b/t/chainlint/subshell-here-doc.expect
@@ -1,10 +1,30 @@
(
- echo wobba gorgo snoot wafta snurb <<-EOF &&
+ echo wobba \
+ gorgo snoot \
+ wafta snurb <<-EOF &&
+ quoth the raven,
+ nevermore...
+ EOF
+
cat <<EOF >bip ?!AMP?!
- echo <<-EOF >bop
+ fish fly high
+EOF
+
+ echo <<-\EOF >bop
+ gomez
+ morticia
+ wednesday
+ pugsly
+ EOF
) &&
(
- cat <<-ARBITRARY >bup &&
- cat <<-ARBITRARY3 >bup3 &&
+ cat <<-\ARBITRARY >bup &&
+ glink
+ FIZZ
+ ARBITRARY
+ cat <<-"ARBITRARY3" >bup3 &&
+ glink
+ FIZZ
+ ARBITRARY3
meep
)
diff --git a/t/chainlint/t7900-subtree.expect b/t/chainlint/t7900-subtree.expect
index 69167da2f2..71b3b3bc20 100644
--- a/t/chainlint/t7900-subtree.expect
+++ b/t/chainlint/t7900-subtree.expect
@@ -4,12 +4,16 @@ 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
diff --git a/t/chainlint/while-loop.expect b/t/chainlint/while-loop.expect
index f272aa21fe..1f5eaea0fd 100644
--- a/t/chainlint/while-loop.expect
+++ b/t/chainlint/while-loop.expect
@@ -2,7 +2,9 @@
while true
do
echo foo ?!AMP?!
- cat <<-EOF ?!LOOP?!
+ cat <<-\EOF ?!LOOP?!
+ bar
+ EOF
done ?!AMP?!
while true; do
echo foo &&
diff --git a/t/helper/test-cache-tree.c b/t/helper/test-cache-tree.c
new file mode 100644
index 0000000000..93051b25f5
--- /dev/null
+++ b/t/helper/test-cache-tree.c
@@ -0,0 +1,64 @@
+#include "test-tool.h"
+#include "cache.h"
+#include "tree.h"
+#include "cache-tree.h"
+#include "parse-options.h"
+
+static char const * const test_cache_tree_usage[] = {
+ N_("test-tool cache-tree <options> (control|prime|update)"),
+ NULL
+};
+
+int cmd__cache_tree(int argc, const char **argv)
+{
+ struct object_id oid;
+ struct tree *tree;
+ int empty = 0;
+ int invalidate_qty = 0;
+ int i;
+
+ struct option options[] = {
+ OPT_BOOL(0, "empty", &empty,
+ N_("clear the cache tree before each iteration")),
+ OPT_INTEGER_F(0, "invalidate", &invalidate_qty,
+ N_("number of entries in the cache tree to invalidate (default 0)"),
+ PARSE_OPT_NONEG),
+ OPT_END()
+ };
+
+ setup_git_directory();
+
+ argc = parse_options(argc, argv, NULL, options, test_cache_tree_usage, 0);
+
+ if (read_cache() < 0)
+ die(_("unable to read index file"));
+
+ oidcpy(&oid, &the_index.cache_tree->oid);
+ tree = parse_tree_indirect(&oid);
+ if (!tree)
+ die(_("not a tree object: %s"), oid_to_hex(&oid));
+
+ if (empty) {
+ /* clear the cache tree & allocate a new one */
+ cache_tree_free(&the_index.cache_tree);
+ the_index.cache_tree = cache_tree();
+ } else if (invalidate_qty) {
+ /* invalidate the specified number of unique paths */
+ float f_interval = (float)the_index.cache_nr / invalidate_qty;
+ int interval = f_interval < 1.0 ? 1 : (int)f_interval;
+ for (i = 0; i < invalidate_qty && i * interval < the_index.cache_nr; i++)
+ cache_tree_invalidate_path(&the_index, the_index.cache[i * interval]->name);
+ }
+
+ if (argc != 1)
+ usage_with_options(test_cache_tree_usage, options);
+ else if (!strcmp(argv[0], "prime"))
+ prime_cache_tree(the_repository, &the_index, tree);
+ else if (!strcmp(argv[0], "update"))
+ cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
+ /* use "control" subcommand to specify no-op */
+ else if (!!strcmp(argv[0], "control"))
+ die(_("Unhandled subcommand '%s'"), argv[0]);
+
+ return 0;
+}
diff --git a/t/helper/test-fake-ssh.c b/t/helper/test-fake-ssh.c
index 2e576bcc11..27323cb367 100644
--- a/t/helper/test-fake-ssh.c
+++ b/t/helper/test-fake-ssh.c
@@ -17,6 +17,7 @@ int cmd_main(int argc, const char **argv)
f = fopen(buf.buf, "w");
if (!f)
die("Could not write to %s", buf.buf);
+ strbuf_release(&buf);
for (i = 0; i < argc; i++)
fprintf(f, "%s%s", i > 0 ? " " : "", i > 0 ? argv[i] : "ssh:");
fprintf(f, "\n");
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index 3ecb830f4a..40dd329e02 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -52,6 +52,21 @@ static int no_job(struct child_process *cp,
return 0;
}
+static void duplicate_output(struct strbuf *process_out,
+ struct strbuf *out,
+ void *pp_cb,
+ void *pp_task_cb)
+{
+ struct string_list list = STRING_LIST_INIT_DUP;
+
+ string_list_split(&list, process_out->buf, '\n', -1);
+ for (size_t i = 0; i < list.nr; i++) {
+ if (strlen(list.items[i].string) > 0)
+ fprintf(stderr, "duplicate_output: %s\n", list.items[i].string);
+ }
+ string_list_clear(&list, 0);
+}
+
static int task_finished(int result,
struct strbuf *err,
void *pp_cb,
@@ -439,6 +454,12 @@ int cmd__run_command(int argc, const char **argv)
opts.ungroup = 1;
}
+ if (!strcmp(argv[1], "--duplicate-output")) {
+ argv += 1;
+ argc -= 1;
+ opts.duplicate_output = duplicate_output;
+ }
+
jobs = atoi(argv[2]);
strvec_clear(&proc.args);
strvec_pushv(&proc.args, (const char **)argv + 3);
diff --git a/t/helper/test-sha1.c b/t/helper/test-sha1.c
index d860c387c3..71fe5c6145 100644
--- a/t/helper/test-sha1.c
+++ b/t/helper/test-sha1.c
@@ -5,3 +5,11 @@ int cmd__sha1(int ac, const char **av)
{
return cmd_hash_impl(ac, av, GIT_HASH_SHA1);
}
+
+int cmd__sha1_is_sha1dc(int argc UNUSED, const char **argv UNUSED)
+{
+#ifdef platform_SHA_IS_SHA1DC
+ return 0;
+#endif
+ return 1;
+}
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index b7d117cd55..e060cc6226 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -111,10 +111,94 @@ static int cmd__submodule_resolve_relative_url(int argc, const char **argv)
return 0;
}
+static int cmd__submodule_config_list(int argc, const char **argv)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ const char *const usage[] = {
+ "test-tool submodule config-list <key>",
+ NULL
+ };
+ argc = parse_options(argc, argv, "test-tools", options, usage,
+ PARSE_OPT_KEEP_ARGV0);
+
+ setup_git_directory();
+
+ if (argc == 2)
+ return print_config_from_gitmodules(the_repository, argv[1]);
+ usage_with_options(usage, options);
+}
+
+static int cmd__submodule_config_set(int argc, const char **argv)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ const char *const usage[] = {
+ "test-tool submodule config-set <key> <value>",
+ NULL
+ };
+ argc = parse_options(argc, argv, "test-tools", options, usage,
+ PARSE_OPT_KEEP_ARGV0);
+
+ setup_git_directory();
+
+ /* Equivalent to ACTION_SET in builtin/config.c */
+ if (argc == 3) {
+ if (!is_writing_gitmodules_ok())
+ die("please make sure that the .gitmodules file is in the working tree");
+
+ return config_set_in_gitmodules_file_gently(argv[1], argv[2]);
+ }
+ usage_with_options(usage, options);
+}
+
+static int cmd__submodule_config_unset(int argc, const char **argv)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ const char *const usage[] = {
+ "test-tool submodule config-unset <key>",
+ NULL
+ };
+
+ setup_git_directory();
+
+ if (argc == 2) {
+ if (!is_writing_gitmodules_ok())
+ die("please make sure that the .gitmodules file is in the working tree");
+ return config_set_in_gitmodules_file_gently(argv[1], NULL);
+ }
+ usage_with_options(usage, options);
+}
+
+static int cmd__submodule_config_writeable(int argc, const char **argv)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ const char *const usage[] = {
+ "test-tool submodule config-writeable",
+ NULL
+ };
+ setup_git_directory();
+
+ if (argc == 1)
+ return is_writing_gitmodules_ok() ? 0 : -1;
+
+ usage_with_options(usage, options);
+}
+
static struct test_cmd cmds[] = {
{ "check-name", cmd__submodule_check_name },
{ "is-active", cmd__submodule_is_active },
{ "resolve-relative-url", cmd__submodule_resolve_relative_url},
+ { "config-list", cmd__submodule_config_list },
+ { "config-set", cmd__submodule_config_set },
+ { "config-unset", cmd__submodule_config_unset },
+ { "config-writeable", cmd__submodule_config_writeable },
};
int cmd__submodule(int argc, const char **argv)
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 01cda9358d..7eb1a26a30 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -14,6 +14,7 @@ static struct test_cmd cmds[] = {
{ "bitmap", cmd__bitmap },
{ "bloom", cmd__bloom },
{ "bundle-uri", cmd__bundle_uri },
+ { "cache-tree", cmd__cache_tree },
{ "chmtime", cmd__chmtime },
{ "config", cmd__config },
{ "crontab", cmd__crontab },
@@ -73,6 +74,7 @@ static struct test_cmd cmds[] = {
{ "scrap-cache-tree", cmd__scrap_cache_tree },
{ "serve-v2", cmd__serve_v2 },
{ "sha1", cmd__sha1 },
+ { "sha1-is-sha1dc", cmd__sha1_is_sha1dc },
{ "sha256", cmd__sha256 },
{ "sigchain", cmd__sigchain },
{ "simple-ipc", cmd__simple_ipc },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index ca2948066f..da7cd6351a 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -8,6 +8,7 @@ int cmd__advise_if_enabled(int argc, const char **argv);
int cmd__bitmap(int argc, const char **argv);
int cmd__bloom(int argc, const char **argv);
int cmd__bundle_uri(int argc, const char **argv);
+int cmd__cache_tree(int argc, const char **argv);
int cmd__chmtime(int argc, const char **argv);
int cmd__config(int argc, const char **argv);
int cmd__crontab(int argc, const char **argv);
@@ -66,6 +67,7 @@ int cmd__run_command(int argc, const char **argv);
int cmd__scrap_cache_tree(int argc, const char **argv);
int cmd__serve_v2(int argc, const char **argv);
int cmd__sha1(int argc, const char **argv);
+int cmd__sha1_is_sha1dc(int argc, const char **argv);
int cmd__oid_array(int argc, const char **argv);
int cmd__sha256(int argc, const char **argv);
int cmd__sigchain(int argc, const char **argv);
diff --git a/t/lib-gettext.sh b/t/lib-gettext.sh
index cc6bb2cdea..dcd6e9c3f7 100644
--- a/t/lib-gettext.sh
+++ b/t/lib-gettext.sh
@@ -7,7 +7,7 @@
. ./test-lib.sh
GIT_TEXTDOMAINDIR="$GIT_BUILD_DIR/po/build/locale"
-GIT_PO_PATH="$GIT_BUILD_DIR/po"
+GIT_PO_PATH="$GIT_SOURCE_DIR/po"
export GIT_TEXTDOMAINDIR GIT_PO_PATH
if test -n "$GIT_TEST_INSTALLED"
diff --git a/t/lib-gitweb.sh b/t/lib-gitweb.sh
index 1f32ca66ea..6f68df247a 100644
--- a/t/lib-gitweb.sh
+++ b/t/lib-gitweb.sh
@@ -49,7 +49,7 @@ EOF
error "Cannot find gitweb at $GITWEB_TEST_INSTALLED."
say "# Testing $SCRIPT_NAME"
else # normal case, use source version of gitweb
- SCRIPT_NAME="$GIT_BUILD_DIR/gitweb/gitweb.perl"
+ SCRIPT_NAME="$GIT_SOURCE_DIR/gitweb/gitweb.perl"
fi
export SCRIPT_NAME
}
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index 1f6b9b08d1..ba9fe36772 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -174,6 +174,11 @@ prepare_httpd() {
fi
}
+enable_http2 () {
+ HTTPD_PARA="$HTTPD_PARA -DHTTP2"
+ test_set_prereq HTTP2
+}
+
start_httpd() {
prepare_httpd >&3 2>&4
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 706799391b..0294739a77 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -29,6 +29,11 @@ ErrorLog error.log
LoadModule setenvif_module modules/mod_setenvif.so
</IfModule>
+<IfDefine HTTP2>
+LoadModule http2_module modules/mod_http2.so
+Protocols h2c
+</IfDefine>
+
<IfVersion < 2.4>
LockFile accept.lock
</IfVersion>
@@ -64,12 +69,20 @@ LockFile accept.lock
<IfModule !mod_access_compat.c>
LoadModule access_compat_module modules/mod_access_compat.so
</IfModule>
-<IfModule !mod_mpm_prefork.c>
- LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
-</IfModule>
<IfModule !mod_unixd.c>
LoadModule unixd_module modules/mod_unixd.so
</IfModule>
+
+<IfDefine HTTP2>
+<IfModule !mod_mpm_event.c>
+ LoadModule mpm_event_module modules/mod_mpm_event.so
+</IfModule>
+</IfDefine>
+<IfDefine !HTTP2>
+<IfModule !mod_mpm_prefork.c>
+ LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
+</IfModule>
+</IfDefine>
</IfVersion>
PassEnv GIT_VALGRIND
diff --git a/t/perf/p0006-read-tree-checkout.sh b/t/perf/p0006-read-tree-checkout.sh
index c481c012d2..325566e18e 100755
--- a/t/perf/p0006-read-tree-checkout.sh
+++ b/t/perf/p0006-read-tree-checkout.sh
@@ -49,6 +49,14 @@ test_perf "read-tree br_base br_ballast ($nr_files)" '
git read-tree -n -m br_base br_ballast
'
+test_perf "read-tree br_ballast_plus_1 ($nr_files)" '
+ # Run read-tree 100 times for clearer performance results & comparisons
+ for i in $(test_seq 100)
+ do
+ git read-tree -n -m br_ballast_plus_1 || return 1
+ done
+'
+
test_perf "switch between br_base br_ballast ($nr_files)" '
git checkout -q br_base &&
git checkout -q br_ballast
diff --git a/t/perf/p0090-cache-tree.sh b/t/perf/p0090-cache-tree.sh
new file mode 100755
index 0000000000..a8eabca2c4
--- /dev/null
+++ b/t/perf/p0090-cache-tree.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+test_description="Tests performance of cache tree update operations"
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+test_checkout_worktree
+
+count=100
+
+test_expect_success 'setup cache tree' '
+ git write-tree
+'
+
+test_cache_tree () {
+ test_perf "$1, $3" "
+ for i in \$(test_seq $count)
+ do
+ test-tool cache-tree $4 $2
+ done
+ "
+}
+
+test_cache_tree_update_functions () {
+ test_cache_tree 'no-op' 'control' "$1" "$2"
+ test_cache_tree 'prime_cache_tree' 'prime' "$1" "$2"
+ test_cache_tree 'cache_tree_update' 'update' "$1" "$2"
+}
+
+test_cache_tree_update_functions "clean" ""
+test_cache_tree_update_functions "invalidate 2" "--invalidate 2"
+test_cache_tree_update_functions "invalidate 50" "--invalidate 50"
+test_cache_tree_update_functions "empty" "--empty"
+
+test_done
diff --git a/t/perf/p1401-ref-operations.sh b/t/perf/p1401-ref-operations.sh
new file mode 100755
index 0000000000..0b88a2f531
--- /dev/null
+++ b/t/perf/p1401-ref-operations.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+test_description="Tests performance of ref operations"
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+test_perf 'git pack-refs (v1)' '
+ git commit --allow-empty -m "change one ref" &&
+ git pack-refs --all
+'
+
+test_perf 'git for-each-ref (v1)' '
+ git for-each-ref --format="%(refname)" >/dev/null
+'
+
+test_perf 'git for-each-ref prefix (v1)' '
+ git for-each-ref --format="%(refname)" refs/tags/ >/dev/null
+'
+
+test_expect_success 'configure packed-refs v2' '
+ git config core.repositoryFormatVersion 1 &&
+ git config --add extensions.refFormat files &&
+ git config --add extensions.refFormat packed &&
+ git config --add extensions.refFormat packed-v2 &&
+ git config refs.packedRefsVersion 2 &&
+ git commit --allow-empty -m "change one ref" &&
+ git pack-refs --all &&
+ test_copy_bytes 16 .git/packed-refs | xxd >actual &&
+ grep PREF actual
+'
+
+test_perf 'git pack-refs (v2)' '
+ git commit --allow-empty -m "change one ref" &&
+ git pack-refs --all
+'
+
+test_perf 'git pack-refs (v2;hashing)' '
+ git commit --allow-empty -m "change one ref" &&
+ git -c refs.hashPackedRefs=true pack-refs --all
+'
+
+test_perf 'git for-each-ref (v2)' '
+ git for-each-ref --format="%(refname)" >/dev/null
+'
+
+test_perf 'git for-each-ref prefix (v2)' '
+ git for-each-ref --format="%(refname)" refs/tags/ >/dev/null
+'
+
+test_done
diff --git a/t/perf/p7102-reset.sh b/t/perf/p7102-reset.sh
new file mode 100755
index 0000000000..9b039e8691
--- /dev/null
+++ b/t/perf/p7102-reset.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+test_description='performance of reset'
+. ./perf-lib.sh
+
+test_perf_default_repo
+test_checkout_worktree
+
+test_perf 'reset --hard with change in tree' '
+ base=$(git rev-parse HEAD) &&
+ test_commit --no-tag A &&
+ new=$(git rev-parse HEAD) &&
+
+ for i in $(test_seq 10)
+ do
+ git reset --hard $new &&
+ git reset --hard $base || return $?
+ done
+'
+
+test_done
diff --git a/t/t0013-sha1dc.sh b/t/t0013-sha1dc.sh
index 9ad76080aa..5324047689 100755
--- a/t/t0013-sha1dc.sh
+++ b/t/t0013-sha1dc.sh
@@ -6,9 +6,11 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
TEST_DATA="$TEST_DIRECTORY/t0013"
-if test -z "$DC_SHA1"
+test_lazy_prereq SHA1_IS_SHA1DC 'test-tool sha1-is-sha1dc'
+
+if ! test_have_prereq SHA1_IS_SHA1DC
then
- skip_all='skipping sha1 collision tests, DC_SHA1 not set'
+ skip_all='skipping sha1 collision tests, not using sha1collisiondetection'
test_done
fi
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index abecd75e4e..46abbeed68 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -8,8 +8,8 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
-TEST_ROOT="$PWD"
-PATH=$TEST_ROOT:$PATH
+PATH=$PWD:$PATH
+TEST_ROOT="$(pwd)"
write_script <<\EOF "$TEST_ROOT/rot13.sh"
tr \
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 5cc62306e3..7d7ecfd571 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -709,4 +709,16 @@ test_expect_success 'subcommands are incompatible with KEEP_DASHDASH unless in c
grep ^BUG err
'
+test_expect_success 'negative magnitude' '
+ test_must_fail test-tool parse-options --magnitude -1 >out 2>err &&
+ grep "non-negative integer" err &&
+ test_must_be_empty out
+'
+
+test_expect_success 'magnitude with units but no numbers' '
+ test_must_fail test-tool parse-options --magnitude m >out 2>err &&
+ grep "non-negative integer" err &&
+ test_must_be_empty out
+'
+
test_done
diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh
index 7b5423eebd..879e536638 100755
--- a/t/t0061-run-command.sh
+++ b/t/t0061-run-command.sh
@@ -130,10 +130,20 @@ World
EOF
test_expect_success 'run_command runs in parallel with more jobs available than tasks' '
- test-tool run-command run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>actual &&
+ test_must_be_empty out &&
test_cmp expect actual
'
+test_expect_success 'run_command runs in parallel with more jobs available than tasks --duplicate-output' '
+ test-tool run-command --duplicate-output run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
+ test_must_be_empty out &&
+ test 4 = $(grep -c "duplicate_output: Hello" err) &&
+ test 4 = $(grep -c "duplicate_output: World" err) &&
+ sed "/duplicate_output/d" err > err1 &&
+ test_cmp expect err1
+'
+
test_expect_success 'run_command runs ungrouped in parallel with more jobs available than tasks' '
test-tool run-command --ungroup run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
test_line_count = 8 out &&
@@ -141,10 +151,20 @@ test_expect_success 'run_command runs ungrouped in parallel with more jobs avail
'
test_expect_success 'run_command runs in parallel with as many jobs as tasks' '
- test-tool run-command run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>actual &&
+ test_must_be_empty out &&
test_cmp expect actual
'
+test_expect_success 'run_command runs in parallel with as many jobs as tasks --duplicate-output' '
+ test-tool run-command --duplicate-output run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
+ test_must_be_empty out &&
+ test 4 = $(grep -c "duplicate_output: Hello" err) &&
+ test 4 = $(grep -c "duplicate_output: World" err) &&
+ sed "/duplicate_output/d" err > err1 &&
+ test_cmp expect err1
+'
+
test_expect_success 'run_command runs ungrouped in parallel with as many jobs as tasks' '
test-tool run-command --ungroup run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
test_line_count = 8 out &&
@@ -152,10 +172,20 @@ test_expect_success 'run_command runs ungrouped in parallel with as many jobs as
'
test_expect_success 'run_command runs in parallel with more tasks than jobs available' '
- test-tool run-command run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>actual &&
+ test_must_be_empty out &&
test_cmp expect actual
'
+test_expect_success 'run_command runs in parallel with more tasks than jobs available --duplicate-output' '
+ test-tool run-command --duplicate-output run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
+ test_must_be_empty out &&
+ test 4 = $(grep -c "duplicate_output: Hello" err) &&
+ test 4 = $(grep -c "duplicate_output: World" err) &&
+ sed "/duplicate_output/d" err > err1 &&
+ test_cmp expect err1
+'
+
test_expect_success 'run_command runs ungrouped in parallel with more tasks than jobs available' '
test-tool run-command --ungroup run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
test_line_count = 8 out &&
@@ -172,10 +202,17 @@ asking for a quick stop
EOF
test_expect_success 'run_command is asked to abort gracefully' '
- test-tool run-command run-command-abort 3 false 2>actual &&
+ test-tool run-command run-command-abort 3 false >out 2>actual &&
+ test_must_be_empty out &&
test_cmp expect actual
'
+test_expect_success 'run_command is asked to abort gracefully --duplicate-output' '
+ test-tool run-command --duplicate-output run-command-abort 3 false >out 2>err &&
+ test_must_be_empty out &&
+ test_cmp expect err
+'
+
test_expect_success 'run_command is asked to abort gracefully (ungroup)' '
test-tool run-command --ungroup run-command-abort 3 false >out 2>err &&
test_must_be_empty out &&
@@ -187,10 +224,17 @@ no further jobs available
EOF
test_expect_success 'run_command outputs ' '
- test-tool run-command run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>actual &&
+ test_must_be_empty out &&
test_cmp expect actual
'
+test_expect_success 'run_command outputs --duplicate-output' '
+ test-tool run-command --duplicate-output run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
+ test_must_be_empty out &&
+ test_cmp expect err
+'
+
test_expect_success 'run_command outputs (ungroup) ' '
test-tool run-command --ungroup run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>err &&
test_must_be_empty out &&
diff --git a/t/t0068-for-each-repo.sh b/t/t0068-for-each-repo.sh
index 4675e85251..3648d439a8 100755
--- a/t/t0068-for-each-repo.sh
+++ b/t/t0068-for-each-repo.sh
@@ -2,15 +2,18 @@
test_description='git for-each-repo builtin'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'run based on configured value' '
git init one &&
git init two &&
git init three &&
+ git init ~/four &&
git -C two commit --allow-empty -m "DID NOT RUN" &&
git config run.key "$TRASH_DIRECTORY/one" &&
git config --add run.key "$TRASH_DIRECTORY/three" &&
+ git config --add run.key "~/four" &&
git for-each-repo --config=run.key commit --allow-empty -m "ran" &&
git -C one log -1 --pretty=format:%s >message &&
grep ran message &&
@@ -18,12 +21,16 @@ test_expect_success 'run based on configured value' '
! grep ran message &&
git -C three log -1 --pretty=format:%s >message &&
grep ran message &&
+ git -C ~/four log -1 --pretty=format:%s >message &&
+ grep ran message &&
git for-each-repo --config=run.key -- commit --allow-empty -m "ran again" &&
git -C one log -1 --pretty=format:%s >message &&
grep again message &&
git -C two log -1 --pretty=format:%s >message &&
! grep again message &&
git -C three log -1 --pretty=format:%s >message &&
+ grep again message &&
+ git -C ~/four log -1 --pretty=format:%s >message &&
grep again message
'
diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh
index 8d59905ef0..574de34198 100755
--- a/t/t0070-fundamental.sh
+++ b/t/t0070-fundamental.sh
@@ -6,6 +6,7 @@ test_description='check that the most basic functions work
Verify wrappers and compatibility functions.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'character classes (isspace, isalpha etc.)' '
diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh
index 742f0fa909..595b24c0ad 100755
--- a/t/t1011-read-tree-sparse-checkout.sh
+++ b/t/t1011-read-tree-sparse-checkout.sh
@@ -12,6 +12,7 @@ test_description='sparse checkout tests
'
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-read-tree.sh
diff --git a/t/t1022-read-tree-partial-clone.sh b/t/t1022-read-tree-partial-clone.sh
index a9953b6a71..cca4380e43 100755
--- a/t/t1022-read-tree-partial-clone.sh
+++ b/t/t1022-read-tree-partial-clone.sh
@@ -3,7 +3,7 @@
test_description='git read-tree in partial clones'
TEST_NO_CREATE_REPO=1
-
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'read-tree in partial clone prefetches in one batch' '
@@ -19,7 +19,7 @@ test_expect_success 'read-tree in partial clone prefetches in one batch' '
git -C server config uploadpack.allowfilter 1 &&
git -C server config uploadpack.allowanysha1inwant 1 &&
git clone --bare --filter=blob:none "file://$(pwd)/server" client &&
- GIT_TRACE_PACKET="$(pwd)/trace" git -C client read-tree $TREE &&
+ GIT_TRACE_PACKET="$(pwd)/trace" git -C client read-tree $TREE $TREE &&
# "done" marks the end of negotiation (once per fetch). Expect that
# only one fetch occurs.
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 4f3aa17c99..c71932b024 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -5,6 +5,12 @@ test_description='adding and checking out large blobs'
. ./test-lib.sh
+test_expect_success 'core.bigFileThreshold must be non-negative' '
+ test_must_fail git -c core.bigFileThreshold=-1 rev-parse >out 2>err &&
+ grep "bad numeric config value" err &&
+ test_must_be_empty out
+'
+
test_expect_success setup '
# clone does not allow us to pass core.bigfilethreshold to
# new repos, so set core.bigfilethreshold globally
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index c6661e61af..2575279ab8 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -2228,6 +2228,12 @@ test_expect_success '--type rejects unknown specifiers' '
test_i18ngrep "unrecognized --type argument" error
'
+test_expect_success '--type=int requires at least one digit' '
+ test_must_fail git config --type int --default m some.key >out 2>error &&
+ grep "bad numeric config value" error &&
+ test_must_be_empty out
+'
+
test_expect_success '--replace-all does not invent newlines' '
q_to_tab >.git/config <<-\EOF &&
[abc]key
diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh
index 13c2b43bba..b5606d93b5 100755
--- a/t/t1404-update-ref-errors.sh
+++ b/t/t1404-update-ref-errors.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='Test git update-ref error handling'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Create some references, perhaps run pack-refs --all, then try to
diff --git a/t/t1409-avoid-packing-refs.sh b/t/t1409-avoid-packing-refs.sh
index be12fb6350..74dedd57e9 100755
--- a/t/t1409-avoid-packing-refs.sh
+++ b/t/t1409-avoid-packing-refs.sh
@@ -2,19 +2,36 @@
test_description='avoid rewriting packed-refs unnecessarily'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Add an identifying mark to the packed-refs file header line. This
# shouldn't upset readers, and it should be omitted if the file is
# ever rewritten.
mark_packed_refs () {
- sed -e "s/^\(#.*\)/\1 t1409 /" .git/packed-refs >.git/packed-refs.new &&
- mv .git/packed-refs.new .git/packed-refs
+ if test "$GIT_TEST_PACKED_REFS_VERSION" = "2"
+ then
+ size=$(wc -c < .git/packed-refs) &&
+ pos=$(expr $size - 4) &&
+ printf "FAKE" | dd of=".git/packed-refs" bs=1 seek="$pos" conv=notrunc
+ else
+ sed -e "s/^\(#.*\)/\1 t1409 /" .git/packed-refs >.git/packed-refs.new &&
+ mv .git/packed-refs.new .git/packed-refs
+ fi
}
# Verify that the packed-refs file is still marked.
check_packed_refs_marked () {
- grep -q '^#.* t1409 ' .git/packed-refs
+ if test "$GIT_TEST_PACKED_REFS_VERSION" = "2"
+ then
+ size=$(wc -c < .git/packed-refs) &&
+ pos=$(expr $size - 4) &&
+ tail -c 4 .git/packed-refs >actual &&
+ printf "FAKE" >expect &&
+ test_cmp expect actual
+ else
+ grep -q '^#.* t1409 ' .git/packed-refs
+ fi
}
test_expect_success 'setup' '
diff --git a/t/t1413-reflog-detach.sh b/t/t1413-reflog-detach.sh
index 934688a1ee..d2a4822d46 100755
--- a/t/t1413-reflog-detach.sh
+++ b/t/t1413-reflog-detach.sh
@@ -4,6 +4,7 @@ test_description='Test reflog interaction with detached HEAD'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
reset_state () {
diff --git a/t/t1501-work-tree.sh b/t/t1501-work-tree.sh
index b75558040f..ae6528aece 100755
--- a/t/t1501-work-tree.sh
+++ b/t/t1501-work-tree.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test separate work tree'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t1600-index.sh b/t/t1600-index.sh
index 010989f90e..24ab90ca04 100755
--- a/t/t1600-index.sh
+++ b/t/t1600-index.sh
@@ -103,4 +103,12 @@ test_expect_success 'index version config precedence' '
test_index_version 0 true 2 2
'
+test_expect_success 'index.computeHash config option' '
+ (
+ rm -f .git/index &&
+ git -c index.computeHash=false add a &&
+ git fsck
+ )
+'
+
test_done
diff --git a/t/t1800-hook.sh b/t/t1800-hook.sh
index 43fcb7c0bf..2ef3579fa7 100755
--- a/t/t1800-hook.sh
+++ b/t/t1800-hook.sh
@@ -95,7 +95,7 @@ test_expect_success 'git hook run -- out-of-repo runs excluded' '
test_expect_success 'git -c core.hooksPath=<PATH> hook run' '
mkdir my-hooks &&
write_script my-hooks/test-hook <<-\EOF &&
- echo Hook ran $1 >>actual
+ echo Hook ran $1
EOF
cat >expect <<-\EOF &&
diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh
index 1f6c4ed042..4b6372f4c3 100755
--- a/t/t2012-checkout-last.sh
+++ b/t/t2012-checkout-last.sh
@@ -5,6 +5,7 @@ test_description='checkout can switch to last branch and merge base'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh
index 771c3c3c50..8581ad3437 100755
--- a/t/t2018-checkout-branch.sh
+++ b/t/t2018-checkout-branch.sh
@@ -3,6 +3,7 @@
test_description='checkout'
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Arguments: [!] <branch> <oid> [<checkout options>]
diff --git a/t/t2025-checkout-no-overlay.sh b/t/t2025-checkout-no-overlay.sh
index 8f13341cf8..3832c3de81 100755
--- a/t/t2025-checkout-no-overlay.sh
+++ b/t/t2025-checkout-no-overlay.sh
@@ -2,6 +2,7 @@
test_description='checkout --no-overlay <tree-ish> -- <pathspec>'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index d587e0b20d..93c340f4af 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -310,6 +310,26 @@ test_expect_success '"add" -B/--detach mutually exclusive' '
test_must_fail git worktree add -B poodle --detach bamboo main
'
+test_expect_success '"add" --orphan/-b mutually exclusive' '
+ test_must_fail git worktree add --orphan poodle -b poodle bamboo
+'
+
+test_expect_success '"add" --orphan/-B mutually exclusive' '
+ test_must_fail git worktree add --orphan poodle -B poodle bamboo
+'
+
+test_expect_success '"add" --orphan/--detach mutually exclusive' '
+ test_must_fail git worktree add --orphan poodle --detach bamboo
+'
+
+test_expect_success '"add" --orphan/--no-checkout mutually exclusive' '
+ test_must_fail git worktree add --orphan poodle --no-checkout bamboo
+'
+
+test_expect_success '"add" -B/--detach mutually exclusive' '
+ test_must_fail git worktree add -B poodle --detach bamboo main
+'
+
test_expect_success '"add -B" fails if the branch is checked out' '
git rev-parse newmain >before &&
test_must_fail git worktree add -B newmain bamboo main &&
@@ -330,6 +350,31 @@ test_expect_success 'add --quiet' '
test_must_be_empty actual
'
+test_expect_success '"add --orphan"' '
+ test_when_finished "git worktree remove -f -f orphandir" &&
+ git worktree add --orphan neworphan orphandir &&
+ echo refs/heads/neworphan >expected &&
+ git -C orphandir symbolic-ref HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '"add --orphan" fails if the branch already exists' '
+ test_when_finished "git branch -D existingbranch" &&
+ test_when_finished "git worktree remove -f -f orphandir" &&
+ git worktree add -b existingbranch orphandir main &&
+ test_must_fail git worktree add --orphan existingbranch orphandir2 &&
+ test ! -d orphandir2
+'
+
+test_expect_success '"add --orphan" with empty repository' '
+ test_when_finished "rm -rf empty_repo" &&
+ echo refs/heads/newbranch >expected &&
+ GIT_DIR="empty_repo" git init --bare &&
+ git -C empty_repo worktree add --orphan newbranch worktreedir &&
+ git -C empty_repo/worktreedir symbolic-ref HEAD >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'local clone from linked checkout' '
git clone --local here here-clone &&
( cd here-clone && git fsck )
diff --git a/t/t3009-ls-files-others-nonsubmodule.sh b/t/t3009-ls-files-others-nonsubmodule.sh
index 963f3462b7..14218b3424 100755
--- a/t/t3009-ls-files-others-nonsubmodule.sh
+++ b/t/t3009-ls-files-others-nonsubmodule.sh
@@ -18,6 +18,7 @@ This test runs git ls-files --others with the following working tree:
git repository with a commit and an untracked file
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup: directories' '
diff --git a/t/t3010-ls-files-killed-modified.sh b/t/t3010-ls-files-killed-modified.sh
index 580e158f99..054178703d 100755
--- a/t/t3010-ls-files-killed-modified.sh
+++ b/t/t3010-ls-files-killed-modified.sh
@@ -41,6 +41,8 @@ Also for modification test, the cache and working tree have:
We should report path0, path1, path2/file2, path3/file3, path7 and path8
modified without reporting path9 and path10. submod1 is also modified.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'git update-index --add to add various paths.' '
diff --git a/t/t3050-subprojects-fetch.sh b/t/t3050-subprojects-fetch.sh
index f1f09abdd9..3884694165 100755
--- a/t/t3050-subprojects-fetch.sh
+++ b/t/t3050-subprojects-fetch.sh
@@ -2,6 +2,7 @@
test_description='fetching and pushing project with subproject'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3060-ls-files-with-tree.sh b/t/t3060-ls-files-with-tree.sh
index 52f76f7b57..c4a72ae446 100755
--- a/t/t3060-ls-files-with-tree.sh
+++ b/t/t3060-ls-files-with-tree.sh
@@ -8,6 +8,8 @@ test_description='git ls-files test (--with-tree).
This test runs git ls-files --with-tree and in particular in
a scenario known to trigger a crash with some versions of git.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 7f605f865b..5a169b68d6 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -279,6 +279,42 @@ test_expect_success 'git branch -M and -C fail on detached HEAD' '
test_cmp expect err
'
+test_expect_success 'git branch -d on orphan HEAD (merged)' '
+ test_when_finished git checkout main &&
+ git checkout --orphan orphan &&
+ test_when_finished "rm -rf .git/objects/commit-graph*" &&
+ git commit-graph write --reachable &&
+ git branch --track to-delete main &&
+ git branch -d to-delete
+'
+
+test_expect_success 'git branch -d on orphan HEAD (merged, graph)' '
+ test_when_finished git checkout main &&
+ git checkout --orphan orphan &&
+ git branch --track to-delete main &&
+ git branch -d to-delete
+'
+
+test_expect_success 'git branch -d on orphan HEAD (unmerged)' '
+ test_when_finished git checkout main &&
+ git checkout --orphan orphan &&
+ test_when_finished "git branch -D to-delete" &&
+ git branch to-delete main &&
+ test_must_fail git branch -d to-delete 2>err &&
+ grep "not fully merged" err
+'
+
+test_expect_success 'git branch -d on orphan HEAD (unmerged, graph)' '
+ test_when_finished git checkout main &&
+ git checkout --orphan orphan &&
+ test_when_finished "git branch -D to-delete" &&
+ git branch to-delete main &&
+ test_when_finished "rm -rf .git/objects/commit-graph*" &&
+ git commit-graph write --reachable &&
+ test_must_fail git branch -d to-delete 2>err &&
+ grep "not fully merged" err
+'
+
test_expect_success 'git branch -v -d t should work' '
git branch t &&
git rev-parse --verify refs/heads/t &&
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 577f32dc71..76251dfe05 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -159,7 +159,7 @@ test_expect_success 'delete ref while another dangling packed ref' '
test_expect_success 'pack ref directly below refs/' '
git update-ref refs/top HEAD &&
git pack-refs --all --prune &&
- grep refs/top .git/packed-refs &&
+ git rev-parse refs/top &&
test_path_is_missing .git/refs/top
'
@@ -197,7 +197,7 @@ test_expect_success 'notice d/f conflict with existing ref' '
test_must_fail git branch foo/bar/baz/lots/of/extra/components
'
-test_expect_success 'reject packed-refs with unterminated line' '
+test_expect_success PACKED_REFS_V1 'reject packed-refs with unterminated line' '
cp .git/packed-refs .git/packed-refs.bak &&
test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
printf "%s" "$HEAD refs/zzzzz" >>.git/packed-refs &&
@@ -206,7 +206,7 @@ test_expect_success 'reject packed-refs with unterminated line' '
test_cmp expected_err err
'
-test_expect_success 'reject packed-refs containing junk' '
+test_expect_success PACKED_REFS_V1 'reject packed-refs containing junk' '
cp .git/packed-refs .git/packed-refs.bak &&
test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
printf "%s\n" "bogus content" >>.git/packed-refs &&
@@ -215,7 +215,7 @@ test_expect_success 'reject packed-refs containing junk' '
test_cmp expected_err err
'
-test_expect_success 'reject packed-refs with a short SHA-1' '
+test_expect_success PACKED_REFS_V1 'reject packed-refs with a short SHA-1' '
cp .git/packed-refs .git/packed-refs.bak &&
test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
printf "%.7s %s\n" $HEAD refs/zzzzz >>.git/packed-refs &&
diff --git a/t/t3212-ref-formats.sh b/t/t3212-ref-formats.sh
new file mode 100755
index 0000000000..5583f16db4
--- /dev/null
+++ b/t/t3212-ref-formats.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+test_description='test across ref formats'
+
+GIT_TEST_PACKED_REFS_VERSION=0
+export GIT_TEST_PACKED_REFS_VERSION
+
+. ./test-lib.sh
+
+test_expect_success 'extensions.refFormat requires core.repositoryFormatVersion=1' '
+ test_when_finished rm -rf broken &&
+
+ # Force sha1 to ensure GIT_TEST_DEFAULT_HASH does
+ # not imply a value of core.repositoryFormatVersion.
+ git init --object-format=sha1 broken &&
+ git -C broken config extensions.refFormat files &&
+ test_must_fail git -C broken status 2>err &&
+ grep "repo version is 0, but v1-only extension found" err
+'
+
+test_expect_success 'invalid extensions.refFormat' '
+ test_when_finished rm -rf broken &&
+ git init broken &&
+ git -C broken config core.repositoryFormatVersion 1 &&
+ git -C broken config extensions.refFormat bogus &&
+ test_must_fail git -C broken status 2>err &&
+ grep "invalid value for '\''extensions.refFormat'\'': '\''bogus'\''" err
+'
+
+test_expect_success 'extensions.refFormat=packed only' '
+ git init only-packed &&
+ (
+ cd only-packed &&
+ git config core.repositoryFormatVersion 1 &&
+ git config extensions.refFormat packed &&
+ test_commit A &&
+ test_path_exists .git/packed-refs &&
+ test_path_is_missing .git/refs/tags/A
+ )
+'
+
+test_expect_success 'extensions.refFormat=files only' '
+ test_commit T &&
+ git pack-refs --all &&
+ git init only-loose &&
+ (
+ cd only-loose &&
+ git config core.repositoryFormatVersion 1 &&
+ git config extensions.refFormat files &&
+ test_commit A &&
+ test_commit B &&
+ test_must_fail git pack-refs 2>err &&
+ grep "refusing to create" err &&
+ test_path_is_missing .git/packed-refs &&
+
+ # Refuse to parse a packed-refs file.
+ cp ../.git/packed-refs .git/packed-refs &&
+ test_must_fail git rev-parse refs/tags/T
+ )
+'
+
+test_expect_success 'extensions.refFormat=files,packed-v2' '
+ test_commit Q &&
+ git pack-refs --all &&
+ git init no-packed-v1 &&
+ (
+ cd no-packed-v1 &&
+ git config core.repositoryFormatVersion 1 &&
+ git config extensions.refFormat files &&
+ git config --add extensions.refFormat packed-v2 &&
+ test_commit A &&
+ test_commit B &&
+
+ # Refuse to parse a v1 packed-refs file.
+ cp ../.git/packed-refs .git/packed-refs &&
+ test_must_fail git rev-parse refs/tags/Q &&
+ rm -f .git/packed-refs &&
+
+ git for-each-ref --format="%(refname) %(objectname)" >expect-all &&
+ git for-each-ref --format="%(refname) %(objectname)" \
+ refs/tags/* >expect-tags &&
+
+ # Create a v2 packed-refs file
+ git pack-refs --all &&
+ test_path_exists .git/packed-refs &&
+ for t in A B
+ do
+ test_path_is_missing .git/refs/tags/$t &&
+ git rev-parse refs/tags/$t || return 1
+ done &&
+
+ git for-each-ref --format="%(refname) %(objectname)" >actual-all &&
+ test_cmp expect-all actual-all &&
+ git for-each-ref --format="%(refname) %(objectname)" \
+ refs/tags/* >actual-tags &&
+ test_cmp expect-tags actual-tags
+ )
+'
+
+test_done
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 3288aaec7d..dedad93a2f 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -521,12 +521,25 @@ test_expect_success 'listing non-existing notes fails' '
test_must_be_empty actual
'
+test_expect_success 'append to existing note without a beginning blank line' '
+ test_when_finished git notes remove HEAD &&
+ cat >expect <<-\EOF &&
+ Initial set of notes
+ Appended notes
+ EOF
+ git notes add -m "Initial set of notes" &&
+ git notes append --no-blank-line -m "Appended notes" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'append to existing note with "git notes append"' '
cat >expect <<-EOF &&
Initial set of notes
More notes appended with git notes append
EOF
+
git notes add -m "Initial set of notes" &&
git notes append -m "More notes appended with git notes append" &&
git notes show >actual &&
@@ -552,6 +565,7 @@ test_expect_success 'appending empty string does not change existing note' '
'
test_expect_success 'git notes append == add when there is no existing note' '
+ test_when_finished git notes remove HEAD &&
git notes remove HEAD &&
test_must_fail git notes list HEAD &&
git notes append -m "Initial set of notes${LF}${LF}More notes appended with git notes append" &&
@@ -560,9 +574,9 @@ test_expect_success 'git notes append == add when there is no existing note' '
'
test_expect_success 'appending empty string to non-existing note does not create note' '
- git notes remove HEAD &&
test_must_fail git notes list HEAD &&
- git notes append -m "" &&
+ git notes append -m "" >output 2>&1 &&
+ grep "Both original and appended notes are empty" output &&
test_must_fail git notes list HEAD
'
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 4f5abb5ad2..462cefd25d 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1964,6 +1964,113 @@ test_expect_success 'respect user edits to update-ref steps' '
test_cmp_rev HEAD refs/heads/no-conflict-branch
'
+test_expect_success '--update-refs: all update-ref lines removed' '
+ git checkout -b test-refs-not-removed no-conflict-branch &&
+ git branch -f base HEAD~4 &&
+ git branch -f first HEAD~3 &&
+ git branch -f second HEAD~3 &&
+ git branch -f third HEAD~1 &&
+ git branch -f tip &&
+
+ test_commit test-refs-not-removed &&
+ git commit --amend --fixup first &&
+
+ git rev-parse first second third tip no-conflict-branch >expect-oids &&
+
+ (
+ set_cat_todo_editor &&
+ test_must_fail git rebase -i --update-refs base >todo.raw &&
+ sed -e "/^update-ref/d" <todo.raw >todo
+ ) &&
+ (
+ set_replace_editor todo &&
+ git rebase -i --update-refs base
+ ) &&
+
+ # Ensure refs are not deleted and their OIDs have not changed
+ git rev-parse first second third tip no-conflict-branch >actual-oids &&
+ test_cmp expect-oids actual-oids
+'
+
+test_expect_success '--update-refs: all update-ref lines removed, then some re-added' '
+ git checkout -b test-refs-not-removed2 no-conflict-branch &&
+ git branch -f base HEAD~4 &&
+ git branch -f first HEAD~3 &&
+ git branch -f second HEAD~3 &&
+ git branch -f third HEAD~1 &&
+ git branch -f tip &&
+
+ test_commit test-refs-not-removed2 &&
+ git commit --amend --fixup first &&
+
+ git rev-parse first second third >expect-oids &&
+
+ (
+ set_cat_todo_editor &&
+ test_must_fail git rebase -i \
+ --autosquash --update-refs \
+ base >todo.raw &&
+ sed -e "/^update-ref/d" <todo.raw >todo
+ ) &&
+
+ # Add a break to the end of the todo so we can edit later
+ echo "break" >>todo &&
+
+ (
+ set_replace_editor todo &&
+ git rebase -i --autosquash --update-refs base &&
+ echo "update-ref refs/heads/tip" >todo &&
+ git rebase --edit-todo &&
+ git rebase --continue
+ ) &&
+
+ # Ensure first/second/third are unchanged, but tip is updated
+ git rev-parse first second third >actual-oids &&
+ test_cmp expect-oids actual-oids &&
+ test_cmp_rev HEAD tip
+'
+
+test_expect_success '--update-refs: --edit-todo with no update-ref lines' '
+ git checkout -b test-refs-not-removed3 no-conflict-branch &&
+ git branch -f base HEAD~4 &&
+ git branch -f first HEAD~3 &&
+ git branch -f second HEAD~3 &&
+ git branch -f third HEAD~1 &&
+ git branch -f tip &&
+
+ test_commit test-refs-not-removed3 &&
+ git commit --amend --fixup first &&
+
+ git rev-parse first second third tip no-conflict-branch >expect-oids &&
+
+ (
+ set_cat_todo_editor &&
+ test_must_fail git rebase -i \
+ --autosquash --update-refs \
+ base >todo.raw &&
+ sed -e "/^update-ref/d" <todo.raw >todo
+ ) &&
+
+ # Add a break to the beginning of the todo so we can resume with no
+ # update-ref lines
+ echo "break" >todo.new &&
+ cat todo >>todo.new &&
+
+ (
+ set_replace_editor todo.new &&
+ git rebase -i --autosquash --update-refs base &&
+
+ # Make no changes when editing so update-refs is still empty
+ cat todo >todo.new &&
+ git rebase --edit-todo &&
+ git rebase --continue
+ ) &&
+
+ # Ensure refs are not deleted and their OIDs have not changed
+ git rev-parse first second third tip no-conflict-branch >actual-oids &&
+ test_cmp expect-oids actual-oids
+'
+
test_expect_success '--update-refs: check failed ref update' '
git checkout -B update-refs-error no-conflict-branch &&
git branch -f base HEAD~4 &&
diff --git a/t/t3409-rebase-environ.sh b/t/t3409-rebase-environ.sh
index 83ffb39d9f..acaf5558db 100755
--- a/t/t3409-rebase-environ.sh
+++ b/t/t3409-rebase-environ.sh
@@ -2,6 +2,7 @@
test_description='git rebase interactive environment'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t3413-rebase-hook.sh b/t/t3413-rebase-hook.sh
index 9fab0d779b..e8456831e8 100755
--- a/t/t3413-rebase-hook.sh
+++ b/t/t3413-rebase-hook.sh
@@ -5,6 +5,7 @@ test_description='git rebase with its hook(s)'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3428-rebase-signoff.sh b/t/t3428-rebase-signoff.sh
index f6993b7e14..e1b1e94764 100755
--- a/t/t3428-rebase-signoff.sh
+++ b/t/t3428-rebase-signoff.sh
@@ -5,6 +5,7 @@ test_description='git rebase --signoff
This test runs git rebase --signoff and make sure that it works.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# A simple file to commit
diff --git a/t/t3429-rebase-edit-todo.sh b/t/t3429-rebase-edit-todo.sh
index abd66f3602..8e0d03969a 100755
--- a/t/t3429-rebase-edit-todo.sh
+++ b/t/t3429-rebase-edit-todo.sh
@@ -2,6 +2,7 @@
test_description='rebase should reread the todo file if an exec modifies it'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh
index f351701fec..fa2a06c19f 100755
--- a/t/t3430-rebase-merges.sh
+++ b/t/t3430-rebase-merges.sh
@@ -138,6 +138,23 @@ test_expect_success '`reset` refuses to overwrite untracked files' '
git rebase --abort
'
+test_expect_success '`reset` rejects trees' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ test_must_fail env GIT_SEQUENCE_EDITOR="echo reset A^{tree} >" \
+ git rebase -i B C >out 2>err &&
+ grep "object .* is a tree" err &&
+ test_must_be_empty out
+'
+
+test_expect_success '`reset` only looks for labels under refs/rewritten/' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git branch refs/rewritten/my-label A &&
+ test_must_fail env GIT_SEQUENCE_EDITOR="echo reset my-label >" \
+ git rebase -i B C >out 2>err &&
+ grep "could not resolve ${SQ}my-label${SQ}" err &&
+ test_must_be_empty out
+'
+
test_expect_success 'failed `merge -C` writes patch (may be rescheduled, too)' '
test_when_finished "test_might_fail git rebase --abort" &&
git checkout -b conflicting-merge A &&
diff --git a/t/t3433-rebase-across-mode-change.sh b/t/t3433-rebase-across-mode-change.sh
index 05df964670..c8172b0852 100755
--- a/t/t3433-rebase-across-mode-change.sh
+++ b/t/t3433-rebase-across-mode-change.sh
@@ -2,6 +2,7 @@
test_description='git rebase across mode change'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index f3e20dd5bb..b298f220e0 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -1638,7 +1638,7 @@ test_expect_success 'no effect on diff from --color-moved with --word-diff' '
test_cmp expect actual
'
-test_expect_success !SANITIZE_LEAK 'no effect on show from --color-moved with --word-diff' '
+test_expect_success 'no effect on show from --color-moved with --word-diff' '
git show --color-moved --word-diff >actual &&
git show --word-diff >expect &&
test_cmp expect actual
@@ -2024,7 +2024,7 @@ test_expect_success '--color-moved rewinds for MIN_ALNUM_COUNT' '
test_cmp expected actual
'
-test_expect_success !SANITIZE_LEAK 'move detection with submodules' '
+test_expect_success 'move detection with submodules' '
test_create_repo bananas &&
echo ripe >bananas/recipe &&
git -C bananas add recipe &&
diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh
index 40164ae07d..e08ee315a7 100755
--- a/t/t4027-diff-submodule.sh
+++ b/t/t4027-diff-submodule.sh
@@ -34,6 +34,25 @@ test_expect_success setup '
subtip=$3 subprev=$2
'
+test_expect_success 'diff in superproject with submodules respects parallel settings' '
+ test_when_finished "rm -f trace.out" &&
+ (
+ GIT_TRACE=$(pwd)/trace.out git diff &&
+ grep "1 tasks" trace.out &&
+ >trace.out &&
+
+ git config submodule.diffJobs 8 &&
+ GIT_TRACE=$(pwd)/trace.out git diff &&
+ grep "8 tasks" trace.out &&
+ >trace.out &&
+
+ GIT_TRACE=$(pwd)/trace.out git -c submodule.diffJobs=0 diff &&
+ grep "preparing to run up to [0-9]* tasks" trace.out &&
+ ! grep "up to 0 tasks" trace.out &&
+ >trace.out
+ )
+'
+
test_expect_success 'git diff --raw HEAD' '
hexsz=$(test_oid hexsz) &&
git diff --raw --abbrev=$hexsz HEAD >actual &&
diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh
index fab351b48a..198dfc9190 100755
--- a/t/t4045-diff-relative.sh
+++ b/t/t4045-diff-relative.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='diff --relative tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh
index b5c281edaa..3ee27e277d 100755
--- a/t/t4052-stat-output.sh
+++ b/t/t4052-stat-output.sh
@@ -8,6 +8,7 @@ test_description='test --stat output of various commands'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
index 3feadf0e35..4e9fa0403d 100755
--- a/t/t4053-diff-no-index.sh
+++ b/t/t4053-diff-no-index.sh
@@ -2,6 +2,7 @@
test_description='diff --no-index'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh
index 28f42a4046..f60f5cbd65 100755
--- a/t/t4067-diff-partial-clone.sh
+++ b/t/t4067-diff-partial-clone.sh
@@ -2,6 +2,7 @@
test_description='behavior of diff when reading objects in a partial clone'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'git show batches blobs' '
diff --git a/t/t4111-apply-subdir.sh b/t/t4111-apply-subdir.sh
index 1618a6dbc7..e9a87d761d 100755
--- a/t/t4111-apply-subdir.sh
+++ b/t/t4111-apply-subdir.sh
@@ -2,6 +2,7 @@
test_description='patching from inconvenient places'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4135-apply-weird-filenames.sh b/t/t4135-apply-weird-filenames.sh
index 6bc3fb97a7..d3502c6fdd 100755
--- a/t/t4135-apply-weird-filenames.sh
+++ b/t/t4135-apply-weird-filenames.sh
@@ -2,6 +2,7 @@
test_description='git apply with weird postimage filenames'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4213-log-tabexpand.sh b/t/t4213-log-tabexpand.sh
index 53a4af3244..590fce95e9 100755
--- a/t/t4213-log-tabexpand.sh
+++ b/t/t4213-log-tabexpand.sh
@@ -2,6 +2,7 @@
test_description='log/show --expand-tabs'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
HT=" "
diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh
index cac85591b5..a8983a0edc 100755
--- a/t/t4301-merge-tree-write-tree.sh
+++ b/t/t4301-merge-tree-write-tree.sh
@@ -860,4 +860,66 @@ test_expect_success '--stdin with both a successful and a conflicted merge' '
test_cmp expect actual
'
+
+test_expect_success '--merge-base is incompatible with --stdin' '
+ test_must_fail git merge-tree --merge-base=side1 --stdin 2>expect &&
+
+ grep "^fatal: --merge-base is incompatible with --stdin" expect
+'
+
+# specify merge-base as parent of branch2
+# git merge-tree --write-tree --merge-base=c2 c1 c3
+# Commit c1: add file1
+# Commit c2: add file2 after c1
+# Commit c3: add file3 after c2
+# Expected: add file3, and file2 does NOT appear
+
+test_expect_success 'specify merge-base as parent of branch2' '
+ # Setup
+ test_when_finished "rm -rf base-b2-p" &&
+ git init base-b2-p &&
+ test_commit -C base-b2-p c1 file1 &&
+ test_commit -C base-b2-p c2 file2 &&
+ test_commit -C base-b2-p c3 file3 &&
+
+ # Testing
+ TREE_OID=$(git -C base-b2-p merge-tree --write-tree --merge-base=c2 c1 c3) &&
+
+ q_to_tab <<-EOF >expect &&
+ 100644 blob $(git -C base-b2-p rev-parse c1:file1)Qfile1
+ 100644 blob $(git -C base-b2-p rev-parse c3:file3)Qfile3
+ EOF
+
+ git -C base-b2-p ls-tree $TREE_OID >actual &&
+ test_cmp expect actual
+'
+
+# Since the earlier tests have verified that individual merge-tree calls
+# are doing the right thing, this test case is only used to verify that
+# we can also trigger merges via --stdin, and that when we do we get
+# the same answer as running a bunch of separate merges.
+
+test_expect_success 'check the input format when --stdin is passed' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo c1 &&
+ test_commit -C repo c2 &&
+ test_commit -C repo c3 &&
+ printf "c1 c3\nc2 -- c1 c3\nc2 c3" | git -C repo merge-tree --stdin >actual &&
+
+ printf "1\0" >expect &&
+ git -C repo merge-tree --write-tree -z c1 c3 >>expect &&
+ printf "\0" >>expect &&
+
+ printf "1\0" >>expect &&
+ git -C repo merge-tree --write-tree -z --merge-base=c2 c1 c3 >>expect &&
+ printf "\0" >>expect &&
+
+ printf "1\0" >>expect &&
+ git -C repo merge-tree --write-tree -z c2 c3 >>expect &&
+ printf "\0" >>expect &&
+
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index 6d693eef82..7d8dee41b0 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -428,8 +428,9 @@ test_bitmap_cases () {
test_line_count = 2 packs &&
test_line_count = 2 bitmaps &&
- git rev-list --use-bitmap-index HEAD 2>err &&
- grep "ignoring extra bitmap file" err
+ GIT_TRACE2_EVENT=$(pwd)/trace2.txt git rev-list --use-bitmap-index HEAD &&
+ grep "opened bitmap" trace2.txt &&
+ grep "ignoring extra bitmap" trace2.txt
)
'
}
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index bb633c9b09..bd8983bb56 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -178,6 +178,25 @@ test_expect_success 'verify blob:limit=1001' '
test_cmp expected observed
'
+test_expect_success 'verify blob:limit=1001+object:type=blob' '
+ git -C r2 ls-files -s large.1000 |
+ test_parse_ls_files_stage_oids |
+ sort >expected &&
+
+ git -C r2 pack-objects --revs --stdout --filter=blob:limit=1001 \
+ --filter=object:type=blob >filter.pack <<-EOF &&
+ HEAD
+ EOF
+ git -C r2 index-pack ../filter.pack &&
+
+ git -C r2 verify-pack -v ../filter.pack >verify_result &&
+ grep blob verify_result |
+ parse_verify_pack_blob_oid |
+ sort >observed &&
+
+ test_cmp expected observed
+'
+
test_expect_success 'verify blob:limit=10001' '
git -C r2 ls-files -s large.1000 large.10000 |
test_parse_ls_files_stage_oids |
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index b160f8b7fb..0c4aadebae 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -122,7 +122,7 @@ test_expect_success 'quickfetch should not copy from alternate' '
'
-test_expect_success 'quickfetch should handle ~1000 refs (on Windows)' '
+test_expect_success PACKED_REFS_V1 'quickfetch should handle ~1000 refs (on Windows)' '
git gc &&
head=$(git rev-parse HEAD) &&
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index 75da8acf8f..b9546ef8e5 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -178,6 +178,7 @@ test_expect_success "submodule.recurse option triggers recursive fetch" '
'
test_expect_success "fetch --recurse-submodules -j2 has the same output behaviour" '
+ test_when_finished "rm -f trace.out" &&
add_submodule_commits &&
(
cd downstream &&
@@ -705,15 +706,22 @@ test_expect_success "'fetch.recurseSubmodules=on-demand' works also without .git
test_expect_success 'fetching submodules respects parallel settings' '
git config fetch.recurseSubmodules true &&
+ test_when_finished "rm -f downstream/trace.out" &&
(
cd downstream &&
GIT_TRACE=$(pwd)/trace.out git fetch &&
grep "1 tasks" trace.out &&
+ >trace.out &&
+
GIT_TRACE=$(pwd)/trace.out git fetch --jobs 7 &&
grep "7 tasks" trace.out &&
+ >trace.out &&
+
git config submodule.fetchJobs 8 &&
GIT_TRACE=$(pwd)/trace.out git fetch &&
grep "8 tasks" trace.out &&
+ >trace.out &&
+
GIT_TRACE=$(pwd)/trace.out git fetch --jobs 9 &&
grep "9 tasks" trace.out &&
>trace.out &&
diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh
index 3f58b515ce..302e4cbdba 100755
--- a/t/t5531-deep-submodule-push.sh
+++ b/t/t5531-deep-submodule-push.sh
@@ -512,6 +512,56 @@ test_expect_success 'push only unpushed submodules recursively' '
test_cmp expected_pub actual_pub
'
+setup_subsub () {
+ git init upstream &&
+ git init upstream/sub &&
+ git init upstream/sub/deepsub &&
+ test_commit -C upstream/sub/deepsub innermost &&
+ git -C upstream/sub submodule add ./deepsub deepsub &&
+ git -C upstream/sub commit -m middle &&
+ git -C upstream submodule add ./sub sub &&
+ git -C upstream commit -m outermost &&
+
+ git -c protocol.file.allow=always clone --recurse-submodules upstream downstream &&
+ git -C downstream/sub/deepsub checkout -b downstream-branch &&
+ git -C downstream/sub checkout -b downstream-branch &&
+ git -C downstream checkout -b downstream-branch
+}
+
+new_downstream_commits () {
+ test_commit -C downstream/sub/deepsub new-innermost &&
+ git -C downstream/sub add deepsub &&
+ git -C downstream/sub commit -m new-middle &&
+ git -C downstream add sub &&
+ git -C downstream commit -m new-outermost
+}
+
+test_expect_success 'push with push.recurseSubmodules=only on superproject' '
+ test_when_finished rm -rf upstream downstream &&
+ setup_subsub &&
+ new_downstream_commits &&
+ git -C downstream config push.recurseSubmodules only &&
+ git -C downstream push origin downstream-branch &&
+
+ test_must_fail git -C upstream rev-parse refs/heads/downstream-branch &&
+ git -C upstream/sub rev-parse refs/heads/downstream-branch &&
+ test_must_fail git -C upstream/sub/deepsub rev-parse refs/heads/downstream-branch
+'
+
+test_expect_success 'push with push.recurseSubmodules=only on superproject and top-level submodule' '
+ test_when_finished rm -rf upstream downstream &&
+ setup_subsub &&
+ new_downstream_commits &&
+ git -C downstream config push.recurseSubmodules only &&
+ git -C downstream/sub config push.recurseSubmodules only &&
+ git -C downstream push origin downstream-branch 2> err &&
+
+ test_must_fail git -C upstream rev-parse refs/heads/downstream-branch &&
+ git -C upstream/sub rev-parse refs/heads/downstream-branch &&
+ git -C upstream/sub/deepsub rev-parse refs/heads/downstream-branch &&
+ grep "recursing into submodule with push.recurseSubmodules=only; using on-demand instead" err
+'
+
test_expect_success 'push propagating the remotes name to a submodule' '
git -C work remote add origin ../pub.git &&
git -C work remote add pub ../pub.git &&
diff --git a/t/t5539-fetch-http-shallow.sh b/t/t5539-fetch-http-shallow.sh
index 3ea75d34ca..5e3b430436 100755
--- a/t/t5539-fetch-http-shallow.sh
+++ b/t/t5539-fetch-http-shallow.sh
@@ -5,6 +5,13 @@ test_description='fetch/clone from a shallow clone over http'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+# If GIT_TEST_PACKED_REFS_VERSION=2, then the packed-refs file will
+# be written in v2 format without extensions.refFormat=packed-v2. This
+# causes issues for the HTTP server which does not carry over the
+# environment variable to the server process.
+GIT_TEST_PACKED_REFS_VERSION=0
+export GIT_TEST_PACKED_REFS_VERSION
+
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
index fbad2d5ff5..495437dd3c 100755
--- a/t/t5541-http-push-smart.sh
+++ b/t/t5541-http-push-smart.sh
@@ -7,6 +7,13 @@ test_description='test smart pushing over http via http-backend'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+# If GIT_TEST_PACKED_REFS_VERSION=2, then the packed-refs file will
+# be written in v2 format without extensions.refFormat=packed-v2. This
+# causes issues for the HTTP server which does not carry over the
+# environment variable to the server process.
+GIT_TEST_PACKED_REFS_VERSION=0
+export GIT_TEST_PACKED_REFS_VERSION
+
. ./test-lib.sh
ROOT_PATH="$PWD"
diff --git a/t/t5542-push-http-shallow.sh b/t/t5542-push-http-shallow.sh
index c2cc83182f..c47b18b9fa 100755
--- a/t/t5542-push-http-shallow.sh
+++ b/t/t5542-push-http-shallow.sh
@@ -5,6 +5,13 @@ test_description='push from/to a shallow clone over http'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+# If GIT_TEST_PACKED_REFS_VERSION=2, then the packed-refs file will
+# be written in v2 format without extensions.refFormat=packed-v2. This
+# causes issues for the HTTP server which does not carry over the
+# environment variable to the server process.
+GIT_TEST_PACKED_REFS_VERSION=0
+export GIT_TEST_PACKED_REFS_VERSION
+
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
diff --git a/t/t5544-pack-objects-hook.sh b/t/t5544-pack-objects-hook.sh
index 54f54f8d2e..1a9e14bbcc 100755
--- a/t/t5544-pack-objects-hook.sh
+++ b/t/t5544-pack-objects-hook.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test custom script in place of pack-objects'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create some history to fetch' '
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 64c6c9f59e..faf6bd44d8 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -1,13 +1,26 @@
#!/bin/sh
-test_description='test smart fetching over http via http-backend'
+: ${HTTP_PROTO:=HTTP}
+test_description="test smart fetching over http via http-backend ($HTTP_PROTO)"
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+# If GIT_TEST_PACKED_REFS_VERSION=2, then the packed-refs file will
+# be written in v2 format without extensions.refFormat=packed-v2. This
+# causes issues for the HTTP server which does not carry over the
+# environment variable to the server process.
+GIT_TEST_PACKED_REFS_VERSION=0
+export GIT_TEST_PACKED_REFS_VERSION
+
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh
+test "$HTTP_PROTO" = "HTTP/2" && enable_http2
start_httpd
+test_expect_success HTTP2 'enable client-side http/2' '
+ git config --global http.version HTTP/2
+'
+
test_expect_success 'setup repository' '
git config push.default matching &&
echo content >file &&
@@ -347,7 +360,10 @@ test_expect_success CMDLINE_LIMIT \
test_expect_success 'large fetch-pack requests can be sent using chunked encoding' '
GIT_TRACE_CURL=true git -c http.postbuffer=65536 \
clone --bare "$HTTPD_URL/smart/repo.git" split.git 2>err &&
- grep "^=> Send header: Transfer-Encoding: chunked" err
+ {
+ test_have_prereq HTTP2 ||
+ grep "^=> Send header: Transfer-Encoding: chunked" err
+ }
'
test_expect_success 'test allowreachablesha1inwant' '
diff --git a/t/t5554-noop-fetch-negotiator.sh b/t/t5554-noop-fetch-negotiator.sh
index 2ac7b5859e..06991e8e8a 100755
--- a/t/t5554-noop-fetch-negotiator.sh
+++ b/t/t5554-noop-fetch-negotiator.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test noop fetch negotiator'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'noop negotiator does not emit any "have"' '
diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh
index 9155f31fa2..3e35322155 100755
--- a/t/t5558-clone-bundle-uri.sh
+++ b/t/t5558-clone-bundle-uri.sh
@@ -2,6 +2,13 @@
test_description='test fetching bundles with --bundle-uri'
+# If GIT_TEST_PACKED_REFS_VERSION=2, then the packed-refs file will
+# be written in v2 format without extensions.refFormat=packed-v2. This
+# causes issues for the HTTP server which does not carry over the
+# environment variable to the server process.
+GIT_TEST_PACKED_REFS_VERSION=0
+export GIT_TEST_PACKED_REFS_VERSION
+
. ./test-lib.sh
test_expect_success 'fail to clone from non-existent file' '
diff --git a/t/t5559-http-fetch-smart-http2.sh b/t/t5559-http-fetch-smart-http2.sh
new file mode 100755
index 0000000000..9eece71c2c
--- /dev/null
+++ b/t/t5559-http-fetch-smart-http2.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+HTTP_PROTO=HTTP/2
+. ./t5551-http-fetch-smart.sh
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index b2524a24c2..23c8999bc5 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -310,6 +310,28 @@ test_expect_success 'clone checking out a tag' '
test_cmp fetch.expected fetch.actual
'
+test_expect_success '--detach detaches and does not create branch' '
+ test_when_finished "rm -fr dst" &&
+ git clone --detach src dst &&
+ (
+ cd dst &&
+ test_must_fail git rev-parse main &&
+ test_must_fail git symbolic-ref HEAD &&
+ test_cmp_rev HEAD refs/remotes/origin/HEAD
+ )
+'
+
+test_expect_success '--detach with --bare detaches but creates branch' '
+ test_when_finished "rm -fr dst" &&
+ git clone --bare --detach src dst &&
+ (
+ cd dst &&
+ git rev-parse main &&
+ test_must_fail git symbolic-ref HEAD &&
+ test_cmp_rev HEAD refs/heads/main
+ )
+'
+
test_expect_success 'set up ssh wrapper' '
cp "$GIT_BUILD_DIR/t/helper/test-fake-ssh$X" \
"$TRASH_DIRECTORY/ssh$X" &&
diff --git a/t/t5610-clone-detached.sh b/t/t5610-clone-detached.sh
index a7ec21eda5..022ed3d87c 100755
--- a/t/t5610-clone-detached.sh
+++ b/t/t5610-clone-detached.sh
@@ -4,6 +4,7 @@ test_description='test cloning a repository with detached HEAD'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
head_is_detached() {
diff --git a/t/t5611-clone-config.sh b/t/t5611-clone-config.sh
index 4b3877216e..727caff443 100755
--- a/t/t5611-clone-config.sh
+++ b/t/t5611-clone-config.sh
@@ -4,6 +4,7 @@ test_description='tests for git clone -c key=value'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'clone -c sets config in cloned repo' '
diff --git a/t/t5614-clone-submodules-shallow.sh b/t/t5614-clone-submodules-shallow.sh
index 0c85ef834a..c2a2bb453e 100755
--- a/t/t5614-clone-submodules-shallow.sh
+++ b/t/t5614-clone-submodules-shallow.sh
@@ -2,6 +2,7 @@
test_description='Test shallow cloning of repos with submodules'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
pwd=$(pwd)
diff --git a/t/t5617-clone-submodules-remote.sh b/t/t5617-clone-submodules.sh
index 6884338249..5767c4d318 100755
--- a/t/t5617-clone-submodules-remote.sh
+++ b/t/t5617-clone-submodules.sh
@@ -1,10 +1,11 @@
#!/bin/sh
-test_description='Test cloning repos with submodules using remote-tracking branches'
+test_description='Test cloning repos with submodules'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
pwd=$(pwd)
@@ -13,10 +14,17 @@ test_expect_success 'setup' '
git config --global protocol.file.allow always &&
git checkout -b main &&
test_commit commit1 &&
+ mkdir subsub &&
+ (
+ cd subsub &&
+ git init &&
+ test_commit subsubcommit1
+ ) &&
mkdir sub &&
(
cd sub &&
git init &&
+ git submodule add "file://$pwd/subsub" subsub &&
test_commit subcommit1 &&
git tag sub_when_added_to_super &&
git branch other
@@ -107,4 +115,35 @@ test_expect_success '--no-also-filter-submodules overrides clone.filterSubmodule
test_cmp_config -C super_clone3/sub false --default false remote.origin.promisor
'
+test_expect_success 'submodule.propagateBranches checks out branches at correct commits' '
+ test_when_finished "git checkout main" &&
+
+ git checkout -b checked-out &&
+ git -C sub checkout -b not-in-clone &&
+ git -C subsub checkout -b not-in-clone &&
+ git clone --recurse-submodules \
+ --branch checked-out \
+ -c submodule.propagateBranches=true \
+ "file://$pwd/." super_clone4 &&
+
+ # Assert that each repo is pointing to "checked-out"
+ for REPO in "super_clone4" "super_clone4/sub" "super_clone4/sub/subsub"
+ do
+ HEAD_BRANCH=$(git -C $REPO symbolic-ref HEAD) &&
+ test $HEAD_BRANCH = "refs/heads/checked-out" || return 1
+ done &&
+
+ # Assert that the submodule branches are pointing to the right revs
+ EXPECT_SUB_OID="$(git -C super_clone4 rev-parse :sub)" &&
+ ACTUAL_SUB_OID="$(git -C super_clone4/sub rev-parse refs/heads/checked-out)" &&
+ test $EXPECT_SUB_OID = $ACTUAL_SUB_OID &&
+ EXPECT_SUBSUB_OID="$(git -C super_clone4/sub rev-parse :subsub)" &&
+ ACTUAL_SUBSUB_OID="$(git -C super_clone4/sub/subsub rev-parse refs/heads/checked-out)" &&
+ test $EXPECT_SUBSUB_OID = $ACTUAL_SUBSUB_OID &&
+
+ # Assert that the submodules do not have branches from their upstream
+ test_must_fail git -C super_clone4/sub rev-parse not-in-clone &&
+ test_must_fail git -C super_clone4/sub/subsub rev-parse not-in-clone
+'
+
test_done
diff --git a/t/t5618-alternate-refs.sh b/t/t5618-alternate-refs.sh
index 3353216f09..f905db0a3f 100755
--- a/t/t5618-alternate-refs.sh
+++ b/t/t5618-alternate-refs.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test handling of --alternate-refs traversal'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Avoid test_commit because we want a specific and known set of refs:
diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh
index e1abc5c2b3..aabf590dda 100755
--- a/t/t6018-rev-list-glob.sh
+++ b/t/t6018-rev-list-glob.sh
@@ -187,6 +187,46 @@ test_expect_success 'rev-parse --exclude=ref with --remotes=glob' '
compare rev-parse "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two"
'
+for section in receive uploadpack
+do
+ test_expect_success "rev-parse --exclude-hidden=$section with --all" '
+ compare "-c transfer.hideRefs=refs/remotes/ rev-parse" "--branches --tags" "--exclude-hidden=$section --all"
+ '
+
+ test_expect_success "rev-parse --exclude-hidden=$section with --all" '
+ compare "-c transfer.hideRefs=refs/heads/subspace/ rev-parse" "--exclude=refs/heads/subspace/* --all" "--exclude-hidden=$section --all"
+ '
+
+ test_expect_success "rev-parse --exclude-hidden=$section with --glob" '
+ compare "-c transfer.hideRefs=refs/heads/subspace/ rev-parse" "--exclude=refs/heads/subspace/* --glob=refs/heads/*" "--exclude-hidden=$section --glob=refs/heads/*"
+ '
+
+ test_expect_success "rev-parse --exclude-hidden=$section can be passed once per pseudo-ref" '
+ compare "-c transfer.hideRefs=refs/remotes/ rev-parse" "--branches --tags --branches --tags" "--exclude-hidden=$section --all --exclude-hidden=$section --all"
+ '
+
+ test_expect_success "rev-parse --exclude-hidden=$section can only be passed once per pseudo-ref" '
+ echo "fatal: --exclude-hidden= passed more than once" >expected &&
+ test_must_fail git rev-parse --exclude-hidden=$section --exclude-hidden=$section 2>err &&
+ test_cmp expected err
+ '
+
+ for pseudoopt in branches tags remotes
+ do
+ test_expect_success "rev-parse --exclude-hidden=$section fails with --$pseudoopt" '
+ echo "error: --exclude-hidden cannot be used together with --$pseudoopt" >expected &&
+ test_must_fail git rev-parse --exclude-hidden=$section --$pseudoopt 2>err &&
+ test_cmp expected err
+ '
+
+ test_expect_success "rev-parse --exclude-hidden=$section fails with --$pseudoopt=pattern" '
+ echo "error: --exclude-hidden cannot be used together with --$pseudoopt" >expected &&
+ test_must_fail git rev-parse --exclude-hidden=$section --$pseudoopt=pattern 2>err &&
+ test_cmp expected err
+ '
+ done
+done
+
test_expect_success 'rev-list --exclude=glob with --branches=glob' '
compare rev-list "--exclude=subspace-* --branches=sub*" "subspace/one subspace/two"
'
diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
new file mode 100755
index 0000000000..32b2b09413
--- /dev/null
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+
+test_description='git rev-list --exclude-hidden test'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit_bulk --id=commit --ref=refs/heads/branch 1 &&
+ COMMIT=$(git rev-parse refs/heads/branch) &&
+ test_commit_bulk --id=tag --ref=refs/tags/lightweight 1 &&
+ TAG=$(git rev-parse refs/tags/lightweight) &&
+ test_commit_bulk --id=hidden --ref=refs/hidden/commit 1 &&
+ HIDDEN=$(git rev-parse refs/hidden/commit) &&
+ test_commit_bulk --id=namespace --ref=refs/namespaces/namespace/refs/namespaced/commit 1 &&
+ NAMESPACE=$(git rev-parse refs/namespaces/namespace/refs/namespaced/commit)
+'
+
+test_expect_success 'invalid section' '
+ echo "fatal: unsupported section for hidden refs: unsupported" >expected &&
+ test_must_fail git rev-list --exclude-hidden=unsupported 2>err &&
+ test_cmp expected err
+'
+
+for section in receive uploadpack
+do
+ test_expect_success "$section: passed multiple times" '
+ echo "fatal: --exclude-hidden= passed more than once" >expected &&
+ test_must_fail git rev-list --exclude-hidden=$section --exclude-hidden=$section 2>err &&
+ test_cmp expected err
+ '
+
+ test_expect_success "$section: without hiddenRefs" '
+ git rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $HIDDEN
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: hidden via transfer.hideRefs" '
+ git -c transfer.hideRefs=refs/hidden/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: hidden via $section.hideRefs" '
+ git -c $section.hideRefs=refs/hidden/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: respects both transfer.hideRefs and $section.hideRefs" '
+ git -c transfer.hideRefs=refs/tags/ -c $section.hideRefs=refs/hidden/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: negation without hidden refs marks everything as uninteresting" '
+ git rev-list --all --exclude-hidden=$section --not --all >out &&
+ test_must_be_empty out
+ '
+
+ test_expect_success "$section: negation with hidden refs marks them as interesting" '
+ git -c transfer.hideRefs=refs/hidden/ rev-list --all --exclude-hidden=$section --not --all >out &&
+ cat >expected <<-EOF &&
+ $HIDDEN
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: hidden refs and excludes work together" '
+ git -c transfer.hideRefs=refs/hidden/ rev-list --exclude=refs/tags/* --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: excluded hidden refs get reset" '
+ git -c transfer.hideRefs=refs/ rev-list --exclude-hidden=$section --all --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $HIDDEN
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: excluded hidden refs can be used with multiple pseudo-refs" '
+ git -c transfer.hideRefs=refs/ rev-list --exclude-hidden=$section --all --exclude-hidden=$section --all >out &&
+ test_must_be_empty out
+ '
+
+ test_expect_success "$section: works with --glob" '
+ git -c transfer.hideRefs=refs/hidden/ rev-list --exclude-hidden=$section --glob=refs/h* >out &&
+ cat >expected <<-EOF &&
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: operates on stripped refs by default" '
+ GIT_NAMESPACE=namespace git -c transfer.hideRefs=refs/namespaced/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $HIDDEN
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: does not hide namespace by default" '
+ GIT_NAMESPACE=namespace git -c transfer.hideRefs=refs/namespaces/namespace/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $HIDDEN
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: can operate on unstripped refs" '
+ GIT_NAMESPACE=namespace git -c transfer.hideRefs=^refs/namespaces/namespace/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $HIDDEN
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ for pseudoopt in remotes branches tags
+ do
+ test_expect_success "$section: fails with --$pseudoopt" '
+ test_must_fail git rev-list --exclude-hidden=$section --$pseudoopt 2>err &&
+ test_i18ngrep "error: --exclude-hidden cannot be used together with --$pseudoopt" err
+ '
+
+ test_expect_success "$section: fails with --$pseudoopt=pattern" '
+ test_must_fail git rev-list --exclude-hidden=$section --$pseudoopt=pattern 2>err &&
+ test_i18ngrep "error: --exclude-hidden cannot be used together with --$pseudoopt" err
+ '
+ done
+done
+
+test_done
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 83931d482f..98a72ff78a 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -34,6 +34,36 @@ HASH2=
HASH3=
HASH4=
+test_bisect_usage () {
+ local code="$1" &&
+ shift &&
+ cat >expect &&
+ test_expect_code $code "$@" >out 2>actual &&
+ test_must_be_empty out &&
+ test_cmp expect actual
+}
+
+test_expect_success 'bisect usage' "
+ test_bisect_usage 1 git bisect reset extra1 extra2 <<-\EOF &&
+ error: 'git bisect reset' requires either no argument or a commit
+ EOF
+ test_bisect_usage 1 git bisect terms extra1 extra2 <<-\EOF &&
+ error: 'git bisect terms' requires 0 or 1 argument
+ EOF
+ test_bisect_usage 1 git bisect next extra1 <<-\EOF &&
+ error: 'git bisect next' requires 0 arguments
+ EOF
+ test_bisect_usage 1 git bisect log extra1 <<-\EOF &&
+ error: We are not bisecting.
+ EOF
+ test_bisect_usage 1 git bisect replay <<-\EOF &&
+ error: no logfile given
+ EOF
+ test_bisect_usage 1 git bisect run <<-\EOF
+ error: 'git bisect run' failed: no command provided.
+ EOF
+"
+
test_expect_success 'set up basic repo with 1 file (hello) and 4 commits' '
add_line_into_file "1: Hello World" hello &&
HASH1=$(git rev-parse --verify HEAD) &&
@@ -252,6 +282,124 @@ test_expect_success 'bisect skip: with commit both bad and skipped' '
grep $HASH4 my_bisect_log.txt
'
+test_bisect_run_args () {
+ test_when_finished "rm -f run.sh actual" &&
+ >actual &&
+ cat >expect.args &&
+ cat <&6 >expect.out &&
+ cat <&7 >expect.err &&
+ write_script run.sh <<-\EOF &&
+ while test $# != 0
+ do
+ echo "<$1>" &&
+ shift
+ done >actual.args
+ EOF
+
+ test_when_finished "git bisect reset" &&
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ git bisect run ./run.sh $@ >actual.out.raw 2>actual.err &&
+ # Prune just the log output
+ sed -n \
+ -e '/^Author:/d' \
+ -e '/^Date:/d' \
+ -e '/^$/d' \
+ -e '/^commit /d' \
+ -e '/^ /d' \
+ -e 'p' \
+ <actual.out.raw >actual.out &&
+ test_cmp expect.out actual.out &&
+ test_cmp expect.err actual.err &&
+ test_cmp expect.args actual.args
+}
+
+test_expect_success 'git bisect run: args, stdout and stderr with no arguments' "
+ test_bisect_run_args <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
+ EOF_ARGS
+ running './run.sh'
+ $HASH4 is the first bad commit
+ bisect found first bad commit
+ EOF_OUT
+ EOF_ERR
+"
+
+test_expect_success 'git bisect run: args, stdout and stderr: "--" argument' "
+ test_bisect_run_args -- <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
+ <-->
+ EOF_ARGS
+ running './run.sh' '--'
+ $HASH4 is the first bad commit
+ bisect found first bad commit
+ EOF_OUT
+ EOF_ERR
+"
+
+test_expect_success 'git bisect run: args, stdout and stderr: "--log foo --no-log bar" arguments' "
+ test_bisect_run_args --log foo --no-log bar <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
+ <--log>
+ <foo>
+ <--no-log>
+ <bar>
+ EOF_ARGS
+ running './run.sh' '--log' 'foo' '--no-log' 'bar'
+ $HASH4 is the first bad commit
+ bisect found first bad commit
+ EOF_OUT
+ EOF_ERR
+"
+
+test_expect_success 'git bisect run: args, stdout and stderr: "--bisect-start" argument' "
+ test_bisect_run_args --bisect-start <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
+ <--bisect-start>
+ EOF_ARGS
+ running './run.sh' '--bisect-start'
+ $HASH4 is the first bad commit
+ bisect found first bad commit
+ EOF_OUT
+ EOF_ERR
+"
+
+test_expect_success 'git bisect run: negative exit code' "
+ write_script fail.sh <<-'EOF' &&
+ exit 255
+ EOF
+ cat <<-'EOF' >expect &&
+ bisect run failed: exit code -1 from './fail.sh' is < 0 or >= 128
+ EOF
+ test_when_finished 'git bisect reset' &&
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ ! git bisect run ./fail.sh 2>err &&
+ sed -En 's/.*(bisect.*code) (-?[0-9]+) (from.*)/\1 -1 \3/p' err >actual &&
+ test_cmp expect actual
+"
+
+test_expect_success 'git bisect run: unable to verify on good' "
+ write_script fail.sh <<-'EOF' &&
+ head=\$(git rev-parse --verify HEAD)
+ good=\$(git rev-parse --verify $HASH1)
+ if test "\$head" = "\$good"
+ then
+ exit 255
+ else
+ exit 127
+ fi
+ EOF
+ cat <<-'EOF' >expect &&
+ unable to verify './fail.sh' on good revision
+ EOF
+ test_when_finished 'git bisect reset' &&
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ ! git bisect run ./fail.sh 2>err &&
+ sed -n 's/.*\(unable to verify.*\)/\1/p' err >actual &&
+ test_cmp expect actual
+"
+
# We want to automatically find the commit that
# added "Another" into hello.
test_expect_success '"git bisect run" simple case' '
@@ -266,6 +414,16 @@ test_expect_success '"git bisect run" simple case' '
git bisect reset
'
+# We want to make sure no arguments has been eaten
+test_expect_success '"git bisect run" simple case' '
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ git bisect run printf "%s %s\n" reset --bisect-skip >my_bisect_log.txt &&
+ grep -e "reset --bisect-skip" my_bisect_log.txt &&
+ git bisect reset
+'
+
# We want to automatically find the commit that
# added "Ciao" into hello.
test_expect_success '"git bisect run" with more complex "git bisect start"' '
diff --git a/t/t6060-merge-index.sh b/t/t6060-merge-index.sh
index ed449abe55..1a8b64cce1 100755
--- a/t/t6060-merge-index.sh
+++ b/t/t6060-merge-index.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='basic git merge-index / git-merge-one-file tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup diverging branches' '
diff --git a/t/t6102-rev-list-unexpected-objects.sh b/t/t6102-rev-list-unexpected-objects.sh
index 4a9a4436e2..9350b5fd2c 100755
--- a/t/t6102-rev-list-unexpected-objects.sh
+++ b/t/t6102-rev-list-unexpected-objects.sh
@@ -121,8 +121,8 @@ test_expect_success 'setup unexpected non-blob tag' '
tag=$(git hash-object -w --literally -t tag broken-tag)
'
-test_expect_success 'TODO (should fail!): traverse unexpected non-blob tag (lone)' '
- git rev-list --objects $tag
+test_expect_success 'traverse unexpected non-blob tag (lone)' '
+ test_must_fail git rev-list --objects $tag
'
test_expect_success 'traverse unexpected non-blob tag (seen)' '
diff --git a/t/t6301-for-each-ref-errors.sh b/t/t6301-for-each-ref-errors.sh
index 40edf9dab5..bfda1f46ad 100755
--- a/t/t6301-for-each-ref-errors.sh
+++ b/t/t6301-for-each-ref-errors.sh
@@ -2,6 +2,7 @@
test_description='for-each-ref errors for broken refs'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
ZEROS=$ZERO_OID
diff --git a/t/t6401-merge-criss-cross.sh b/t/t6401-merge-criss-cross.sh
index 9d5e992878..1962310408 100755
--- a/t/t6401-merge-criss-cross.sh
+++ b/t/t6401-merge-criss-cross.sh
@@ -8,6 +8,8 @@
test_description='Test criss-cross merge'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'prepare repository' '
diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh
index 8650a88c40..5e4e4dd6d9 100755
--- a/t/t6406-merge-attr.sh
+++ b/t/t6406-merge-attr.sh
@@ -8,6 +8,7 @@ test_description='per path merge controlled by merge attribute'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t6407-merge-binary.sh b/t/t6407-merge-binary.sh
index e8a28717ce..0753fc95f4 100755
--- a/t/t6407-merge-binary.sh
+++ b/t/t6407-merge-binary.sh
@@ -5,6 +5,7 @@ test_description='ask merge-recursive to merge binary files'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t6415-merge-dir-to-symlink.sh b/t/t6415-merge-dir-to-symlink.sh
index 2655e295f5..ae00492c76 100755
--- a/t/t6415-merge-dir-to-symlink.sh
+++ b/t/t6415-merge-dir-to-symlink.sh
@@ -4,6 +4,7 @@ test_description='merging when a directory was replaced with a symlink'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create a commit where dir a/b changed to symlink' '
diff --git a/t/t6435-merge-sparse.sh b/t/t6435-merge-sparse.sh
index fde4aa3cd1..78628fb248 100755
--- a/t/t6435-merge-sparse.sh
+++ b/t/t6435-merge-sparse.sh
@@ -3,6 +3,7 @@
test_description='merge with sparse files'
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# test_file $filename $content
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 8c37bceb33..d72cef8826 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -60,8 +60,8 @@ test_expect_success 'checking the commit' '
test_expect_success 'mv --dry-run does not move file' '
git mv -n path0/COPYING MOVED &&
- test -f path0/COPYING &&
- test ! -f MOVED
+ test_path_is_file path0/COPYING &&
+ test_path_is_missing MOVED
'
test_expect_success 'checking -k on non-existing file' '
@@ -71,25 +71,25 @@ test_expect_success 'checking -k on non-existing file' '
test_expect_success 'checking -k on untracked file' '
>untracked1 &&
git mv -k untracked1 path0 &&
- test -f untracked1 &&
- test ! -f path0/untracked1
+ test_path_is_file untracked1 &&
+ test_path_is_missing path0/untracked1
'
test_expect_success 'checking -k on multiple untracked files' '
>untracked2 &&
git mv -k untracked1 untracked2 path0 &&
- test -f untracked1 &&
- test -f untracked2 &&
- test ! -f path0/untracked1 &&
- test ! -f path0/untracked2
+ test_path_is_file untracked1 &&
+ test_path_is_file untracked2 &&
+ test_path_is_missing path0/untracked1 &&
+ test_path_is_missing path0/untracked2
'
test_expect_success 'checking -f on untracked file with existing target' '
>path0/untracked1 &&
test_must_fail git mv -f untracked1 path0 &&
- test ! -f .git/index.lock &&
- test -f untracked1 &&
- test -f path0/untracked1
+ test_path_is_missing .git/index.lock &&
+ test_path_is_file untracked1 &&
+ test_path_is_file path0/untracked1
'
# clean up the mess in case bad things happen
@@ -215,8 +215,8 @@ test_expect_success 'absolute pathname' '
git add sub/file &&
git mv sub "$(pwd)/in" &&
- ! test -d sub &&
- test -d in &&
+ test_path_is_missing sub &&
+ test_path_is_dir in &&
git ls-files --error-unmatch in/file
)
'
@@ -234,8 +234,8 @@ test_expect_success 'absolute pathname outside should fail' '
git add sub/file &&
test_must_fail git mv sub "$out/out" &&
- test -d sub &&
- ! test -d ../in &&
+ test_path_is_dir sub &&
+ test_path_is_missing ../in &&
git ls-files --error-unmatch sub/file
)
'
@@ -295,8 +295,8 @@ test_expect_success 'git mv should overwrite symlink to a file' '
git add moved &&
test_must_fail git mv moved symlink &&
git mv -f moved symlink &&
- ! test -e moved &&
- test -f symlink &&
+ test_path_is_missing moved &&
+ test_path_is_file symlink &&
test "$(cat symlink)" = 1 &&
git update-index --refresh &&
git diff-files --quiet
@@ -312,13 +312,13 @@ test_expect_success 'git mv should overwrite file with a symlink' '
git add moved &&
test_must_fail git mv symlink moved &&
git mv -f symlink moved &&
- ! test -e symlink &&
+ test_path_is_missing symlink &&
git update-index --refresh &&
git diff-files --quiet
'
test_expect_success SYMLINKS 'check moved symlink' '
- test -h moved
+ test_path_is_symlink moved
'
rm -f moved symlink
@@ -352,7 +352,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and no .gitm
) &&
mkdir mod &&
git mv sub mod/sub &&
- ! test -e sub &&
+ test_path_is_missing sub &&
test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
git -C mod/sub status &&
git update-index --refresh &&
@@ -372,7 +372,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and .gitmodu
) &&
mkdir mod &&
git mv sub mod/sub &&
- ! test -e sub &&
+ test_path_is_missing sub &&
test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
git -C mod/sub status &&
echo mod/sub >expected &&
@@ -389,7 +389,7 @@ test_expect_success 'git mv moves a submodule with gitfile' '
entry="$(git ls-files --stage sub | cut -f 1)" &&
mkdir mod &&
git -C mod mv ../sub/ . &&
- ! test -e sub &&
+ test_path_is_missing sub &&
test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
git -C mod/sub status &&
echo mod/sub >expected &&
@@ -408,7 +408,7 @@ test_expect_success 'mv does not complain when no .gitmodules file is found' '
mkdir mod &&
git mv sub mod/sub 2>actual.err &&
test_must_be_empty actual.err &&
- ! test -e sub &&
+ test_path_is_missing sub &&
test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
git -C mod/sub status &&
git update-index --refresh &&
@@ -423,13 +423,13 @@ test_expect_success 'mv will error out on a modified .gitmodules file unless sta
entry="$(git ls-files --stage sub | cut -f 1)" &&
mkdir mod &&
test_must_fail git mv sub mod/sub 2>actual.err &&
- test -s actual.err &&
- test -e sub &&
+ test_file_not_empty actual.err &&
+ test_path_exists sub &&
git diff-files --quiet -- sub &&
git add .gitmodules &&
git mv sub mod/sub 2>actual.err &&
test_must_be_empty actual.err &&
- ! test -e sub &&
+ test_path_is_missing sub &&
test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
git -C mod/sub status &&
git update-index --refresh &&
@@ -447,7 +447,7 @@ test_expect_success 'mv issues a warning when section is not found in .gitmodule
mkdir mod &&
git mv sub mod/sub 2>actual.err &&
test_cmp expect.err actual.err &&
- ! test -e sub &&
+ test_path_is_missing sub &&
test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
git -C mod/sub status &&
git update-index --refresh &&
@@ -460,7 +460,7 @@ test_expect_success 'mv --dry-run does not touch the submodule or .gitmodules' '
git submodule update &&
mkdir mod &&
git mv -n sub mod/sub 2>actual.err &&
- test -f sub/.git &&
+ test_path_is_file sub/.git &&
git diff-index --exit-code HEAD &&
git update-index --refresh &&
git diff-files --quiet -- sub .gitmodules
@@ -474,10 +474,10 @@ test_expect_success 'checking out a commit before submodule moved needs manual u
git status -s sub2 >actual &&
echo "?? sub2/" >expected &&
test_cmp expected actual &&
- ! test -f sub/.git &&
- test -f sub2/.git &&
+ test_path_is_missing sub/.git &&
+ test_path_is_file sub2/.git &&
git submodule update &&
- test -f sub/.git &&
+ test_path_is_file sub/.git &&
rm -rf sub2 &&
git diff-index --exit-code HEAD &&
git update-index --refresh &&
diff --git a/t/t7065-wtstatus-slow.sh b/t/t7065-wtstatus-slow.sh
new file mode 100755
index 0000000000..8d08a962f8
--- /dev/null
+++ b/t/t7065-wtstatus-slow.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+test_description='test status when slow untracked files'
+
+. ./test-lib.sh
+
+GIT_TEST_UF_DELAY_WARNING=1
+export GIT_TEST_UF_DELAY_WARNING
+
+test_expect_success setup '
+ git checkout -b test &&
+ cat >.gitignore <<-\EOF &&
+ /actual
+ /expected
+ /out
+ EOF
+ git add .gitignore &&
+ git commit -m "Add .gitignore"
+'
+
+test_expect_success 'when core.untrackedCache and fsmonitor are unset' '
+ test_might_fail git config --unset-all core.untrackedCache &&
+ test_might_fail git config --unset-all core.fsmonitor &&
+ git status >out &&
+ sed "s/[0-9]\.[0-9][0-9]/X/g" out >actual &&
+ cat >expected <<-\EOF &&
+ On branch test
+
+ It took X seconds to enumerate untracked files.
+ See '"'"'git help status'"'"' for information on how to improve this.
+
+ nothing to commit, working tree clean
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'when core.untrackedCache true, but not fsmonitor' '
+ test_config core.untrackedCache true &&
+ test_might_fail git config --unset-all core.fsmonitor &&
+ git status >out &&
+ sed "s/[0-9]\.[0-9][0-9]/X/g" out >actual &&
+ cat >expected <<-\EOF &&
+ On branch test
+
+ It took X seconds to enumerate untracked files.
+ See '"'"'git help status'"'"' for information on how to improve this.
+
+ nothing to commit, working tree clean
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'when core.untrackedCache true, and fsmonitor' '
+ test_config core.untrackedCache true &&
+ test_config core.fsmonitor true &&
+ git status >out &&
+ sed "s/[0-9]\.[0-9][0-9]/X/g" out >actual &&
+ cat >expected <<-\EOF &&
+ On branch test
+
+ It took X seconds to enumerate untracked files,
+ but the results were cached, and subsequent runs may be faster.
+ See '"'"'git help status'"'"' for information on how to improve this.
+
+ nothing to commit, working tree clean
+ EOF
+ test_cmp expected actual
+'
+
+test_done
diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh
index a60153f9f3..18bbd9975e 100755
--- a/t/t7103-reset-bare.sh
+++ b/t/t7103-reset-bare.sh
@@ -63,7 +63,7 @@ test_expect_success '"mixed" reset is not allowed in bare' '
test_must_fail git reset --mixed HEAD^
'
-test_expect_success !SANITIZE_LEAK '"soft" reset is allowed in bare' '
+test_expect_success '"soft" reset is allowed in bare' '
git reset --soft HEAD^ &&
git show --pretty=format:%s >out &&
echo one >expect &&
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index a989aafaf5..eae6a46ef3 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -579,6 +579,16 @@ test_expect_success 'status should be "modified" after submodule commit' '
grep "^+$rev2" list
'
+test_expect_success '"submodule --cached" command forms should be identical' '
+ git submodule status --cached >expect &&
+
+ git submodule --cached >actual &&
+ test_cmp expect actual &&
+
+ git submodule --cached status >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'the --cached sha1 should be rev1' '
git submodule --cached status >list &&
grep "^+$rev1" list
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index f094e3d7f3..b749d35f78 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -1179,4 +1179,160 @@ test_expect_success 'submodule update --recursive skip submodules with strategy=
test_cmp expect.err actual.err
'
+test_expect_success 'setup superproject with submodule.propagateBranches' '
+ git init sub1 &&
+ test_commit -C sub1 "sub1" &&
+ git init branch-super &&
+ git -C branch-super submodule add ../sub1 sub1 &&
+ git -C branch-super commit -m "super" &&
+
+ # Clone into a clean repo that we can cp around
+ git clone --recurse-submodules \
+ -c submodule.propagateBranches=true \
+ branch-super branch-super-clean &&
+ git -C branch-super-clean config submodule.propagateBranches true &&
+
+ # sub2 will not be in the clone. We will fetch the containing
+ # superproject commit and clone sub2 with "git submodule update".
+ git init sub2 &&
+ test_commit -C sub2 "sub2" &&
+ git -C branch-super submodule add ../sub2 sub2 &&
+ git -C branch-super commit -m "add sub2"
+'
+
+test_clean_submodule ()
+{
+ local negate super_dir sub_dir expect_oid actual_oid &&
+ if test "$1" = "!"
+ then
+ negate=t
+ shift
+ fi
+ super_dir="$1" &&
+ sub_dir="$2" &&
+ expect_oid="$(git -C "$super_dir" rev-parse ":$sub_dir")" &&
+ actual_oid="$(git -C "$super_dir/$sub_dir" rev-parse HEAD)" &&
+ if test -n "$negate"
+ then
+ ! test "$expect_oid" = "$actual_oid"
+ else
+ test "$expect_oid" = "$actual_oid"
+ fi
+}
+
+# Test the behavior of a newly cloned submodule
+test_expect_success 'branches - newly-cloned submodule, detached HEAD' '
+ test_when_finished "rm -fr branch-super-cloned" &&
+ cp -r branch-super-clean branch-super-cloned &&
+
+ git -C branch-super-cloned fetch origin main &&
+ git -C branch-super-cloned checkout FETCH_HEAD &&
+ git -C branch-super-cloned/sub1 checkout --detach &&
+ git -C branch-super-cloned submodule update &&
+
+ # sub1 and sub2 should be in detached HEAD
+ git -C branch-super-cloned/sub1 rev-parse --verify HEAD &&
+ test_must_fail git -C branch-super-cloned/sub1 symbolic-ref HEAD &&
+ test_clean_submodule branch-super-cloned sub1 &&
+ git -C branch-super-cloned/sub2 rev-parse --verify HEAD &&
+ test_must_fail git -C branch-super-cloned/sub2 symbolic-ref HEAD &&
+ test_clean_submodule branch-super-cloned sub2
+'
+
+test_expect_success 'branches - newly-cloned submodule, branch checked out' '
+ test_when_finished "rm -fr branch-super-cloned" &&
+ cp -r branch-super-clean branch-super-cloned &&
+
+ git -C branch-super-cloned fetch origin main &&
+ git -C branch-super-cloned checkout FETCH_HEAD &&
+ git -C branch-super-cloned branch new-branch &&
+ git -C branch-super-cloned checkout new-branch &&
+ git -C branch-super-cloned/sub1 branch new-branch &&
+ git -C branch-super-cloned submodule update &&
+
+ # Ignore sub1, we will test it later.
+ # sub2 should check out the branch
+ HEAD_BRANCH2=$(git -C branch-super-cloned/sub2 symbolic-ref HEAD) &&
+ test $HEAD_BRANCH2 = "refs/heads/new-branch" &&
+ test_clean_submodule branch-super-cloned sub2
+'
+
+# Test the behavior of an already-cloned submodule.
+# NEEDSWORK When updating with branches, we always use the branch instead of the
+# gitlink's OID. This results in some imperfect behavior:
+#
+# - If the gitlink's OID disagrees with the branch OID, updating with branches
+# may result in a dirty worktree
+# - If the branch does not exist, the update fails.
+#
+# We will reevaluate when "git checkout --recurse-submodules" supports branches
+# For now, just test for this imperfect behavior.
+test_expect_success 'branches - correct branch checked out, OIDs agree' '
+ test_when_finished "rm -fr branch-super-cloned" &&
+ cp -r branch-super-clean branch-super-cloned &&
+
+ git -C branch-super-cloned branch --recurse-submodules new-branch &&
+ git -C branch-super-cloned checkout new-branch &&
+ git -C branch-super-cloned/sub1 checkout new-branch &&
+ git -C branch-super-cloned submodule update &&
+
+ HEAD_BRANCH1=$(git -C branch-super-cloned/sub1 symbolic-ref HEAD) &&
+ test $HEAD_BRANCH1 = "refs/heads/new-branch" &&
+ test_clean_submodule branch-super-cloned sub1
+'
+
+test_expect_success 'branches - correct branch checked out, OIDs disagree' '
+ test_when_finished "rm -fr branch-super-cloned" &&
+ cp -r branch-super-clean branch-super-cloned &&
+
+ git -C branch-super-cloned branch --recurse-submodules new-branch &&
+ git -C branch-super-cloned checkout new-branch &&
+ git -C branch-super-cloned/sub1 checkout new-branch &&
+ test_commit -C branch-super-cloned/sub1 new-commit &&
+ git -C branch-super-cloned submodule update &&
+
+ HEAD_BRANCH1=$(git -C branch-super-cloned/sub1 symbolic-ref HEAD) &&
+ test $HEAD_BRANCH1 = "refs/heads/new-branch" &&
+ test_clean_submodule ! branch-super-cloned sub1
+'
+
+test_expect_success 'branches - other branch checked out, correct branch exists, OIDs agree' '
+ test_when_finished "rm -fr branch-super-cloned" &&
+ cp -r branch-super-clean branch-super-cloned &&
+
+ git -C branch-super-cloned branch --recurse-submodules new-branch &&
+ git -C branch-super-cloned checkout new-branch &&
+ git -C branch-super-cloned/sub1 checkout main &&
+ git -C branch-super-cloned submodule update &&
+
+ HEAD_BRANCH1=$(git -C branch-super-cloned/sub1 symbolic-ref HEAD) &&
+ test $HEAD_BRANCH1 = "refs/heads/new-branch" &&
+ test_clean_submodule branch-super-cloned sub1
+'
+
+test_expect_success 'branches - other branch checked out, correct branch exists, OIDs disagree' '
+ test_when_finished "rm -fr branch-super-cloned" &&
+ cp -r branch-super-clean branch-super-cloned &&
+
+ git -C branch-super-cloned branch --recurse-submodules new-branch &&
+ git -C branch-super-cloned checkout new-branch &&
+ git -C branch-super-cloned/sub1 checkout new-branch &&
+ test_commit -C branch-super-cloned/sub1 new-commit &&
+ git -C branch-super-cloned/sub1 checkout main &&
+ git -C branch-super-cloned submodule update &&
+
+ HEAD_BRANCH1=$(git -C branch-super-cloned/sub1 symbolic-ref HEAD) &&
+ test $HEAD_BRANCH1 = "refs/heads/new-branch" &&
+ test_clean_submodule ! branch-super-cloned sub1
+'
+
+test_expect_success 'branches - other branch checked out, correct branch does not exist' '
+ test_when_finished "rm -fr branch-super-cloned" &&
+ cp -r branch-super-clean branch-super-cloned &&
+
+ git -C branch-super-cloned branch new-branch &&
+ git -C branch-super-cloned checkout new-branch &&
+ test_must_fail git -C branch-super-cloned submodule update
+'
+
test_done
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index 59bd150166..8d7b234beb 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -154,6 +154,11 @@ test_expect_success 'use "submodule foreach" to checkout 2nd level submodule' '
)
'
+test_expect_success 'usage: foreach -- --not-an-option' '
+ test_expect_code 1 git submodule foreach -- --not-an-option &&
+ test_expect_code 1 git -C clone2 submodule foreach -- --not-an-option
+'
+
test_expect_success 'use "foreach --recursive" to checkout all submodules' '
(
cd clone2 &&
diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh
index c583c4e373..c0167944ab 100755
--- a/t/t7411-submodule-config.sh
+++ b/t/t7411-submodule-config.sh
@@ -137,44 +137,44 @@ test_expect_success 'error in history in fetchrecursesubmodule lets continue' '
)
'
-test_expect_success 'reading submodules config from the working tree with "submodule--helper config"' '
+test_expect_success 'reading submodules config from the working tree' '
(cd super &&
echo "../submodule" >expect &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
)
'
-test_expect_success 'unsetting submodules config from the working tree with "submodule--helper config --unset"' '
+test_expect_success 'unsetting submodules config from the working tree' '
(cd super &&
- git submodule--helper config --unset submodule.submodule.url &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-unset submodule.submodule.url &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_must_be_empty actual
)
'
-test_expect_success 'writing submodules config with "submodule--helper config"' '
+test_expect_success 'writing submodules config' '
(cd super &&
echo "new_url" >expect &&
- git submodule--helper config submodule.submodule.url "new_url" &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-set submodule.submodule.url "new_url" &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
)
'
-test_expect_success 'overwriting unstaged submodules config with "submodule--helper config"' '
+test_expect_success 'overwriting unstaged submodules config' '
test_when_finished "git -C super checkout .gitmodules" &&
(cd super &&
echo "newer_url" >expect &&
- git submodule--helper config submodule.submodule.url "newer_url" &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-set submodule.submodule.url "newer_url" &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
)
'
test_expect_success 'writeable .gitmodules when it is in the working tree' '
- git -C super submodule--helper config --check-writeable
+ test-tool -C super submodule config-writeable
'
test_expect_success 'writeable .gitmodules when it is nowhere in the repository' '
@@ -183,7 +183,7 @@ test_expect_success 'writeable .gitmodules when it is nowhere in the repository'
(cd super &&
git rm .gitmodules &&
git commit -m "remove .gitmodules from the current branch" &&
- git submodule--helper config --check-writeable
+ test-tool submodule config-writeable
)
'
@@ -191,7 +191,7 @@ test_expect_success 'non-writeable .gitmodules when it is in the index but not i
test_when_finished "git -C super checkout .gitmodules" &&
(cd super &&
rm -f .gitmodules &&
- test_must_fail git submodule--helper config --check-writeable
+ test_must_fail test-tool submodule config-writeable
)
'
@@ -200,7 +200,7 @@ test_expect_success 'non-writeable .gitmodules when it is in the current branch
test_when_finished "git -C super reset --hard $ORIG" &&
(cd super &&
git rm .gitmodules &&
- test_must_fail git submodule--helper config --check-writeable
+ test_must_fail test-tool submodule config-writeable
)
'
@@ -208,11 +208,11 @@ test_expect_success 'reading submodules config from the index when .gitmodules i
ORIG=$(git -C super rev-parse HEAD) &&
test_when_finished "git -C super reset --hard $ORIG" &&
(cd super &&
- git submodule--helper config submodule.submodule.url "staged_url" &&
+ test-tool submodule config-set submodule.submodule.url "staged_url" &&
git add .gitmodules &&
rm -f .gitmodules &&
echo "staged_url" >expect &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
)
'
@@ -223,7 +223,7 @@ test_expect_success 'reading submodules config from the current branch when .git
(cd super &&
git rm .gitmodules &&
echo "../submodule" >expect &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
)
'
diff --git a/t/t7412-submodule-absorbgitdirs.sh b/t/t7412-submodule-absorbgitdirs.sh
index 2859695c6d..a5cd6db7ac 100755
--- a/t/t7412-submodule-absorbgitdirs.sh
+++ b/t/t7412-submodule-absorbgitdirs.sh
@@ -18,13 +18,19 @@ test_expect_success 'setup a real submodule' '
'
test_expect_success 'absorb the git dir' '
+ >expect &&
+ >actual &&
>expect.1 &&
>expect.2 &&
>actual.1 &&
>actual.2 &&
git status >expect.1 &&
git -C sub1 rev-parse HEAD >expect.2 &&
- git submodule absorbgitdirs &&
+ cat >expect <<-\EOF &&
+ Migrating git directory of '\''sub1'\'' from '\''sub1/.git'\'' to '\''.git/modules/sub1'\''
+ EOF
+ git submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual &&
git fsck &&
test -f sub1/.git &&
test -d .git/modules/sub1 &&
@@ -37,7 +43,8 @@ test_expect_success 'absorb the git dir' '
test_expect_success 'absorbing does not fail for deinitialized submodules' '
test_when_finished "git submodule update --init" &&
git submodule deinit --all &&
- git submodule absorbgitdirs &&
+ git submodule absorbgitdirs 2>err &&
+ test_must_be_empty err &&
test -d .git/modules/sub1 &&
test -d sub1 &&
! test -e sub1/.git
@@ -56,7 +63,11 @@ test_expect_success 'setup nested submodule' '
test_expect_success 'absorb the git dir in a nested submodule' '
git status >expect.1 &&
git -C sub1/nested rev-parse HEAD >expect.2 &&
- git submodule absorbgitdirs &&
+ cat >expect <<-\EOF &&
+ Migrating git directory of '\''sub1/nested'\'' from '\''sub1/nested/.git'\'' to '\''.git/modules/sub1/modules/nested'\''
+ EOF
+ git submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual &&
test -f sub1/nested/.git &&
test -d .git/modules/sub1/modules/nested &&
git status >actual.1 &&
@@ -87,7 +98,11 @@ test_expect_success 're-setup nested submodule' '
test_expect_success 'absorb the git dir in a nested submodule' '
git status >expect.1 &&
git -C sub1/nested rev-parse HEAD >expect.2 &&
- git submodule absorbgitdirs &&
+ cat >expect <<-\EOF &&
+ Migrating git directory of '\''sub1'\'' from '\''sub1/.git'\'' to '\''.git/modules/sub1'\''
+ EOF
+ git submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual &&
test -f sub1/.git &&
test -f sub1/nested/.git &&
test -d .git/modules/sub1/modules/nested &&
@@ -107,7 +122,11 @@ test_expect_success 'setup a gitlink with missing .gitmodules entry' '
test_expect_success 'absorbing the git dir fails for incomplete submodules' '
git status >expect.1 &&
git -C sub2 rev-parse HEAD >expect.2 &&
- test_must_fail git submodule absorbgitdirs &&
+ cat >expect <<-\EOF &&
+ fatal: could not lookup name for submodule '\''sub2'\''
+ EOF
+ test_must_fail git submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual &&
git -C sub2 fsck &&
test -d sub2/.git &&
git status >actual &&
@@ -127,8 +146,11 @@ test_expect_success 'setup a submodule with multiple worktrees' '
'
test_expect_success 'absorbing fails for a submodule with multiple worktrees' '
- test_must_fail git submodule absorbgitdirs sub3 2>error &&
- test_i18ngrep "not supported" error
+ cat >expect <<-\EOF &&
+ fatal: could not lookup name for submodule '\''sub2'\''
+ EOF
+ test_must_fail git submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual
'
test_done
diff --git a/t/t7418-submodule-sparse-gitmodules.sh b/t/t7418-submodule-sparse-gitmodules.sh
index d5874200fd..dde11ecce8 100755
--- a/t/t7418-submodule-sparse-gitmodules.sh
+++ b/t/t7418-submodule-sparse-gitmodules.sh
@@ -50,12 +50,12 @@ test_expect_success 'sparse checkout setup which hides .gitmodules' '
test_expect_success 'reading gitmodules config file when it is not checked out' '
echo "../submodule" >expect &&
- git -C super submodule--helper config submodule.submodule.url >actual &&
+ test-tool -C super submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
'
test_expect_success 'not writing gitmodules config file when it is not checked out' '
- test_must_fail git -C super submodule--helper config submodule.submodule.url newurl &&
+ test_must_fail test-tool -C super submodule config-set submodule.submodule.url newurl &&
test_path_is_missing super/.gitmodules
'
diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh
new file mode 100755
index 0000000000..ab946ec940
--- /dev/null
+++ b/t/t7422-submodule-output.sh
@@ -0,0 +1,170 @@
+#!/bin/sh
+
+test_description='submodule --cached, --quiet etc. output'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-t3100.sh
+
+setup_sub () {
+ local d="$1" &&
+ shift &&
+ git $@ clone . "$d" &&
+ git $@ submodule add ./"$d"
+}
+
+normalize_status () {
+ sed -e 's/-g[0-9a-f]*/-gHASH/'
+}
+
+test_expect_success 'setup' '
+ test_commit A &&
+ test_commit B &&
+ setup_sub S &&
+ setup_sub S.D &&
+ setup_sub S.C &&
+ setup_sub S.C.D &&
+ setup_sub X &&
+ git add S* &&
+ test_commit C &&
+
+ # recursive in X/
+ git -C X pull &&
+ GIT_ALLOW_PROTOCOL=file git -C X submodule update --init &&
+
+ # dirty
+ for d in S.D X/S.D
+ do
+ echo dirty >"$d"/A.t || return 1
+ done &&
+
+ # commit (for --cached)
+ for d in S.C* X/S.C*
+ do
+ git -C "$d" reset --hard A || return 1
+ done &&
+
+ # dirty
+ for d in S*.D X/S*.D
+ do
+ echo dirty >"$d/C2.t" || return 1
+ done &&
+
+ for ref in A B C
+ do
+ # Not different with SHA-1 and SHA-256, just (ab)using
+ # test_oid_cache as a variable bag to avoid using
+ # $(git rev-parse ...).
+ oid=$(git rev-parse $ref) &&
+ test_oid_cache <<-EOF || return 1
+ $ref sha1:$oid
+ $ref sha256:$oid
+ EOF
+ done
+'
+
+for opts in "" "status"
+do
+ test_expect_success "git submodule $opts" '
+ sed -e "s/^>//" >expect <<-EOF &&
+ > $(test_oid B) S (B)
+ >+$(test_oid A) S.C (A)
+ >+$(test_oid A) S.C.D (A)
+ > $(test_oid B) S.D (B)
+ >+$(test_oid C) X (C)
+ EOF
+ git submodule $opts >actual.raw &&
+ normalize_status <actual.raw >actual &&
+ test_cmp expect actual
+ '
+done
+
+for opts in \
+ "status --recursive"
+do
+ test_expect_success "git submodule $opts" '
+ sed -e "s/^>//" >expect <<-EOF &&
+ > $(test_oid B) S (B)
+ >+$(test_oid A) S.C (A)
+ >+$(test_oid A) S.C.D (A)
+ > $(test_oid B) S.D (B)
+ >+$(test_oid C) X (C)
+ > $(test_oid B) X/S (B)
+ >+$(test_oid A) X/S.C (A)
+ >+$(test_oid A) X/S.C.D (A)
+ > $(test_oid B) X/S.D (B)
+ > $(test_oid B) X/X (B)
+ EOF
+ git submodule $opts >actual.raw &&
+ normalize_status <actual.raw >actual &&
+ test_cmp expect actual
+ '
+done
+
+for opts in \
+ "--quiet" \
+ "--quiet status" \
+ "status --quiet"
+do
+ test_expect_success "git submodule $opts" '
+ git submodule $opts >out &&
+ test_must_be_empty out
+ '
+done
+
+for opts in \
+ "--cached" \
+ "--cached status" \
+ "status --cached"
+do
+ test_expect_success "git submodule $opts" '
+ sed -e "s/^>//" >expect <<-EOF &&
+ > $(test_oid B) S (B)
+ >+$(test_oid B) S.C (B)
+ >+$(test_oid B) S.C.D (B)
+ > $(test_oid B) S.D (B)
+ >+$(test_oid B) X (B)
+ EOF
+ git submodule $opts >actual.raw &&
+ normalize_status <actual.raw >actual &&
+ test_cmp expect actual
+ '
+done
+
+for opts in \
+ "--cached --quiet" \
+ "--cached --quiet status" \
+ "--cached status --quiet" \
+ "--quiet status --cached" \
+ "status --cached --quiet"
+do
+ test_expect_success "git submodule $opts" '
+ git submodule $opts >out &&
+ test_must_be_empty out
+ '
+done
+
+for opts in \
+ "status --cached --recursive" \
+ "--cached status --recursive"
+do
+ test_expect_success "git submodule $opts" '
+ sed -e "s/^>//" >expect <<-EOF &&
+ > $(test_oid B) S (B)
+ >+$(test_oid B) S.C (B)
+ >+$(test_oid B) S.C.D (B)
+ > $(test_oid B) S.D (B)
+ >+$(test_oid B) X (B)
+ > $(test_oid B) X/S (B)
+ >+$(test_oid B) X/S.C (B)
+ >+$(test_oid B) X/S.C.D (B)
+ > $(test_oid B) X/S.D (B)
+ > $(test_oid B) X/X (B)
+ EOF
+ git submodule $opts >actual.raw &&
+ normalize_status <actual.raw >actual &&
+ test_cmp expect actual
+ '
+done
+
+test_done
diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh
index a39de8c112..07ca46fb0d 100755
--- a/t/t7504-commit-msg-hook.sh
+++ b/t/t7504-commit-msg-hook.sh
@@ -5,6 +5,7 @@ test_description='commit-msg hook'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'with no hook' '
diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
index d050091345..52a82b703f 100755
--- a/t/t7506-status-submodule.sh
+++ b/t/t7506-status-submodule.sh
@@ -412,4 +412,23 @@ test_expect_success 'status with added file in nested submodule (short)' '
EOF
'
+test_expect_success 'status in superproject with submodules respects parallel settings' '
+ test_when_finished "rm -f trace.out" &&
+ (
+ GIT_TRACE=$(pwd)/trace.out git status &&
+ grep "1 tasks" trace.out &&
+ >trace.out &&
+
+ git config submodule.diffJobs 8 &&
+ GIT_TRACE=$(pwd)/trace.out git status &&
+ grep "8 tasks" trace.out &&
+ >trace.out &&
+
+ GIT_TRACE=$(pwd)/trace.out git -c submodule.diffJobs=0 status &&
+ grep "preparing to run up to [0-9]* tasks" trace.out &&
+ ! grep "up to 0 tasks" trace.out &&
+ >trace.out
+ )
+'
+
test_done
diff --git a/t/t7517-per-repo-email.sh b/t/t7517-per-repo-email.sh
index 163ae80468..efc6496e2b 100755
--- a/t/t7517-per-repo-email.sh
+++ b/t/t7517-per-repo-email.sh
@@ -9,6 +9,7 @@ test_description='per-repo forced setting of email address'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a likely user.useConfigOnly use case' '
diff --git a/t/t7520-ignored-hook-warning.sh b/t/t7520-ignored-hook-warning.sh
index dc57526e6f..184b258989 100755
--- a/t/t7520-ignored-hook-warning.sh
+++ b/t/t7520-ignored-hook-warning.sh
@@ -2,6 +2,7 @@
test_description='ignored hook warning'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t7605-merge-resolve.sh b/t/t7605-merge-resolve.sh
index 5d56c38546..62d935d31c 100755
--- a/t/t7605-merge-resolve.sh
+++ b/t/t7605-merge-resolve.sh
@@ -4,6 +4,7 @@ test_description='git merge
Testing the resolve strategy.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7609-mergetool--lib.sh b/t/t7609-mergetool--lib.sh
index 8b1c3bd39f..2090d12a48 100755
--- a/t/t7609-mergetool--lib.sh
+++ b/t/t7609-mergetool--lib.sh
@@ -8,7 +8,7 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'mergetool --tool=vimdiff creates the expected layout' '
- . "$GIT_BUILD_DIR"/mergetools/vimdiff &&
+ . "$GIT_SOURCE_DIR"/mergetools/vimdiff &&
run_unit_tests
'
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 8cc64729ad..7b957022f1 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -33,7 +33,7 @@ test_expect_success 'setup' '
git add foo &&
git commit -m "Add foo"
) &&
- git submodule add git://example.com/submod submod &&
+ git submodule add file:///dev/null submod &&
git add file1 "spaced name" file1[1-4] subdir/file3 .gitmodules submod &&
git commit -m "add initial versions" &&
@@ -614,7 +614,7 @@ test_expect_success 'submodule in subdirectory' '
)
) &&
test_when_finished "rm -rf subdir/subdir_module" &&
- git submodule add git://example.com/subsubmodule subdir/subdir_module &&
+ git submodule add file:///dev/null subdir/subdir_module &&
git add subdir/subdir_module &&
git commit -m "add submodule in subdirectory" &&
diff --git a/t/t7614-merge-signoff.sh b/t/t7614-merge-signoff.sh
index fee258d4f0..cf96a35e8e 100755
--- a/t/t7614-merge-signoff.sh
+++ b/t/t7614-merge-signoff.sh
@@ -8,6 +8,7 @@ This test runs git merge --signoff and makes sure that it works.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Setup test files
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index 5be483bf88..c630e0d52d 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -543,4 +543,125 @@ test_expect_success '-n overrides repack.updateServerInfo=true' '
test_server_info_missing
'
+test_expect_success '--expire-to stores pruned objects (now)' '
+ git init expire-to-now &&
+ (
+ cd expire-to-now &&
+
+ git branch -M main &&
+
+ test_commit base &&
+
+ git checkout -b cruft &&
+ test_commit --no-tag cruft &&
+
+ git rev-list --objects --no-object-names main..cruft >moved.raw &&
+ sort moved.raw >moved.want &&
+
+ git rev-list --all --objects --no-object-names >expect.raw &&
+ sort expect.raw >expect &&
+
+ git checkout main &&
+ git branch -D cruft &&
+ git reflog expire --all --expire=all &&
+
+ git init --bare expired.git &&
+ git repack -d \
+ --cruft --cruft-expiration="now" \
+ --expire-to="expired.git/objects/pack/pack" &&
+
+ expired="$(ls expired.git/objects/pack/pack-*.idx)" &&
+ test_path_is_file "${expired%.idx}.mtimes" &&
+
+ # Since the `--cruft-expiration` is "now", the effective
+ # behavior is to move _all_ unreachable objects out to
+ # the location in `--expire-to`.
+ git show-index <$expired >expired.raw &&
+ cut -d" " -f2 expired.raw | sort >expired.objects &&
+ git rev-list --all --objects --no-object-names \
+ >remaining.objects &&
+
+ # ...in other words, the combined contents of this
+ # repository and expired.git should be the same as the
+ # set of objects we started with.
+ cat expired.objects remaining.objects | sort >actual &&
+ test_cmp expect actual &&
+
+ # The "moved" objects (i.e., those in expired.git)
+ # should be the same as the cruft objects which were
+ # expired in the previous step.
+ test_cmp moved.want expired.objects
+ )
+'
+
+test_expect_success '--expire-to stores pruned objects (5.minutes.ago)' '
+ git init expire-to-5.minutes.ago &&
+ (
+ cd expire-to-5.minutes.ago &&
+
+ git branch -M main &&
+
+ test_commit base &&
+
+ # Create two classes of unreachable objects, one which
+ # is older than 5 minutes (stale), and another which is
+ # newer (recent).
+ for kind in stale recent
+ do
+ git checkout -b $kind main &&
+ test_commit --no-tag $kind || return 1
+ done &&
+
+ git rev-list --objects --no-object-names main..stale >in &&
+ stale="$(git pack-objects $objdir/pack/pack <in)" &&
+ mtime="$(test-tool chmtime --get =-600 $objdir/pack/pack-$stale.pack)" &&
+
+ # expect holds the set of objects we expect to find in
+ # this repository after repacking
+ git rev-list --objects --no-object-names recent >expect.raw &&
+ sort expect.raw >expect &&
+
+ # moved.want holds the set of objects we expect to find
+ # in expired.git
+ git rev-list --objects --no-object-names main..stale >out &&
+ sort out >moved.want &&
+
+ git checkout main &&
+ git branch -D stale recent &&
+ git reflog expire --all --expire=all &&
+ git prune-packed &&
+
+ git init --bare expired.git &&
+ git repack -d \
+ --cruft --cruft-expiration=5.minutes.ago \
+ --expire-to="expired.git/objects/pack/pack" &&
+
+ # Some of the remaining objects in this repository are
+ # unreachable, so use `cat-file --batch-all-objects`
+ # instead of `rev-list` to get their names
+ git cat-file --batch-all-objects --batch-check="%(objectname)" \
+ >remaining.objects &&
+ sort remaining.objects >actual &&
+ test_cmp expect actual &&
+
+ (
+ cd expired.git &&
+
+ expired="$(ls objects/pack/pack-*.mtimes)" &&
+ test-tool pack-mtimes $(basename $expired) >out &&
+ cut -d" " -f1 out | sort >../moved.got &&
+
+ # Ensure that there are as many objects with the
+ # expected mtime as were moved to expired.git.
+ #
+ # In other words, ensure that the recorded
+ # mtimes of any moved objects was written
+ # correctly.
+ grep " $mtime$" out >matching &&
+ test_line_count = $(wc -l <../moved.want) matching
+ ) &&
+ test_cmp moved.want moved.got
+ )
+'
+
test_done
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 96bdd42045..823331e44a 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -500,9 +500,28 @@ test_expect_success 'register and unregister' '
git config --global --get-all maintenance.repo >actual &&
test_cmp before actual &&
+ git config --file ./other --add maintenance.repo /existing1 &&
+ git config --file ./other --add maintenance.repo /existing2 &&
+ git config --file ./other --get-all maintenance.repo >before &&
+
+ git maintenance register --config-file ./other &&
+ test_cmp_config false maintenance.auto &&
+ git config --file ./other --get-all maintenance.repo >between &&
+ cp before expect &&
+ pwd >>expect &&
+ test_cmp expect between &&
+
+ git maintenance unregister --config-file ./other &&
+ git config --file ./other --get-all maintenance.repo >actual &&
+ test_cmp before actual &&
+
test_must_fail git maintenance unregister 2>err &&
grep "is not registered" err &&
- git maintenance unregister --force
+ git maintenance unregister --force &&
+
+ test_must_fail git maintenance unregister --config-file ./other 2>err &&
+ grep "is not registered" err &&
+ git maintenance unregister --config-file ./other --force
'
test_expect_success !MINGW 'register and unregister with regex metacharacters' '
diff --git a/t/t9003-help-autocorrect.sh b/t/t9003-help-autocorrect.sh
index f00deaf381..4b9cb4c942 100755
--- a/t/t9003-help-autocorrect.sh
+++ b/t/t9003-help-autocorrect.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='help.autocorrect finding a match'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh
index 419f055721..743fbe1fe4 100755
--- a/t/t9115-git-svn-dcommit-funky-renames.sh
+++ b/t/t9115-git-svn-dcommit-funky-renames.sh
@@ -5,7 +5,6 @@
test_description='git svn dcommit can commit renames of files with ugly names'
-TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
test_expect_success 'load repository with strange names' '
diff --git a/t/t9146-git-svn-empty-dirs.sh b/t/t9146-git-svn-empty-dirs.sh
index 79c26ed69c..09606f1b3c 100755
--- a/t/t9146-git-svn-empty-dirs.sh
+++ b/t/t9146-git-svn-empty-dirs.sh
@@ -4,7 +4,6 @@
test_description='git svn creates empty directories'
-TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
test_expect_success 'initialize repo' '
diff --git a/t/t9148-git-svn-propset.sh b/t/t9148-git-svn-propset.sh
index 6cc76a07b3..aebb28995e 100755
--- a/t/t9148-git-svn-propset.sh
+++ b/t/t9148-git-svn-propset.sh
@@ -5,7 +5,6 @@
test_description='git svn propset tests'
-TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
test_expect_success 'setup propset via import' '
diff --git a/t/t9160-git-svn-preserve-empty-dirs.sh b/t/t9160-git-svn-preserve-empty-dirs.sh
index 9cf7a1427a..36c6b1a12f 100755
--- a/t/t9160-git-svn-preserve-empty-dirs.sh
+++ b/t/t9160-git-svn-preserve-empty-dirs.sh
@@ -9,7 +9,6 @@ This test uses git to clone a Subversion repository that contains empty
directories, and checks that corresponding directories are created in the
local Git repository with placeholder files.'
-TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
GIT_REPO=git-svn-repo
diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh
index be51a8bb7a..25f500cf68 100755
--- a/t/t9210-scalar.sh
+++ b/t/t9210-scalar.sh
@@ -166,6 +166,20 @@ test_expect_success 'scalar reconfigure' '
test true = "$(git -C one/src config core.preloadIndex)"
'
+test_expect_success '`reconfigure -a` removes stale config entries' '
+ git init stale/src &&
+ scalar register stale &&
+ scalar list >scalar.repos &&
+ grep stale scalar.repos &&
+
+ grep -v stale scalar.repos >expect &&
+
+ rm -rf stale &&
+ scalar reconfigure -a &&
+ scalar list >scalar.repos &&
+ test_cmp expect scalar.repos
+'
+
test_expect_success 'scalar delete without enlistment shows a usage' '
test_expect_code 129 scalar delete
'
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 43de868b80..27e3aa46c1 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -33,7 +33,7 @@ complete ()
GIT_TESTING_ALL_COMMAND_LIST='add checkout check-attr rebase ls-files'
GIT_TESTING_PORCELAIN_COMMAND_LIST='add checkout rebase'
-. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash"
+. "$GIT_SOURCE_DIR/contrib/completion/git-completion.bash"
# We don't need this function to actually join words or do anything special.
# Also, it's cleaner to avoid touching bash's internal completion variables.
@@ -2255,6 +2255,38 @@ test_expect_success 'checkout completes ref names' '
EOF
'
+test_expect_success 'checkout does not match ref names of a different case' '
+ test_completion "git checkout M" ""
+'
+
+test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGNORE_CASE' '
+ (
+ . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+ GIT_COMPLETION_IGNORE_CASE=1 && export GIT_COMPLETION_IGNORE_CASE &&
+ test_completion "git checkout M" <<-\EOF
+ main Z
+ mybranch Z
+ mytag Z
+ EOF
+ )
+'
+
+test_expect_success 'checkout completes pseudo refs' '
+ test_completion "git checkout H" <<-\EOF
+ HEAD Z
+ EOF
+'
+
+test_expect_success 'checkout completes pseudo refs case insensitively with GIT_COMPLETION_IGNORE_CASE' '
+ (
+ . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+ GIT_COMPLETION_IGNORE_CASE=1 && export GIT_COMPLETION_IGNORE_CASE &&
+ test_completion "git checkout h" <<-\EOF
+ HEAD Z
+ EOF
+ )
+'
+
test_expect_success 'git -C <path> checkout uses the right repo' '
test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
branch-in-other Z
@@ -2567,7 +2599,7 @@ test_expect_success 'sourcing the completion script clears cached commands' '
(
__git_compute_all_commands &&
verbose test -n "$__git_all_commands" &&
- . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+ . "$GIT_SOURCE_DIR/contrib/completion/git-completion.bash" &&
verbose test -z "$__git_all_commands"
)
'
@@ -2576,7 +2608,7 @@ test_expect_success 'sourcing the completion script clears cached merge strategi
(
__git_compute_merge_strategies &&
verbose test -n "$__git_merge_strategies" &&
- . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+ . "$GIT_SOURCE_DIR/contrib/completion/git-completion.bash" &&
verbose test -z "$__git_merge_strategies"
)
'
@@ -2587,7 +2619,7 @@ test_expect_success 'sourcing the completion script clears cached --options' '
verbose test -n "$__gitcomp_builtin_checkout" &&
__gitcomp_builtin notes_edit &&
verbose test -n "$__gitcomp_builtin_notes_edit" &&
- . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+ . "$GIT_SOURCE_DIR/contrib/completion/git-completion.bash" &&
verbose test -z "$__gitcomp_builtin_checkout" &&
verbose test -z "$__gitcomp_builtin_notes_edit"
)
@@ -2599,7 +2631,7 @@ test_expect_success 'option aliases are not shown by default' '
test_expect_success 'option aliases are shown with GIT_COMPLETION_SHOW_ALL' '
(
- . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+ . "$GIT_SOURCE_DIR/contrib/completion/git-completion.bash" &&
GIT_COMPLETION_SHOW_ALL=1 && export GIT_COMPLETION_SHOW_ALL &&
test_completion "git clone --recurs" <<-\EOF
--recurse-submodules Z
@@ -2610,7 +2642,7 @@ test_expect_success 'option aliases are shown with GIT_COMPLETION_SHOW_ALL' '
test_expect_success 'plumbing commands are excluded without GIT_COMPLETION_SHOW_ALL_COMMANDS' '
(
- . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+ . "$GIT_SOURCE_DIR/contrib/completion/git-completion.bash" &&
sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
# Just mainporcelain, not plumbing commands
@@ -2622,7 +2654,7 @@ test_expect_success 'plumbing commands are excluded without GIT_COMPLETION_SHOW_
test_expect_success 'all commands are shown with GIT_COMPLETION_SHOW_ALL_COMMANDS (also main non-builtin)' '
(
- . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+ . "$GIT_SOURCE_DIR/contrib/completion/git-completion.bash" &&
GIT_COMPLETION_SHOW_ALL_COMMANDS=1 &&
export GIT_COMPLETION_SHOW_ALL_COMMANDS &&
sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index d459fae655..06f0abfc29 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -10,7 +10,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./lib-bash.sh
-. "$GIT_BUILD_DIR/contrib/completion/git-prompt.sh"
+. "$GIT_SOURCE_DIR/contrib/completion/git-prompt.sh"
actual="$TRASH_DIRECTORY/actual"
c_red='\\[\\e[31m\\]'
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 796093a7b3..2acfd733e7 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1450,72 +1450,6 @@ test_skip_or_die () {
error "$2"
}
-# The following mingw_* functions obey POSIX shell syntax, but are actually
-# bash scripts, and are meant to be used only with bash on Windows.
-
-# A test_cmp function that treats LF and CRLF equal and avoids to fork
-# diff when possible.
-mingw_test_cmp () {
- # Read text into shell variables and compare them. If the results
- # are different, use regular diff to report the difference.
- local test_cmp_a= test_cmp_b=
-
- # When text came from stdin (one argument is '-') we must feed it
- # to diff.
- local stdin_for_diff=
-
- # Since it is difficult to detect the difference between an
- # empty input file and a failure to read the files, we go straight
- # to diff if one of the inputs is empty.
- if test -s "$1" && test -s "$2"
- then
- # regular case: both files non-empty
- mingw_read_file_strip_cr_ test_cmp_a <"$1"
- mingw_read_file_strip_cr_ test_cmp_b <"$2"
- elif test -s "$1" && test "$2" = -
- then
- # read 2nd file from stdin
- mingw_read_file_strip_cr_ test_cmp_a <"$1"
- mingw_read_file_strip_cr_ test_cmp_b
- stdin_for_diff='<<<"$test_cmp_b"'
- elif test "$1" = - && test -s "$2"
- then
- # read 1st file from stdin
- mingw_read_file_strip_cr_ test_cmp_a
- mingw_read_file_strip_cr_ test_cmp_b <"$2"
- stdin_for_diff='<<<"$test_cmp_a"'
- fi
- test -n "$test_cmp_a" &&
- test -n "$test_cmp_b" &&
- test "$test_cmp_a" = "$test_cmp_b" ||
- eval "diff -u \"\$@\" $stdin_for_diff"
-}
-
-# $1 is the name of the shell variable to fill in
-mingw_read_file_strip_cr_ () {
- # Read line-wise using LF as the line separator
- # and use IFS to strip CR.
- local line
- while :
- do
- if IFS=$'\r' read -r -d $'\n' line
- then
- # good
- line=$line$'\n'
- else
- # we get here at EOF, but also if the last line
- # was not terminated by LF; in the latter case,
- # some text was read
- if test -z "$line"
- then
- # EOF, really
- break
- fi
- fi
- eval "$1=\$$1\$line"
- done
-}
-
# Like "env FOO=BAR some-program", but run inside a subshell, which means
# it also works for shell functions (though those functions cannot impact
# the environment outside of the test_env invocation).
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 6db377f68b..cd085c652b 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -47,9 +47,21 @@ then
echo "PANIC: Running in a $TEST_DIRECTORY that doesn't end in '/t'?" >&2
exit 1
fi
-if test -f "$GIT_BUILD_DIR/GIT-BUILD-DIR"
+
+# For CMake the top-level source directory is different from our build
+# directory. With the top-level Makefile they're the same.
+GIT_SOURCE_DIR="$GIT_BUILD_DIR"
+
+GIT_AUTO_CONTRIB_BUILDSYSTEMS_OUT=
+if test -n "$GIT_TEST_BUILD_DIR"
then
- GIT_BUILD_DIR="$(cat "$GIT_BUILD_DIR/GIT-BUILD-DIR")" || exit 1
+ GIT_BUILD_DIR="$GIT_TEST_BUILD_DIR"
+elif ! test -x "$GIT_BUILD_DIR/git" &&
+ test -x "$GIT_BUILD_DIR/contrib/buildsystems/out/git"
+then
+ GIT_BUILD_DIR="$GIT_SOURCE_DIR/contrib/buildsystems/out"
+ GIT_AUTO_CONTRIB_BUILDSYSTEMS_OUT=t
+
# On Windows, we must convert Windows paths lest they contain a colon
case "$(uname -s)" in
*MINGW*)
@@ -1447,7 +1459,7 @@ then
make_valgrind_symlink $file
done
# special-case the mergetools loadables
- make_symlink "$GIT_BUILD_DIR"/mergetools "$GIT_VALGRIND/bin/mergetools"
+ make_symlink "$GIT_SOURCE_DIR"/mergetools "$GIT_VALGRIND/bin/mergetools"
OLDIFS=$IFS
IFS=:
for path in $PATH
@@ -1500,6 +1512,8 @@ GIT_CONFIG_NOSYSTEM=1
GIT_ATTR_NOSYSTEM=1
GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/.."
export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM GIT_CEILING_DIRECTORIES
+MERGE_TOOLS_DIR="$GIT_SOURCE_DIR/mergetools"
+export MERGE_TOOLS_DIR
if test -z "$GIT_TEST_CMP"
then
@@ -1628,6 +1642,13 @@ remove_trash_directory "$TRASH_DIRECTORY" || {
BAIL_OUT 'cannot prepare test area'
}
+# Emitting this now because earlier we didn't have "say", but not in
+# anything using lib-subtest.sh
+if test -n "$GIT_AUTO_CONTRIB_BUILDSYSTEMS_OUT" && test -t 1
+then
+ say "setup: had no ../git, but found & used cmake built git in ../contrib/buildsystems/out/git"
+fi
+
remove_trash=t
if test -z "$TEST_NO_CREATE_REPO"
then
@@ -1721,7 +1742,7 @@ case $uname_s in
test_set_prereq SED_STRIPS_CR
test_set_prereq GREP_STRIPS_CR
test_set_prereq WINDOWS
- GIT_TEST_CMP=mingw_test_cmp
+ GIT_TEST_CMP="GIT_DIR=/dev/null git diff --no-index --ignore-cr-at-eol --"
;;
*CYGWIN*)
test_set_prereq POSIXPERM
@@ -1954,3 +1975,7 @@ test_lazy_prereq FSMONITOR_DAEMON '
git version --build-options >output &&
grep "feature: fsmonitor--daemon" output
'
+
+test_lazy_prereq PACKED_REFS_V1 '
+ test "$GIT_TEST_PACKED_REFS_VERSION" -ne "2"
+' \ No newline at end of file