aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/helper/test-bitmap.c8
-rw-r--r--t/helper/test-find-pack.c2
-rw-r--r--t/helper/test-pack-mtimes.c2
-rw-r--r--t/helper/test-parse-options.c17
-rw-r--r--t/helper/test-partial-clone.c4
-rw-r--r--t/helper/test-read-graph.c8
-rw-r--r--t/helper/test-read-midx.c2
-rw-r--r--t/helper/test-ref-store.c4
-rw-r--r--t/helper/test-string-list.c96
-rw-r--r--t/meson.build3
-rwxr-xr-xt/t0001-init.sh45
-rwxr-xr-xt/t0021-conversion.sh4
-rwxr-xr-xt/t0063-string-list.sh142
-rwxr-xr-xt/t0610-reftable-basics.sh6
-rwxr-xr-xt/t0612-reftable-jgit-compatibility.sh13
-rwxr-xr-xt/t0613-reftable-write-options.sh24
-rwxr-xr-xt/t1006-cat-file.sh2
-rwxr-xr-xt/t1007-hash-object.sh4
-rwxr-xr-xt/t1021-rerere-in-workdir.sh58
-rwxr-xr-xt/t1300-config.sh11
-rwxr-xr-xt/t1400-update-ref.sh74
-rwxr-xr-xt/t1416-ref-transaction-hooks.sh2
-rwxr-xr-xt/t1517-outside-repo.sh7
-rwxr-xr-xt/t2400-worktree-add.sh20
-rwxr-xr-xt/t3000-ls-files-others.sh19
-rwxr-xr-xt/t3903-stash.sh173
-rwxr-xr-xt/t4013-diff-various.sh27
-rwxr-xr-xt/t4042-diff-textconv-caching.sh12
-rwxr-xr-xt/t4140-apply-ita.sh31
-rwxr-xr-xt/t4150-am.sh2
-rwxr-xr-xt/t4202-log.sh40
-rwxr-xr-xt/t4203-mailmap.sh33
-rwxr-xr-xt/t5004-archive-corner-cases.sh5
-rwxr-xr-xt/t5300-pack-object.sh6
-rwxr-xr-xt/t5310-pack-bitmaps.sh30
-rwxr-xr-xt/t5323-pack-redundant.sh5
-rwxr-xr-xt/t5331-pack-objects-stdin.sh122
-rwxr-xr-xt/t5333-pseudo-merge-bitmaps.sh4
-rwxr-xr-xt/t5408-send-pack-stdin.sh15
-rwxr-xr-xt/t5505-remote.sh14
-rwxr-xr-xt/t5516-fetch-push.sh17
-rwxr-xr-xt/t5558-clone-bundle-uri.sh23
-rwxr-xr-xt/t6422-merge-rename-corner-cases.sh10
-rwxr-xr-xt/t7007-show.sh24
-rwxr-xr-xt/t7406-submodule-update.sh61
-rwxr-xr-xt/t7422-submodule-output.sh9
-rwxr-xr-xt/t7450-bad-git-dotfiles.sh33
-rwxr-xr-xt/t7528-signed-commit-ssh.sh32
-rwxr-xr-xt/t7600-merge.sh74
-rwxr-xr-xt/t7704-repack-cruft.sh145
-rwxr-xr-xt/t7900-maintenance.sh19
-rwxr-xr-xt/t9001-send-email.sh7
-rwxr-xr-xt/t9300-fast-import.sh12
-rwxr-xr-xt/t9301-fast-import-notes.sh2
-rw-r--r--t/test-lib-functions.sh21
-rw-r--r--t/test-lib.sh7
-rw-r--r--t/unit-tests/u-string-list.c227
57 files changed, 1340 insertions, 479 deletions
diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c
index 3f23f21072..16a01669e4 100644
--- a/t/helper/test-bitmap.c
+++ b/t/helper/test-bitmap.c
@@ -10,6 +10,11 @@ static int bitmap_list_commits(void)
return test_bitmap_commits(the_repository);
}
+static int bitmap_list_commits_with_offset(void)
+{
+ return test_bitmap_commits_with_offset(the_repository);
+}
+
static int bitmap_dump_hashes(void)
{
return test_bitmap_hashes(the_repository);
@@ -36,6 +41,8 @@ int cmd__bitmap(int argc, const char **argv)
if (argc == 2 && !strcmp(argv[1], "list-commits"))
return bitmap_list_commits();
+ if (argc == 2 && !strcmp(argv[1], "list-commits-with-offset"))
+ return bitmap_list_commits_with_offset();
if (argc == 2 && !strcmp(argv[1], "dump-hashes"))
return bitmap_dump_hashes();
if (argc == 2 && !strcmp(argv[1], "dump-pseudo-merges"))
@@ -46,6 +53,7 @@ int cmd__bitmap(int argc, const char **argv)
return bitmap_dump_pseudo_merge_objects(atoi(argv[2]));
usage("\ttest-tool bitmap list-commits\n"
+ "\ttest-tool bitmap list-commits-with-offset\n"
"\ttest-tool bitmap dump-hashes\n"
"\ttest-tool bitmap dump-pseudo-merges\n"
"\ttest-tool bitmap dump-pseudo-merge-commits <n>\n"
diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c
index 76c2f4eba8..611a13a326 100644
--- a/t/helper/test-find-pack.c
+++ b/t/helper/test-find-pack.c
@@ -2,7 +2,7 @@
#include "test-tool.h"
#include "object-name.h"
-#include "object-store.h"
+#include "odb.h"
#include "packfile.h"
#include "parse-options.h"
#include "setup.h"
diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c
index fdf1b13437..d51aaa3dc4 100644
--- a/t/helper/test-pack-mtimes.c
+++ b/t/helper/test-pack-mtimes.c
@@ -3,7 +3,7 @@
#include "test-tool.h"
#include "hex.h"
#include "strbuf.h"
-#include "object-store.h"
+#include "odb.h"
#include "packfile.h"
#include "pack-mtimes.h"
#include "setup.h"
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index f2663dd0c0..68579d83f3 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -131,6 +131,7 @@ int cmd__parse_options(int argc, const char **argv)
.short_name = 'B',
.long_name = "no-fear",
.value = &boolean,
+ .precision = sizeof(boolean),
.help = "be brave",
.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
.defval = 1,
@@ -148,9 +149,16 @@ int cmd__parse_options(int argc, const char **argv)
OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1),
OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2),
- OPT_CALLBACK_F(0, "mode34", &integer, "(3|4)",
- "set integer to 3 or 4 (cmdmode option)",
- PARSE_OPT_CMDMODE, mode34_callback),
+ {
+ .type = OPTION_CALLBACK,
+ .long_name = "mode34",
+ .value = &integer,
+ .precision = sizeof(integer),
+ .argh = "(3|4)",
+ .help = "set integer to 3 or 4 (cmdmode option)",
+ .flags = PARSE_OPT_CMDMODE,
+ .callback = mode34_callback,
+ },
OPT_CALLBACK('L', "length", &integer, "str",
"get length of <str>", length_callback),
OPT_FILENAME('F', "file", &file, "set file to <file>"),
@@ -170,6 +178,7 @@ int cmd__parse_options(int argc, const char **argv)
.type = OPTION_COUNTUP,
.short_name = '+',
.value = &boolean,
+ .precision = sizeof(boolean),
.help = "same as -b",
.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
},
@@ -177,6 +186,7 @@ int cmd__parse_options(int argc, const char **argv)
.type = OPTION_COUNTUP,
.long_name = "ambiguous",
.value = &ambiguous,
+ .precision = sizeof(ambiguous),
.help = "positive ambiguity",
.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
},
@@ -184,6 +194,7 @@ int cmd__parse_options(int argc, const char **argv)
.type = OPTION_COUNTUP,
.long_name = "no-ambiguous",
.value = &ambiguous,
+ .precision = sizeof(ambiguous),
.help = "negative ambiguity",
.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
},
diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c
index 34f1aee558..d848800749 100644
--- a/t/helper/test-partial-clone.c
+++ b/t/helper/test-partial-clone.c
@@ -1,7 +1,7 @@
#include "test-tool.h"
#include "hex.h"
#include "repository.h"
-#include "object-store.h"
+#include "odb.h"
#include "setup.h"
/*
@@ -23,7 +23,7 @@ static void object_info(const char *gitdir, const char *oid_hex)
die("could not init repo");
if (parse_oid_hex_algop(oid_hex, &oid, &p, r.hash_algo))
die("could not parse oid");
- if (oid_object_info_extended(&r, &oid, &oi, 0))
+ if (odb_read_object_info_extended(r.objects, &oid, &oi, 0))
die("could not obtain object info");
printf("%d\n", (int) size);
diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c
index 8b413b644b..ef5339bbee 100644
--- a/t/helper/test-read-graph.c
+++ b/t/helper/test-read-graph.c
@@ -3,7 +3,7 @@
#include "test-tool.h"
#include "commit-graph.h"
#include "repository.h"
-#include "object-store.h"
+#include "odb.h"
#include "bloom.h"
#include "setup.h"
@@ -73,15 +73,15 @@ static void dump_graph_bloom_filters(struct commit_graph *graph)
int cmd__read_graph(int argc, const char **argv)
{
struct commit_graph *graph = NULL;
- struct object_directory *odb;
+ struct odb_source *source;
int ret = 0;
setup_git_directory();
- odb = the_repository->objects->odb;
+ source = the_repository->objects->sources;
prepare_repo_settings(the_repository);
- graph = read_commit_graph_one(the_repository, odb);
+ graph = read_commit_graph_one(the_repository, source);
if (!graph) {
ret = 1;
goto done;
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
index ac81390899..da2aa036b5 100644
--- a/t/helper/test-read-midx.c
+++ b/t/helper/test-read-midx.c
@@ -4,7 +4,7 @@
#include "hex.h"
#include "midx.h"
#include "repository.h"
-#include "object-store.h"
+#include "odb.h"
#include "pack-bitmap.h"
#include "packfile.h"
#include "setup.h"
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 4cfc7c90b5..8d9a271845 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -5,7 +5,7 @@
#include "refs.h"
#include "setup.h"
#include "worktree.h"
-#include "object-store.h"
+#include "odb.h"
#include "path.h"
#include "repository.h"
#include "strbuf.h"
@@ -79,7 +79,7 @@ static const char **get_store(const char **argv, struct ref_store **refs)
if (!repo_submodule_path_append(the_repository,
&sb, gitdir, "objects/"))
die("computing submodule path failed");
- add_to_alternates_memory(sb.buf);
+ odb_add_to_alternates_memory(the_repository->objects, sb.buf);
strbuf_release(&sb);
*refs = repo_get_submodule_ref_store(the_repository, gitdir);
diff --git a/t/helper/test-string-list.c b/t/helper/test-string-list.c
index 6f10c5a435..6be0cdb8e2 100644
--- a/t/helper/test-string-list.c
+++ b/t/helper/test-string-list.c
@@ -1,105 +1,9 @@
-#define DISABLE_SIGN_COMPARE_WARNINGS
-
#include "test-tool.h"
#include "strbuf.h"
#include "string-list.h"
-/*
- * Parse an argument into a string list. arg should either be a
- * ':'-separated list of strings, or "-" to indicate an empty string
- * list (as opposed to "", which indicates a string list containing a
- * single empty string). list->strdup_strings must be set.
- */
-static void parse_string_list(struct string_list *list, const char *arg)
-{
- if (!strcmp(arg, "-"))
- return;
-
- (void)string_list_split(list, arg, ':', -1);
-}
-
-static void write_list(const struct string_list *list)
-{
- int i;
- for (i = 0; i < list->nr; i++)
- printf("[%d]: \"%s\"\n", i, list->items[i].string);
-}
-
-static void write_list_compact(const struct string_list *list)
-{
- int i;
- if (!list->nr)
- printf("-\n");
- else {
- printf("%s", list->items[0].string);
- for (i = 1; i < list->nr; i++)
- printf(":%s", list->items[i].string);
- printf("\n");
- }
-}
-
-static int prefix_cb(struct string_list_item *item, void *cb_data)
-{
- const char *prefix = (const char *)cb_data;
- return starts_with(item->string, prefix);
-}
-
int cmd__string_list(int argc, const char **argv)
{
- if (argc == 5 && !strcmp(argv[1], "split")) {
- struct string_list list = STRING_LIST_INIT_DUP;
- int i;
- const char *s = argv[2];
- int delim = *argv[3];
- int maxsplit = atoi(argv[4]);
-
- i = string_list_split(&list, s, delim, maxsplit);
- printf("%d\n", i);
- write_list(&list);
- string_list_clear(&list, 0);
- return 0;
- }
-
- if (argc == 5 && !strcmp(argv[1], "split_in_place")) {
- struct string_list list = STRING_LIST_INIT_NODUP;
- int i;
- char *s = xstrdup(argv[2]);
- const char *delim = argv[3];
- int maxsplit = atoi(argv[4]);
-
- i = string_list_split_in_place(&list, s, delim, maxsplit);
- printf("%d\n", i);
- write_list(&list);
- string_list_clear(&list, 0);
- free(s);
- return 0;
- }
-
- if (argc == 4 && !strcmp(argv[1], "filter")) {
- /*
- * Retain only the items that have the specified prefix.
- * Arguments: list|- prefix
- */
- struct string_list list = STRING_LIST_INIT_DUP;
- const char *prefix = argv[3];
-
- parse_string_list(&list, argv[2]);
- filter_string_list(&list, 0, prefix_cb, (void *)prefix);
- write_list_compact(&list);
- string_list_clear(&list, 0);
- return 0;
- }
-
- if (argc == 3 && !strcmp(argv[1], "remove_duplicates")) {
- struct string_list list = STRING_LIST_INIT_DUP;
-
- parse_string_list(&list, argv[2]);
- string_list_remove_duplicates(&list, 0);
- write_list_compact(&list);
- string_list_clear(&list, 0);
- return 0;
- }
-
if (argc == 2 && !strcmp(argv[1], "sort")) {
struct string_list list = STRING_LIST_INIT_NODUP;
struct strbuf sb = STRBUF_INIT;
diff --git a/t/meson.build b/t/meson.build
index 50e89e764a..1af289425d 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -11,6 +11,7 @@ clar_test_suites = [
'unit-tests/u-reftable-tree.c',
'unit-tests/u-strbuf.c',
'unit-tests/u-strcmp-offset.c',
+ 'unit-tests/u-string-list.c',
'unit-tests/u-strvec.c',
'unit-tests/u-trailer.c',
'unit-tests/u-urlmatch-normalization.c',
@@ -123,7 +124,6 @@ integration_tests = [
't0060-path-utils.sh',
't0061-run-command.sh',
't0062-revision-walking.sh',
- 't0063-string-list.sh',
't0066-dir-iterator.sh',
't0067-parse_pathspec_file.sh',
't0068-for-each-repo.sh',
@@ -178,7 +178,6 @@ integration_tests = [
't1015-read-index-unmerged.sh',
't1016-compatObjectFormat.sh',
't1020-subdirectory.sh',
- 't1021-rerere-in-workdir.sh',
't1022-read-tree-partial-clone.sh',
't1050-large.sh',
't1051-large-conversion.sh',
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index f11a40811f..f593c53687 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -658,6 +658,17 @@ test_expect_success 'init warns about invalid init.defaultRefFormat' '
test_cmp expected actual
'
+test_expect_success 'default ref format' '
+ test_when_finished "rm -rf refformat" &&
+ (
+ sane_unset GIT_DEFAULT_REF_FORMAT &&
+ git init refformat
+ ) &&
+ git version --build-options | sed -ne "s/^default-ref-format: //p" >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
backends="files reftable"
for format in $backends
do
@@ -738,6 +749,40 @@ test_expect_success "GIT_DEFAULT_REF_FORMAT= overrides init.defaultRefFormat" '
test_cmp expect actual
'
+test_expect_success "init with feature.experimental=true" '
+ test_when_finished "rm -rf refformat" &&
+ test_config_global feature.experimental true &&
+ (
+ sane_unset GIT_DEFAULT_REF_FORMAT &&
+ git init refformat
+ ) &&
+ echo reftable >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success "init.defaultRefFormat overrides feature.experimental=true" '
+ test_when_finished "rm -rf refformat" &&
+ test_config_global feature.experimental true &&
+ test_config_global init.defaultRefFormat files &&
+ (
+ sane_unset GIT_DEFAULT_REF_FORMAT &&
+ git init refformat
+ ) &&
+ echo files >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success "GIT_DEFAULT_REF_FORMAT= overrides feature.experimental=true" '
+ test_when_finished "rm -rf refformat" &&
+ test_config_global feature.experimental true &&
+ GIT_DEFAULT_REF_FORMAT=files git init refformat &&
+ echo files >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
for from_format in $backends
do
test_expect_success "re-init with same format ($from_format)" '
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index bf10d253ec..f0d50d769e 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -281,7 +281,7 @@ test_expect_success 'required filter with absent smudge field' '
test_expect_success 'filtering large input to small output should use little memory' '
test_config filter.devnull.clean "cat >/dev/null" &&
test_config filter.devnull.required true &&
- for i in $(test_seq 1 30); do printf "%1048576d" 1 || return 1; done >30MB &&
+ test_seq -f "%1048576d" 1 30 >30MB &&
echo "30MB filter=devnull" >.gitattributes &&
GIT_MMAP_LIMIT=1m GIT_ALLOC_LIMIT=1m git add 30MB
'
@@ -299,7 +299,7 @@ test_expect_success 'filter that does not read is fine' '
test_expect_success EXPENSIVE 'filter large file' '
test_config filter.largefile.smudge cat &&
test_config filter.largefile.clean cat &&
- for i in $(test_seq 1 2048); do printf "%1048576d" 1 || return 1; done >2GB &&
+ test_seq -f "%1048576d" 1 2048 >2GB &&
echo "2GB filter=largefile" >.gitattributes &&
git add 2GB 2>err &&
test_must_be_empty err &&
diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh
deleted file mode 100755
index aac63ba506..0000000000
--- a/t/t0063-string-list.sh
+++ /dev/null
@@ -1,142 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2012 Michael Haggerty
-#
-
-test_description='Test string list functionality'
-
-. ./test-lib.sh
-
-test_split () {
- cat >expected &&
- test_expect_success "split $1 at $2, max $3" "
- test-tool string-list split '$1' '$2' '$3' >actual &&
- test_cmp expected actual &&
- test-tool string-list split_in_place '$1' '$2' '$3' >actual &&
- test_cmp expected actual
- "
-}
-
-test_split_in_place() {
- cat >expected &&
- test_expect_success "split (in place) $1 at $2, max $3" "
- test-tool string-list split_in_place '$1' '$2' '$3' >actual &&
- test_cmp expected actual
- "
-}
-
-test_split "foo:bar:baz" ":" "-1" <<EOF
-3
-[0]: "foo"
-[1]: "bar"
-[2]: "baz"
-EOF
-
-test_split "foo:bar:baz" ":" "0" <<EOF
-1
-[0]: "foo:bar:baz"
-EOF
-
-test_split "foo:bar:baz" ":" "1" <<EOF
-2
-[0]: "foo"
-[1]: "bar:baz"
-EOF
-
-test_split "foo:bar:baz" ":" "2" <<EOF
-3
-[0]: "foo"
-[1]: "bar"
-[2]: "baz"
-EOF
-
-test_split "foo:bar:" ":" "-1" <<EOF
-3
-[0]: "foo"
-[1]: "bar"
-[2]: ""
-EOF
-
-test_split "" ":" "-1" <<EOF
-1
-[0]: ""
-EOF
-
-test_split ":" ":" "-1" <<EOF
-2
-[0]: ""
-[1]: ""
-EOF
-
-test_split_in_place "foo:;:bar:;:baz:;:" ":;" "-1" <<EOF
-10
-[0]: "foo"
-[1]: ""
-[2]: ""
-[3]: "bar"
-[4]: ""
-[5]: ""
-[6]: "baz"
-[7]: ""
-[8]: ""
-[9]: ""
-EOF
-
-test_split_in_place "foo:;:bar:;:baz" ":;" "0" <<EOF
-1
-[0]: "foo:;:bar:;:baz"
-EOF
-
-test_split_in_place "foo:;:bar:;:baz" ":;" "1" <<EOF
-2
-[0]: "foo"
-[1]: ";:bar:;:baz"
-EOF
-
-test_split_in_place "foo:;:bar:;:baz" ":;" "2" <<EOF
-3
-[0]: "foo"
-[1]: ""
-[2]: ":bar:;:baz"
-EOF
-
-test_split_in_place "foo:;:bar:;:" ":;" "-1" <<EOF
-7
-[0]: "foo"
-[1]: ""
-[2]: ""
-[3]: "bar"
-[4]: ""
-[5]: ""
-[6]: ""
-EOF
-
-test_expect_success "test filter_string_list" '
- test "x-" = "x$(test-tool string-list filter - y)" &&
- test "x-" = "x$(test-tool string-list filter no y)" &&
- test yes = "$(test-tool string-list filter yes y)" &&
- test yes = "$(test-tool string-list filter no:yes y)" &&
- test yes = "$(test-tool string-list filter yes:no y)" &&
- test y1:y2 = "$(test-tool string-list filter y1:y2 y)" &&
- test y2:y1 = "$(test-tool string-list filter y2:y1 y)" &&
- test "x-" = "x$(test-tool string-list filter x1:x2 y)"
-'
-
-test_expect_success "test remove_duplicates" '
- test "x-" = "x$(test-tool string-list remove_duplicates -)" &&
- test "x" = "x$(test-tool string-list remove_duplicates "")" &&
- test a = "$(test-tool string-list remove_duplicates a)" &&
- test a = "$(test-tool string-list remove_duplicates a:a)" &&
- test a = "$(test-tool string-list remove_duplicates a:a:a:a:a)" &&
- test a:b = "$(test-tool string-list remove_duplicates a:b)" &&
- test a:b = "$(test-tool string-list remove_duplicates a:a:b)" &&
- test a:b = "$(test-tool string-list remove_duplicates a:b:b)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:b:c)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:a:b:c)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:b:b:c)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:b:c:c)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:a:b:b:c:c)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:a:a:b:b:b:c:c:c)"
-'
-
-test_done
diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh
index 1be534a895..3ea5d51532 100755
--- a/t/t0610-reftable-basics.sh
+++ b/t/t0610-reftable-basics.sh
@@ -477,11 +477,7 @@ test_expect_success !CYGWIN 'ref transaction: many concurrent writers' '
test_commit --no-tag initial &&
head=$(git rev-parse HEAD) &&
- for i in $(test_seq 100)
- do
- printf "%s commit\trefs/heads/branch-%s\n" "$head" "$i" ||
- return 1
- done >expect &&
+ test_seq -f "$head commit\trefs/heads/branch-%d" 100 >expect &&
printf "%s commit\trefs/heads/main\n" "$head" >>expect &&
for i in $(test_seq 100)
diff --git a/t/t0612-reftable-jgit-compatibility.sh b/t/t0612-reftable-jgit-compatibility.sh
index d0d7e80b49..7df2ad5817 100755
--- a/t/t0612-reftable-jgit-compatibility.sh
+++ b/t/t0612-reftable-jgit-compatibility.sh
@@ -112,14 +112,11 @@ test_expect_success 'JGit can read multi-level index' '
cd repo &&
test_commit A &&
- awk "
- BEGIN {
- print \"start\";
- for (i = 0; i < 10000; i++)
- printf \"create refs/heads/branch-%d HEAD\n\", i;
- print \"commit\";
- }
- " >input &&
+ {
+ echo start &&
+ test_seq -f "create refs/heads/branch-%d HEAD" 10000 &&
+ echo commit
+ } >input &&
git update-ref --stdin <input &&
test_same_refs &&
diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh
index 6447920c9b..d77e601111 100755
--- a/t/t0613-reftable-write-options.sh
+++ b/t/t0613-reftable-write-options.sh
@@ -66,11 +66,7 @@ test_expect_success 'many refs results in multiple blocks' '
(
cd repo &&
test_commit initial &&
- for i in $(test_seq 200)
- do
- printf "update refs/heads/branch-%d HEAD\n" "$i" ||
- return 1
- done >input &&
+ test_seq -f "update refs/heads/branch-%d HEAD" 200 >input &&
git update-ref --stdin <input &&
git pack-refs &&
@@ -180,11 +176,7 @@ test_expect_success 'restart interval at every single record' '
(
cd repo &&
test_commit initial &&
- for i in $(test_seq 10)
- do
- printf "update refs/heads/branch-%d HEAD\n" "$i" ||
- return 1
- done >input &&
+ test_seq -f "update refs/heads/branch-%d HEAD" 10 >input &&
git update-ref --stdin <input &&
git -c reftable.restartInterval=1 pack-refs &&
@@ -224,11 +216,7 @@ test_expect_success 'object index gets written by default with ref index' '
(
cd repo &&
test_commit initial &&
- for i in $(test_seq 5)
- do
- printf "update refs/heads/branch-%d HEAD\n" "$i" ||
- return 1
- done >input &&
+ test_seq -f "update refs/heads/branch-%d HEAD" 5 >input &&
git update-ref --stdin <input &&
git -c reftable.blockSize=100 pack-refs &&
@@ -263,11 +251,7 @@ test_expect_success 'object index can be disabled' '
(
cd repo &&
test_commit initial &&
- for i in $(test_seq 5)
- do
- printf "update refs/heads/branch-%d HEAD\n" "$i" ||
- return 1
- done >input &&
+ test_seq -f "update refs/heads/branch-%d HEAD" 5 >input &&
git update-ref --stdin <input &&
git -c reftable.blockSize=100 -c reftable.indexObjects=false pack-refs &&
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index f123ef1e36..1f61b666a7 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -197,7 +197,7 @@ $content"
# FIXME: %(rest) is incompatible with object names that include whitespace,
# e.g. HEAD:path/to/a/file with spaces. Use the resolved OID as input to
# test this instead of the raw object name.
- if echo "$object_name" | grep " "; then
+ if echo "$object_name" | grep -q " "; then
test_rest=test_expect_failure
else
test_rest=test_expect_success
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index 64658b3ba5..de076293b6 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -252,9 +252,9 @@ test_expect_success '--literally complains about non-standard types' '
test_must_fail git hash-object -t bogus --literally --stdin
'
-test_expect_success '--stdin outside of repository (uses SHA-1)' '
+test_expect_success '--stdin outside of repository (uses default hash)' '
nongit git hash-object --stdin <hello >actual &&
- echo "$(test_oid --hash=sha1 hello)" >expect &&
+ echo "$(test_oid --hash=builtin hello)" >expect &&
test_cmp expect actual
'
diff --git a/t/t1021-rerere-in-workdir.sh b/t/t1021-rerere-in-workdir.sh
deleted file mode 100755
index 0b892894eb..0000000000
--- a/t/t1021-rerere-in-workdir.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/sh
-
-test_description='rerere run in a workdir'
-GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
-export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-
-. ./test-lib.sh
-
-test_expect_success SYMLINKS setup '
- git config rerere.enabled true &&
- >world &&
- git add world &&
- test_tick &&
- git commit -m initial &&
-
- echo hello >world &&
- test_tick &&
- git commit -a -m hello &&
-
- git checkout -b side HEAD^ &&
- echo goodbye >world &&
- test_tick &&
- git commit -a -m goodbye &&
-
- git checkout main
-'
-
-test_expect_success SYMLINKS 'rerere in workdir' '
- rm -rf .git/rr-cache &&
- "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" . work &&
- (
- cd work &&
- test_must_fail git merge side &&
- git rerere status >actual &&
- echo world >expect &&
- test_cmp expect actual
- )
-'
-
-# This fails because we don't resolve relative symlink in mkdir_in_gitdir()
-# For the purpose of helping contrib/workdir/git-new-workdir users, we do not
-# have to support relative symlinks, but it might be nicer to make this work
-# with a relative symbolic link someday.
-test_expect_failure SYMLINKS 'rerere in workdir (relative)' '
- rm -rf .git/rr-cache &&
- "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" . krow &&
- (
- cd krow &&
- rm -f .git/rr-cache &&
- ln -s ../.git/rr-cache .git/rr-cache &&
- test_must_fail git merge side &&
- git rerere status >actual &&
- echo world >expect &&
- test_cmp expect actual
- )
-'
-
-test_done
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 51a85e83c2..f856821839 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -2851,4 +2851,15 @@ test_expect_success 'writing to stdin is rejected' '
done
+test_expect_success 'writing value with trailing CR not stripped on read' '
+ test_when_finished "rm -rf cr-test" &&
+
+ printf "bar\r\n" >expect &&
+ git init cr-test &&
+ git -C cr-test config set core.foo $(printf "bar\r") &&
+ git -C cr-test config get core.foo >actual &&
+
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index d29d23cb89..96648a6e5d 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -1380,10 +1380,7 @@ test_expect_success 'fails with duplicate ref update via symref' '
test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction creating branches does not burst open file limit' '
(
- for i in $(test_seq 33)
- do
- echo "create refs/heads/$i HEAD" || exit 1
- done >large_input &&
+ test_seq -f "create refs/heads/%d HEAD" 33 >large_input &&
run_with_limited_open_files git update-ref --stdin <large_input &&
git rev-parse --verify -q refs/heads/33
)
@@ -1391,10 +1388,7 @@ test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction creating branches
test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction deleting branches does not burst open file limit' '
(
- for i in $(test_seq 33)
- do
- echo "delete refs/heads/$i HEAD" || exit 1
- done >large_input &&
+ test_seq -f "delete refs/heads/%d HEAD" 33 >large_input &&
run_with_limited_open_files git update-ref --stdin <large_input &&
test_must_fail git rev-parse --verify -q refs/heads/33
)
@@ -2299,6 +2293,51 @@ do
test_grep -q "refname conflict" stdout
)
'
+
+ test_expect_success "stdin $type batch-updates delete incorrect symbolic ref" '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit c1 &&
+ head=$(git rev-parse HEAD) &&
+ git symbolic-ref refs/heads/symbolic refs/heads/non-existent &&
+
+ format_command $type "delete refs/heads/symbolic" "$head" >stdin &&
+ git update-ref $type --stdin --batch-updates <stdin >stdout &&
+ test_grep "reference does not exist" stdout
+ )
+ '
+
+ test_expect_success "stdin $type batch-updates delete with incorrect old_oid" '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit c1 &&
+ git branch new-branch &&
+ test_commit c2 &&
+ head=$(git rev-parse HEAD) &&
+
+ format_command $type "delete refs/heads/new-branch" "$head" >stdin &&
+ git update-ref $type --stdin --batch-updates <stdin >stdout &&
+ test_grep "incorrect old value provided" stdout
+ )
+ '
+
+ test_expect_success "stdin $type batch-updates delete non-existent ref" '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit commit &&
+ head=$(git rev-parse HEAD) &&
+
+ format_command $type "delete refs/heads/non-existent" "$head" >stdin &&
+ git update-ref $type --stdin --batch-updates <stdin >stdout &&
+ test_grep "reference does not exist" stdout
+ )
+ '
done
test_expect_success 'update-ref should also create reflog for HEAD' '
@@ -2310,4 +2349,23 @@ test_expect_success 'update-ref should also create reflog for HEAD' '
test_cmp expect actual
'
+test_expect_success REFFILES 'empty directories are pruned when aborting a transaction' '
+ test_path_is_missing .git/refs/heads/nested &&
+ git update-ref --stdin <<-EOF &&
+ create refs/heads/nested/something HEAD
+ prepare
+ abort
+ EOF
+ test_path_is_missing .git/refs/heads/nested
+'
+
+test_expect_success REFFILES 'empty directories are pruned when not committing' '
+ test_path_is_missing .git/refs/heads/nested &&
+ git update-ref --stdin <<-EOF &&
+ create refs/heads/nested/something HEAD
+ prepare
+ EOF
+ test_path_is_missing .git/refs/heads/nested
+'
+
test_done
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 8c777f7cf8..d91dd3a3b5 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -120,8 +120,6 @@ test_expect_success 'interleaving hook calls succeed' '
cat >expect <<-EOF &&
hooks/update refs/tags/PRE $ZERO_OID $PRE_OID
- hooks/reference-transaction prepared
- hooks/reference-transaction committed
hooks/update refs/tags/POST $ZERO_OID $POST_OID
hooks/reference-transaction prepared
hooks/reference-transaction committed
diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh
index 6824581317..8f59b867f2 100755
--- a/t/t1517-outside-repo.sh
+++ b/t/t1517-outside-repo.sh
@@ -114,4 +114,11 @@ test_expect_success 'update-server-info does not crash with -h' '
test_grep "[Uu]sage: git update-server-info " usage
'
+test_expect_success 'prune does not crash with -h' '
+ test_expect_code 129 git prune -h >usage &&
+ test_grep "[Uu]sage: git prune " usage &&
+ test_expect_code 129 nongit git prune -h >usage &&
+ test_grep "[Uu]sage: git prune " usage
+'
+
test_done
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index 90638fa886..023e1301c8 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -42,8 +42,8 @@ test_expect_success '"add" using - shorthand' '
test_expect_success '"add" refuses to checkout locked branch' '
test_must_fail git worktree add zere main &&
- ! test -d zere &&
- ! test -d .git/worktrees/zere
+ test_path_is_missing zere &&
+ test_path_is_missing .git/worktrees/zere
'
test_expect_success 'checking out paths not complaining about linked checkouts' '
@@ -70,14 +70,14 @@ test_expect_success '"add" worktree' '
test_expect_success '"add" worktree with lock' '
git worktree add --detach --lock here-with-lock main &&
test_when_finished "git worktree unlock here-with-lock || :" &&
- test -f .git/worktrees/here-with-lock/locked
+ test_path_is_file .git/worktrees/here-with-lock/locked
'
test_expect_success '"add" worktree with lock and reason' '
lock_reason="why not" &&
git worktree add --detach --lock --reason "$lock_reason" here-with-lock-reason main &&
test_when_finished "git worktree unlock here-with-lock-reason || :" &&
- test -f .git/worktrees/here-with-lock-reason/locked &&
+ test_path_is_file .git/worktrees/here-with-lock-reason/locked &&
echo "$lock_reason" >expect &&
test_cmp expect .git/worktrees/here-with-lock-reason/locked
'
@@ -412,14 +412,14 @@ test_expect_success '"add --orphan" with empty repository' '
test_expect_success '"add" worktree with orphan branch and lock' '
git worktree add --lock --orphan -b orphanbr orphan-with-lock &&
test_when_finished "git worktree unlock orphan-with-lock || :" &&
- test -f .git/worktrees/orphan-with-lock/locked
+ test_path_is_file .git/worktrees/orphan-with-lock/locked
'
test_expect_success '"add" worktree with orphan branch, lock, and reason' '
lock_reason="why not" &&
git worktree add --detach --lock --reason "$lock_reason" orphan-with-lock-reason main &&
test_when_finished "git worktree unlock orphan-with-lock-reason || :" &&
- test -f .git/worktrees/orphan-with-lock-reason/locked &&
+ test_path_is_file .git/worktrees/orphan-with-lock-reason/locked &&
echo "$lock_reason" >expect &&
test_cmp expect .git/worktrees/orphan-with-lock-reason/locked
'
@@ -474,7 +474,7 @@ test_expect_success 'local clone --shared from linked checkout' '
test_expect_success '"add" worktree with --no-checkout' '
git worktree add --no-checkout -b swamp swamp &&
- ! test -e swamp/init.t &&
+ test_path_is_missing swamp/init.t &&
git -C swamp reset --hard &&
test_cmp init.t swamp/init.t
'
@@ -497,7 +497,7 @@ test_expect_success 'put a worktree under rebase' '
test_expect_success 'add a worktree, checking out a rebased branch' '
test_must_fail git worktree add new-rebase under-rebase &&
- ! test -d new-rebase
+ test_path_is_missing new-rebase
'
test_expect_success 'checking out a rebased branch from another worktree' '
@@ -535,7 +535,7 @@ test_expect_success 'checkout a branch under bisect' '
git worktree list >actual &&
grep "under-bisect.*detached HEAD" actual &&
test_must_fail git worktree add new-bisect under-bisect &&
- ! test -d new-bisect
+ test_path_is_missing new-bisect
)
'
@@ -1165,7 +1165,7 @@ test_expect_success '"add" not tripped up by magic worktree matching"' '
test_expect_success FUNNYNAMES 'sanitize generated worktree name' '
git worktree add --detach ". weird*..?.lock.lock" &&
- test -d .git/worktrees/---weird-.-
+ test_path_is_dir .git/worktrees/---weird-.-
'
test_expect_success '"add" should not fail because of another bad worktree' '
diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh
index 13f66fd649..b41e7f0daa 100755
--- a/t/t3000-ls-files-others.sh
+++ b/t/t3000-ls-files-others.sh
@@ -73,25 +73,6 @@ test_expect_success 'ls-files --others handles non-submodule .git' '
test_cmp expected1 output
'
-test_expect_success SYMLINKS 'ls-files --others with symlinked submodule' '
- git init super &&
- git init sub &&
- (
- cd sub &&
- >a &&
- git add a &&
- git commit -m sub &&
- git pack-refs --all
- ) &&
- (
- cd super &&
- "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" ../sub sub &&
- git ls-files --others --exclude-standard >../actual
- ) &&
- echo sub/ >expect &&
- test_cmp expect actual
-'
-
test_expect_success 'setup nested pathspec search' '
test_create_repo nested &&
(
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 74666ff3e4..0bb4648e36 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -11,6 +11,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-unique-files.sh
+test_expect_success 'setup' '
+ test_oid_cache <<-EOF
+ export_base sha1:73c9bab443d1f88ac61aa533d2eeaaa15451239c
+ export_base sha256:f210fa6346e3e2ce047bdb570426b17075980c1ac01fec8fc4b75bd3ab4bcfe4
+ EOF
+'
+
test_expect_success 'usage on cmd and subcommand invalid option' '
test_expect_code 129 git stash --invalid-option 2>usage &&
grep "or: git stash" usage &&
@@ -1177,6 +1184,28 @@ test_expect_success 'stash -- <pathspec> stashes and restores the file' '
test_path_is_file bar
'
+test_expect_success 'stash --patch <pathspec> stash and restores the file' '
+ test_write_lines b c >file &&
+ git commit -m "add a few lines" file &&
+ test_write_lines a b c d >file &&
+ test_write_lines b c d >expect-file &&
+ echo changed-other-file >other-file &&
+ test_write_lines s y n | git stash -m "stash bar" --patch file &&
+ test_cmp expect-file file &&
+ echo changed-other-file >expect &&
+ test_cmp expect other-file &&
+ git checkout HEAD -- file &&
+ git stash pop &&
+ test_cmp expect other-file &&
+ test_write_lines a b c >expect &&
+ test_cmp expect file
+'
+
+test_expect_success 'stash <pathspec> -p is rejected' '
+ test_must_fail git stash file -p 2>err &&
+ test_grep "subcommand wasn${SQ}t specified; ${SQ}push${SQ} can${SQ}t be assumed due to unexpected token ${SQ}file${SQ}" err
+'
+
test_expect_success 'stash -- <pathspec> stashes in subdirectory' '
mkdir sub &&
>foo &&
@@ -1412,6 +1441,100 @@ test_expect_success 'stash --keep-index --include-untracked with empty tree' '
)
'
+test_expect_success 'stash export and import round-trip stashes' '
+ git reset &&
+ >untracked &&
+ >tracked1 &&
+ >tracked2 &&
+ git add tracked* &&
+ git stash -- &&
+ >subdir/untracked &&
+ >subdir/tracked1 &&
+ >subdir/tracked2 &&
+ git add subdir/tracked* &&
+ git stash --include-untracked -- subdir/ &&
+ git tag t-stash0 stash@{0} &&
+ git tag t-stash1 stash@{1} &&
+ simple=$(git stash export --print) &&
+ git stash clear &&
+ git stash import "$simple" &&
+ test_cmp_rev stash@{0} t-stash0 &&
+ test_cmp_rev stash@{1} t-stash1 &&
+ git stash export --to-ref refs/heads/foo &&
+ test_cmp_rev "$(test_oid empty_tree)" foo: &&
+ test_cmp_rev "$(test_oid empty_tree)" foo^: &&
+ test_cmp_rev t-stash0 foo^2 &&
+ test_cmp_rev t-stash1 foo^^2 &&
+ git log --first-parent --format="%s" refs/heads/foo >log &&
+ grep "^git stash: " log >log2 &&
+ test_line_count = 13 log2 &&
+ git stash clear &&
+ git stash import foo &&
+ test_cmp_rev stash@{0} t-stash0 &&
+ test_cmp_rev stash@{1} t-stash1
+'
+
+test_expect_success 'stash import appends commits' '
+ git log --format=oneline -g refs/stash >out &&
+ cat out out >out2 &&
+ git stash import refs/heads/foo &&
+ git log --format=oneline -g refs/stash >actual &&
+ test_line_count = $(wc -l <out2) actual
+'
+
+test_expect_success 'stash export can accept specified stashes' '
+ git stash clear &&
+ git stash import foo &&
+ git stash export --to-ref refs/heads/bar stash@{1} stash@{0} &&
+ git stash clear &&
+ git stash import refs/heads/bar &&
+ test_cmp_rev stash@{1} t-stash0 &&
+ test_cmp_rev stash@{0} t-stash1 &&
+ git log --format=oneline -g refs/stash >actual &&
+ test_line_count = 2 actual
+'
+
+test_expect_success 'stash export rejects invalid arguments' '
+ test_must_fail git stash export --print --to-ref refs/heads/invalid 2>err &&
+ grep "exactly one of --print and --to-ref is required" err &&
+ test_must_fail git stash export 2>err2 &&
+ grep "exactly one of --print and --to-ref is required" err2
+'
+
+test_expect_success 'stash can import and export zero stashes' '
+ git stash clear &&
+ git stash export --to-ref refs/heads/baz &&
+ test_cmp_rev "$(test_oid empty_tree)" baz: &&
+ test_cmp_rev "$(test_oid export_base)" baz &&
+ test_must_fail git rev-parse baz^1 &&
+ git stash import baz &&
+ test_must_fail git rev-parse refs/stash
+'
+
+test_expect_success 'stash rejects invalid attempts to import commits' '
+ git stash import foo &&
+ test_must_fail git stash import HEAD 2>output &&
+ oid=$(git rev-parse HEAD) &&
+ grep "$oid is not a valid exported stash commit" output &&
+ test_cmp_rev stash@{0} t-stash0 &&
+
+ git checkout --orphan orphan &&
+ git commit-tree $(test_oid empty_tree) -p "$oid" -p "$oid^" -m "" >fake-commit &&
+ git update-ref refs/heads/orphan "$(cat fake-commit)" &&
+ oid=$(git rev-parse HEAD) &&
+ test_must_fail git stash import orphan 2>output &&
+ grep "found stash commit $oid without expected prefix" output &&
+ test_cmp_rev stash@{0} t-stash0 &&
+
+ git checkout --orphan orphan2 &&
+ git commit-tree $(test_oid empty_tree) -m "" >fake-commit &&
+ git update-ref refs/heads/orphan2 "$(cat fake-commit)" &&
+ oid=$(git rev-parse HEAD) &&
+ test_must_fail git stash import orphan2 2>output &&
+ grep "found root commit $oid with invalid data" output &&
+ test_cmp_rev stash@{0} t-stash0
+'
+
test_expect_success 'stash apply should succeed with unmodified file' '
echo base >file &&
git add file &&
@@ -1549,11 +1672,9 @@ test_expect_success 'stash create reports a locked index' '
echo change >A.file &&
touch .git/index.lock &&
- cat >expect <<-EOF &&
- error: could not write index
- EOF
test_must_fail git stash create 2>err &&
- test_cmp expect err
+ test_grep "error: could not write index" err &&
+ test_grep "error: Unable to create '.*index.lock'" err
)
'
@@ -1566,11 +1687,9 @@ test_expect_success 'stash push reports a locked index' '
echo change >A.file &&
touch .git/index.lock &&
- cat >expect <<-EOF &&
- error: could not write index
- EOF
test_must_fail git stash push 2>err &&
- test_cmp expect err
+ test_grep "error: could not write index" err &&
+ test_grep "error: Unable to create '.*index.lock'" err
)
'
@@ -1584,11 +1703,41 @@ test_expect_success 'stash apply reports a locked index' '
git stash push &&
touch .git/index.lock &&
- cat >expect <<-EOF &&
- error: could not write index
- EOF
test_must_fail git stash apply 2>err &&
- test_cmp expect err
+ test_grep "error: could not write index" err &&
+ test_grep "error: Unable to create '.*index.lock'" err
+ )
+'
+
+test_expect_success 'submodules does not affect the branch recorded in stash message' '
+ git init sub_project &&
+ (
+ cd sub_project &&
+ echo "Initial content in sub_project" >sub_file.txt &&
+ git add sub_file.txt &&
+ git commit -m "Initial commit in sub_project"
+ ) &&
+
+ git init main_project &&
+ (
+ cd main_project &&
+ echo "Initial content in main_project" >main_file.txt &&
+ git add main_file.txt &&
+ git commit -m "Initial commit in main_project" &&
+
+ git -c protocol.file.allow=always submodule add ../sub_project sub &&
+ git commit -m "Added submodule sub_project" &&
+
+ git checkout -b feature_main &&
+ git -C sub checkout -b feature_sub &&
+
+ git checkout -b work_branch &&
+ echo "Important work to be stashed" >work_item.txt &&
+ git add work_item.txt &&
+ git stash push -m "custom stash for work_branch" &&
+
+ git stash list >../actual_stash_list.txt &&
+ grep "On work_branch: custom stash for work_branch" ../actual_stash_list.txt
)
'
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 782d97fb7d..8ebd170451 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -206,14 +206,30 @@ do
expect="$TEST_DIRECTORY/t4013/diff.$test"
actual="$pfx-diff.$test"
- test_expect_success "git $cmd # magic is ${magic:-(not used)}" '
+ case "$cmd" in
+ whatchanged | whatchanged" "*)
+ prereq=!WITH_BREAKING_CHANGES
+ ;;
+ *)
+ prereq=;;
+ esac
+
+ test_expect_success $prereq "git $cmd # magic is ${magic:-(not used)}" '
{
echo "$ git $cmd"
+
+ case "$cmd" in
+ whatchanged | whatchanged" "*)
+ run="whatchanged --i-still-use-this"
+ run="$run ${cmd#whatchanged}" ;;
+ *)
+ run=$cmd ;;
+ esac &&
case "$magic" in
"")
- GIT_PRINT_SHA1_ELLIPSIS=yes git $cmd ;;
+ GIT_PRINT_SHA1_ELLIPSIS=yes git $run ;;
noellipses)
- git $cmd ;;
+ git $run ;;
esac |
sed -e "s/^\\(-*\\)$V\\(-*\\)\$/\\1g-i-t--v-e-r-s-i-o-n\2/" \
-e "s/^\\(.*mixed; boundary=\"-*\\)$V\\(-*\\)\"\$/\\1g-i-t--v-e-r-s-i-o-n\2\"/"
@@ -460,6 +476,11 @@ diff-tree --stat --compact-summary initial mode
diff-tree -R --stat --compact-summary initial mode
EOF
+test_expect_success !WITH_BREAKING_CHANGES 'whatchanged needs --i-still-use-this' '
+ test_must_fail git whatchanged >message 2>&1 &&
+ test_grep "nominated for removal" message
+'
+
test_expect_success 'log -m matches pure log' '
git log master >result &&
process_diffs result >expected &&
diff --git a/t/t4042-diff-textconv-caching.sh b/t/t4042-diff-textconv-caching.sh
index ff0e73531b..31018ceba2 100755
--- a/t/t4042-diff-textconv-caching.sh
+++ b/t/t4042-diff-textconv-caching.sh
@@ -120,6 +120,14 @@ test_expect_success 'log notes cache and still use cache for -p' '
'
test_expect_success 'caching is silently ignored outside repo' '
+ test_oid_cache <<-\EOM &&
+ oid1 sha1:5626abf
+ oid1 sha256:a4ed1f3
+ oid2 sha1:f719efd
+ oid2 sha256:aa9e7dc
+ EOM
+ oid1=$(test_oid --hash=builtin oid1) &&
+ oid2=$(test_oid --hash=builtin oid2) &&
mkdir -p non-repo &&
echo one >non-repo/one &&
echo two >non-repo/two &&
@@ -129,9 +137,9 @@ test_expect_success 'caching is silently ignored outside repo' '
-c diff.test.textconv="tr a-z A-Z <" \
-c diff.test.cachetextconv=true \
diff --no-index one two >actual &&
- cat >expect <<-\EOF &&
+ cat >expect <<-EOF &&
diff --git a/one b/two
- index 5626abf..f719efd 100644
+ index $oid1..$oid2 100644
--- a/one
+++ b/two
@@ -1 +1 @@
diff --git a/t/t4140-apply-ita.sh b/t/t4140-apply-ita.sh
index c614eaf04c..0b11a8aef4 100755
--- a/t/t4140-apply-ita.sh
+++ b/t/t4140-apply-ita.sh
@@ -7,6 +7,10 @@ test_description='git apply of i-t-a file'
test_expect_success setup '
test_write_lines 1 2 3 4 5 >blueprint &&
+ cat blueprint >committed-file &&
+ git add committed-file &&
+ git commit -m "commit" &&
+
cat blueprint >test-file &&
git add -N test-file &&
git diff >creation-patch &&
@@ -14,7 +18,14 @@ test_expect_success setup '
rm -f test-file &&
git diff >deletion-patch &&
- grep "deleted file mode 100644" deletion-patch
+ grep "deleted file mode 100644" deletion-patch &&
+
+ git rm -f test-file &&
+ test_write_lines 6 >>committed-file &&
+ cat blueprint >test-file &&
+ git add -N test-file &&
+ git diff >complex-patch &&
+ git restore committed-file
'
test_expect_success 'apply creation patch to ita path (--cached)' '
@@ -53,4 +64,22 @@ test_expect_success 'apply deletion patch to ita path (--index)' '
git ls-files --stage --error-unmatch test-file
'
+test_expect_success 'apply creation patch to existing index with -N' '
+ git rm -f test-file &&
+ cat blueprint >index-file &&
+ git add index-file &&
+ git apply -N creation-patch &&
+
+ git ls-files --stage --error-unmatch index-file &&
+ git ls-files --stage --error-unmatch test-file
+'
+
+test_expect_success 'apply complex patch with -N' '
+ git rm -f test-file index-file &&
+ git apply -N complex-patch &&
+
+ git ls-files --stage --error-unmatch test-file &&
+ git diff | grep "a/committed-file"
+'
+
test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 2ae93d3c96..699a81ab5c 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -1086,7 +1086,7 @@ test_expect_success 'am works with multi-line in-body headers' '
# bump from, date, and subject down to in-body header
awk "
/^From:/{
- print \"From: x <x\@example.com>\";
+ print \"From: x <x@example.com>\";
print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\";
print \"Subject: x\n\";
}; 1
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 51f7beb59f..05cee9e41b 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -134,6 +134,12 @@ test_expect_success 'diff-filter=D' '
'
+test_expect_success 'all-negative filter' '
+ git log --no-renames --format=%s --diff-filter=d HEAD >actual &&
+ printf "%s\n" fifth fourth third second initial >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'diff-filter=R' '
git log -M --pretty="format:%s" --diff-filter=R HEAD >actual &&
@@ -486,10 +492,16 @@ test_expect_success !FAIL_PREREQS 'log with various grep.patternType configurati
)
'
-for cmd in show whatchanged reflog format-patch
+cmds="show reflog format-patch"
+if test_have_prereq !WITH_BREAKING_CHANGES
+then
+ cmds="$cmds whatchanged"
+fi
+for cmd in $cmds
do
case "$cmd" in
format-patch) myarg="HEAD~.." ;;
+ whatchanged) myarg=--i-still-use-this ;;
*) myarg= ;;
esac
@@ -1201,20 +1213,27 @@ test_expect_success 'reflog is expected format' '
test_cmp expect actual
'
-test_expect_success 'whatchanged is expected format' '
+test_expect_success !WITH_BREAKING_CHANGES 'whatchanged is expected format' '
+ whatchanged="whatchanged --i-still-use-this" &&
git log --no-merges --raw >expect &&
- git whatchanged >actual &&
+ git $whatchanged >actual &&
test_cmp expect actual
'
test_expect_success 'log.abbrevCommit configuration' '
+ whatchanged="whatchanged --i-still-use-this" &&
+
git log --abbrev-commit >expect.log.abbrev &&
git log --no-abbrev-commit >expect.log.full &&
git log --pretty=raw >expect.log.raw &&
git reflog --abbrev-commit >expect.reflog.abbrev &&
git reflog --no-abbrev-commit >expect.reflog.full &&
- git whatchanged --abbrev-commit >expect.whatchanged.abbrev &&
- git whatchanged --no-abbrev-commit >expect.whatchanged.full &&
+
+ if test_have_prereq !WITH_BREAKING_CHANGES
+ then
+ git $whatchanged --abbrev-commit >expect.whatchanged.abbrev &&
+ git $whatchanged --no-abbrev-commit >expect.whatchanged.full
+ fi &&
test_config log.abbrevCommit true &&
@@ -1231,10 +1250,13 @@ test_expect_success 'log.abbrevCommit configuration' '
git reflog --no-abbrev-commit >actual &&
test_cmp expect.reflog.full actual &&
- git whatchanged >actual &&
- test_cmp expect.whatchanged.abbrev actual &&
- git whatchanged --no-abbrev-commit >actual &&
- test_cmp expect.whatchanged.full actual
+ if test_have_prereq !WITH_BREAKING_CHANGES
+ then
+ git $whatchanged >actual &&
+ test_cmp expect.whatchanged.abbrev actual &&
+ git $whatchanged --no-abbrev-commit >actual &&
+ test_cmp expect.whatchanged.full actual
+ fi
'
test_expect_success '--abbrev-commit with core.abbrev=false' '
diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh
index 4a6242ff99..74b7ddccb2 100755
--- a/t/t4203-mailmap.sh
+++ b/t/t4203-mailmap.sh
@@ -1133,4 +1133,37 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us
test_cmp expect actual
'
+test_expect_success 'git cat-file --mailmap works with different author and committer' '
+ test_when_finished "rm .mailmap" &&
+ cat >.mailmap <<-\EOF &&
+ Mailmapped User <mailmapped-user@gitlab.com> C O Mitter <committer@example.com>
+ EOF
+ git commit --allow-empty -m "different author/committer" \
+ --author="Different Author <different@example.com>" &&
+ cat >expect <<-\EOF &&
+ author Different Author <different@example.com>
+ committer Mailmapped User <mailmapped-user@gitlab.com>
+ EOF
+ git cat-file --mailmap commit HEAD >log &&
+ sed -n -e "/^author /s/>.*/>/p" -e "/^committer /s/>.*/>/p" log >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git cat-file --mailmap maps both author and committer when both need mapping' '
+ test_when_finished "rm .mailmap" &&
+ cat >.mailmap <<-\EOF &&
+ Mapped Author <mapped-author@example.com> <different@example.com>
+ Mapped Committer <mapped-committer@example.com> C O Mitter <committer@example.com>
+ EOF
+ git commit --allow-empty -m "both author and committer mapped" \
+ --author="Different Author <different@example.com>" &&
+ cat >expect <<-\EOF &&
+ author Mapped Author <mapped-author@example.com>
+ committer Mapped Committer <mapped-committer@example.com>
+ EOF
+ git cat-file --mailmap commit HEAD >log &&
+ sed -n -e "/^author /s/>.*/>/p" -e "/^committer /s/>.*/>/p" log >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index 5174995191..027dedd976 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -176,10 +176,7 @@ test_expect_success EXPENSIVE,UNZIP,UNZIP_ZIP64_SUPPORT \
blob=$(echo $s | git hash-object -w --stdin) &&
# create tree containing 65500 entries of that blob
- for i in $(test_seq 1 65500)
- do
- echo "100644 blob $blob $i" || return 1
- done >tree &&
+ test_seq -f "100644 blob $blob\t%d" 1 65500 >tree &&
tree=$(git mktree <tree) &&
# zip it, creating an archive a bit bigger than 4GB
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index ae72158b94..73445782e7 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -525,7 +525,7 @@ test_expect_success 'index-pack --strict <pack> works in non-repo' '
test_path_is_file foo.idx
'
-test_expect_success SHA1 'show-index works OK outside a repository' '
+test_expect_success DEFAULT_HASH_ALGORITHM 'show-index works OK outside a repository' '
nongit git show-index <foo.idx
'
@@ -658,7 +658,7 @@ do
test_commit -C repo initial &&
git -C repo repack -ad &&
git -C repo verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx &&
- if test $hash = sha1
+ if test $hash = $GIT_TEST_BUILTIN_HASH
then
nongit git verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx
else
@@ -676,7 +676,7 @@ do
test_commit -C repo initial &&
git -C repo repack -ad &&
git -C repo index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack &&
- if test $hash = sha1
+ if test $hash = $GIT_TEST_BUILTIN_HASH
then
nongit git index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack
else
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index b6926f1027..6718fb98c0 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -495,6 +495,36 @@ test_bitmap_cases () {
grep "ignoring extra bitmap" trace2.txt
)
'
+
+ test_expect_success 'load corrupt bitmap' '
+ rm -fr repo &&
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
+
+ test_commit base &&
+
+ git repack -adb &&
+ bitmap="$(ls .git/objects/pack/pack-*.bitmap)" &&
+ chmod +w $bitmap &&
+
+ test-tool bitmap list-commits-with-offset >offsets &&
+ xor_off=$(head -n1 offsets | awk "{print \$3}") &&
+ printf '\161' |
+ dd of=$bitmap count=1 bs=1 conv=notrunc seek=$xor_off &&
+
+ git rev-list --objects --no-object-names HEAD >expect.raw &&
+ git rev-list --objects --use-bitmap-index --no-object-names HEAD \
+ >actual.raw &&
+
+ sort expect.raw >expect &&
+ sort actual.raw >actual &&
+
+ test_cmp expect actual
+ )
+ '
}
test_bitmap_cases
diff --git a/t/t5323-pack-redundant.sh b/t/t5323-pack-redundant.sh
index bc30bc9652..2d96afd6f7 100755
--- a/t/t5323-pack-redundant.sh
+++ b/t/t5323-pack-redundant.sh
@@ -45,6 +45,11 @@ fi
main_repo=main.git
shared_repo=shared.git
+test_expect_success 'pack-redundant needs --i-still-use-this' '
+ test_must_fail git pack-redundant >message 2>&1 &&
+ test_grep "nominated for removal" message
+'
+
git_pack_redundant='git pack-redundant --i-still-use-this'
# Create commits in <repo> and assign each commit's oid to shell variables
diff --git a/t/t5331-pack-objects-stdin.sh b/t/t5331-pack-objects-stdin.sh
index b48c0cbe8f..4a8df5a389 100755
--- a/t/t5331-pack-objects-stdin.sh
+++ b/t/t5331-pack-objects-stdin.sh
@@ -64,7 +64,7 @@ test_expect_success '--stdin-packs is incompatible with --filter' '
cd stdin-packs &&
test_must_fail git pack-objects --stdin-packs --stdout \
--filter=blob:none </dev/null 2>err &&
- test_grep "cannot use --filter with --stdin-packs" err
+ test_grep "options .--stdin-packs. and .--filter. cannot be used together" err
)
'
@@ -236,4 +236,124 @@ test_expect_success 'pack-objects --stdin with packfiles from main and alternate
test_cmp expected-objects actual-objects
'
+objdir=.git/objects
+packdir=$objdir/pack
+
+objects_in_packs () {
+ for p in "$@"
+ do
+ git show-index <"$packdir/pack-$p.idx" || return 1
+ done >objects.raw &&
+
+ cut -d' ' -f2 objects.raw | sort &&
+ rm -f objects.raw
+}
+
+test_expect_success '--stdin-packs=follow walks into unknown packs' '
+ test_when_finished "rm -fr repo" &&
+
+ git init repo &&
+ (
+ cd repo &&
+
+ for c in A B C D
+ do
+ test_commit "$c" || return 1
+ done &&
+
+ A="$(echo A | git pack-objects --revs $packdir/pack)" &&
+ B="$(echo A..B | git pack-objects --revs $packdir/pack)" &&
+ C="$(echo B..C | git pack-objects --revs $packdir/pack)" &&
+ D="$(echo C..D | git pack-objects --revs $packdir/pack)" &&
+ test_commit E &&
+
+ git prune-packed &&
+
+ cat >in <<-EOF &&
+ pack-$B.pack
+ ^pack-$C.pack
+ pack-$D.pack
+ EOF
+
+ # With just --stdin-packs, pack "A" is unknown to us, so
+ # only objects from packs "B" and "D" are included in
+ # the output pack.
+ P=$(git pack-objects --stdin-packs $packdir/pack <in) &&
+ objects_in_packs $B $D >expect &&
+ objects_in_packs $P >actual &&
+ test_cmp expect actual &&
+
+ # But with --stdin-packs=follow, objects from both
+ # included packs reach objects from the unknown pack, so
+ # objects from pack "A" is included in the output pack
+ # in addition to the above.
+ P=$(git pack-objects --stdin-packs=follow $packdir/pack <in) &&
+ objects_in_packs $A $B $D >expect &&
+ objects_in_packs $P >actual &&
+ test_cmp expect actual &&
+
+ # And with --unpacked, we will pick up objects from unknown
+ # packs that are reachable from loose objects. Loose object E
+ # reaches objects in pack A, but there are three excluded packs
+ # in between.
+ #
+ # The resulting pack should include objects reachable from E
+ # that are not present in packs B, C, or D, along with those
+ # present in pack A.
+ cat >in <<-EOF &&
+ ^pack-$B.pack
+ ^pack-$C.pack
+ ^pack-$D.pack
+ EOF
+
+ P=$(git pack-objects --stdin-packs=follow --unpacked \
+ $packdir/pack <in) &&
+
+ {
+ objects_in_packs $A &&
+ git rev-list --objects --no-object-names D..E
+ }>expect.raw &&
+ sort expect.raw >expect &&
+ objects_in_packs $P >actual &&
+ test_cmp expect actual
+ )
+'
+
+stdin_packs__follow_with_only () {
+ rm -fr stdin_packs__follow_with_only &&
+ git init stdin_packs__follow_with_only &&
+ (
+ cd stdin_packs__follow_with_only &&
+
+ test_commit A &&
+ test_commit B &&
+
+ git rev-parse "$@" >B.objects &&
+
+ echo A | git pack-objects --revs $packdir/pack &&
+ B="$(git pack-objects $packdir/pack <B.objects)" &&
+
+ git cat-file --batch-check="%(objectname)" --batch-all-objects >objs &&
+ for obj in $(cat objs)
+ do
+ rm -f $objdir/$(test_oid_to_path $obj) || return 1
+ done &&
+
+ ( cd $packdir && ls pack-*.pack ) >in &&
+ git pack-objects --stdin-packs=follow --stdout >/dev/null <in
+ )
+}
+
+test_expect_success '--stdin-packs=follow tolerates missing blobs' '
+ stdin_packs__follow_with_only HEAD HEAD^{tree}
+'
+
+test_expect_success '--stdin-packs=follow tolerates missing trees' '
+ stdin_packs__follow_with_only HEAD HEAD:B.t
+'
+
+test_expect_success '--stdin-packs=follow tolerates missing commits' '
+ stdin_packs__follow_with_only HEAD HEAD^{tree}
+'
+
test_done
diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh
index ba5ae6a00c..1f7a5d82ee 100755
--- a/t/t5333-pseudo-merge-bitmaps.sh
+++ b/t/t5333-pseudo-merge-bitmaps.sh
@@ -234,8 +234,8 @@ test_expect_success 'pseudo-merge pattern with capture groups' '
test_commit_bulk 16 &&
git rev-list HEAD~16.. >in &&
- sed "s|\(.*\)|create refs/remotes/$r/tags/\1 \1" in |
- git update-ref --stdin || return 1
+ sed "s|\(.*\)|create refs/remotes/$r/tags/\1 \1|" in >refs &&
+ git update-ref --stdin <refs || return 1
done &&
git \
diff --git a/t/t5408-send-pack-stdin.sh b/t/t5408-send-pack-stdin.sh
index 526a675045..ec339761c2 100755
--- a/t/t5408-send-pack-stdin.sh
+++ b/t/t5408-send-pack-stdin.sh
@@ -69,15 +69,24 @@ test_expect_success 'stdin mixed with cmdline' '
test_expect_success 'cmdline refs written in order' '
clear_remote &&
- test_must_fail git send-pack remote.git A:foo B:foo &&
- verify_push A foo
+ test_must_fail git send-pack remote.git A:foo B:foo 2>err &&
+ test_grep "multiple updates for ref ${SQ}refs/heads/foo${SQ} not allowed" err &&
+ test_must_fail git --git-dir=remote.git rev-parse foo
+'
+
+test_expect_success 'cmdline refs with multiple duplicates' '
+ clear_remote &&
+ test_must_fail git send-pack remote.git A:foo B:foo C:foo 2>err &&
+ test_grep "multiple updates for ref ${SQ}refs/heads/foo${SQ} not allowed" err &&
+ test_must_fail git --git-dir=remote.git rev-parse foo
'
test_expect_success '--stdin refs come after cmdline' '
clear_remote &&
echo A:foo >input &&
test_must_fail git send-pack remote.git --stdin B:foo <input &&
- verify_push B foo
+ test_grep "multiple updates for ref ${SQ}refs/heads/foo${SQ} not allowed" err &&
+ test_must_fail git --git-dir=remote.git rev-parse foo
'
test_expect_success 'refspecs and --mirror do not mix (cmdline)' '
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index bef0250e89..2701eef85e 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -1644,4 +1644,18 @@ test_expect_success 'empty config clears remote.*.pushurl list' '
test_cmp expect actual
'
+test_expect_success 'forbid adding subset of existing remote' '
+ test_when_finished "git remote rm outer" &&
+ git remote add outer url &&
+ test_must_fail git remote add outer/inner url 2>err &&
+ test_grep ".outer/inner. is a subset of existing remote .outer." err
+'
+
+test_expect_success 'forbid adding superset of existing remote' '
+ test_when_finished "git remote rm outer/inner" &&
+ git remote add outer/inner url &&
+ test_must_fail git remote add outer url 2>err &&
+ test_grep ".outer. is a superset of existing remote .outer/inner." err
+'
+
test_done
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 782f5f93ea..4e9c27b0f2 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -744,8 +744,8 @@ test_expect_success 'pushing valid refs triggers post-receive and post-update ho
EOF
cat >update.expect <<-EOF &&
- refs/heads/main $orgmain $newmain
refs/heads/next $orgnext $newnext
+ refs/heads/main $orgmain $newmain
EOF
cat >post-receive.expect <<-EOF &&
@@ -808,8 +808,8 @@ test_expect_success 'deletion of a non-existent ref is not fed to post-receive a
EOF
cat >update.expect <<-EOF &&
- refs/heads/main $orgmain $newmain
refs/heads/nonexistent $ZERO_OID $ZERO_OID
+ refs/heads/main $orgmain $newmain
EOF
cat >post-receive.expect <<-EOF &&
@@ -868,10 +868,10 @@ test_expect_success 'mixed ref updates, deletes, invalid deletes trigger hooks w
EOF
cat >update.expect <<-EOF &&
- refs/heads/main $orgmain $newmain
refs/heads/next $orgnext $newnext
- refs/heads/seen $orgseen $newseen
refs/heads/nonexistent $ZERO_OID $ZERO_OID
+ refs/heads/main $orgmain $newmain
+ refs/heads/seen $orgseen $newseen
EOF
cat >post-receive.expect <<-EOF &&
@@ -1919,4 +1919,13 @@ test_expect_success 'push with config pack.usePathWalk=true' '
test_region pack-objects path-walk path-walk.txt
'
+test_expect_success 'push with F/D conflict with deletion and creation' '
+ test_when_finished "git branch -D branch" &&
+ git branch branch/conflict &&
+ mk_test testrepo heads/branch/conflict &&
+ git branch -D branch/conflict &&
+ git branch branch &&
+ git push testrepo :refs/heads/branch/conflict refs/heads/branch
+'
+
test_done
diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh
index 9b211a626b..7a0943bd36 100755
--- a/t/t5558-clone-bundle-uri.sh
+++ b/t/t5558-clone-bundle-uri.sh
@@ -1279,6 +1279,29 @@ test_expect_success 'bundles are downloaded once during fetch --all' '
trace-mult.txt >bundle-fetches &&
test_line_count = 1 bundle-fetches
'
+
+test_expect_success 'bundles with space in URI are rejected' '
+ test_when_finished "rm -rf busted repo" &&
+ mkdir -p "$HOME/busted/ /$HOME/repo/.git/objects/bundles" &&
+ git clone --bundle-uri="$HTTPD_URL/bogus $HOME/busted/" "$HTTPD_URL/smart/fetch.git" repo 2>err &&
+ test_grep "error: bundle-uri: URI is malformed: " err &&
+ find busted -type f >files &&
+ test_must_be_empty files
+'
+
+test_expect_success 'bundles with newline in URI are rejected' '
+ test_when_finished "rm -rf busted repo" &&
+ git clone --bundle-uri="$HTTPD_URL/bogus\nget $HTTPD_URL/bogus $HOME/busted" "$HTTPD_URL/smart/fetch.git" repo 2>err &&
+ test_grep "error: bundle-uri: URI is malformed: " err &&
+ test_path_is_missing "$HOME/busted"
+'
+
+test_expect_success 'bundles with newline in target path are rejected' '
+ git clone --bundle-uri="$HTTPD_URL/bogus" "$HTTPD_URL/smart/fetch.git" "$(printf "escape\nget $HTTPD_URL/bogus .")" 2>err &&
+ test_grep "error: bundle-uri: filename is malformed: " err &&
+ test_path_is_missing escape
+'
+
# Do not add tests here unless they use the HTTP server, as they will
# not run unless the HTTP dependencies exist.
diff --git a/t/t6422-merge-rename-corner-cases.sh b/t/t6422-merge-rename-corner-cases.sh
index 9cbe7ca782..f14c0fb30e 100755
--- a/t/t6422-merge-rename-corner-cases.sh
+++ b/t/t6422-merge-rename-corner-cases.sh
@@ -1146,10 +1146,7 @@ test_conflicts_with_adds_and_renames() {
cd simple_${sideL}_${sideR} &&
# Create some related files now
- for i in $(test_seq 1 10)
- do
- echo Random base content line $i
- done >file_v1 &&
+ test_seq -f "Random base content line %d" 1 10 >file_v1 &&
cp file_v1 file_v2 &&
echo modification >>file_v2 &&
@@ -1293,10 +1290,7 @@ test_setup_nested_conflicts_from_rename_rename () {
cd nested_conflicts_from_rename_rename &&
# Create some related files now
- for i in $(test_seq 1 10)
- do
- echo Random base content line $i
- done >file_v1 &&
+ test_seq -f "Random base content line %d" 1 10 >file_v1 &&
cp file_v1 file_v2 &&
cp file_v1 file_v3 &&
diff --git a/t/t7007-show.sh b/t/t7007-show.sh
index d6cc69e0f2..2d322b53d1 100755
--- a/t/t7007-show.sh
+++ b/t/t7007-show.sh
@@ -167,4 +167,28 @@ test_expect_success 'show --graph is forbidden' '
test_must_fail git show --graph HEAD
'
+test_expect_success 'show unmerged index' '
+ git reset --hard &&
+
+ git switch -C base &&
+ echo "base" >conflicting &&
+ git add conflicting &&
+ git commit -m "base" &&
+
+ git branch hello &&
+ git branch goodbye &&
+
+ git switch hello &&
+ echo "hello" >conflicting &&
+ git commit -am "hello" &&
+
+ git switch goodbye &&
+ echo "goodbye" >conflicting &&
+ git commit -am "goodbye" &&
+
+ git switch hello &&
+ test_must_fail git merge goodbye &&
+ git show --merge HEAD
+'
+
test_done
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index ab76d4b6dc..3adab12091 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -1137,6 +1137,67 @@ test_expect_success 'setup clean recursive superproject' '
git clone --recurse-submodules top top-clean
'
+test_expect_success 'submodule update with multiple remotes' '
+ test_when_finished "rm -fr top-cloned" &&
+ cp -r top-clean top-cloned &&
+
+ # Create a commit in each repo, starting with bottom
+ test_commit -C bottom multiple_remote_commit &&
+ # Create middle commit
+ git -C middle/bottom fetch &&
+ git -C middle/bottom checkout -f FETCH_HEAD &&
+ git -C middle add bottom &&
+ git -C middle commit -m "multiple_remote_commit" &&
+ # Create top commit
+ git -C top/middle fetch &&
+ git -C top/middle checkout -f FETCH_HEAD &&
+ git -C top add middle &&
+ git -C top commit -m "multiple_remote_commit" &&
+
+ # rename the submodule remote
+ git -C top-cloned/middle remote rename origin upstream &&
+
+ # Add another remote
+ git -C top-cloned/middle remote add other bogus &&
+
+ # Make the update of "middle" a no-op, otherwise we error out
+ # because of its unmerged state
+ test_config -C top-cloned submodule.middle.update !true &&
+ git -C top-cloned submodule update --recursive 2>actual.err &&
+ cat >expect.err <<-\EOF &&
+ EOF
+ test_cmp expect.err actual.err
+'
+
+test_expect_success 'submodule update with renamed remote' '
+ test_when_finished "rm -fr top-cloned" &&
+ cp -r top-clean top-cloned &&
+
+ # Create a commit in each repo, starting with bottom
+ test_commit -C bottom rename_commit &&
+ # Create middle commit
+ git -C middle/bottom fetch &&
+ git -C middle/bottom checkout -f FETCH_HEAD &&
+ git -C middle add bottom &&
+ git -C middle commit -m "rename_commit" &&
+ # Create top commit
+ git -C top/middle fetch &&
+ git -C top/middle checkout -f FETCH_HEAD &&
+ git -C top add middle &&
+ git -C top commit -m "rename_commit" &&
+
+ # rename the submodule remote
+ git -C top-cloned/middle remote rename origin upstream &&
+
+ # Make the update of "middle" a no-op, otherwise we error out
+ # because of its unmerged state
+ test_config -C top-cloned submodule.middle.update !true &&
+ git -C top-cloned submodule update --recursive 2>actual.err &&
+ cat >expect.err <<-\EOF &&
+ EOF
+ test_cmp expect.err actual.err
+'
+
test_expect_success 'submodule update should skip unmerged submodules' '
test_when_finished "rm -fr top-cloned" &&
cp -r top-clean top-cloned &&
diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh
index 023a5cbdc4..aea1ddf117 100755
--- a/t/t7422-submodule-output.sh
+++ b/t/t7422-submodule-output.sh
@@ -180,17 +180,14 @@ test_expect_success !MINGW 'git submodule status --recursive propagates SIGPIPE'
COMMIT=$(git rev-parse HEAD) &&
for i in $(test_seq 2000)
do
- printf "[submodule \"sm-$i\"]\npath = recursive-submodule-path-$i\n" "$i" ||
+ echo "[submodule \"sm-$i\"]" &&
+ echo "path = recursive-submodule-path-$i" ||
return 1
done >gitmodules &&
BLOB=$(git hash-object -w --stdin <gitmodules) &&
printf "100644 blob $BLOB\t.gitmodules\n" >tree &&
- for i in $(test_seq 2000)
- do
- printf "160000 commit $COMMIT\trecursive-submodule-path-%d\n" "$i" ||
- return 1
- done >>tree &&
+ test_seq -f "160000 commit $COMMIT\trecursive-submodule-path-%d" 2000 >>tree &&
TREE=$(git mktree <tree) &&
COMMIT=$(git commit-tree "$TREE") &&
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index 9367794641..14b5743b96 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -372,4 +372,37 @@ test_expect_success 'checkout -f --recurse-submodules must not use a nested gitd
test_path_is_missing nested_checkout/thing2/.git
'
+test_expect_success SYMLINKS,!WINDOWS,!MINGW 'submodule must not checkout into different directory' '
+ test_when_finished "rm -rf sub repo bad-clone" &&
+
+ git init sub &&
+ write_script sub/post-checkout <<-\EOF &&
+ touch "$PWD/foo"
+ EOF
+ git -C sub add post-checkout &&
+ git -C sub commit -m hook &&
+
+ git init repo &&
+ git -C repo -c protocol.file.allow=always submodule add "$PWD/sub" sub &&
+ git -C repo mv sub $(printf "sub\r") &&
+
+ # Ensure config values containing CR are wrapped in quotes.
+ git config unset -f repo/.gitmodules submodule.sub.path &&
+ printf "\tpath = \"sub\r\"\n" >>repo/.gitmodules &&
+
+ git config unset -f repo/.git/modules/sub/config core.worktree &&
+ {
+ printf "[core]\n" &&
+ printf "\tworktree = \"../../../sub\r\"\n"
+ } >>repo/.git/modules/sub/config &&
+
+ ln -s .git/modules/sub/hooks repo/sub &&
+ git -C repo add -A &&
+ git -C repo commit -m submodule &&
+
+ git -c protocol.file.allow=always clone --recurse-submodules repo bad-clone &&
+ ! test -f "$PWD/foo" &&
+ test -f $(printf "bad-clone/sub\r/post-checkout")
+'
+
test_done
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
index 065f780636..0f887a3ebe 100755
--- a/t/t7528-signed-commit-ssh.sh
+++ b/t/t7528-signed-commit-ssh.sh
@@ -84,18 +84,26 @@ test_expect_success GPGSSH 'sign commits using literal public keys with ssh-agen
test_config gpg.format ssh &&
eval $(ssh-agent) &&
test_when_finished "kill ${SSH_AGENT_PID}" &&
- ssh-add "${GPGSSH_KEY_PRIMARY}" &&
- echo 1 >file && git add file &&
- git commit -a -m rsa-inline -S"$(cat "${GPGSSH_KEY_PRIMARY}.pub")" &&
- echo 2 >file &&
- test_config user.signingkey "$(cat "${GPGSSH_KEY_PRIMARY}.pub")" &&
- git commit -a -m rsa-config -S &&
- ssh-add "${GPGSSH_KEY_ECDSA}" &&
- echo 3 >file &&
- git commit -a -m ecdsa-inline -S"key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" &&
- echo 4 >file &&
- test_config user.signingkey "key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" &&
- git commit -a -m ecdsa-config -S
+ test_when_finished "test_unconfig user.signingkey" &&
+ mkdir tmpdir &&
+ TMPDIR="$(pwd)/tmpdir" &&
+ (
+ export TMPDIR &&
+ ssh-add "${GPGSSH_KEY_PRIMARY}" &&
+ echo 1 >file && git add file &&
+ git commit -a -m rsa-inline -S"$(cat "${GPGSSH_KEY_PRIMARY}.pub")" &&
+ echo 2 >file &&
+ git config user.signingkey "$(cat "${GPGSSH_KEY_PRIMARY}.pub")" &&
+ git commit -a -m rsa-config -S &&
+ ssh-add "${GPGSSH_KEY_ECDSA}" &&
+ echo 3 >file &&
+ git commit -a -m ecdsa-inline -S"key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" &&
+ echo 4 >file &&
+ git config user.signingkey "key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" &&
+ git commit -a -m ecdsa-config -S
+ ) &&
+ find tmpdir -type f >tmpfiles &&
+ test_must_be_empty tmpfiles
'
test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'create signed commits with keys having defined lifetimes' '
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 2a8df29219..9838094b66 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -185,8 +185,19 @@ test_expect_success 'reject non-strategy with a git-merge-foo name' '
test_expect_success 'merge c0 with c1' '
echo "OBJID HEAD@{0}: merge c1: Fast-forward" >reflog.expected &&
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ create mode 100644 other
+ EOF
+
git reset --hard c0 &&
- git merge c1 &&
+ git merge c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual &&
verify_merge file result.1 &&
verify_head "$c1" &&
@@ -205,6 +216,67 @@ test_expect_success 'merge c0 with c1 with --ff-only' '
verify_head "$c1"
'
+test_expect_success 'the same merge with merge.stat=diffstat' '
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ create mode 100644 other
+ EOF
+
+ git reset --hard c0 &&
+ git -c merge.stat=diffstat merge c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'the same merge with compact summary' '
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other (new) | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ EOF
+
+ git reset --hard c0 &&
+ git merge --compact-summary c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'the same merge with compact summary' '
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other (new) | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ EOF
+
+ git reset --hard c0 &&
+ git merge --compact-summary c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'the same merge with merge.stat=compact' '
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other (new) | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ EOF
+
+ git reset --hard c0 &&
+ git -c merge.stat=compact merge c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual
+'
+
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge from unborn branch' '
diff --git a/t/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh
index 8aebfb45f5..aa2e2e6ad8 100755
--- a/t/t7704-repack-cruft.sh
+++ b/t/t7704-repack-cruft.sh
@@ -724,4 +724,149 @@ test_expect_success 'cruft repack respects --quiet' '
)
'
+setup_cruft_exclude_tests() {
+ git init "$1" &&
+ (
+ cd "$1" &&
+
+ git config repack.midxMustContainCruft false &&
+
+ test_commit one &&
+
+ test_commit --no-tag two &&
+ two="$(git rev-parse HEAD)" &&
+ test_commit --no-tag three &&
+ three="$(git rev-parse HEAD)" &&
+ git reset --hard one &&
+ git reflog expire --all --expire=all &&
+
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack --cruft -d &&
+
+ git merge $two &&
+ test_commit four
+ )
+}
+
+test_expect_success 'repack --write-midx excludes cruft where possible' '
+ setup_cruft_exclude_tests exclude-cruft-when-possible &&
+ (
+ cd exclude-cruft-when-possible &&
+
+ GIT_TEST_MULTI_PACK_INDEX=0 \
+ git repack -d --geometric=2 --write-midx --write-bitmap-index &&
+
+ test-tool read-midx --show-objects $objdir >midx &&
+ cruft="$(ls $packdir/*.mtimes)" &&
+ test_grep ! "$(basename "$cruft" .mtimes).idx" midx &&
+
+ git rev-list --all --objects --no-object-names >reachable.raw &&
+ sort reachable.raw >reachable.objects &&
+ awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects &&
+
+ test_cmp reachable.objects midx.objects
+ )
+'
+
+test_expect_success 'repack --write-midx includes cruft when instructed' '
+ setup_cruft_exclude_tests exclude-cruft-when-instructed &&
+ (
+ cd exclude-cruft-when-instructed &&
+
+ GIT_TEST_MULTI_PACK_INDEX=0 \
+ git -c repack.midxMustContainCruft=true repack \
+ -d --geometric=2 --write-midx --write-bitmap-index &&
+
+ test-tool read-midx --show-objects $objdir >midx &&
+ cruft="$(ls $packdir/*.mtimes)" &&
+ test_grep "$(basename "$cruft" .mtimes).idx" midx &&
+
+ git cat-file --batch-check="%(objectname)" --batch-all-objects \
+ >all.objects &&
+ awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects &&
+
+ test_cmp all.objects midx.objects
+ )
+'
+
+test_expect_success 'repack --write-midx includes cruft when necessary' '
+ setup_cruft_exclude_tests exclude-cruft-when-necessary &&
+ (
+ cd exclude-cruft-when-necessary &&
+
+ test_path_is_file $(ls $packdir/pack-*.mtimes) &&
+ ( cd $packdir && ls pack-*.idx ) | sort >packs.all &&
+ git multi-pack-index write --stdin-packs --bitmap <packs.all &&
+
+ test_commit five &&
+ GIT_TEST_MULTI_PACK_INDEX=0 \
+ git repack -d --geometric=2 --write-midx --write-bitmap-index &&
+
+ test-tool read-midx --show-objects $objdir >midx &&
+ awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects &&
+ git cat-file --batch-all-objects --batch-check="%(objectname)" \
+ >expect.objects &&
+ test_cmp expect.objects midx.objects &&
+
+ grep "^pack-" midx >midx.packs &&
+ test_line_count = "$(($(wc -l <packs.all) + 1))" midx.packs
+ )
+'
+
+test_expect_success 'repack --write-midx includes cruft when already geometric' '
+ git init repack--write-midx-geometric-noop &&
+ (
+ cd repack--write-midx-geometric-noop &&
+
+ git branch -M main &&
+ test_commit A &&
+ test_commit B &&
+
+ git checkout -B side &&
+ test_commit --no-tag C &&
+ C="$(git rev-parse HEAD)" &&
+
+ git checkout main &&
+ git branch -D side &&
+ git reflog expire --all --expire=all &&
+
+ # At this point we have two packs: one containing the
+ # objects belonging to commits A and B, and another
+ # (cruft) pack containing the objects belonging to
+ # commit C.
+ git repack --cruft -d &&
+
+ # Create a third pack which contains a merge commit
+ # making commit C reachable again.
+ #
+ # --no-ff is important here, as it ensures that we
+ # actually write a new object and subsequently a new
+ # pack to contain it.
+ git merge --no-ff $C &&
+ git repack -d &&
+
+ ls $packdir/pack-*.idx | sort >packs.all &&
+ cruft="$(ls $packdir/pack-*.mtimes)" &&
+ cruft="${cruft%.mtimes}.idx" &&
+
+ for idx in $(grep -v $cruft <packs.all)
+ do
+ git show-index <$idx >out &&
+ wc -l <out || return 1
+ done >sizes.raw &&
+
+ # Make sure that there are two non-cruft packs, and
+ # that one of them contains at least twice as many
+ # objects as the other, ensuring that they are already
+ # in a geometric progression.
+ sort -n sizes.raw >sizes &&
+ test_line_count = 2 sizes &&
+ s1=$(head -n 1 sizes) &&
+ s2=$(tail -n 1 sizes) &&
+ test "$s2" -gt "$((2 * $s1))" &&
+
+ git -c repack.midxMustContainCruft=false repack --geometric=2 \
+ --write-midx --write-bitmap-index
+ )
+'
+
test_done
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 8cf89e285f..ddd273d8dc 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -49,9 +49,9 @@ test_expect_success 'run [--auto|--quiet]' '
git maintenance run --auto 2>/dev/null &&
GIT_TRACE2_EVENT="$(pwd)/run-no-quiet.txt" \
git maintenance run --no-quiet 2>/dev/null &&
- test_subcommand git gc --quiet --no-detach <run-no-auto.txt &&
- test_subcommand ! git gc --auto --quiet --no-detach <run-auto.txt &&
- test_subcommand git gc --no-quiet --no-detach <run-no-quiet.txt
+ test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-no-auto.txt &&
+ test_subcommand ! git gc --auto --quiet --no-detach --skip-foreground-tasks <run-auto.txt &&
+ test_subcommand git gc --no-quiet --no-detach --skip-foreground-tasks <run-no-quiet.txt
'
test_expect_success 'maintenance.auto config option' '
@@ -154,9 +154,9 @@ test_expect_success 'run --task=<task>' '
git maintenance run --task=commit-graph 2>/dev/null &&
GIT_TRACE2_EVENT="$(pwd)/run-both.txt" \
git maintenance run --task=commit-graph --task=gc 2>/dev/null &&
- test_subcommand ! git gc --quiet --no-detach <run-commit-graph.txt &&
- test_subcommand git gc --quiet --no-detach <run-gc.txt &&
- test_subcommand git gc --quiet --no-detach <run-both.txt &&
+ test_subcommand ! git gc --quiet --no-detach --skip-foreground-tasks <run-commit-graph.txt &&
+ test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-gc.txt &&
+ test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-both.txt &&
test_subcommand git commit-graph write --split --reachable --no-progress <run-commit-graph.txt &&
test_subcommand ! git commit-graph write --split --reachable --no-progress <run-gc.txt &&
test_subcommand git commit-graph write --split --reachable --no-progress <run-both.txt
@@ -610,7 +610,12 @@ test_expect_success 'rerere-gc task with --auto honors maintenance.rerere-gc.aut
test_expect_success '--auto and --schedule incompatible' '
test_must_fail git maintenance run --auto --schedule=daily 2>err &&
- test_grep "at most one" err
+ test_grep "cannot be used together" err
+'
+
+test_expect_success '--task and --schedule incompatible' '
+ test_must_fail git maintenance run --task=pack-refs --schedule=daily 2>err &&
+ test_grep "cannot be used together" err
'
test_expect_success 'invalid --schedule value' '
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 0c1af43f6f..e56e0c8d77 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -201,6 +201,13 @@ test_expect_success $PREREQ 'cc trailer with get_maintainer.pl output' '
test_cmp expected-cc commandline1
'
+test_expect_failure $PREREQ 'invalid smtp server port value' '
+ clean_fake_sendmail &&
+ git send-email -1 --to=recipient@example.com \
+ --smtp-server-port=bogus-symbolic-name \
+ --smtp-server="$(pwd)/fake.sendmail"
+'
+
test_expect_success $PREREQ 'setup expect' "
cat >expected-show-all-headers <<\EOF
0001-Second.patch
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index b258dbf1df..4dc3d645bf 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -120,7 +120,7 @@ test_expect_success 'A: create pack from stdin' '
INPUT_END
git fast-import --export-marks=marks.out <input &&
- git whatchanged main
+ git log --raw main
'
test_expect_success 'A: verify pack' '
@@ -279,7 +279,7 @@ test_expect_success 'A: verify marks import does not crash' '
INPUT_END
git fast-import --import-marks=marks.out <input &&
- git whatchanged verify--import-marks
+ git log --raw verify--import-marks
'
test_expect_success 'A: verify pack' '
@@ -652,7 +652,7 @@ test_expect_success 'C: incremental import create pack from stdin' '
INPUT_END
git fast-import <input &&
- git whatchanged branch
+ git log --raw branch
'
test_expect_success 'C: verify pack' '
@@ -715,7 +715,7 @@ test_expect_success 'D: inline data in commit' '
INPUT_END
git fast-import <input &&
- git whatchanged branch
+ git log --raw branch
'
test_expect_success 'D: verify pack' '
@@ -882,7 +882,7 @@ test_expect_success 'H: deletall, add 1' '
INPUT_END
git fast-import <input &&
- git whatchanged H
+ git log --raw H
'
test_expect_success 'H: verify pack' '
@@ -2066,7 +2066,7 @@ test_expect_success 'Q: commit notes' '
INPUT_END
git fast-import <input &&
- git whatchanged notes-test
+ git log --raw notes-test
'
test_expect_success 'Q: verify pack' '
diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh
index 1ae4d7c0d3..e62173cf1f 100755
--- a/t/t9301-fast-import-notes.sh
+++ b/t/t9301-fast-import-notes.sh
@@ -76,7 +76,7 @@ INPUT_END
test_expect_success 'set up main branch' '
git fast-import <input &&
- git whatchanged main
+ git log --raw main
'
commit4=$(git rev-parse refs/heads/main)
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index bee4a2ca34..a28de7b19b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1451,9 +1451,21 @@ test_cmp_fspath () {
# test_seq 1 5 -- outputs 1 2 3 4 5 one line at a time
#
# or with one argument (end), in which case it starts counting
-# from 1.
+# from 1. In addition to the start/end arguments, you can pass an optional
+# printf format. For example:
+#
+# test_seq -f "line %d" 1 5
+#
+# would print 5 lines, "line 1" through "line 5".
test_seq () {
+ local fmt="%d"
+ case "$1" in
+ -f)
+ fmt="$2"
+ shift 2
+ ;;
+ esac
case $# in
1) set 1 "$@" ;;
2) ;;
@@ -1462,7 +1474,7 @@ test_seq () {
test_seq_counter__=$1
while test "$test_seq_counter__" -le "$2"
do
- echo "$test_seq_counter__"
+ printf "$fmt\n" "$test_seq_counter__"
test_seq_counter__=$(( $test_seq_counter__ + 1 ))
done
}
@@ -1695,7 +1707,7 @@ test_set_hash () {
# Detect the hash algorithm in use.
test_detect_hash () {
- case "$GIT_TEST_DEFAULT_HASH" in
+ case "${GIT_TEST_DEFAULT_HASH:-$GIT_TEST_BUILTIN_HASH}" in
"sha256")
test_hash_algo=sha256
test_compat_hash_algo=sha1
@@ -1767,6 +1779,9 @@ test_oid () {
--hash=compat)
algo="$test_compat_hash_algo" &&
shift;;
+ --hash=builtin)
+ algo="$GIT_TEST_BUILTIN_HASH" &&
+ shift;;
--hash=*)
algo="${1#--hash=}" &&
shift;;
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 51370a201c..6dc2022ee1 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -536,7 +536,8 @@ export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
export EDITOR
-GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-sha1}"
+GIT_TEST_BUILTIN_HASH=$("$GIT_BUILD_DIR/git" version --build-options | sed -ne 's/^default-hash: //p')
+GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-$GIT_TEST_BUILTIN_HASH}"
export GIT_DEFAULT_HASH
GIT_DEFAULT_REF_FORMAT="${GIT_TEST_DEFAULT_REF_FORMAT:-files}"
export GIT_DEFAULT_REF_FORMAT
@@ -1908,6 +1909,10 @@ test_lazy_prereq SHA1 '
esac
'
+test_lazy_prereq DEFAULT_HASH_ALGORITHM '
+ test "$GIT_TEST_BUILTIN_HASH" = "$GIT_DEFAULT_HASH"
+'
+
test_lazy_prereq DEFAULT_REPO_FORMAT '
test_have_prereq SHA1,REFFILES
'
diff --git a/t/unit-tests/u-string-list.c b/t/unit-tests/u-string-list.c
new file mode 100644
index 0000000000..d4ba5f9fa5
--- /dev/null
+++ b/t/unit-tests/u-string-list.c
@@ -0,0 +1,227 @@
+#include "unit-test.h"
+#include "string-list.h"
+
+static void t_vcreate_string_list_dup(struct string_list *list,
+ int free_util, va_list ap)
+{
+ const char *arg;
+
+ cl_assert(list->strdup_strings);
+
+ string_list_clear(list, free_util);
+ while ((arg = va_arg(ap, const char *)))
+ string_list_append(list, arg);
+}
+
+static void t_create_string_list_dup(struct string_list *list, int free_util, ...)
+{
+ va_list ap;
+
+ cl_assert(list->strdup_strings);
+
+ string_list_clear(list, free_util);
+ va_start(ap, free_util);
+ t_vcreate_string_list_dup(list, free_util, ap);
+ va_end(ap);
+}
+
+static void t_string_list_clear(struct string_list *list, int free_util)
+{
+ string_list_clear(list, free_util);
+ cl_assert_equal_p(list->items, NULL);
+ cl_assert_equal_i(list->nr, 0);
+ cl_assert_equal_i(list->alloc, 0);
+}
+
+static void t_string_list_equal(struct string_list *list,
+ struct string_list *expected_strings)
+{
+ cl_assert_equal_i(list->nr, expected_strings->nr);
+ cl_assert(list->nr <= list->alloc);
+ for (size_t i = 0; i < expected_strings->nr; i++)
+ cl_assert_equal_s(list->items[i].string,
+ expected_strings->items[i].string);
+}
+
+static void t_string_list_split(const char *data, int delim, int maxsplit, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
+ struct string_list list = STRING_LIST_INIT_DUP;
+ va_list ap;
+ int len;
+
+ va_start(ap, maxsplit);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
+ string_list_clear(&list, 0);
+ len = string_list_split(&list, data, delim, maxsplit);
+ cl_assert_equal_i(len, expected_strings.nr);
+ t_string_list_equal(&list, &expected_strings);
+
+ string_list_clear(&expected_strings, 0);
+ string_list_clear(&list, 0);
+}
+
+void test_string_list__split(void)
+{
+ t_string_list_split("foo:bar:baz", ':', -1, "foo", "bar", "baz", NULL);
+ t_string_list_split("foo:bar:baz", ':', 0, "foo:bar:baz", NULL);
+ t_string_list_split("foo:bar:baz", ':', 1, "foo", "bar:baz", NULL);
+ t_string_list_split("foo:bar:baz", ':', 2, "foo", "bar", "baz", NULL);
+ t_string_list_split("foo:bar:", ':', -1, "foo", "bar", "", NULL);
+ t_string_list_split("", ':', -1, "", NULL);
+ t_string_list_split(":", ':', -1, "", "", NULL);
+}
+
+static void t_string_list_split_in_place(const char *data, const char *delim,
+ int maxsplit, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
+ struct string_list list = STRING_LIST_INIT_NODUP;
+ char *string = xstrdup(data);
+ va_list ap;
+ int len;
+
+ va_start(ap, maxsplit);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
+ string_list_clear(&list, 0);
+ len = string_list_split_in_place(&list, string, delim, maxsplit);
+ cl_assert_equal_i(len, expected_strings.nr);
+ t_string_list_equal(&list, &expected_strings);
+
+ free(string);
+ string_list_clear(&expected_strings, 0);
+ string_list_clear(&list, 0);
+}
+
+void test_string_list__split_in_place(void)
+{
+ t_string_list_split_in_place("foo:;:bar:;:baz:;:", ":;", -1,
+ "foo", "", "", "bar", "", "", "baz", "", "", "", NULL);
+ t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 0,
+ "foo:;:bar:;:baz", NULL);
+ t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 1,
+ "foo", ";:bar:;:baz", NULL);
+ t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 2,
+ "foo", "", ":bar:;:baz", NULL);
+ t_string_list_split_in_place("foo:;:bar:;:", ":;", -1,
+ "foo", "", "", "bar", "", "", "", NULL);
+}
+
+static int prefix_cb(struct string_list_item *item, void *cb_data)
+{
+ const char *prefix = (const char *)cb_data;
+ return starts_with(item->string, prefix);
+}
+
+static void t_string_list_filter(struct string_list *list, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
+ const char *prefix = "y";
+ va_list ap;
+
+ va_start(ap, list);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
+ filter_string_list(list, 0, prefix_cb, (void *)prefix);
+ t_string_list_equal(list, &expected_strings);
+
+ string_list_clear(&expected_strings, 0);
+}
+
+void test_string_list__filter(void)
+{
+ struct string_list list = STRING_LIST_INIT_DUP;
+
+ t_create_string_list_dup(&list, 0, NULL);
+ t_string_list_filter(&list, NULL);
+
+ t_create_string_list_dup(&list, 0, "no", NULL);
+ t_string_list_filter(&list, NULL);
+
+ t_create_string_list_dup(&list, 0, "yes", NULL);
+ t_string_list_filter(&list, "yes", NULL);
+
+ t_create_string_list_dup(&list, 0, "no", "yes", NULL);
+ t_string_list_filter(&list, "yes", NULL);
+
+ t_create_string_list_dup(&list, 0, "yes", "no", NULL);
+ t_string_list_filter(&list, "yes", NULL);
+
+ t_create_string_list_dup(&list, 0, "y1", "y2", NULL);
+ t_string_list_filter(&list, "y1", "y2", NULL);
+
+ t_create_string_list_dup(&list, 0, "y2", "y1", NULL);
+ t_string_list_filter(&list, "y2", "y1", NULL);
+
+ t_create_string_list_dup(&list, 0, "x1", "x2", NULL);
+ t_string_list_filter(&list, NULL);
+
+ t_string_list_clear(&list, 0);
+}
+
+static void t_string_list_remove_duplicates(struct string_list *list, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
+ va_list ap;
+
+ va_start(ap, list);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
+ string_list_remove_duplicates(list, 0);
+ t_string_list_equal(list, &expected_strings);
+
+ string_list_clear(&expected_strings, 0);
+}
+
+void test_string_list__remove_duplicates(void)
+{
+ struct string_list list = STRING_LIST_INIT_DUP;
+
+ t_create_string_list_dup(&list, 0, NULL);
+ t_string_list_remove_duplicates(&list, NULL);
+
+ t_create_string_list_dup(&list, 0, "", NULL);
+ t_string_list_remove_duplicates(&list, "", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", NULL);
+ t_string_list_remove_duplicates(&list, "a", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", NULL);
+ t_string_list_remove_duplicates(&list, "a", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", "a", NULL);
+ t_string_list_remove_duplicates(&list, "a", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", "b", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "b", "b", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "b", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", "b", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "b", "b", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "b", "c", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", "b", "b", "c", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", "a", "b", "b", "b",
+ "c", "c", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_string_list_clear(&list, 0);
+}