summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/helper/test-date.c5
-rw-r--r--t/helper/test-progress.c50
-rw-r--r--t/helper/test-run-command.c6
-rwxr-xr-xt/t0006-date.sh2
-rwxr-xr-xt/t0012-help.sh94
-rwxr-xr-xt/t0500-progress-display.sh109
-rwxr-xr-xt/t1006-cat-file.sh135
-rwxr-xr-xt/t1011-read-tree-sparse-checkout.sh23
-rwxr-xr-xt/t1090-sparse-checkout-scope.sh19
-rwxr-xr-xt/t1091-sparse-checkout-builtin.sh125
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh41
-rwxr-xr-xt/t1512-rev-parse-disambiguation.sh81
-rwxr-xr-xt/t2060-switch.sh11
-rwxr-xr-xt/t2400-worktree-add.sh58
-rwxr-xr-xt/t3007-ls-files-recurse-submodules.sh18
-rwxr-xr-xt/t3705-add-sparse-checkout.sh2
-rwxr-xr-xt/t3903-stash.sh32
-rwxr-xr-xt/t4150-am.sh2
-rwxr-xr-xt/t4202-log.sh24
-rwxr-xr-xt/t5302-pack-index.sh8
-rwxr-xr-xt/t5316-pack-delta-depth.sh6
-rwxr-xr-xt/t5503-tagfollow.sh74
-rwxr-xr-xt/t5510-fetch.sh29
-rwxr-xr-xt/t5571-pre-push-hook.sh94
-rwxr-xr-xt/t5617-clone-submodules-remote.sh41
-rwxr-xr-xt/t6030-bisect-porcelain.sh45
-rwxr-xr-xt/t6428-merge-conflicts-sparse.sh23
-rwxr-xr-xt/t7012-skip-worktree-writing.sh44
-rwxr-xr-xt/t7500-commit-template-squash-signoff.sh2
-rwxr-xr-xt/t7810-grep.sh186
-rwxr-xr-xt/t7814-grep-recurse-submodules.sh41
-rwxr-xr-xt/t7817-grep-sparse-checkout.sh11
-rw-r--r--t/test-lib-functions.sh29
-rw-r--r--t/test-lib.sh50
34 files changed, 1238 insertions, 282 deletions
diff --git a/t/helper/test-date.c b/t/helper/test-date.c
index 099eff4f0f..45951b1df8 100644
--- a/t/helper/test-date.c
+++ b/t/helper/test-date.c
@@ -1,5 +1,6 @@
#include "test-tool.h"
#include "cache.h"
+#include "date.h"
static const char *usage_msg = "\n"
" test-tool date relative [time_t]...\n"
@@ -34,7 +35,7 @@ static void show_human_dates(const char **argv)
static void show_dates(const char **argv, const char *format)
{
- struct date_mode mode;
+ struct date_mode mode = DATE_MODE_INIT;
parse_date_format(format, &mode);
for (; *argv; argv++) {
@@ -53,6 +54,8 @@ static void show_dates(const char **argv, const char *format)
printf("%s -> %s\n", *argv, show_date(t, tz, &mode));
}
+
+ date_mode_release(&mode);
}
static void parse_dates(const char **argv)
diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c
index 5d05cbe789..6cc9735b60 100644
--- a/t/helper/test-progress.c
+++ b/t/helper/test-progress.c
@@ -3,6 +3,9 @@
*
* Reads instructions from standard input, one instruction per line:
*
+ * "start <total>[ <title>]" - Call start_progress(title, total),
+ * Uses the default title of "Working hard"
+ * if the " <title>" is omitted.
* "progress <items>" - Call display_progress() with the given item count
* as parameter.
* "throughput <bytes> <millis> - Call display_throughput() with the given
@@ -10,6 +13,7 @@
* specify the time elapsed since the
* start_progress() call.
* "update" - Set the 'progress_update' flag.
+ * "stop" - Call stop_progress().
*
* See 't0500-progress-display.sh' for examples.
*/
@@ -19,34 +23,50 @@
#include "parse-options.h"
#include "progress.h"
#include "strbuf.h"
+#include "string-list.h"
int cmd__progress(int argc, const char **argv)
{
- int total = 0;
- const char *title;
+ const char *const default_title = "Working hard";
+ struct string_list titles = STRING_LIST_INIT_DUP;
struct strbuf line = STRBUF_INIT;
- struct progress *progress;
+ struct progress *progress = NULL;
const char *usage[] = {
- "test-tool progress [--total=<n>] <progress-title>",
+ "test-tool progress <stdin",
NULL
};
struct option options[] = {
- OPT_INTEGER(0, "total", &total, "total number of items"),
OPT_END(),
};
argc = parse_options(argc, argv, NULL, options, usage, 0);
- if (argc != 1)
- die("need a title for the progress output");
- title = argv[0];
+ if (argc)
+ usage_with_options(usage, options);
progress_testing = 1;
- progress = start_progress(title, total);
while (strbuf_getline(&line, stdin) != EOF) {
char *end;
- if (skip_prefix(line.buf, "progress ", (const char **) &end)) {
+ if (skip_prefix(line.buf, "start ", (const char **) &end)) {
+ uint64_t total = strtoull(end, &end, 10);
+ const char *title;
+
+ /*
+ * We can't use "end + 1" as an argument to
+ * start_progress(), it doesn't xstrdup() its
+ * "title" argument. We need to hold onto a
+ * valid "char *" for it until the end.
+ */
+ if (!*end)
+ title = default_title;
+ else if (*end == ' ')
+ title = string_list_insert(&titles, end + 1)->string;
+ else
+ die("invalid input: '%s'\n", line.buf);
+
+ progress = start_progress(title, total);
+ } else if (skip_prefix(line.buf, "progress ", (const char **) &end)) {
uint64_t item_count = strtoull(end, &end, 10);
if (*end != '\0')
die("invalid input: '%s'\n", line.buf);
@@ -63,12 +83,16 @@ int cmd__progress(int argc, const char **argv)
die("invalid input: '%s'\n", line.buf);
progress_test_ns = test_ms * 1000 * 1000;
display_throughput(progress, byte_count);
- } else if (!strcmp(line.buf, "update"))
+ } else if (!strcmp(line.buf, "update")) {
progress_test_force_update();
- else
+ } else if (!strcmp(line.buf, "stop")) {
+ stop_progress(&progress);
+ } else {
die("invalid input: '%s'\n", line.buf);
+ }
}
- stop_progress(&progress);
+ strbuf_release(&line);
+ string_list_clear(&titles, 0);
return 0;
}
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index 913775a14b..8f370cd89f 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -221,9 +221,9 @@ static int quote_stress_test(int argc, const char **argv)
struct strbuf out = STRBUF_INIT;
struct strvec args = STRVEC_INIT;
struct option options[] = {
- OPT_INTEGER('n', "trials", &trials, "Number of trials"),
- OPT_INTEGER('s', "skip", &skip, "Skip <n> trials"),
- OPT_BOOL('m', "msys2", &msys2, "Test quoting for MSYS2's sh"),
+ OPT_INTEGER('n', "trials", &trials, "number of trials"),
+ OPT_INTEGER('s', "skip", &skip, "skip <n> trials"),
+ OPT_BOOL('m', "msys2", &msys2, "test quoting for MSYS2's sh"),
OPT_END()
};
const char * const usage[] = {
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index 794186961e..2490162071 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test date parsing and printing'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# arbitrary reference time: 2009-08-30 19:20:00
diff --git a/t/t0012-help.sh b/t/t0012-help.sh
index cbd725ccac..6c3e1f7159 100755
--- a/t/t0012-help.sh
+++ b/t/t0012-help.sh
@@ -35,6 +35,9 @@ test_expect_success 'basic help commands' '
'
test_expect_success 'invalid usage' '
+ test_expect_code 129 git help -a add &&
+ test_expect_code 129 git help --all add &&
+
test_expect_code 129 git help -g add &&
test_expect_code 129 git help -a -c &&
@@ -46,6 +49,29 @@ test_expect_success 'invalid usage' '
test_expect_code 129 git help --config-sections-for-completion add
'
+for opt in '-a' '-g' '-c' '--config-for-completion' '--config-sections-for-completion'
+do
+ test_expect_success "invalid usage of '$opt' with [-i|-m|-w]" '
+ git help $opt &&
+ test_expect_code 129 git help $opt -i &&
+ test_expect_code 129 git help $opt -m &&
+ test_expect_code 129 git help $opt -w
+ '
+
+ if test "$opt" = "-a"
+ then
+ continue
+ fi
+
+ test_expect_success "invalid usage of '$opt' with --no-external-commands" '
+ test_expect_code 129 git help $opt --no-external-commands
+ '
+
+ test_expect_success "invalid usage of '$opt' with --no-aliases" '
+ test_expect_code 129 git help $opt --no-external-commands
+ '
+done
+
test_expect_success "works for commands and guides by default" '
configure_help &&
git help status &&
@@ -138,6 +164,74 @@ test_expect_success 'git help --config-sections-for-completion' '
test_cmp human.munged sections
'
+test_section_spacing () {
+ cat >expect &&
+ "$@" >out &&
+ grep -E "(^[^ ]|^$)" out >actual
+}
+
+test_section_spacing_trailer () {
+ test_section_spacing "$@" &&
+ test_expect_code 1 git >out &&
+ sed -n '/list available subcommands/,$p' <out >>expect
+}
+
+
+for cmd in git "git help"
+do
+ test_expect_success "'$cmd' section spacing" '
+ test_section_spacing_trailer git help <<-\EOF &&
+ usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
+
+ These are common Git commands used in various situations:
+
+ start a working area (see also: git help tutorial)
+
+ work on the current change (see also: git help everyday)
+
+ examine the history and state (see also: git help revisions)
+
+ grow, mark and tweak your common history
+
+ collaborate (see also: git help workflows)
+
+ EOF
+ test_cmp expect actual
+ '
+done
+
+test_expect_success "'git help -a' section spacing" '
+ test_section_spacing \
+ git help -a --no-external-commands --no-aliases <<-\EOF &&
+ See '\''git help <command>'\'' to read about a specific subcommand
+
+ Main Porcelain Commands
+
+ Ancillary Commands / Manipulators
+
+ Ancillary Commands / Interrogators
+
+ Interacting with Others
+
+ Low-level Commands / Manipulators
+
+ Low-level Commands / Interrogators
+
+ Low-level Commands / Syncing Repositories
+
+ Low-level Commands / Internal Helpers
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success "'git help -g' section spacing" '
+ test_section_spacing_trailer git help -g <<-\EOF &&
+ The Git concept guides are:
+
+ EOF
+ test_cmp expect actual
+'
+
test_expect_success 'generate builtin list' '
mkdir -p sub &&
git --list-cmds=builtins >builtins
diff --git a/t/t0500-progress-display.sh b/t/t0500-progress-display.sh
index 22058b503a..1eb3a8306b 100755
--- a/t/t0500-progress-display.sh
+++ b/t/t0500-progress-display.sh
@@ -2,6 +2,7 @@
test_description='progress display'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
show_cr () {
@@ -17,6 +18,7 @@ test_expect_success 'simple progress display' '
EOF
cat >in <<-\EOF &&
+ start 0
update
progress 1
update
@@ -25,8 +27,9 @@ test_expect_success 'simple progress display' '
progress 4
update
progress 5
+ stop
EOF
- test-tool progress "Working hard" <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -41,11 +44,13 @@ test_expect_success 'progress display with total' '
EOF
cat >in <<-\EOF &&
+ start 3
progress 1
progress 2
progress 3
+ stop
EOF
- test-tool progress --total=3 "Working hard" <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -62,14 +67,14 @@ Working hard.......2.........3.........4.........5.........6:
EOF
cat >in <<-\EOF &&
+ start 100000 Working hard.......2.........3.........4.........5.........6
progress 100
progress 1000
progress 10000
progress 100000
+ stop
EOF
- test-tool progress --total=100000 \
- "Working hard.......2.........3.........4.........5.........6" \
- <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -88,16 +93,16 @@ Working hard.......2.........3.........4.........5.........6:
EOF
cat >in <<-\EOF &&
+ start 100000 Working hard.......2.........3.........4.........5.........6
update
progress 1
update
progress 2
progress 10000
progress 100000
+ stop
EOF
- test-tool progress --total=100000 \
- "Working hard.......2.........3.........4.........5.........6" \
- <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -116,14 +121,14 @@ Working hard.......2.........3.........4.........5.........6:
EOF
cat >in <<-\EOF &&
+ start 100000 Working hard.......2.........3.........4.........5.........6
progress 25000
progress 50000
progress 75000
progress 100000
+ stop
EOF
- test-tool progress --total=100000 \
- "Working hard.......2.........3.........4.........5.........6" \
- <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -140,14 +145,14 @@ Working hard.......2.........3.........4.........5.........6.........7.........:
EOF
cat >in <<-\EOF &&
+ start 100000 Working hard.......2.........3.........4.........5.........6.........7.........
progress 25000
progress 50000
progress 75000
progress 100000
+ stop
EOF
- test-tool progress --total=100000 \
- "Working hard.......2.........3.........4.........5.........6.........7........." \
- <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -164,12 +169,14 @@ test_expect_success 'progress shortens - crazy caller' '
EOF
cat >in <<-\EOF &&
+ start 1000
progress 100
progress 200
progress 1
progress 1000
+ stop
EOF
- test-tool progress --total=1000 "Working hard" <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -185,6 +192,7 @@ test_expect_success 'progress display with throughput' '
EOF
cat >in <<-\EOF &&
+ start 0
throughput 102400 1000
update
progress 10
@@ -197,8 +205,9 @@ test_expect_success 'progress display with throughput' '
throughput 409600 4000
update
progress 40
+ stop
EOF
- test-tool progress "Working hard" <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -214,6 +223,7 @@ test_expect_success 'progress display with throughput and total' '
EOF
cat >in <<-\EOF &&
+ start 40
throughput 102400 1000
progress 10
throughput 204800 2000
@@ -222,8 +232,9 @@ test_expect_success 'progress display with throughput and total' '
progress 30
throughput 409600 4000
progress 40
+ stop
EOF
- test-tool progress --total=40 "Working hard" <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -239,6 +250,7 @@ test_expect_success 'cover up after throughput shortens' '
EOF
cat >in <<-\EOF &&
+ start 0
throughput 409600 1000
update
progress 1
@@ -251,8 +263,9 @@ test_expect_success 'cover up after throughput shortens' '
throughput 1638400 4000
update
progress 4
+ stop
EOF
- test-tool progress "Working hard" <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -267,6 +280,7 @@ test_expect_success 'cover up after throughput shortens a lot' '
EOF
cat >in <<-\EOF &&
+ start 0
throughput 1 1000
update
progress 1
@@ -276,8 +290,9 @@ test_expect_success 'cover up after throughput shortens a lot' '
throughput 3145728 3000
update
progress 3
+ stop
EOF
- test-tool progress "Working hard" <in 2>stderr &&
+ test-tool progress <in 2>stderr &&
show_cr <stderr >out &&
test_cmp expect out
@@ -285,6 +300,7 @@ test_expect_success 'cover up after throughput shortens a lot' '
test_expect_success 'progress generates traces' '
cat >in <<-\EOF &&
+ start 40
throughput 102400 1000
update
progress 10
@@ -297,10 +313,11 @@ test_expect_success 'progress generates traces' '
throughput 409600 4000
update
progress 40
+ stop
EOF
- GIT_TRACE2_EVENT="$(pwd)/trace.event" test-tool progress --total=40 \
- "Working hard" <in 2>stderr &&
+ GIT_TRACE2_EVENT="$(pwd)/trace.event" test-tool progress \
+ <in 2>stderr &&
# t0212/parse_events.perl intentionally omits regions and data.
test_region progress "Working hard" trace.event &&
@@ -308,4 +325,54 @@ test_expect_success 'progress generates traces' '
grep "\"key\":\"total_bytes\",\"value\":\"409600\"" trace.event
'
+test_expect_success 'progress generates traces: stop / start' '
+ cat >in <<-\EOF &&
+ start 0
+ stop
+ EOF
+
+ GIT_TRACE2_EVENT="$PWD/trace-startstop.event" test-tool progress \
+ <in 2>stderr &&
+ test_region progress "Working hard" trace-startstop.event
+'
+
+test_expect_success 'progress generates traces: start without stop' '
+ cat >in <<-\EOF &&
+ start 0
+ EOF
+
+ GIT_TRACE2_EVENT="$PWD/trace-start.event" \
+ LSAN_OPTIONS=detect_leaks=0 \
+ test-tool progress \
+ <in 2>stderr &&
+ grep region_enter.*progress trace-start.event &&
+ ! grep region_leave.*progress trace-start.event
+'
+
+test_expect_success 'progress generates traces: stop without start' '
+ cat >in <<-\EOF &&
+ stop
+ EOF
+
+ GIT_TRACE2_EVENT="$PWD/trace-stop.event" test-tool progress \
+ <in 2>stderr &&
+ ! grep region_enter.*progress trace-stop.event &&
+ ! grep region_leave.*progress trace-stop.event
+'
+
+test_expect_success 'progress generates traces: start with active progress bar (no stops)' '
+ cat >in <<-\EOF &&
+ start 0 One
+ start 0 Two
+ EOF
+
+ GIT_TRACE2_EVENT="$PWD/trace-2start.event" \
+ LSAN_OPTIONS=detect_leaks=0 \
+ test-tool progress \
+ <in 2>stderr &&
+ grep region_enter.*progress.*One trace-2start.event &&
+ grep region_enter.*progress.*Two trace-2start.event &&
+ ! grep region_leave trace-2start.event
+'
+
test_done
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 145eee11df..1b85207694 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -105,13 +105,18 @@ strlen () {
}
maybe_remove_timestamp () {
- if test -z "$2"; then
- echo_without_newline "$1"
- else
- echo_without_newline "$(printf '%s\n' "$1" | sed -e 's/ [0-9][0-9]* [-+][0-9][0-9][0-9][0-9]$//')"
- fi
+ if test -z "$2"; then
+ echo_without_newline "$1"
+ else
+ echo_without_newline "$(printf '%s\n' "$1" | remove_timestamp)"
+ fi
}
+remove_timestamp () {
+ sed -e 's/ [0-9][0-9]* [-+][0-9][0-9][0-9][0-9]$//'
+}
+
+
run_tests () {
type=$1
sha1=$2
@@ -177,12 +182,36 @@ $content"
test_cmp expect actual
'
+ for opt in --buffer --no-buffer
+ do
+ test -z "$content" ||
+ test_expect_success "--batch-command $opt output of $type content is correct" '
+ maybe_remove_timestamp "$batch_output" $no_ts >expect &&
+ maybe_remove_timestamp "$(test_write_lines "contents $sha1" |
+ git cat-file --batch-command $opt)" $no_ts >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "--batch-command $opt output of $type info is correct" '
+ echo "$sha1 $type $size" >expect &&
+ test_write_lines "info $sha1" |
+ git cat-file --batch-command $opt >actual &&
+ test_cmp expect actual
+ '
+ done
+
test_expect_success "custom --batch-check format" '
echo "$type $sha1" >expect &&
echo $sha1 | git cat-file --batch-check="%(objecttype) %(objectname)" >actual &&
test_cmp expect actual
'
+ test_expect_success "custom --batch-command format" '
+ echo "$type $sha1" >expect &&
+ echo "info $sha1" | git cat-file --batch-command="%(objecttype) %(objectname)" >actual &&
+ test_cmp expect actual
+ '
+
test_expect_success '--batch-check with %(rest)' '
echo "$type this is some extra content" >expect &&
echo "$sha1 this is some extra content" |
@@ -224,6 +253,22 @@ test_expect_success "setup" '
run_tests 'blob' $hello_sha1 $hello_size "$hello_content" "$hello_content"
+test_expect_success '--batch-command --buffer with flush for blob info' '
+ echo "$hello_sha1 blob $hello_size" >expect &&
+ test_write_lines "info $hello_sha1" "flush" |
+ GIT_TEST_CAT_FILE_NO_FLUSH_ON_EXIT=1 \
+ git cat-file --batch-command --buffer >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--batch-command --buffer without flush for blob info' '
+ touch output &&
+ test_write_lines "info $hello_sha1" |
+ GIT_TEST_CAT_FILE_NO_FLUSH_ON_EXIT=1 \
+ git cat-file --batch-command --buffer >>output &&
+ test_must_be_empty output
+'
+
test_expect_success '--batch-check without %(rest) considers whole line' '
echo "$hello_sha1 blob $hello_size" >expect &&
git update-index --add --cacheinfo 100644 $hello_sha1 "white space" &&
@@ -267,7 +312,7 @@ test_expect_success \
"Reach a blob from a tag pointing to it" \
"test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\""
-for batch in batch batch-check
+for batch in batch batch-check batch-command
do
for opt in t s e p
do
@@ -373,6 +418,49 @@ test_expect_success "--batch-check with multiple sha1s gives correct format" '
"$(echo_without_newline "$batch_check_input" | git cat-file --batch-check)"
'
+test_expect_success '--batch-command with multiple info calls gives correct format' '
+ cat >expect <<-EOF &&
+ $hello_sha1 blob $hello_size
+ $tree_sha1 tree $tree_size
+ $commit_sha1 commit $commit_size
+ $tag_sha1 tag $tag_size
+ deadbeef missing
+ EOF
+
+ git cat-file --batch-command --buffer >actual <<-EOF &&
+ info $hello_sha1
+ info $tree_sha1
+ info $commit_sha1
+ info $tag_sha1
+ info deadbeef
+ EOF
+
+ test_cmp expect actual
+'
+
+test_expect_success '--batch-command with multiple command calls gives correct format' '
+ remove_timestamp >expect <<-EOF &&
+ $hello_sha1 blob $hello_size
+ $hello_content
+ $commit_sha1 commit $commit_size
+ $commit_content
+ $tag_sha1 tag $tag_size
+ $tag_content
+ deadbeef missing
+ EOF
+
+ git cat-file --batch-command --buffer >actual_raw <<-EOF &&
+ contents $hello_sha1
+ contents $commit_sha1
+ contents $tag_sha1
+ contents deadbeef
+ flush
+ EOF
+
+ remove_timestamp <actual_raw >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'setup blobs which are likely to delta' '
test-tool genrandom foo 10240 >foo &&
{ cat foo && echo plus; } >foo-plus &&
@@ -963,5 +1051,40 @@ test_expect_success 'cat-file --batch-all-objects --batch-check ignores replace'
echo "$orig commit $orig_size" >expect &&
test_cmp expect actual
'
+test_expect_success 'batch-command empty command' '
+ echo "" >cmd &&
+ test_expect_code 128 git cat-file --batch-command <cmd 2>err &&
+ grep "^fatal:.*empty command in input.*" err
+'
+
+test_expect_success 'batch-command whitespace before command' '
+ echo " info deadbeef" >cmd &&
+ test_expect_code 128 git cat-file --batch-command <cmd 2>err &&
+ grep "^fatal:.*whitespace before command.*" err
+'
+
+test_expect_success 'batch-command unknown command' '
+ echo unknown_command >cmd &&
+ test_expect_code 128 git cat-file --batch-command <cmd 2>err &&
+ grep "^fatal:.*unknown command.*" err
+'
+
+test_expect_success 'batch-command missing arguments' '
+ echo "info" >cmd &&
+ test_expect_code 128 git cat-file --batch-command <cmd 2>err &&
+ grep "^fatal:.*info requires arguments.*" err
+'
+
+test_expect_success 'batch-command flush with arguments' '
+ echo "flush arg" >cmd &&
+ test_expect_code 128 git cat-file --batch-command --buffer <cmd 2>err &&
+ grep "^fatal:.*flush takes no arguments.*" err
+'
+
+test_expect_success 'batch-command flush without --buffer' '
+ echo "flush" >cmd &&
+ test_expect_code 128 git cat-file --batch-command <cmd 2>err &&
+ grep "^fatal:.*flush is only for --buffer mode.*" err
+'
test_done
diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh
index 24092c09a9..dd957be1b7 100755
--- a/t/t1011-read-tree-sparse-checkout.sh
+++ b/t/t1011-read-tree-sparse-checkout.sh
@@ -187,11 +187,32 @@ test_expect_success 'read-tree updates worktree, absent case' '
test ! -f init.t
'
+test_expect_success 'read-tree will not throw away dirty changes, non-sparse' '
+ echo "/*" >.git/info/sparse-checkout &&
+ read_tree_u_must_succeed -m -u HEAD &&
+
+ echo dirty >init.t &&
+ read_tree_u_must_fail -m -u HEAD^ &&
+ test_path_is_file init.t &&
+ grep -q dirty init.t
+'
+
+test_expect_success 'read-tree will not throw away dirty changes, sparse' '
+ echo "/*" >.git/info/sparse-checkout &&
+ read_tree_u_must_succeed -m -u HEAD &&
+
+ echo dirty >init.t &&
+ echo sub/added >.git/info/sparse-checkout &&
+ read_tree_u_must_fail -m -u HEAD^ &&
+ test_path_is_file init.t &&
+ grep -q dirty init.t
+'
+
test_expect_success 'read-tree updates worktree, dirty case' '
echo sub/added >.git/info/sparse-checkout &&
git checkout -f top &&
echo dirty >init.t &&
- read_tree_u_must_succeed -m -u HEAD^ &&
+ read_tree_u_must_fail -m -u HEAD^ &&
grep -q dirty init.t &&
rm init.t
'
diff --git a/t/t1090-sparse-checkout-scope.sh b/t/t1090-sparse-checkout-scope.sh
index 3deb490187..d1833c0f31 100755
--- a/t/t1090-sparse-checkout-scope.sh
+++ b/t/t1090-sparse-checkout-scope.sh
@@ -52,6 +52,25 @@ test_expect_success 'return to full checkout of main' '
test "$(cat b)" = "modified"
'
+test_expect_success 'skip-worktree on files outside sparse patterns' '
+ git sparse-checkout disable &&
+ git sparse-checkout set --no-cone "a*" &&
+ git checkout-index --all --ignore-skip-worktree-bits &&
+
+ git ls-files -t >output &&
+ ! grep ^S output >actual &&
+ test_must_be_empty actual &&
+
+ test_config sparse.expectFilesOutsideOfPatterns true &&
+ cat <<-\EOF >expect &&
+ S b
+ S c
+ EOF
+ git ls-files -t >output &&
+ grep ^S output >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'in partial clone, sparse checkout only fetches needed blobs' '
test_create_repo server &&
git clone "file://$(pwd)/server" client &&
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index 3592d12442..9a90031018 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -126,7 +126,7 @@ test_expect_success 'switching to cone mode with non-cone mode patterns' '
cd bad-patterns &&
git sparse-checkout init &&
git sparse-checkout add dir &&
- git config core.sparseCheckoutCone true &&
+ git config --worktree core.sparseCheckoutCone true &&
test_must_fail git sparse-checkout add dir 2>err &&
grep "existing sparse-checkout patterns do not use cone mode" err
)
@@ -155,9 +155,9 @@ test_expect_success 'interaction with clone --no-checkout (unborn index)' '
'
test_expect_success 'set enables config' '
- git init empty-config &&
+ git init worktree-config &&
(
- cd empty-config &&
+ cd worktree-config &&
test_commit test file &&
test_path_is_missing .git/config.worktree &&
git sparse-checkout set nothing &&
@@ -210,6 +210,21 @@ test_expect_success 'add to sparse-checkout' '
check_files repo "a folder1 folder2"
'
+test_expect_success 'worktree: add copies sparse-checkout patterns' '
+ cat repo/.git/info/sparse-checkout >old &&
+ test_when_finished cp old repo/.git/info/sparse-checkout &&
+ test_when_finished git -C repo worktree remove ../worktree &&
+ git -C repo sparse-checkout set --no-cone "/*" &&
+ git -C repo worktree add --quiet ../worktree 2>err &&
+ test_must_be_empty err &&
+ new="$(git -C worktree rev-parse --git-path info/sparse-checkout)" &&
+ test_path_is_file "$new" &&
+ test_cmp repo/.git/info/sparse-checkout "$new" &&
+ git -C worktree sparse-checkout set --cone &&
+ test_cmp_config -C worktree true core.sparseCheckoutCone &&
+ test_must_fail git -C repo core.sparseCheckoutCone
+'
+
test_expect_success 'cone mode: match patterns' '
git -C repo config --worktree core.sparseCheckoutCone true &&
rm -rf repo/a repo/folder1 repo/folder2 &&
@@ -261,7 +276,7 @@ test_expect_success 'sparse-index enabled and disabled' '
test_cmp expect actual &&
git -C repo config --list >config &&
- ! grep index.sparse config
+ test_cmp_config -C repo false index.sparse
'
test_expect_success 'cone mode: init and set' '
@@ -495,6 +510,37 @@ test_expect_failure 'sparse-checkout reapply' '
git -C tweak sparse-checkout disable
'
+test_expect_success 'reapply can handle config options' '
+ git -C repo sparse-checkout init --cone --no-sparse-index &&
+ git -C repo config --worktree --list >actual &&
+ cat >expect <<-\EOF &&
+ core.sparsecheckout=true
+ core.sparsecheckoutcone=true
+ index.sparse=false
+ EOF
+ test_cmp expect actual &&
+
+ git -C repo sparse-checkout reapply --no-cone --no-sparse-index &&
+ git -C repo config --worktree --list >actual &&
+ cat >expect <<-\EOF &&
+ core.sparsecheckout=true
+ core.sparsecheckoutcone=false
+ index.sparse=false
+ EOF
+ test_cmp expect actual &&
+
+ git -C repo sparse-checkout reapply --cone --sparse-index &&
+ git -C repo config --worktree --list >actual &&
+ cat >expect <<-\EOF &&
+ core.sparsecheckout=true
+ core.sparsecheckoutcone=true
+ index.sparse=true
+ EOF
+ test_cmp expect actual &&
+
+ git -C repo sparse-checkout disable
+'
+
test_expect_success 'cone mode: set with core.ignoreCase=true' '
rm repo/.git/info/sparse-checkout &&
git -C repo sparse-checkout init --cone &&
@@ -524,17 +570,17 @@ test_expect_success 'interaction with submodules' '
'
test_expect_success 'different sparse-checkouts with worktrees' '
+ git -C repo sparse-checkout set --cone deep folder1 &&
git -C repo worktree add --detach ../worktree &&
- check_files worktree "a deep folder1 folder2" &&
- git -C worktree sparse-checkout init --cone &&
- git -C repo sparse-checkout set folder1 &&
- git -C worktree sparse-checkout set deep/deeper1 &&
- check_files repo a folder1 &&
- check_files worktree a deep
+ check_files worktree "a deep folder1" &&
+ git -C repo sparse-checkout set --cone folder1 &&
+ git -C worktree sparse-checkout set --cone deep/deeper1 &&
+ check_files repo "a folder1" &&
+ check_files worktree "a deep"
'
test_expect_success 'set using filename keeps file on-disk' '
- git -C repo sparse-checkout set a deep &&
+ git -C repo sparse-checkout set --skip-checks a deep &&
cat >expect <<-\EOF &&
/*
!/*/
@@ -645,7 +691,7 @@ test_expect_success BSLASHPSPEC 'pattern-checks: escaped characters' '
git -C escaped reset --hard $COMMIT &&
check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist" zglob[!a]? &&
git -C escaped sparse-checkout init --cone &&
- git -C escaped sparse-checkout set zbad\\dir/bogus "zdoes*not*exist" "zdoes*exist" "zglob[!a]?" &&
+ git -C escaped sparse-checkout set --skip-checks zbad\\dir/bogus "zdoes*not*exist" "zdoes*exist" "zglob[!a]?" &&
cat >expect <<-\EOF &&
/*
!/*/
@@ -770,4 +816,59 @@ test_expect_success 'malformed cone-mode patterns' '
grep "warning: disabling cone pattern matching" err
'
+test_expect_success 'set from subdir pays attention to prefix' '
+ git -C repo sparse-checkout disable &&
+ git -C repo/deep sparse-checkout set --cone deeper2 ../folder1 &&
+
+ git -C repo sparse-checkout list >actual &&
+
+ cat >expect <<-\EOF &&
+ deep/deeper2
+ folder1
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'add from subdir pays attention to prefix' '
+ git -C repo sparse-checkout set --cone deep/deeper2 &&
+ git -C repo/deep sparse-checkout add deeper1/deepest ../folder1 &&
+
+ git -C repo sparse-checkout list >actual &&
+
+ cat >expect <<-\EOF &&
+ deep/deeper1/deepest
+ deep/deeper2
+ folder1
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'set from subdir in non-cone mode throws an error' '
+ git -C repo sparse-checkout disable &&
+ test_must_fail git -C repo/deep sparse-checkout set --no-cone deeper2 ../folder1 2>error &&
+
+ grep "run from the toplevel directory in non-cone mode" error
+'
+
+test_expect_success 'set from subdir in non-cone mode throws an error' '
+ git -C repo sparse-checkout set --no-cone deep/deeper2 &&
+ test_must_fail git -C repo/deep sparse-checkout add deeper1/deepest ../folder1 2>error &&
+
+ grep "run from the toplevel directory in non-cone mode" error
+'
+
+test_expect_success 'by default, cone mode will error out when passed files' '
+ git -C repo sparse-checkout reapply --cone &&
+ test_must_fail git -C repo sparse-checkout add .gitignore 2>error &&
+
+ grep ".gitignore.*is not a directory" error
+'
+
+test_expect_success 'by default, non-cone mode will warn on individual files' '
+ git -C repo sparse-checkout reapply --no-cone &&
+ git -C repo sparse-checkout add .gitignore 2>warning &&
+
+ grep "pass a leading slash before paths.*if you want a single file" warning
+'
+
test_done
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index f3a059e5af..2a04b532f9 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -367,7 +367,7 @@ test_expect_success 'status/add: outside sparse cone' '
write_script edit-contents <<-\EOF &&
echo text >>$1
EOF
- run_on_sparse ../edit-contents folder1/a &&
+ run_on_all ../edit-contents folder1/a &&
run_on_all ../edit-contents folder1/new &&
test_sparse_match git status --porcelain=v2 &&
@@ -376,8 +376,8 @@ test_expect_success 'status/add: outside sparse cone' '
test_sparse_match test_must_fail git add folder1/a &&
grep "Disable or modify the sparsity rules" sparse-checkout-err &&
test_sparse_unstaged folder1/a &&
- test_sparse_match test_must_fail git add --refresh folder1/a &&
- grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_all_match git add --refresh folder1/a &&
+ test_must_be_empty sparse-checkout-err &&
test_sparse_unstaged folder1/a &&
test_sparse_match test_must_fail git add folder1/new &&
grep "Disable or modify the sparsity rules" sparse-checkout-err &&
@@ -643,11 +643,11 @@ test_expect_success 'update-index modify outside sparse definition' '
run_on_sparse cp ../initial-repo/folder1/a folder1/a &&
run_on_all ../edit-contents folder1/a &&
- # If file has skip-worktree enabled, update-index does not modify the
- # index entry
- test_sparse_match git update-index folder1/a &&
- test_sparse_match git status --porcelain=v2 &&
- test_must_be_empty sparse-checkout-out &&
+ # If file has skip-worktree enabled, but the file is present, it is
+ # treated the same as if skip-worktree is disabled
+ test_all_match git status --porcelain=v2 &&
+ test_all_match git update-index folder1/a &&
+ test_all_match git status --porcelain=v2 &&
# When skip-worktree is disabled (even on files outside sparse cone), file
# is updated in the index
@@ -1331,30 +1331,27 @@ test_expect_success 'ls-files' '
test_cmp dense sparse &&
# Set up a strange condition of having a file edit
- # outside of the sparse-checkout cone. This is just
- # to verify that sparse-checkout and sparse-index
- # behave the same in this case.
+ # outside of the sparse-checkout cone. We want to verify
+ # that all modes handle this the same, and detect the
+ # modification.
write_script edit-content <<-\EOF &&
- mkdir folder1 &&
+ mkdir -p folder1 &&
echo content >>folder1/a
EOF
- run_on_sparse ../edit-content &&
+ run_on_all ../edit-content &&
- # ls-files does not currently notice modified files whose
- # cache entries are marked SKIP_WORKTREE. This may change
- # in the future, but here we test that sparse index does
- # not accidentally create a change of behavior.
- test_sparse_match git ls-files --modified &&
- test_must_be_empty sparse-checkout-out &&
- test_must_be_empty sparse-index-out &&
+ test_all_match git ls-files --modified &&
git -C sparse-index ls-files --sparse --modified >sparse-index-out &&
- test_must_be_empty sparse-index-out &&
+ cat >expect <<-\EOF &&
+ folder1/a
+ EOF
+ test_cmp expect sparse-index-out &&
# Add folder1 to the sparse-checkout cone and
# check that ls-files shows the expanded files.
test_sparse_match git sparse-checkout add folder1 &&
- test_sparse_match git ls-files --modified &&
+ test_all_match git ls-files --modified &&
test_all_match git ls-files &&
git -C sparse-index ls-files --sparse >actual &&
diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh
index b0119bf8bc..98cefe3b70 100755
--- a/t/t1512-rev-parse-disambiguation.sh
+++ b/t/t1512-rev-parse-disambiguation.sh
@@ -25,6 +25,87 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
+test_cmp_failed_rev_parse () {
+ dir=$1
+ rev=$2
+
+ cat >expect &&
+ test_must_fail git -C "$dir" rev-parse "$rev" 2>actual.raw &&
+ sed "s/\($rev\)[0-9a-f]*/\1.../" <actual.raw >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'ambiguous blob output' '
+ git init --bare blob.prefix &&
+ (
+ cd blob.prefix &&
+
+ # Both start with "dead..", under both SHA-1 and SHA-256
+ echo brocdnra | git hash-object -w --stdin &&
+ echo brigddsv | git hash-object -w --stdin &&
+
+ # Both start with "beef.."
+ echo 1agllotbh | git hash-object -w --stdin &&
+ echo 1bbfctrkc | git hash-object -w --stdin
+ ) &&
+
+ test_must_fail git -C blob.prefix rev-parse dead &&
+ test_cmp_failed_rev_parse blob.prefix beef <<-\EOF
+ error: short object ID beef... is ambiguous
+ hint: The candidates are:
+ hint: beef... blob
+ hint: beef... blob
+ fatal: ambiguous argument '\''beef...'\'': unknown revision or path not in the working tree.
+ Use '\''--'\'' to separate paths from revisions, like this:
+ '\''git <command> [<revision>...] -- [<file>...]'\''
+ EOF
+'
+
+test_expect_success 'ambiguous loose bad object parsed as OBJ_BAD' '
+ git init --bare blob.bad &&
+ (
+ cd blob.bad &&
+
+ # Both have the prefix "bad0"
+ echo xyzfaowcoh | git hash-object -t bad -w --stdin --literally &&
+ echo xyzhjpyvwl | git hash-object -t bad -w --stdin --literally
+ ) &&
+
+ test_cmp_failed_rev_parse blob.bad bad0 <<-\EOF
+ error: short object ID bad0... is ambiguous
+ fatal: invalid object type
+ EOF
+'
+
+test_expect_success POSIXPERM 'ambigous zlib corrupt loose blob' '
+ git init --bare blob.corrupt &&
+ (
+ cd blob.corrupt &&
+
+ # Both have the prefix "cafe"
+ echo bnkxmdwz | git hash-object -w --stdin &&
+ oid=$(echo bmwsjxzi | git hash-object -w --stdin) &&
+
+ oidf=objects/$(test_oid_to_path "$oid") &&
+ chmod 755 $oidf &&
+ echo broken >$oidf
+ ) &&
+
+ test_cmp_failed_rev_parse blob.corrupt cafe <<-\EOF
+ error: short object ID cafe... is ambiguous
+ error: inflate: data stream error (incorrect header check)
+ error: unable to unpack cafe... header
+ error: inflate: data stream error (incorrect header check)
+ error: unable to unpack cafe... header
+ hint: The candidates are:
+ hint: cafe... [bad object]
+ hint: cafe... blob
+ fatal: ambiguous argument '\''cafe...'\'': unknown revision or path not in the working tree.
+ Use '\''--'\'' to separate paths from revisions, like this:
+ '\''git <command> [<revision>...] -- [<file>...]'\''
+ EOF
+'
+
if ! test_have_prereq SHA1
then
skip_all='not using SHA-1 for objects'
diff --git a/t/t2060-switch.sh b/t/t2060-switch.sh
index ebb961be29..5a7caf958c 100755
--- a/t/t2060-switch.sh
+++ b/t/t2060-switch.sh
@@ -32,6 +32,17 @@ test_expect_success 'switch and detach' '
test_must_fail git symbolic-ref HEAD
'
+test_expect_success 'suggestion to detach' '
+ test_must_fail git switch main^{commit} 2>stderr &&
+ grep "try again with the --detach option" stderr
+'
+
+test_expect_success 'suggestion to detach is suppressed with advice.suggestDetachingHead=false' '
+ test_config advice.suggestDetachingHead false &&
+ test_must_fail git switch main^{commit} 2>stderr &&
+ ! grep "try again with the --detach option" stderr
+'
+
test_expect_success 'switch and detach current branch' '
test_when_finished git switch main &&
git switch main &&
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index 37ad79470f..43139af08f 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -165,8 +165,62 @@ test_expect_success '"add" default branch of a bare repo' '
(
git clone --bare . bare2 &&
cd bare2 &&
- git worktree add ../there3 main
- )
+ git worktree add ../there3 main &&
+ cd ../there3 &&
+ # Simple check that a Git command does not
+ # immediately fail with the current setup
+ git status
+ ) &&
+ cat >expect <<-EOF &&
+ init.t
+ EOF
+ ls there3 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '"add" to bare repo with worktree config' '
+ (
+ git clone --bare . bare3 &&
+ cd bare3 &&
+ git config extensions.worktreeconfig true &&
+
+ # Add config values that are erroneous to have in
+ # a config.worktree file outside of the main
+ # working tree, to check that Git filters them out
+ # when copying config during "git worktree add".
+ git config --worktree core.bare true &&
+ git config --worktree core.worktree "$(pwd)" &&
+
+ # We want to check that bogus.key is copied
+ git config --worktree bogus.key value &&
+ git config --unset core.bare &&
+ git worktree add ../there4 main &&
+ cd ../there4 &&
+
+ # Simple check that a Git command does not
+ # immediately fail with the current setup
+ git status &&
+ git worktree add --detach ../there5 &&
+ cd ../there5 &&
+ git status
+ ) &&
+
+ # the worktree has the arbitrary value copied.
+ test_cmp_config -C there4 value bogus.key &&
+ test_cmp_config -C there5 value bogus.key &&
+
+ # however, core.bare and core.worktree were removed.
+ test_must_fail git -C there4 config core.bare &&
+ test_must_fail git -C there4 config core.worktree &&
+
+ cat >expect <<-EOF &&
+ init.t
+ EOF
+
+ ls there4 >actual &&
+ test_cmp expect actual &&
+ ls there5 >actual &&
+ test_cmp expect actual
'
test_expect_success 'checkout with grafts' '
diff --git a/t/t3007-ls-files-recurse-submodules.sh b/t/t3007-ls-files-recurse-submodules.sh
index 4a08000713..dd7770e85d 100755
--- a/t/t3007-ls-files-recurse-submodules.sh
+++ b/t/t3007-ls-files-recurse-submodules.sh
@@ -34,6 +34,23 @@ test_expect_success 'ls-files correctly outputs files in submodule' '
test_cmp expect actual
'
+test_expect_success '--stage' '
+ GITMODULES_HASH=$(git rev-parse HEAD:.gitmodules) &&
+ A_HASH=$(git rev-parse HEAD:a) &&
+ B_HASH=$(git rev-parse HEAD:b/b) &&
+ C_HASH=$(git -C submodule rev-parse HEAD:c) &&
+
+ cat >expect <<-EOF &&
+ 100644 $GITMODULES_HASH 0 .gitmodules
+ 100644 $A_HASH 0 a
+ 100644 $B_HASH 0 b/b
+ 100644 $C_HASH 0 submodule/c
+ EOF
+
+ git ls-files --stage --recurse-submodules >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'ls-files correctly outputs files in submodule with -z' '
lf_to_nul >expect <<-\EOF &&
.gitmodules
@@ -292,7 +309,6 @@ test_incompatible_with_recurse_submodules () {
test_incompatible_with_recurse_submodules --deleted
test_incompatible_with_recurse_submodules --modified
test_incompatible_with_recurse_submodules --others
-test_incompatible_with_recurse_submodules --stage
test_incompatible_with_recurse_submodules --killed
test_incompatible_with_recurse_submodules --unmerged
diff --git a/t/t3705-add-sparse-checkout.sh b/t/t3705-add-sparse-checkout.sh
index 81f3384eee..95609046c6 100755
--- a/t/t3705-add-sparse-checkout.sh
+++ b/t/t3705-add-sparse-checkout.sh
@@ -19,6 +19,7 @@ setup_sparse_entry () {
fi &&
git add sparse_entry &&
git update-index --skip-worktree sparse_entry &&
+ git config core.sparseCheckout false &&
git commit --allow-empty -m "ensure sparse_entry exists at HEAD" &&
SPARSE_ENTRY_BLOB=$(git rev-parse :sparse_entry)
}
@@ -126,6 +127,7 @@ test_expect_success 'git add --chmod does not update sparse entries' '
'
test_expect_success 'git add --renormalize does not update sparse entries' '
+ test_when_finished rm .gitattributes &&
test_config core.autocrlf false &&
setup_sparse_entry "LINEONE\r\nLINETWO\r\n" &&
echo "sparse_entry text=auto" >.gitattributes &&
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index b149e2af44..f36e121210 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -390,10 +390,11 @@ test_expect_success SYMLINKS 'stash file to symlink' '
rm file &&
ln -s file2 file &&
git stash save "file to symlink" &&
- test -f file &&
+ test_path_is_file_not_symlink file &&
test bar = "$(cat file)" &&
git stash apply &&
- case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
+ test_path_is_symlink file &&
+ test "$(test_readlink file)" = file2
'
test_expect_success SYMLINKS 'stash file to symlink (stage rm)' '
@@ -401,10 +402,11 @@ test_expect_success SYMLINKS 'stash file to symlink (stage rm)' '
git rm file &&
ln -s file2 file &&
git stash save "file to symlink (stage rm)" &&
- test -f file &&
+ test_path_is_file_not_symlink file &&
test bar = "$(cat file)" &&
git stash apply &&
- case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
+ test_path_is_symlink file &&
+ test "$(test_readlink file)" = file2
'
test_expect_success SYMLINKS 'stash file to symlink (full stage)' '
@@ -413,10 +415,11 @@ test_expect_success SYMLINKS 'stash file to symlink (full stage)' '
ln -s file2 file &&
git add file &&
git stash save "file to symlink (full stage)" &&
- test -f file &&
+ test_path_is_file_not_symlink file &&
test bar = "$(cat file)" &&
git stash apply &&
- case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
+ test_path_is_symlink file &&
+ test "$(test_readlink file)" = file2
'
# This test creates a commit with a symlink used for the following tests
@@ -487,7 +490,7 @@ test_expect_failure 'stash directory to file' '
rm -fr dir &&
echo bar >dir &&
git stash save "directory to file" &&
- test -d dir &&
+ test_path_is_dir dir &&
test foo = "$(cat dir/file)" &&
test_must_fail git stash apply &&
test bar = "$(cat dir)" &&
@@ -500,10 +503,10 @@ test_expect_failure 'stash file to directory' '
mkdir file &&
echo foo >file/file &&
git stash save "file to directory" &&
- test -f file &&
+ test_path_is_file file &&
test bar = "$(cat file)" &&
git stash apply &&
- test -f file/file &&
+ test_path_is_file file/file &&
test foo = "$(cat file/file)"
'
@@ -1042,6 +1045,17 @@ test_expect_success 'create stores correct message' '
test_cmp expect actual
'
+test_expect_success 'create when branch name has /' '
+ test_when_finished "git checkout main" &&
+ git checkout -b some/topic &&
+ >foo &&
+ git add foo &&
+ STASH_ID=$(git stash create "create test message") &&
+ echo "On some/topic: create test message" >expect &&
+ git show --pretty=%s -s ${STASH_ID} >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'create with multiple arguments for the message' '
>foo &&
git add foo &&
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 6caff0ca39..159fae8d01 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -1169,7 +1169,7 @@ test_expect_success 'invalid when passing the --empty option alone' '
test_when_finished "git am --abort || :" &&
git checkout empty-commit^ &&
test_must_fail git am --empty empty-commit.patch 2>err &&
- echo "error: Invalid value for --empty: empty-commit.patch" >expected &&
+ echo "error: invalid value for '\''--empty'\'': '\''empty-commit.patch'\''" >expected &&
test_cmp expected err
'
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 544f0aa82e..55fac64446 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -462,6 +462,30 @@ test_expect_success !FAIL_PREREQS 'log with various grep.patternType configurati
)
'
+for cmd in show whatchanged reflog format-patch
+do
+ case "$cmd" in
+ format-patch) myarg="HEAD~.." ;;
+ *) myarg= ;;
+ esac
+
+ test_expect_success "$cmd: understands grep.patternType, like 'log'" '
+ git init "pattern-type-$cmd" &&
+ (
+ cd "pattern-type-$cmd" &&
+ test_commit 1 file A &&
+ test_commit "(1|2)" file B 2 &&
+
+ git -c grep.patternType=fixed $cmd --grep="..." $myarg >actual &&
+ test_must_be_empty actual &&
+
+ git -c grep.patternType=basic $cmd --grep="..." $myarg >actual &&
+ test_file_not_empty actual
+ )
+ '
+done
+test_done
+
test_expect_success 'log --author' '
cat >expect <<-\EOF &&
Author: <BOLD;RED>A U<RESET> Thor <author@example.com>
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index 8ee67df38f..b0095ab41d 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -284,4 +284,12 @@ test_expect_success 'index-pack -v --stdin produces progress for both phases' '
test_i18ngrep "Resolving deltas" err
'
+test_expect_success 'too-large packs report the breach' '
+ pack=$(git pack-objects --all pack </dev/null) &&
+ sz="$(test_file_size pack-$pack.pack)" &&
+ test "$sz" -gt 20 &&
+ test_must_fail git index-pack --max-input-size=20 pack-$pack.pack 2>err &&
+ grep "maximum allowed size (20 bytes)" err
+'
+
test_done
diff --git a/t/t5316-pack-delta-depth.sh b/t/t5316-pack-delta-depth.sh
index df524f7b6d..e9045009a1 100755
--- a/t/t5316-pack-delta-depth.sh
+++ b/t/t5316-pack-delta-depth.sh
@@ -64,7 +64,11 @@ test_expect_success 'create series of packs' '
echo $cur &&
echo "$(git rev-parse :file) file"
} | git pack-objects --stdout >tmp &&
- git index-pack --stdin --fix-thin <tmp || return 1
+ GIT_TRACE2_EVENT=$PWD/trace \
+ git index-pack -v --stdin --fix-thin <tmp || return 1 &&
+ grep -c region_enter.*progress trace >enter &&
+ grep -c region_leave.*progress trace >leave &&
+ test_cmp enter leave &&
prev=$cur
done
'
diff --git a/t/t5503-tagfollow.sh b/t/t5503-tagfollow.sh
index 195fc64dd4..e72fdc2534 100755
--- a/t/t5503-tagfollow.sh
+++ b/t/t5503-tagfollow.sh
@@ -160,4 +160,78 @@ test_expect_success 'new clone fetch main and tags' '
test_cmp expect actual
'
+test_expect_success 'atomic fetch with failing backfill' '
+ git init clone3 &&
+
+ # We want to test whether a failure when backfilling tags correctly
+ # aborts the complete transaction when `--atomic` is passed: we should
+ # neither create the branch nor should we create the tag when either
+ # one of both fails to update correctly.
+ #
+ # To trigger failure we simply abort when backfilling a tag.
+ write_script clone3/.git/hooks/reference-transaction <<-\EOF &&
+ while read oldrev newrev reference
+ do
+ if test "$reference" = refs/tags/tag1
+ then
+ exit 1
+ fi
+ done
+ EOF
+
+ test_must_fail git -C clone3 fetch --atomic .. $B:refs/heads/something &&
+ test_must_fail git -C clone3 rev-parse --verify refs/heads/something &&
+ test_must_fail git -C clone3 rev-parse --verify refs/tags/tag2
+'
+
+test_expect_success 'atomic fetch with backfill should use single transaction' '
+ git init clone4 &&
+
+ # Fetching with the `--atomic` flag should update all references in a
+ # single transaction, including backfilled tags. We thus expect to see
+ # a single reference transaction for the created branch and tags.
+ cat >expected <<-EOF &&
+ prepared
+ $ZERO_OID $B refs/heads/something
+ $ZERO_OID $S refs/tags/tag2
+ $ZERO_OID $T refs/tags/tag1
+ committed
+ $ZERO_OID $B refs/heads/something
+ $ZERO_OID $S refs/tags/tag2
+ $ZERO_OID $T refs/tags/tag1
+ EOF
+
+ write_script clone4/.git/hooks/reference-transaction <<-\EOF &&
+ ( echo "$*" && cat ) >>actual
+ EOF
+
+ git -C clone4 fetch --atomic .. $B:refs/heads/something &&
+ test_cmp expected clone4/actual
+'
+
+test_expect_success 'backfill failure causes command to fail' '
+ git init clone5 &&
+
+ write_script clone5/.git/hooks/reference-transaction <<-EOF &&
+ while read oldrev newrev reference
+ do
+ if test "\$reference" = refs/tags/tag1
+ then
+ # Create a nested tag below the actual tag we
+ # wanted to write, which causes a D/F conflict
+ # later when we want to commit refs/tags/tag1.
+ # We cannot just `exit 1` here given that this
+ # would cause us to die immediately.
+ git update-ref refs/tags/tag1/nested $B
+ exit \$!
+ fi
+ done
+ EOF
+
+ test_must_fail git -C clone5 fetch .. $B:refs/heads/something &&
+ test $B = $(git -C clone5 rev-parse --verify refs/heads/something) &&
+ test $S = $(git -C clone5 rev-parse --verify tag2) &&
+ test_must_fail git -C clone5 rev-parse --verify tag1
+'
+
test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index ef0da0a63b..48e14e2dab 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -343,6 +343,35 @@ test_expect_success 'fetch --atomic --append appends to FETCH_HEAD' '
test_cmp expected atomic/.git/FETCH_HEAD
'
+test_expect_success 'fetch --atomic --prune executes a single reference transaction only' '
+ test_when_finished "rm -rf \"$D\"/atomic" &&
+
+ cd "$D" &&
+ git branch scheduled-for-deletion &&
+ git clone . atomic &&
+ git branch -D scheduled-for-deletion &&
+ git branch new-branch &&
+ head_oid=$(git rev-parse HEAD) &&
+
+ # Fetching with the `--atomic` flag should update all references in a
+ # single transaction.
+ cat >expected <<-EOF &&
+ prepared
+ $ZERO_OID $ZERO_OID refs/remotes/origin/scheduled-for-deletion
+ $ZERO_OID $head_oid refs/remotes/origin/new-branch
+ committed
+ $ZERO_OID $ZERO_OID refs/remotes/origin/scheduled-for-deletion
+ $ZERO_OID $head_oid refs/remotes/origin/new-branch
+ EOF
+
+ write_script atomic/.git/hooks/reference-transaction <<-\EOF &&
+ ( echo "$*" && cat ) >>actual
+ EOF
+
+ git -C atomic fetch --atomic --prune origin &&
+ test_cmp expected atomic/actual
+'
+
test_expect_success '--refmap="" ignores configured refspec' '
cd "$TRASH_DIRECTORY" &&
git clone "$D" remote-refs &&
diff --git a/t/t5571-pre-push-hook.sh b/t/t5571-pre-push-hook.sh
index 660f876eec..96d6ecc0af 100755
--- a/t/t5571-pre-push-hook.sh
+++ b/t/t5571-pre-push-hook.sh
@@ -11,7 +11,7 @@ HOOKDIR="$(git rev-parse --git-dir)/hooks"
HOOK="$HOOKDIR/pre-push"
mkdir -p "$HOOKDIR"
write_script "$HOOK" <<EOF
-cat >/dev/null
+cat >actual
exit 0
EOF
@@ -20,10 +20,16 @@ test_expect_success 'setup' '
git init --bare repo1 &&
git remote add parent1 repo1 &&
test_commit one &&
- git push parent1 HEAD:foreign
+ cat >expect <<-EOF &&
+ HEAD $(git rev-parse HEAD) refs/heads/foreign $(test_oid zero)
+ EOF
+
+ test_when_finished "rm actual" &&
+ git push parent1 HEAD:foreign &&
+ test_cmp expect actual
'
write_script "$HOOK" <<EOF
-cat >/dev/null
+cat >actual
exit 1
EOF
@@ -32,11 +38,18 @@ export COMMIT1
test_expect_success 'push with failing hook' '
test_commit two &&
- test_must_fail git push parent1 HEAD
+ cat >expect <<-EOF &&
+ HEAD $(git rev-parse HEAD) refs/heads/main $(test_oid zero)
+ EOF
+
+ test_when_finished "rm actual" &&
+ test_must_fail git push parent1 HEAD &&
+ test_cmp expect actual
'
test_expect_success '--no-verify bypasses hook' '
- git push --no-verify parent1 HEAD
+ git push --no-verify parent1 HEAD &&
+ test_path_is_missing actual
'
COMMIT2="$(git rev-parse HEAD)"
@@ -48,15 +61,15 @@ echo "$2" >>actual
cat >>actual
EOF
-cat >expected <<EOF
-parent1
-repo1
-refs/heads/main $COMMIT2 refs/heads/foreign $COMMIT1
-EOF
-
test_expect_success 'push with hook' '
+ cat >expect <<-EOF &&
+ parent1
+ repo1
+ refs/heads/main $COMMIT2 refs/heads/foreign $COMMIT1
+ EOF
+
git push parent1 main:foreign &&
- diff expected actual
+ test_cmp expect actual
'
test_expect_success 'add a branch' '
@@ -67,49 +80,48 @@ test_expect_success 'add a branch' '
COMMIT3="$(git rev-parse HEAD)"
export COMMIT3
-cat >expected <<EOF
-parent1
-repo1
-refs/heads/other $COMMIT3 refs/heads/foreign $COMMIT2
-EOF
-
test_expect_success 'push to default' '
+ cat >expect <<-EOF &&
+ parent1
+ repo1
+ refs/heads/other $COMMIT3 refs/heads/foreign $COMMIT2
+ EOF
git push &&
- diff expected actual
+ test_cmp expect actual
'
-cat >expected <<EOF
-parent1
-repo1
-refs/tags/one $COMMIT1 refs/tags/tag1 $ZERO_OID
-HEAD~ $COMMIT2 refs/heads/prev $ZERO_OID
-EOF
-
test_expect_success 'push non-branches' '
+ cat >expect <<-EOF &&
+ parent1
+ repo1
+ refs/tags/one $COMMIT1 refs/tags/tag1 $ZERO_OID
+ HEAD~ $COMMIT2 refs/heads/prev $ZERO_OID
+ EOF
+
git push parent1 one:tag1 HEAD~:refs/heads/prev &&
- diff expected actual
+ test_cmp expect actual
'
-cat >expected <<EOF
-parent1
-repo1
-(delete) $ZERO_OID refs/heads/prev $COMMIT2
-EOF
-
test_expect_success 'push delete' '
+ cat >expect <<-EOF &&
+ parent1
+ repo1
+ (delete) $ZERO_OID refs/heads/prev $COMMIT2
+ EOF
+
git push parent1 :prev &&
- diff expected actual
+ test_cmp expect actual
'
-cat >expected <<EOF
-repo1
-repo1
-HEAD $COMMIT3 refs/heads/other $ZERO_OID
-EOF
-
test_expect_success 'push to URL' '
+ cat >expect <<-EOF &&
+ repo1
+ repo1
+ HEAD $COMMIT3 refs/heads/other $ZERO_OID
+ EOF
+
git push repo1 HEAD &&
- diff expected actual
+ test_cmp expect actual
'
test_expect_success 'set up many-ref tests' '
diff --git a/t/t5617-clone-submodules-remote.sh b/t/t5617-clone-submodules-remote.sh
index e2dbb4eaba..ca8f80083a 100755
--- a/t/t5617-clone-submodules-remote.sh
+++ b/t/t5617-clone-submodules-remote.sh
@@ -28,6 +28,13 @@ test_expect_success 'setup' '
)
'
+# bare clone giving "srv.bare" for use as our server.
+test_expect_success 'setup bare clone for server' '
+ git clone --bare "file://$(pwd)/." srv.bare &&
+ git -C srv.bare config --local uploadpack.allowfilter 1 &&
+ git -C srv.bare config --local uploadpack.allowanysha1inwant 1
+'
+
test_expect_success 'clone with --no-remote-submodules' '
test_when_finished "rm -rf super_clone" &&
git clone --recurse-submodules --no-remote-submodules "file://$pwd/." super_clone &&
@@ -65,4 +72,38 @@ test_expect_success 'clone with --single-branch' '
)
'
+# do basic partial clone from "srv.bare"
+# confirm partial clone was registered in the local config for super and sub.
+test_expect_success 'clone with --filter' '
+ git clone --recurse-submodules \
+ --filter blob:none --also-filter-submodules \
+ "file://$pwd/srv.bare" super_clone &&
+ test_cmp_config -C super_clone true remote.origin.promisor &&
+ test_cmp_config -C super_clone blob:none remote.origin.partialclonefilter &&
+ test_cmp_config -C super_clone/sub true remote.origin.promisor &&
+ test_cmp_config -C super_clone/sub blob:none remote.origin.partialclonefilter
+'
+
+# check that clone.filterSubmodules works (--also-filter-submodules can be
+# omitted)
+test_expect_success 'filters applied with clone.filterSubmodules' '
+ test_config_global clone.filterSubmodules true &&
+ git clone --recurse-submodules --filter blob:none \
+ "file://$pwd/srv.bare" super_clone2 &&
+ test_cmp_config -C super_clone2 true remote.origin.promisor &&
+ test_cmp_config -C super_clone2 blob:none remote.origin.partialclonefilter &&
+ test_cmp_config -C super_clone2/sub true remote.origin.promisor &&
+ test_cmp_config -C super_clone2/sub blob:none remote.origin.partialclonefilter
+'
+
+test_expect_success '--no-also-filter-submodules overrides clone.filterSubmodules=true' '
+ test_config_global clone.filterSubmodules true &&
+ git clone --recurse-submodules --filter blob:none \
+ --no-also-filter-submodules \
+ "file://$pwd/srv.bare" super_clone3 &&
+ test_cmp_config -C super_clone3 true remote.origin.promisor &&
+ test_cmp_config -C super_clone3 blob:none remote.origin.partialclonefilter &&
+ test_cmp_config -C super_clone3/sub false --default false remote.origin.promisor
+'
+
test_done
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 1be85d064e..5382e5d216 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -278,6 +278,51 @@ test_expect_success '"git bisect run" with more complex "git bisect start"' '
git bisect reset
'
+test_expect_success 'bisect run accepts exit code 126 as bad' '
+ test_when_finished "git bisect reset" &&
+ write_script test_script.sh <<-\EOF &&
+ ! grep Another hello || exit 126 >/dev/null
+ EOF
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ git bisect run ./test_script.sh >my_bisect_log.txt &&
+ grep "$HASH3 is the first bad commit" my_bisect_log.txt
+'
+
+test_expect_success POSIXPERM 'bisect run fails with non-executable test script' '
+ test_when_finished "git bisect reset" &&
+ >not-executable.sh &&
+ chmod -x not-executable.sh &&
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ test_must_fail git bisect run ./not-executable.sh >my_bisect_log.txt &&
+ ! grep "is the first bad commit" my_bisect_log.txt
+'
+
+test_expect_success 'bisect run accepts exit code 127 as bad' '
+ test_when_finished "git bisect reset" &&
+ write_script test_script.sh <<-\EOF &&
+ ! grep Another hello || exit 127 >/dev/null
+ EOF
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ git bisect run ./test_script.sh >my_bisect_log.txt &&
+ grep "$HASH3 is the first bad commit" my_bisect_log.txt
+'
+
+test_expect_success 'bisect run fails with missing test script' '
+ test_when_finished "git bisect reset" &&
+ rm -f does-not-exist.sh &&
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ test_must_fail git bisect run ./does-not-exist.sh >my_bisect_log.txt &&
+ ! grep "is the first bad commit" my_bisect_log.txt
+'
+
# $HASH1 is good, $HASH5 is bad, we skip $HASH3
# but $HASH4 is good,
# so we should find $HASH5 as the first bad commit
diff --git a/t/t6428-merge-conflicts-sparse.sh b/t/t6428-merge-conflicts-sparse.sh
index 7e8bf497f8..142c9aaabc 100755
--- a/t/t6428-merge-conflicts-sparse.sh
+++ b/t/t6428-merge-conflicts-sparse.sh
@@ -112,7 +112,7 @@ test_expect_success 'conflicting entries written to worktree even if sparse' '
)
'
-test_expect_merge_algorithm failure success 'present-despite-SKIP_WORKTREE handled reasonably' '
+test_expect_success 'present-despite-SKIP_WORKTREE handled reasonably' '
test_setup_numerals in_the_way &&
(
cd numerals_in_the_way &&
@@ -132,26 +132,13 @@ test_expect_merge_algorithm failure success 'present-despite-SKIP_WORKTREE handl
test_must_fail git merge -s recursive B^0 &&
- git ls-files -t >index_files &&
- test_cmp expected-index index_files &&
+ test_path_is_missing .git/MERGE_HEAD &&
- test_path_is_file README &&
test_path_is_file numerals &&
- test_cmp expected-merge numerals &&
-
- # There should still be a file with "foobar" in it
- grep foobar * &&
-
- # 5 other files:
- # * expected-merge
- # * expected-index
- # * index_files
- # * others
- # * whatever name was given to the numerals file that had
- # "foobar" in it
- git ls-files -o >others &&
- test_line_count = 5 others
+ # numerals should still have "foobar" in it
+ echo foobar >expect &&
+ test_cmp expect numerals
)
'
diff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh
index a1080b94e3..cb9f1a6981 100755
--- a/t/t7012-skip-worktree-writing.sh
+++ b/t/t7012-skip-worktree-writing.sh
@@ -171,50 +171,20 @@ test_expect_success 'stash restore in sparse checkout' '
# Put a file in the working directory in the way
echo in the way >modified &&
- git stash apply &&
+ test_must_fail git stash apply 2>error&&
- # Ensure stash vivifies modifies paths...
- cat >expect <<-EOF &&
- H addme
- H modified
- H removeme
- H subdir/A
- S untouched
- EOF
- git ls-files -t >actual &&
- test_cmp expect actual &&
+ grep "changes.*would be overwritten by merge" error &&
- # ...and that the paths show up in status as changed...
- cat >expect <<-EOF &&
- A addme
- M modified
- D removeme
- M subdir/A
- ?? actual
- ?? expect
- ?? modified.stash.XXXXXX
- EOF
- git status --porcelain | \
- sed -e s/stash......./stash.XXXXXX/ >actual &&
- test_cmp expect actual &&
+ echo in the way >expect &&
+ test_cmp expect modified &&
+ git diff --quiet HEAD ":!modified" &&
# ...and that working directory reflects the files correctly
- test_path_is_file addme &&
+ test_path_is_missing addme &&
test_path_is_file modified &&
test_path_is_missing removeme &&
test_path_is_file subdir/A &&
- test_path_is_missing untouched &&
-
- # ...including that we have the expected "modified" file...
- cat >expect <<-EOF &&
- modified
- tweaked
- EOF
- test_cmp expect modified &&
-
- # ...and that the other "modified" file is still present...
- echo in the way >expect &&
- test_cmp expect modified.stash.*
+ test_path_is_missing untouched
)
'
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 91964653a0..5fcaa0b4f2 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
'
test_expect_success '--fixup=reword: -F give error message' '
- echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
+ echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
test_must_fail git commit --fixup=reword:HEAD~ -F msg 2>actual &&
test_cmp expect actual
'
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 424c31c328..6935601171 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -98,6 +98,37 @@ test_expect_success 'grep should not segfault with a bad input' '
test_invalid_grep_expression --and -e A
+test_pattern_type () {
+ H=$1 &&
+ HC=$2 &&
+ L=$3 &&
+ type=$4 &&
+ shift 4 &&
+
+ expected_str= &&
+ case "$type" in
+ BRE)
+ expected_str="${HC}ab:a+bc"
+ ;;
+ ERE)
+ expected_str="${HC}ab:abc"
+ ;;
+ FIX)
+ expected_str="${HC}ab:a+b*c"
+ ;;
+ *)
+ BUG "unknown pattern type '$type'"
+ ;;
+ esac &&
+ config_str="$@" &&
+
+ test_expect_success "grep $L with '$config_str' interpreted as $type" '
+ echo $expected_str >expected &&
+ git $config_str grep "a+b*c" $H ab >actual &&
+ test_cmp expected actual
+ '
+}
+
for H in HEAD ''
do
case "$H" in
@@ -393,35 +424,13 @@ do
git grep --no-recursive -n -e vvv $H -- t . >actual &&
test_cmp expected actual
'
- test_expect_success "grep $L with grep.extendedRegexp=false" '
- echo "${HC}ab:a+bc" >expected &&
- git -c grep.extendedRegexp=false grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
- test_expect_success "grep $L with grep.extendedRegexp=true" '
- echo "${HC}ab:abc" >expected &&
- git -c grep.extendedRegexp=true grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
- test_expect_success "grep $L with grep.patterntype=basic" '
- echo "${HC}ab:a+bc" >expected &&
- git -c grep.patterntype=basic grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
-
- test_expect_success "grep $L with grep.patterntype=extended" '
- echo "${HC}ab:abc" >expected &&
- git -c grep.patterntype=extended grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
-
- test_expect_success "grep $L with grep.patterntype=fixed" '
- echo "${HC}ab:a+b*c" >expected &&
- git -c grep.patterntype=fixed grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
+ test_pattern_type "$H" "$HC" "$L" BRE -c grep.extendedRegexp=false
+ test_pattern_type "$H" "$HC" "$L" ERE -c grep.extendedRegexp=true
+ test_pattern_type "$H" "$HC" "$L" BRE -c grep.patternType=basic
+ test_pattern_type "$H" "$HC" "$L" ERE -c grep.patternType=extended
+ test_pattern_type "$H" "$HC" "$L" FIX -c grep.patternType=fixed
test_expect_success PCRE "grep $L with grep.patterntype=perl" '
echo "${HC}ab:a+b*c" >expected &&
@@ -433,59 +442,76 @@ do
test_must_fail git -c grep.patterntype=perl grep "foo.*bar"
'
- test_expect_success "grep $L with grep.patternType=default and grep.extendedRegexp=true" '
- echo "${HC}ab:abc" >expected &&
- git \
- -c grep.patternType=default \
- -c grep.extendedRegexp=true \
- grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
-
- test_expect_success "grep $L with grep.extendedRegexp=true and grep.patternType=default" '
- echo "${HC}ab:abc" >expected &&
- git \
- -c grep.extendedRegexp=true \
- -c grep.patternType=default \
- grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
-
- test_expect_success "grep $L with grep.patternType=extended and grep.extendedRegexp=false" '
- echo "${HC}ab:abc" >expected &&
- git \
- -c grep.patternType=extended \
- -c grep.extendedRegexp=false \
- grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
-
- test_expect_success "grep $L with grep.patternType=basic and grep.extendedRegexp=true" '
- echo "${HC}ab:a+bc" >expected &&
- git \
- -c grep.patternType=basic \
- -c grep.extendedRegexp=true \
- grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
-
- test_expect_success "grep $L with grep.extendedRegexp=false and grep.patternType=extended" '
- echo "${HC}ab:abc" >expected &&
- git \
- -c grep.extendedRegexp=false \
- -c grep.patternType=extended \
- grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
-
- test_expect_success "grep $L with grep.extendedRegexp=true and grep.patternType=basic" '
- echo "${HC}ab:a+bc" >expected &&
- git \
- -c grep.extendedRegexp=true \
- -c grep.patternType=basic \
- grep "a+b*c" $H ab >actual &&
- test_cmp expected actual
- '
+ test_pattern_type "$H" "$HC" "$L" ERE \
+ -c grep.patternType=default \
+ -c grep.extendedRegexp=true
+ test_pattern_type "$H" "$HC" "$L" ERE \
+ -c grep.extendedRegexp=true \
+ -c grep.patternType=default
+ test_pattern_type "$H" "$HC" "$L" ERE \
+ -c grep.patternType=extended \
+ -c grep.extendedRegexp=false
+ test_pattern_type "$H" "$HC" "$L" BRE \
+ -c grep.patternType=basic \
+ -c grep.extendedRegexp=true
+ test_pattern_type "$H" "$HC" "$L" ERE \
+ -c grep.extendedRegexp=false \
+ -c grep.patternType=extended
+ test_pattern_type "$H" "$HC" "$L" BRE \
+ -c grep.extendedRegexp=true \
+ -c grep.patternType=basic
+
+ # grep.extendedRegexp is last-one-wins
+ test_pattern_type "$H" "$HC" "$L" BRE \
+ -c grep.extendedRegexp=true \
+ -c grep.extendedRegexp=false
+
+ # grep.patternType=basic pays no attention to grep.extendedRegexp
+ test_pattern_type "$H" "$HC" "$L" BRE \
+ -c grep.extendedRegexp=true \
+ -c grep.patternType=basic \
+ -c grep.extendedRegexp=false
+
+ # grep.patternType=extended pays no attention to grep.extendedRegexp
+ test_pattern_type "$H" "$HC" "$L" ERE \
+ -c grep.extendedRegexp=true \
+ -c grep.patternType=extended \
+ -c grep.extendedRegexp=false
+
+ # grep.extendedRegexp is used with a last-one-wins grep.patternType=default
+ test_pattern_type "$H" "$HC" "$L" ERE \
+ -c grep.patternType=fixed \
+ -c grep.extendedRegexp=true \
+ -c grep.patternType=default
+
+ # grep.extendedRegexp is used with earlier grep.patternType=default
+ test_pattern_type "$H" "$HC" "$L" ERE \
+ -c grep.extendedRegexp=false \
+ -c grep.patternType=default \
+ -c grep.extendedRegexp=true
+
+ # grep.extendedRegexp is used with a last-one-loses grep.patternType=default
+ test_pattern_type "$H" "$HC" "$L" ERE \
+ -c grep.extendedRegexp=false \
+ -c grep.extendedRegexp=true \
+ -c grep.patternType=default
+
+ # grep.extendedRegexp and grep.patternType are both last-one-wins independently
+ test_pattern_type "$H" "$HC" "$L" BRE \
+ -c grep.patternType=default \
+ -c grep.extendedRegexp=true \
+ -c grep.patternType=basic
+
+ # grep.patternType=extended and grep.patternType=default
+ test_pattern_type "$H" "$HC" "$L" BRE \
+ -c grep.patternType=extended \
+ -c grep.patternType=default
+
+ # grep.patternType=[extended -> default -> fixed] (BRE)" '
+ test_pattern_type "$H" "$HC" "$L" FIX \
+ -c grep.patternType=extended \
+ -c grep.patternType=default \
+ -c grep.patternType=fixed
test_expect_success "grep --count $L" '
echo ${HC}ab:3 >expected &&
diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh
index 058e5d0c96..a4476dc492 100755
--- a/t/t7814-grep-recurse-submodules.sh
+++ b/t/t7814-grep-recurse-submodules.sh
@@ -544,4 +544,45 @@ test_expect_failure 'grep saves textconv cache in the appropriate repository' '
test_path_is_file "$sub_textconv_cache"
'
+test_expect_success 'grep partially-cloned submodule' '
+ # Set up clean superproject and submodule for partial cloning.
+ git init super &&
+ git init super/sub &&
+ (
+ cd super &&
+ test_commit --no-tag "Add file in superproject" \
+ super-file "Some content for super-file" &&
+ test_commit -C sub --no-tag "Add file in submodule" \
+ sub-file "Some content for sub-file" &&
+ git submodule add ./sub &&
+ git commit -m "Add other as submodule sub" &&
+ test_tick &&
+ test_commit -C sub --no-tag --append "Update file in submodule" \
+ sub-file "Some more content for sub-file" &&
+ git add sub &&
+ git commit -m "Update submodule" &&
+ test_tick &&
+ git config --local uploadpack.allowfilter 1 &&
+ git config --local uploadpack.allowanysha1inwant 1 &&
+ git -C sub config --local uploadpack.allowfilter 1 &&
+ git -C sub config --local uploadpack.allowanysha1inwant 1
+ ) &&
+ # Clone the superproject & submodule, then make sure we can lazy-fetch submodule objects.
+ git clone --filter=blob:none --also-filter-submodules \
+ --recurse-submodules "file://$(pwd)/super" partial &&
+ (
+ cd partial &&
+ cat >expect <<-\EOF &&
+ HEAD^:sub/sub-file:Some content for sub-file
+ HEAD^:super-file:Some content for super-file
+ EOF
+
+ GIT_TRACE2_EVENT="$(pwd)/trace2.log" git grep -e content \
+ --recurse-submodules HEAD^ >actual &&
+ test_cmp expect actual &&
+ # Verify that we actually fetched data from the promisor remote:
+ grep \"category\":\"promisor\",\"key\":\"fetch_count\",\"value\":\"1\" trace2.log
+ )
+'
+
test_done
diff --git a/t/t7817-grep-sparse-checkout.sh b/t/t7817-grep-sparse-checkout.sh
index 590b99bbb6..eb59564565 100755
--- a/t/t7817-grep-sparse-checkout.sh
+++ b/t/t7817-grep-sparse-checkout.sh
@@ -83,10 +83,13 @@ test_expect_success 'setup' '
# The test below covers a special case: the sparsity patterns exclude '/b' and
# sparse checkout is enabled, but the path exists in the working tree (e.g.
-# manually created after `git sparse-checkout init`). git grep should skip it.
+# manually created after `git sparse-checkout init`). Although b is marked
+# as SKIP_WORKTREE, git grep should notice it IS present in the worktree and
+# report it.
test_expect_success 'working tree grep honors sparse checkout' '
cat >expect <<-EOF &&
a:text
+ b:new-text
EOF
test_when_finished "rm -f b" &&
echo "new-text" >b &&
@@ -126,12 +129,16 @@ test_expect_success 'grep --cached searches entries with the SKIP_WORKTREE bit'
'
# Note that sub2/ is present in the worktree but it is excluded by the sparsity
-# patterns, so grep should not recurse into it.
+# patterns. We also explicitly mark it as SKIP_WORKTREE in case it got cleared
+# by previous git commands. Thus sub2 starts as SKIP_WORKTREE but since it is
+# present in the working tree, grep should recurse into it.
test_expect_success 'grep --recurse-submodules honors sparse checkout in submodule' '
cat >expect <<-EOF &&
a:text
sub/B/b:text
+ sub2/a:text
EOF
+ git update-index --skip-worktree sub2 &&
git grep --recurse-submodules "text" >actual &&
test_cmp expect actual
'
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 85385d2ede..0f439c99d6 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -856,6 +856,16 @@ test_path_is_file () {
fi
}
+test_path_is_file_not_symlink () {
+ test "$#" -ne 1 && BUG "1 param"
+ test_path_is_file "$1" &&
+ if test -h "$1"
+ then
+ echo "$1 shouldn't be a symbolic link"
+ false
+ fi
+}
+
test_path_is_dir () {
test "$#" -ne 1 && BUG "1 param"
if ! test -d "$1"
@@ -865,6 +875,16 @@ test_path_is_dir () {
fi
}
+test_path_is_dir_not_symlink () {
+ test "$#" -ne 1 && BUG "1 param"
+ test_path_is_dir "$1" &&
+ if test -h "$1"
+ then
+ echo "$1 shouldn't be a symbolic link"
+ false
+ fi
+}
+
test_path_exists () {
test "$#" -ne 1 && BUG "1 param"
if ! test -e "$1"
@@ -874,6 +894,15 @@ test_path_exists () {
fi
}
+test_path_is_symlink () {
+ test "$#" -ne 1 && BUG "1 param"
+ if ! test -h "$1"
+ then
+ echo "Symbolic link $1 doesn't exist"
+ false
+ fi
+}
+
# Check if the directory exists and is empty as expected, barf otherwise.
test_dir_is_empty () {
test "$#" -ne 1 && BUG "1 param"
diff --git a/t/test-lib.sh b/t/test-lib.sh
index e4716b0b86..9af5fb7674 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -19,13 +19,20 @@
# t/ subdirectory and are run in 'trash directory' subdirectory.
if test -z "$TEST_DIRECTORY"
then
- # We allow tests to override this, in case they want to run tests
- # outside of t/, e.g. for running tests on the test library
- # itself.
- TEST_DIRECTORY=$(pwd)
-else
# ensure that TEST_DIRECTORY is an absolute path so that it
# is valid even if the current working directory is changed
+ TEST_DIRECTORY=$(pwd)
+else
+ # The TEST_DIRECTORY will always be the path to the "t"
+ # directory in the git.git checkout. This is overridden by
+ # e.g. t/lib-subtest.sh, but only because its $(pwd) is
+ # different. Those tests still set "$TEST_DIRECTORY" to the
+ # same path.
+ #
+ # See use of "$GIT_BUILD_DIR" and "$TEST_DIRECTORY" below for
+ # hard assumptions about "$GIT_BUILD_DIR/t" existing and being
+ # the "$TEST_DIRECTORY", and e.g. "$TEST_DIRECTORY/helper"
+ # needing to exist.
TEST_DIRECTORY=$(cd "$TEST_DIRECTORY" && pwd) || exit 1
fi
if test -z "$TEST_OUTPUT_DIRECTORY"
@@ -34,19 +41,42 @@ then
# elsewhere
TEST_OUTPUT_DIRECTORY=$TEST_DIRECTORY
fi
-GIT_BUILD_DIR="$TEST_DIRECTORY"/..
+GIT_BUILD_DIR="${TEST_DIRECTORY%/t}"
+if test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR"
+then
+ echo "PANIC: Running in a $TEST_DIRECTORY that doesn't end in '/t'?" >&2
+ exit 1
+fi
+
+# Prepend a string to a VAR using an arbitrary ":" delimiter, not
+# adding the delimiter if VAR or VALUE is empty. I.e. a generalized:
+#
+# VAR=$1${VAR:+${1:+$2}$VAR}
+#
+# Usage (using ":" as the $2 delimiter):
+#
+# prepend_var VAR : VALUE
+prepend_var () {
+ eval "$1=$3\${$1:+${3:+$2}\$$1}"
+}
+
+# If [AL]SAN is in effect we want to abort so that we notice
+# problems. The GIT_SAN_OPTIONS variable can be used to set common
+# defaults shared between [AL]SAN_OPTIONS.
+prepend_var GIT_SAN_OPTIONS : abort_on_error=1
+prepend_var GIT_SAN_OPTIONS : strip_path_prefix=\"$GIT_BUILD_DIR/\"
# If we were built with ASAN, it may complain about leaks
# of program-lifetime variables. Disable it by default to lower
# the noise level. This needs to happen at the start of the script,
# before we even do our "did we build git yet" check (since we don't
# want that one to complain to stderr).
-: ${ASAN_OPTIONS=detect_leaks=0:abort_on_error=1}
+prepend_var ASAN_OPTIONS : $GIT_SAN_OPTIONS
+prepend_var ASAN_OPTIONS : detect_leaks=0
export ASAN_OPTIONS
-# If LSAN is in effect we _do_ want leak checking, but we still
-# want to abort so that we notice the problems.
-: ${LSAN_OPTIONS=abort_on_error=1}
+prepend_var LSAN_OPTIONS : $GIT_SAN_OPTIONS
+prepend_var LSAN_OPTIONS : fast_unwind_on_malloc=0
export LSAN_OPTIONS
if test ! -f "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS