summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/helper/test-find-pack.c3
-rw-r--r--t/helper/test-pack-deltas.c10
-rw-r--r--t/helper/test-pack-mtimes.c2
-rw-r--r--t/lib-gpg.sh24
-rw-r--r--t/meson.build4
-rw-r--r--t/pack-refs-tests.sh431
-rwxr-xr-xt/perf/p6010-merge-base.sh101
-rwxr-xr-xt/t0001-init.sh16
-rwxr-xr-xt/t0008-ignores.sh11
-rwxr-xr-xt/t0014-alias.sh57
-rwxr-xr-xt/t0300-credentials.sh19
-rwxr-xr-xt/t0600-reffiles-backend.sh26
-rwxr-xr-xt/t0601-reffiles-pack-refs.sh430
-rwxr-xr-xt/t0613-reftable-write-options.sh24
-rwxr-xr-xt/t0614-reftable-fsck.sh58
-rwxr-xr-xt/t1010-mktree.sh13
-rwxr-xr-xt/t1016-compatObjectFormat.sh2
-rwxr-xr-xt/t1091-sparse-checkout-builtin.sh175
-rwxr-xr-xt/t1300-config.sh349
-rwxr-xr-xt/t1400-update-ref.sh53
-rwxr-xr-xt/t1421-reflog-write.sh36
-rwxr-xr-xt/t1450-fsck.sh54
-rwxr-xr-xt/t1463-refs-optimize.sh17
-rwxr-xr-xt/t1500-rev-parse.sh34
-rwxr-xr-xt/t2401-worktree-prune.sh34
-rwxr-xr-xt/t3206-range-diff.sh16
-rwxr-xr-xt/t3415-rebase-autosquash.sh28
-rwxr-xr-xt/t3701-add-interactive.sh126
-rwxr-xr-xt/t3903-stash.sh49
-rwxr-xr-xt/t3905-stash-include-untracked.sh1
-rwxr-xr-xt/t4013-diff-various.sh257
-rw-r--r--t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_main (renamed from t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master)2
-rw-r--r--t/t4013/diff.diff-tree_--cc_--patch-with-stat_main (renamed from t/t4013/diff.diff-tree_--cc_--patch-with-stat_master)2
-rw-r--r--t/t4013/diff.diff-tree_--cc_--shortstat_main (renamed from t/t4013/diff.diff-tree_--cc_--shortstat_master)2
-rw-r--r--t/t4013/diff.diff-tree_--cc_--stat_--summary_main (renamed from t/t4013/diff.diff-tree_-c_--stat_--summary_master)2
-rw-r--r--t/t4013/diff.diff-tree_--cc_--stat_main (renamed from t/t4013/diff.diff-tree_-c_--stat_master)2
-rw-r--r--t/t4013/diff.diff-tree_--cc_main (renamed from t/t4013/diff.diff-tree_--cc_master)2
-rw-r--r--t/t4013/diff.diff-tree_-c_--abbrev_main (renamed from t/t4013/diff.diff-tree_-c_--abbrev_master)2
-rw-r--r--t/t4013/diff.diff-tree_-c_--stat_--summary_main (renamed from t/t4013/diff.diff-tree_--cc_--stat_--summary_master)2
-rw-r--r--t/t4013/diff.diff-tree_-c_--stat_main (renamed from t/t4013/diff.diff-tree_--cc_--stat_master)2
-rw-r--r--t/t4013/diff.diff-tree_-c_main (renamed from t/t4013/diff.diff-tree_-c_master)2
-rw-r--r--t/t4013/diff.diff-tree_-m_main (renamed from t/t4013/diff.diff-tree_-m_master)2
-rw-r--r--t/t4013/diff.diff-tree_-p_-m_main (renamed from t/t4013/diff.diff-tree_-p_-m_master)2
-rw-r--r--t/t4013/diff.diff-tree_-p_main2
-rw-r--r--t/t4013/diff.diff-tree_-p_master2
-rw-r--r--t/t4013/diff.diff-tree_main2
-rw-r--r--t/t4013/diff.diff-tree_master2
-rw-r--r--t/t4013/diff.diff_--dirstat_--cc_main~1_main3
-rw-r--r--t/t4013/diff.diff_--dirstat_--cc_master~1_master3
-rw-r--r--t/t4013/diff.diff_--dirstat_main~1_main~23
-rw-r--r--t/t4013/diff.diff_--dirstat_master~1_master~23
-rw-r--r--t/t4013/diff.diff_--line-prefix=abc_main_main^_side (renamed from t/t4013/diff.diff_--line-prefix=abc_master_master^_side)2
-rw-r--r--t/t4013/diff.diff_main_main^_side (renamed from t/t4013/diff.diff_master_master^_side)2
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..main (renamed from t/t4013/diff.format-patch_--attach_--stdout_initial..master)2
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..main^ (renamed from t/t4013/diff.format-patch_--attach_--stdout_initial..master^)2
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..main (renamed from t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master)2
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..main (renamed from t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master)2
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..main (renamed from t/t4013/diff.format-patch_--inline_--stdout_initial..master)2
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..main^ (renamed from t/t4013/diff.format-patch_--inline_--stdout_initial..master^)2
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..main^^ (renamed from t/t4013/diff.format-patch_--inline_--stdout_initial..master^^)2
-rw-r--r--t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..main^ (renamed from t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^)2
-rw-r--r--t/t4013/diff.format-patch_--stdout_--no-numbered_initial..main (renamed from t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master)2
-rw-r--r--t/t4013/diff.format-patch_--stdout_--numbered_initial..main (renamed from t/t4013/diff.format-patch_--stdout_--numbered_initial..master)2
-rw-r--r--t/t4013/diff.format-patch_--stdout_initial..main (renamed from t/t4013/diff.format-patch_--stdout_initial..master)2
-rw-r--r--t/t4013/diff.format-patch_--stdout_initial..main^ (renamed from t/t4013/diff.format-patch_--stdout_initial..master^)2
-rw-r--r--t/t4013/diff.log_--cc_-m_-p_main (renamed from t/t4013/diff.log_-c_-m_-p_master)2
-rw-r--r--t/t4013/diff.log_--decorate=full_--all2
-rw-r--r--t/t4013/diff.log_--decorate=full_--clear-decorations_--all2
-rw-r--r--t/t4013/diff.log_--decorate=full_--decorate-all_--all2
-rw-r--r--t/t4013/diff.log_--decorate_--all2
-rw-r--r--t/t4013/diff.log_--decorate_--clear-decorations_--all2
-rw-r--r--t/t4013/diff.log_--decorate_--decorate-all_--all2
-rw-r--r--t/t4013/diff.log_--diff-merges=first-parent_main (renamed from t/t4013/diff.log_--diff-merges=first-parent_master)2
-rw-r--r--t/t4013/diff.log_--diff-merges=off_-p_--first-parent_main (renamed from t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master)2
-rw-r--r--t/t4013/diff.log_--first-parent_--diff-merges=off_-p_main (renamed from t/t4013/diff.log_--first-parent_--diff-merges=off_-p_master)2
-rw-r--r--t/t4013/diff.log_--no-diff-merges_-p_--first-parent_main (renamed from t/t4013/diff.log_--diff-merges=off_-p_--first-parent_master)2
-rw-r--r--t/t4013/diff.log_--patch-with-stat_--summary_main_--_dir_ (renamed from t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_)2
-rw-r--r--t/t4013/diff.log_--patch-with-stat_main (renamed from t/t4013/diff.log_--patch-with-stat_master)2
-rw-r--r--t/t4013/diff.log_--patch-with-stat_main_--_dir_ (renamed from t/t4013/diff.log_--patch-with-stat_master_--_dir_)2
-rw-r--r--t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_main (renamed from t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master)2
-rw-r--r--t/t4013/diff.log_--root_--patch-with-stat_--summary_main (renamed from t/t4013/diff.log_--root_--patch-with-stat_--summary_master)2
-rw-r--r--t/t4013/diff.log_--root_--patch-with-stat_main (renamed from t/t4013/diff.log_--root_--patch-with-stat_master)2
-rw-r--r--t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_main (renamed from t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master)2
-rw-r--r--t/t4013/diff.log_--root_-p_main (renamed from t/t4013/diff.log_--root_-p_master)2
-rw-r--r--t/t4013/diff.log_--root_main (renamed from t/t4013/diff.log_--root_master)2
-rw-r--r--t/t4013/diff.log_-GF_-p_--pickaxe-all_main (renamed from t/t4013/diff.log_-GF_-p_--pickaxe-all_master)2
-rw-r--r--t/t4013/diff.log_-GF_-p_main (renamed from t/t4013/diff.log_-GF_-p_master)2
-rw-r--r--t/t4013/diff.log_-GF_main (renamed from t/t4013/diff.log_-SF_master)2
-rw-r--r--t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_main (renamed from t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_master)2
-rw-r--r--t/t4013/diff.log_-SF_-p_main (renamed from t/t4013/diff.log_-SF_-p_master)2
-rw-r--r--t/t4013/diff.log_-SF_main (renamed from t/t4013/diff.log_-GF_master)2
-rw-r--r--t/t4013/diff.log_-SF_main_--max-count=02
-rw-r--r--t/t4013/diff.log_-SF_main_--max-count=1 (renamed from t/t4013/diff.log_-SF_master_--max-count=2)2
-rw-r--r--t/t4013/diff.log_-SF_main_--max-count=27
-rw-r--r--t/t4013/diff.log_-SF_master_--max-count=02
-rw-r--r--t/t4013/diff.log_-SF_master_--max-count=17
-rw-r--r--t/t4013/diff.log_-S_F_main (renamed from t/t4013/diff.log_-S_F_master)2
-rw-r--r--t/t4013/diff.log_-c_-m_-p_main (renamed from t/t4013/diff.log_--cc_-m_-p_master)2
-rw-r--r--t/t4013/diff.log_-m_--raw_main (renamed from t/t4013/diff.log_-m_--raw_master)2
-rw-r--r--t/t4013/diff.log_-m_--stat_main (renamed from t/t4013/diff.log_-m_--stat_master)2
-rw-r--r--t/t4013/diff.log_-m_-p_--first-parent_main (renamed from t/t4013/diff.log_-m_-p_--first-parent_master)2
-rw-r--r--t/t4013/diff.log_-m_-p_main (renamed from t/t4013/diff.log_-m_-p_master)2
-rw-r--r--t/t4013/diff.log_-p_--diff-merges=first-parent_main (renamed from t/t4013/diff.log_-p_--diff-merges=first-parent_master)2
-rw-r--r--t/t4013/diff.log_-p_--first-parent_main (renamed from t/t4013/diff.log_-p_--first-parent_master)2
-rw-r--r--t/t4013/diff.log_-p_main (renamed from t/t4013/diff.log_-p_master)2
-rw-r--r--t/t4013/diff.log_main (renamed from t/t4013/diff.log_master)2
-rw-r--r--t/t4013/diff.noellipses-diff-tree_-c_--abbrev_main (renamed from t/t4013/diff.noellipses-diff-tree_-c_--abbrev_master)2
-rw-r--r--t/t4013/diff.noellipses-whatchanged_--root_main (renamed from t/t4013/diff.noellipses-whatchanged_--root_master)2
-rw-r--r--t/t4013/diff.noellipses-whatchanged_-SF_main (renamed from t/t4013/diff.noellipses-whatchanged_-SF_master)2
-rw-r--r--t/t4013/diff.noellipses-whatchanged_main (renamed from t/t4013/diff.noellipses-whatchanged_master)2
-rw-r--r--t/t4013/diff.show_--first-parent_main (renamed from t/t4013/diff.show_--first-parent_master)2
-rw-r--r--t/t4013/diff.show_-c_main (renamed from t/t4013/diff.show_-c_master)2
-rw-r--r--t/t4013/diff.show_-m_main (renamed from t/t4013/diff.show_-m_master)2
-rw-r--r--t/t4013/diff.show_main (renamed from t/t4013/diff.show_master)2
-rw-r--r--t/t4013/diff.whatchanged_--patch-with-stat_--summary_main_--_dir_ (renamed from t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_)2
-rw-r--r--t/t4013/diff.whatchanged_--patch-with-stat_main (renamed from t/t4013/diff.whatchanged_--patch-with-stat_master)2
-rw-r--r--t/t4013/diff.whatchanged_--patch-with-stat_main_--_dir_ (renamed from t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_)2
-rw-r--r--t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_main (renamed from t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master)2
-rw-r--r--t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_main (renamed from t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master)2
-rw-r--r--t/t4013/diff.whatchanged_--root_--patch-with-stat_main (renamed from t/t4013/diff.whatchanged_--root_--patch-with-stat_master)2
-rw-r--r--t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_main (renamed from t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master)2
-rw-r--r--t/t4013/diff.whatchanged_--root_-p_main (renamed from t/t4013/diff.whatchanged_--root_-p_master)2
-rw-r--r--t/t4013/diff.whatchanged_--root_main (renamed from t/t4013/diff.whatchanged_--root_master)2
-rw-r--r--t/t4013/diff.whatchanged_-SF_-p_main (renamed from t/t4013/diff.whatchanged_-SF_-p_master)2
-rw-r--r--t/t4013/diff.whatchanged_-SF_main (renamed from t/t4013/diff.whatchanged_-SF_master)2
-rw-r--r--t/t4013/diff.whatchanged_-p_main (renamed from t/t4013/diff.whatchanged_-p_master)2
-rw-r--r--t/t4013/diff.whatchanged_main (renamed from t/t4013/diff.whatchanged_master)2
-rwxr-xr-xt/t4020-diff-external.sh10
-rwxr-xr-xt/t4035-diff-quiet.sh4
-rwxr-xr-xt/t4053-diff-no-index.sh16
-rwxr-xr-xt/t5318-commit-graph.sh44
-rwxr-xr-xt/t5510-fetch.sh114
-rwxr-xr-xt/t6302-for-each-ref-filter.sh65
-rwxr-xr-xt/t7500-commit-template-squash-signoff.sh51
-rwxr-xr-xt/t7508-status.sh11
-rwxr-xr-xt/t7528-signed-commit-ssh.sh2
-rwxr-xr-xt/t7900-maintenance.sh245
-rwxr-xr-xt/t8020-last-modified.sh22
-rwxr-xr-xt/t9305-fast-import-signatures.sh106
-rwxr-xr-xt/t9306-fast-import-signed-tags.sh80
-rwxr-xr-xt/t9350-fast-export.sh48
-rwxr-xr-xt/t9902-completion.sh6
-rw-r--r--t/test-lib-functions.sh9
-rw-r--r--t/test-lib.sh26
-rw-r--r--t/unit-tests/clar/.github/workflows/ci.yml37
-rw-r--r--t/unit-tests/clar/CMakeLists.txt13
-rw-r--r--t/unit-tests/clar/README.md37
-rw-r--r--t/unit-tests/clar/clar.c154
-rw-r--r--t/unit-tests/clar/clar.h83
-rw-r--r--t/unit-tests/clar/clar/fixtures.h6
-rw-r--r--t/unit-tests/clar/clar/fs.h29
-rw-r--r--t/unit-tests/clar/clar/print.h71
-rw-r--r--t/unit-tests/clar/clar/sandbox.h226
-rw-r--r--t/unit-tests/clar/clar/summary.h5
-rw-r--r--t/unit-tests/clar/example/CMakeLists.txt28
-rw-r--r--t/unit-tests/clar/example/example.c6
-rw-r--r--t/unit-tests/clar/example/main.c (renamed from t/unit-tests/clar/test/main.c.sample)2
-rwxr-xr-xt/unit-tests/clar/generate.py28
-rw-r--r--t/unit-tests/clar/test/CMakeLists.txt34
-rw-r--r--t/unit-tests/clar/test/clar_test.h16
-rw-r--r--t/unit-tests/clar/test/expected/help12
-rw-r--r--t/unit-tests/clar/test/expected/quiet44
-rw-r--r--t/unit-tests/clar/test/expected/specific_test9
-rw-r--r--t/unit-tests/clar/test/expected/stop_on_failure8
-rw-r--r--t/unit-tests/clar/test/expected/suite_names2
-rw-r--r--t/unit-tests/clar/test/expected/summary.xml41
-rw-r--r--t/unit-tests/clar/test/expected/summary_with_filename49
-rw-r--r--t/unit-tests/clar/test/expected/summary_without_filename49
-rw-r--r--t/unit-tests/clar/test/expected/tap92
-rw-r--r--t/unit-tests/clar/test/expected/without_arguments48
-rw-r--r--t/unit-tests/clar/test/main.c41
-rw-r--r--t/unit-tests/clar/test/selftest.c370
-rw-r--r--t/unit-tests/clar/test/selftest.h3
-rw-r--r--t/unit-tests/clar/test/suites/CMakeLists.txt53
-rw-r--r--t/unit-tests/clar/test/suites/combined.c (renamed from t/unit-tests/clar/test/sample.c)37
-rw-r--r--t/unit-tests/clar/test/suites/main.c27
-rw-r--r--t/unit-tests/clar/test/suites/pointer.c13
-rw-r--r--t/unit-tests/clar/test/suites/resources/test/file (renamed from t/unit-tests/clar/test/resources/test/file)0
-rw-r--r--t/unit-tests/u-reftable-basics.c24
179 files changed, 4034 insertions, 1188 deletions
diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c
index 611a13a326..fc4b8a77b3 100644
--- a/t/helper/test-find-pack.c
+++ b/t/helper/test-find-pack.c
@@ -39,11 +39,12 @@ int cmd__find_pack(int argc, const char **argv)
if (repo_get_oid(the_repository, argv[0], &oid))
die("cannot parse %s as an object name", argv[0]);
- for (p = get_all_packs(the_repository); p; p = p->next)
+ repo_for_each_pack(the_repository, p) {
if (find_pack_entry_one(&oid, p)) {
printf("%s\n", p->pack_name);
actual_count++;
}
+ }
if (count > -1 && count != actual_count)
die("bad packfile count %d instead of %d", actual_count, count);
diff --git a/t/helper/test-pack-deltas.c b/t/helper/test-pack-deltas.c
index 4caa024b1e..4981401eaa 100644
--- a/t/helper/test-pack-deltas.c
+++ b/t/helper/test-pack-deltas.c
@@ -51,16 +51,14 @@ static void write_ref_delta(struct hashfile *f,
unsigned long size, base_size, delta_size, compressed_size, hdrlen;
enum object_type type;
void *base_buf, *delta_buf;
- void *buf = repo_read_object_file(the_repository,
- oid, &type,
- &size);
+ void *buf = odb_read_object(the_repository->objects,
+ oid, &type, &size);
if (!buf)
die("unable to read %s", oid_to_hex(oid));
- base_buf = repo_read_object_file(the_repository,
- base, &type,
- &base_size);
+ base_buf = odb_read_object(the_repository->objects,
+ base, &type, &base_size);
if (!base_buf)
die("unable to read %s", oid_to_hex(base));
diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c
index d51aaa3dc4..7a8ee1de24 100644
--- a/t/helper/test-pack-mtimes.c
+++ b/t/helper/test-pack-mtimes.c
@@ -37,7 +37,7 @@ int cmd__pack_mtimes(int argc, const char **argv)
if (argc != 2)
usage(pack_mtimes_usage);
- for (p = get_all_packs(the_repository); p; p = p->next) {
+ repo_for_each_pack(the_repository, p) {
strbuf_addstr(&buf, basename(p->pack_name));
strbuf_strip_suffix(&buf, ".pack");
strbuf_addstr(&buf, ".mtimes");
diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh
index 937b876bd0..b99ae39a06 100644
--- a/t/lib-gpg.sh
+++ b/t/lib-gpg.sh
@@ -9,6 +9,16 @@
GNUPGHOME="$(pwd)/gpghome"
export GNUPGHOME
+# All the "test_lazy_prereq GPG*" below should use
+# `prepare_gnupghome()` either directly or through a call to
+# `test_have_prereq GPG*`. That's because `gpg` and `gpgsm`
+# only create the directory specified using "$GNUPGHOME" or
+# `--homedir` if it's the default (usually "~/.gnupg").
+prepare_gnupghome() {
+ mkdir -p "$GNUPGHOME" &&
+ chmod 0700 "$GNUPGHOME"
+}
+
test_lazy_prereq GPG '
gpg_version=$(gpg --version 2>&1)
test $? != 127 || exit 1
@@ -38,8 +48,7 @@ test_lazy_prereq GPG '
# To export ownertrust:
# gpg --homedir /tmp/gpghome --export-ownertrust \
# > lib-gpg/ownertrust
- mkdir "$GNUPGHOME" &&
- chmod 0700 "$GNUPGHOME" &&
+ prepare_gnupghome &&
(gpgconf --kill all || : ) &&
gpg --homedir "${GNUPGHOME}" --import \
"$TEST_DIRECTORY"/lib-gpg/keyring.gpg &&
@@ -63,6 +72,14 @@ test_lazy_prereq GPG2 '
;;
*)
(gpgconf --kill all || : ) &&
+
+ # NEEDSWORK: prepare_gnupghome() should definitely be
+ # called here, but it looks like it exposes a
+ # pre-existing, hidden bug by allowing some tests in
+ # t1016-compatObjectFormat.sh to run instead of being
+ # skipped. See:
+ # https://lore.kernel.org/git/ZoV8b2RvYxLOotSJ@teonanacatl.net/
+
gpg --homedir "${GNUPGHOME}" --import \
"$TEST_DIRECTORY"/lib-gpg/keyring.gpg &&
gpg --homedir "${GNUPGHOME}" --import-ownertrust \
@@ -132,8 +149,7 @@ test_lazy_prereq GPGSSH '
test $? = 0 || exit 1;
# Setup some keys and an allowed signers file
- mkdir -p "${GNUPGHOME}" &&
- chmod 0700 "${GNUPGHOME}" &&
+ prepare_gnupghome &&
(setfacl -k "${GNUPGHOME}" 2>/dev/null || true) &&
ssh-keygen -t ed25519 -N "" -C "git ed25519 key" -f "${GPGSSH_KEY_PRIMARY}" >/dev/null &&
ssh-keygen -t rsa -b 2048 -N "" -C "git rsa2048 key" -f "${GPGSSH_KEY_SECONDARY}" >/dev/null &&
diff --git a/t/meson.build b/t/meson.build
index 9e426f8edc..a5531df415 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -146,6 +146,7 @@ integration_tests = [
't0611-reftable-httpd.sh',
't0612-reftable-jgit-compatibility.sh',
't0613-reftable-write-options.sh',
+ 't0614-reftable-fsck.sh',
't1000-read-tree-m-3way.sh',
't1001-read-tree-m-2way.sh',
't1002-read-tree-m-u-2way.sh',
@@ -213,6 +214,7 @@ integration_tests = [
't1460-refs-migrate.sh',
't1461-refs-list.sh',
't1462-refs-exists.sh',
+ 't1463-refs-optimize.sh',
't1500-rev-parse.sh',
't1501-work-tree.sh',
't1502-rev-parse-parseopt.sh',
@@ -1035,6 +1037,8 @@ integration_tests = [
't9302-fast-import-unpack-limit.sh',
't9303-fast-import-compression.sh',
't9304-fast-import-marks.sh',
+ 't9305-fast-import-signatures.sh',
+ 't9306-fast-import-signed-tags.sh',
't9350-fast-export.sh',
't9351-fast-export-anonymize.sh',
't9400-git-cvsserver-server.sh',
diff --git a/t/pack-refs-tests.sh b/t/pack-refs-tests.sh
new file mode 100644
index 0000000000..3dbcc01718
--- /dev/null
+++ b/t/pack-refs-tests.sh
@@ -0,0 +1,431 @@
+pack_refs=${pack_refs:-pack-refs}
+
+test_expect_success 'enable reflogs' '
+ git config core.logallrefupdates true
+'
+
+test_expect_success 'prepare a trivial repository' '
+ echo Hello > A &&
+ git update-index --add A &&
+ git commit -m "Initial commit." &&
+ HEAD=$(git rev-parse --verify HEAD)
+'
+
+test_expect_success '${pack_refs} --prune --all' '
+ test_path_is_missing .git/packed-refs &&
+ git ${pack_refs} --no-prune --all &&
+ test_path_is_file .git/packed-refs &&
+ N=$(find .git/refs -type f | wc -l) &&
+ test "$N" != 0 &&
+
+ git ${pack_refs} --prune --all &&
+ test_path_is_file .git/packed-refs &&
+ N=$(find .git/refs -type f) &&
+ test -z "$N"
+'
+
+SHA1=
+
+test_expect_success 'see if git show-ref works as expected' '
+ git branch a &&
+ SHA1=$(cat .git/refs/heads/a) &&
+ echo "$SHA1 refs/heads/a" >expect &&
+ git show-ref a >result &&
+ test_cmp expect result
+'
+
+test_expect_success 'see if a branch still exists when packed' '
+ git branch b &&
+ git ${pack_refs} --all &&
+ rm -f .git/refs/heads/b &&
+ echo "$SHA1 refs/heads/b" >expect &&
+ git show-ref b >result &&
+ test_cmp expect result
+'
+
+test_expect_success 'git branch c/d should barf if branch c exists' '
+ git branch c &&
+ git ${pack_refs} --all &&
+ rm -f .git/refs/heads/c &&
+ test_must_fail git branch c/d
+'
+
+test_expect_success 'see if a branch still exists after git ${pack_refs} --prune' '
+ git branch e &&
+ git ${pack_refs} --all --prune &&
+ echo "$SHA1 refs/heads/e" >expect &&
+ git show-ref e >result &&
+ test_cmp expect result
+'
+
+test_expect_success 'see if git ${pack_refs} --prune remove ref files' '
+ git branch f &&
+ git ${pack_refs} --all --prune &&
+ ! test -f .git/refs/heads/f
+'
+
+test_expect_success 'see if git ${pack_refs} --prune removes empty dirs' '
+ git branch r/s/t &&
+ git ${pack_refs} --all --prune &&
+ ! test -e .git/refs/heads/r
+'
+
+test_expect_success 'git branch g should work when git branch g/h has been deleted' '
+ git branch g/h &&
+ git ${pack_refs} --all --prune &&
+ git branch -d g/h &&
+ git branch g &&
+ git ${pack_refs} --all &&
+ git branch -d g
+'
+
+test_expect_success 'git branch i/j/k should barf if branch i exists' '
+ git branch i &&
+ git ${pack_refs} --all --prune &&
+ test_must_fail git branch i/j/k
+'
+
+test_expect_success 'test git branch k after branch k/l/m and k/lm have been deleted' '
+ git branch k/l &&
+ git branch k/lm &&
+ git branch -d k/l &&
+ git branch k/l/m &&
+ git branch -d k/l/m &&
+ git branch -d k/lm &&
+ git branch k
+'
+
+test_expect_success 'test git branch n after some branch deletion and pruning' '
+ git branch n/o &&
+ git branch n/op &&
+ git branch -d n/o &&
+ git branch n/o/p &&
+ git branch -d n/op &&
+ git ${pack_refs} --all --prune &&
+ git branch -d n/o/p &&
+ git branch n
+'
+
+test_expect_success 'test excluded refs are not packed' '
+ git branch dont_pack1 &&
+ git branch dont_pack2 &&
+ git branch pack_this &&
+ git ${pack_refs} --all --exclude "refs/heads/dont_pack*" &&
+ test -f .git/refs/heads/dont_pack1 &&
+ test -f .git/refs/heads/dont_pack2 &&
+ ! test -f .git/refs/heads/pack_this'
+
+test_expect_success 'test --no-exclude refs clears excluded refs' '
+ git branch dont_pack3 &&
+ git branch dont_pack4 &&
+ git ${pack_refs} --all --exclude "refs/heads/dont_pack*" --no-exclude &&
+ ! test -f .git/refs/heads/dont_pack3 &&
+ ! test -f .git/refs/heads/dont_pack4'
+
+test_expect_success 'test only included refs are packed' '
+ git branch pack_this1 &&
+ git branch pack_this2 &&
+ git tag dont_pack5 &&
+ git ${pack_refs} --include "refs/heads/pack_this*" &&
+ test -f .git/refs/tags/dont_pack5 &&
+ ! test -f .git/refs/heads/pack_this1 &&
+ ! test -f .git/refs/heads/pack_this2'
+
+test_expect_success 'test --no-include refs clears included refs' '
+ git branch pack1 &&
+ git branch pack2 &&
+ git ${pack_refs} --include "refs/heads/pack*" --no-include &&
+ test -f .git/refs/heads/pack1 &&
+ test -f .git/refs/heads/pack2'
+
+test_expect_success 'test --exclude takes precedence over --include' '
+ git branch dont_pack5 &&
+ git ${pack_refs} --include "refs/heads/pack*" --exclude "refs/heads/pack*" &&
+ test -f .git/refs/heads/dont_pack5'
+
+test_expect_success 'see if up-to-date packed refs are preserved' '
+ git branch q &&
+ git ${pack_refs} --all --prune &&
+ git update-ref refs/heads/q refs/heads/q &&
+ ! test -f .git/refs/heads/q
+'
+
+test_expect_success 'pack, prune and repack' '
+ git tag foo &&
+ git ${pack_refs} --all --prune &&
+ git show-ref >all-of-them &&
+ git ${pack_refs} &&
+ git show-ref >again &&
+ test_cmp all-of-them again
+'
+
+test_expect_success 'explicit ${pack_refs} with dangling packed reference' '
+ git commit --allow-empty -m "soon to be garbage-collected" &&
+ git ${pack_refs} --all &&
+ git reset --hard HEAD^ &&
+ git reflog expire --expire=all --all &&
+ git prune --expire=all &&
+ git ${pack_refs} --all 2>result &&
+ test_must_be_empty result
+'
+
+test_expect_success 'delete ref with dangling packed version' '
+ git checkout -b lamb &&
+ git commit --allow-empty -m "future garbage" &&
+ git ${pack_refs} --all &&
+ git reset --hard HEAD^ &&
+ git checkout main &&
+ git reflog expire --expire=all --all &&
+ git prune --expire=all &&
+ git branch -d lamb 2>result &&
+ test_must_be_empty result
+'
+
+test_expect_success 'delete ref while another dangling packed ref' '
+ git branch lamb &&
+ git commit --allow-empty -m "future garbage" &&
+ git ${pack_refs} --all &&
+ git reset --hard HEAD^ &&
+ git reflog expire --expire=all --all &&
+ git prune --expire=all &&
+ git branch -d lamb 2>result &&
+ test_must_be_empty result
+'
+
+test_expect_success 'pack ref directly below refs/' '
+ git update-ref refs/top HEAD &&
+ git ${pack_refs} --all --prune &&
+ grep refs/top .git/packed-refs &&
+ test_path_is_missing .git/refs/top
+'
+
+test_expect_success 'do not pack ref in refs/bisect' '
+ git update-ref refs/bisect/local HEAD &&
+ git ${pack_refs} --all --prune &&
+ ! grep refs/bisect/local .git/packed-refs >/dev/null &&
+ test_path_is_file .git/refs/bisect/local
+'
+
+test_expect_success 'disable reflogs' '
+ git config core.logallrefupdates false &&
+ rm -rf .git/logs
+'
+
+test_expect_success 'create packed foo/bar/baz branch' '
+ git branch foo/bar/baz &&
+ git ${pack_refs} --all --prune &&
+ test_path_is_missing .git/refs/heads/foo/bar/baz &&
+ test_must_fail git reflog exists refs/heads/foo/bar/baz
+'
+
+test_expect_success 'notice d/f conflict with existing directory' '
+ test_must_fail git branch foo &&
+ test_must_fail git branch foo/bar
+'
+
+test_expect_success 'existing directory reports concrete ref' '
+ test_must_fail git branch foo 2>stderr &&
+ test_grep refs/heads/foo/bar/baz stderr
+'
+
+test_expect_success 'notice d/f conflict with existing ref' '
+ test_must_fail git branch foo/bar/baz/extra &&
+ test_must_fail git branch foo/bar/baz/lots/of/extra/components
+'
+
+test_expect_success 'reject packed-refs with unterminated line' '
+ cp .git/packed-refs .git/packed-refs.bak &&
+ test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
+ printf "%s" "$HEAD refs/zzzzz" >>.git/packed-refs &&
+ echo "fatal: unterminated line in .git/packed-refs: $HEAD refs/zzzzz" >expected_err &&
+ test_must_fail git for-each-ref >out 2>err &&
+ test_cmp expected_err err
+'
+
+test_expect_success 'reject packed-refs containing junk' '
+ cp .git/packed-refs .git/packed-refs.bak &&
+ test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
+ printf "%s\n" "bogus content" >>.git/packed-refs &&
+ echo "fatal: unexpected line in .git/packed-refs: bogus content" >expected_err &&
+ test_must_fail git for-each-ref >out 2>err &&
+ test_cmp expected_err err
+'
+
+test_expect_success 'reject packed-refs with a short SHA-1' '
+ cp .git/packed-refs .git/packed-refs.bak &&
+ test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
+ printf "%.7s %s\n" $HEAD refs/zzzzz >>.git/packed-refs &&
+ printf "fatal: unexpected line in .git/packed-refs: %.7s %s\n" $HEAD refs/zzzzz >expected_err &&
+ test_must_fail git for-each-ref >out 2>err &&
+ test_cmp expected_err err
+'
+
+test_expect_success 'timeout if packed-refs.lock exists' '
+ LOCK=.git/packed-refs.lock &&
+ >"$LOCK" &&
+ test_when_finished "rm -f $LOCK" &&
+ test_must_fail git ${pack_refs} --all --prune
+'
+
+test_expect_success 'retry acquiring packed-refs.lock' '
+ LOCK=.git/packed-refs.lock &&
+ >"$LOCK" &&
+ test_when_finished "wait && rm -f $LOCK" &&
+ {
+ ( sleep 1 && rm -f $LOCK ) &
+ } &&
+ git -c core.packedrefstimeout=3000 ${pack_refs} --all --prune
+'
+
+test_expect_success SYMLINKS 'pack symlinked packed-refs' '
+ # First make sure that symlinking works when reading:
+ git update-ref refs/heads/lossy refs/heads/main &&
+ git for-each-ref >all-refs-before &&
+ mv .git/packed-refs .git/my-deviant-packed-refs &&
+ ln -s my-deviant-packed-refs .git/packed-refs &&
+ git for-each-ref >all-refs-linked &&
+ test_cmp all-refs-before all-refs-linked &&
+ git ${pack_refs} --all --prune &&
+ git for-each-ref >all-refs-packed &&
+ test_cmp all-refs-before all-refs-packed &&
+ test -h .git/packed-refs &&
+ test "$(test_readlink .git/packed-refs)" = "my-deviant-packed-refs"
+'
+
+# The 'packed-refs' file is stored directly in .git/. This means it is global
+# to the repository, and can only contain refs that are shared across all
+# worktrees.
+test_expect_success 'refs/worktree must not be packed' '
+ test_commit initial &&
+ test_commit wt1 &&
+ test_commit wt2 &&
+ git worktree add wt1 wt1 &&
+ git worktree add wt2 wt2 &&
+ git checkout initial &&
+ git update-ref refs/worktree/foo HEAD &&
+ git -C wt1 update-ref refs/worktree/foo HEAD &&
+ git -C wt2 update-ref refs/worktree/foo HEAD &&
+ git ${pack_refs} --all &&
+ test_path_is_missing .git/refs/tags/wt1 &&
+ test_path_is_file .git/refs/worktree/foo &&
+ test_path_is_file .git/worktrees/wt1/refs/worktree/foo &&
+ test_path_is_file .git/worktrees/wt2/refs/worktree/foo
+'
+
+# we do not want to count on running ${pack_refs} to
+# actually pack it, as it is perfectly reasonable to
+# skip processing a broken ref
+test_expect_success 'create packed-refs file with broken ref' '
+ test_tick && git commit --allow-empty -m one &&
+ recoverable=$(git rev-parse HEAD) &&
+ test_tick && git commit --allow-empty -m two &&
+ missing=$(git rev-parse HEAD) &&
+ rm -f .git/refs/heads/main &&
+ cat >.git/packed-refs <<-EOF &&
+ $missing refs/heads/main
+ $recoverable refs/heads/other
+ EOF
+ echo $missing >expect &&
+ git rev-parse refs/heads/main >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '${pack_refs} does not silently delete broken packed ref' '
+ git ${pack_refs} --all --prune &&
+ git rev-parse refs/heads/main >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '${pack_refs} does not drop broken refs during deletion' '
+ git update-ref -d refs/heads/other &&
+ git rev-parse refs/heads/main >actual &&
+ test_cmp expect actual
+'
+
+for command in "git ${pack_refs} --all --auto" "git maintenance run --task=${pack_refs} --auto"
+do
+ test_expect_success "$command does not repack below 16 refs without packed-refs" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config set maintenance.auto false &&
+ git commit --allow-empty --message "initial" &&
+
+ # Create 14 additional references, which brings us to
+ # 15 together with the default branch.
+ printf "create refs/heads/loose-%d HEAD\n" $(test_seq 14) >stdin &&
+ git update-ref --stdin <stdin &&
+ test_path_is_missing .git/packed-refs &&
+ git ${pack_refs} --auto --all &&
+ test_path_is_missing .git/packed-refs &&
+
+ # Create the 16th reference, which should cause us to repack.
+ git update-ref refs/heads/loose-15 HEAD &&
+ git ${pack_refs} --auto --all &&
+ test_path_is_file .git/packed-refs
+ )
+ '
+
+ test_expect_success "$command does not repack below 16 refs with small packed-refs" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config set maintenance.auto false &&
+ git commit --allow-empty --message "initial" &&
+
+ git ${pack_refs} --all &&
+ test_line_count = 2 .git/packed-refs &&
+
+ # Create 15 loose references.
+ printf "create refs/heads/loose-%d HEAD\n" $(test_seq 15) >stdin &&
+ git update-ref --stdin <stdin &&
+ git ${pack_refs} --auto --all &&
+ test_line_count = 2 .git/packed-refs &&
+
+ # Create the 16th loose reference, which should cause us to repack.
+ git update-ref refs/heads/loose-17 HEAD &&
+ git ${pack_refs} --auto --all &&
+ test_line_count = 18 .git/packed-refs
+ )
+ '
+
+ test_expect_success "$command scales with size of packed-refs" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config set maintenance.auto false &&
+ git commit --allow-empty --message "initial" &&
+
+ # Create 99 packed refs. This should cause the heuristic
+ # to require more than the minimum amount of loose refs.
+ test_seq 99 |
+ while read i
+ do
+ printf "create refs/heads/packed-%d HEAD\n" $i || return 1
+ done >stdin &&
+ git update-ref --stdin <stdin &&
+ git ${pack_refs} --all &&
+ test_line_count = 101 .git/packed-refs &&
+
+ # Create 24 loose refs, which should not yet cause us to repack.
+ printf "create refs/heads/loose-%d HEAD\n" $(test_seq 24) >stdin &&
+ git update-ref --stdin <stdin &&
+ git ${pack_refs} --auto --all &&
+ test_line_count = 101 .git/packed-refs &&
+
+ # Create another handful of refs to cross the border.
+ # Note that we explicitly do not check for strict
+ # boundaries here, as this also depends on the size of
+ # the object hash.
+ printf "create refs/heads/addn-%d HEAD\n" $(test_seq 10) >stdin &&
+ git update-ref --stdin <stdin &&
+ git ${pack_refs} --auto --all &&
+ test_line_count = 135 .git/packed-refs
+ )
+ '
+done
+
+test_done
diff --git a/t/perf/p6010-merge-base.sh b/t/perf/p6010-merge-base.sh
new file mode 100755
index 0000000000..54f52fa23e
--- /dev/null
+++ b/t/perf/p6010-merge-base.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+test_description='Test git merge-base'
+
+. ./perf-lib.sh
+
+test_perf_fresh_repo
+
+#
+# Creates lots of merges to make history traversal costly. In
+# particular it creates 2^($max_level-1)-1 2-way merges on top of
+# 2^($max_level-1) root commits. E.g., the commit history looks like
+# this for a $max_level of 3:
+#
+# _1_
+# / \
+# 2 3
+# / \ / \
+# 4 5 6 7
+#
+# The numbers are the fast-import marks, which also are the commit
+# messages. 1 is the HEAD commit and a merge, 2 and 3 are also merges,
+# 4-7 are the root commits.
+#
+build_history () {
+ local max_level="$1" &&
+ local level="${2:-1}" &&
+ local mark="${3:-1}" &&
+ if test $level -eq $max_level
+ then
+ echo "reset refs/heads/master" &&
+ echo "from $ZERO_OID" &&
+ echo "commit refs/heads/master" &&
+ echo "mark :$mark" &&
+ echo "committer C <c@example.com> 1234567890 +0000" &&
+ echo "data <<EOF" &&
+ echo "$mark" &&
+ echo "EOF"
+ else
+ local level1=$((level+1)) &&
+ local mark1=$((2*mark)) &&
+ local mark2=$((2*mark+1)) &&
+ build_history $max_level $level1 $mark1 &&
+ build_history $max_level $level1 $mark2 &&
+ echo "commit refs/heads/master" &&
+ echo "mark :$mark" &&
+ echo "committer C <c@example.com> 1234567890 +0000" &&
+ echo "data <<EOF" &&
+ echo "$mark" &&
+ echo "EOF" &&
+ echo "from :$mark1" &&
+ echo "merge :$mark2"
+ fi
+}
+
+#
+# Creates a new merge history in the same shape as build_history does,
+# while reusing the same root commits. This way the two top commits
+# have 2^($max_level-1) merge bases between them.
+#
+build_history2 () {
+ local max_level="$1" &&
+ local level="${2:-1}" &&
+ local mark="${3:-1}" &&
+ if test $level -lt $max_level
+ then
+ local level1=$((level+1)) &&
+ local mark1=$((2*mark)) &&
+ local mark2=$((2*mark+1)) &&
+ build_history2 $max_level $level1 $mark1 &&
+ build_history2 $max_level $level1 $mark2 &&
+ echo "commit refs/heads/master" &&
+ echo "mark :$mark" &&
+ echo "committer C <c@example.com> 1234567890 +0000" &&
+ echo "data <<EOF" &&
+ echo "$mark II" &&
+ echo "EOF" &&
+ echo "from :$mark1" &&
+ echo "merge :$mark2"
+ fi
+}
+
+test_expect_success 'setup' '
+ max_level=15 &&
+ build_history $max_level | git fast-import --export-marks=marks &&
+ git tag one &&
+ build_history2 $max_level | git fast-import --import-marks=marks --force &&
+ git tag two &&
+ git gc &&
+ git log --format=%H --no-merges >expect
+'
+
+test_perf 'git merge-base' '
+ git merge-base --all one two >actual
+'
+
+test_expect_success 'verify result' '
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index f593c53687..618da080dc 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -883,6 +883,22 @@ test_expect_success 'advice on unconfigured init.defaultBranch disabled' '
test_grep ! "hint: " err
'
+test_expect_success 'default branch name' '
+ if test_have_prereq WITH_BREAKING_CHANGES
+ then
+ expect=main
+ else
+ expect=master
+ fi &&
+ echo "refs/heads/$expect" >expect &&
+ (
+ sane_unset GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+ git init default-initial-branch-name
+ ) &&
+ git -C default-initial-branch-name symbolic-ref HEAD >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'overridden default main branch name (env)' '
test_config_global init.defaultBranch nmb &&
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=env git init main-branch-env &&
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index 273d71411f..db8bde280e 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -847,6 +847,17 @@ test_expect_success 'directories and ** matches' '
test_cmp expect actual
'
+test_expect_success '** not confused by matching leading prefix' '
+ cat >.gitignore <<-\EOF &&
+ foo**/bar
+ EOF
+ git check-ignore foobar foo/bar >actual &&
+ cat >expect <<-\EOF &&
+ foo/bar
+ EOF
+ test_cmp expect actual
+'
+
############################################################################
#
# test whitespace handling
diff --git a/t/t0014-alias.sh b/t/t0014-alias.sh
index 854d59ec58..07a53e7366 100755
--- a/t/t0014-alias.sh
+++ b/t/t0014-alias.sh
@@ -27,6 +27,20 @@ test_expect_success 'looping aliases - internal execution' '
test_grep "^fatal: alias loop detected: expansion of" output
'
+test_expect_success 'looping aliases - deprecated builtins' '
+ test_config alias.whatchanged pack-redundant &&
+ test_config alias.pack-redundant whatchanged &&
+ cat >expect <<-EOF &&
+ ${SQ}whatchanged${SQ} is aliased to ${SQ}pack-redundant${SQ}
+ ${SQ}pack-redundant${SQ} is aliased to ${SQ}whatchanged${SQ}
+ fatal: alias loop detected: expansion of ${SQ}whatchanged${SQ} does not terminate:
+ whatchanged <==
+ pack-redundant ==>
+ EOF
+ test_must_fail git whatchanged -h 2>actual &&
+ test_cmp expect actual
+'
+
# This test is disabled until external loops are fixed, because would block
# the test suite for a full minute.
#
@@ -55,4 +69,47 @@ test_expect_success 'tracing a shell alias with arguments shows trace of prepare
test_cmp expect actual
'
+can_alias_deprecated_builtin () {
+ cmd="$1" &&
+ # some git(1) commands will fail for `-h` (the case for
+ # git-status as of 2025-09-07)
+ test_might_fail git status -h >expect &&
+ test_file_not_empty expect &&
+ test_might_fail git -c alias."$cmd"=status "$cmd" -h >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'can alias-shadow deprecated builtins' '
+ for cmd in $(git --list-cmds=deprecated)
+ do
+ can_alias_deprecated_builtin "$cmd" || return 1
+ done
+'
+
+test_expect_success 'can alias-shadow via two deprecated builtins' '
+ # some git(1) commands will fail... (see above)
+ test_might_fail git status -h >expect &&
+ test_file_not_empty expect &&
+ test_might_fail git -c alias.whatchanged=pack-redundant \
+ -c alias.pack-redundant=status whatchanged -h >actual &&
+ test_cmp expect actual
+'
+
+cannot_alias_regular_builtin () {
+ cmd="$1" &&
+ # some git(1) commands will fail... (see above)
+ test_might_fail git "$cmd" -h >expect &&
+ test_file_not_empty expect &&
+ test_might_fail git -c alias."$cmd"=status "$cmd" -h >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'cannot alias-shadow a sample of regular builtins' '
+ for cmd in grep check-ref-format interpret-trailers \
+ checkout-index fast-import diagnose rev-list prune
+ do
+ cannot_alias_regular_builtin "$cmd" || return 1
+ done
+'
+
test_done
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index cb3a85c7ff..07aa834d33 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -991,18 +991,24 @@ test_expect_success 'url parser not confused by encoded markers' '
test_expect_success 'credential config with partial URLs' '
echo "echo password=yep" | write_script git-credential-yep &&
- test_write_lines url=https://user@example.com/repo.git >stdin &&
+ test_write_lines url=https://user@example.com/org/repo.git >stdin &&
for partial in \
example.com \
+ example.com/org/repo.git \
user@example.com \
+ user@example.com/org/repo.git \
https:// \
https://example.com \
https://example.com/ \
+ https://example.com/org \
+ https://example.com/org/ \
+ https://example.com/org/repo.git \
https://user@example.com \
https://user@example.com/ \
- https://example.com/repo.git \
- https://user@example.com/repo.git \
- /repo.git
+ https://user@example.com/org \
+ https://user@example.com/org/ \
+ https://user@example.com/org/repo.git \
+ /org/repo.git
do
git -c credential.$partial.helper=yep \
credential fill <stdin >stdout &&
@@ -1012,7 +1018,12 @@ test_expect_success 'credential config with partial URLs' '
for partial in \
dont.use.this \
+ example.com/o \
+ user@example.com/o \
http:// \
+ https://example.com/o \
+ https://user@example.com/o \
+ /o \
/repo
do
git -c credential.$partial.helper=yep \
diff --git a/t/t0600-reffiles-backend.sh b/t/t0600-reffiles-backend.sh
index 1e62c791d9..b11126ed47 100755
--- a/t/t0600-reffiles-backend.sh
+++ b/t/t0600-reffiles-backend.sh
@@ -477,9 +477,29 @@ test_expect_success SYMLINKS 'symref transaction supports symlinks' '
prepare
commit
EOF
- git update-ref --no-deref --stdin <stdin &&
- test_path_is_symlink .git/TEST_SYMREF_HEAD &&
- test "$(test_readlink .git/TEST_SYMREF_HEAD)" = refs/heads/new
+ git update-ref --no-deref --stdin <stdin 2>err &&
+ if test_have_prereq WITH_BREAKING_CHANGES
+ then
+ test_path_is_file .git/TEST_SYMREF_HEAD &&
+ echo "ref: refs/heads/new" >expect &&
+ test_cmp expect .git/TEST_SYMREF_HEAD &&
+ test_must_be_empty err
+ else
+ test_path_is_symlink .git/TEST_SYMREF_HEAD &&
+ test "$(test_readlink .git/TEST_SYMREF_HEAD)" = refs/heads/new &&
+ cat >expect <<-EOF &&
+ warning: ${SQ}core.preferSymlinkRefs=true${SQ} is nominated for removal.
+ hint: The use of symbolic links for symbolic refs is deprecated
+ hint: and will be removed in Git 3.0. The configuration that
+ hint: tells Git to use them is thus going away. You can unset
+ hint: it with:
+ hint:
+ hint: git config unset core.preferSymlinkRefs
+ hint:
+ hint: Git will then use the textual symref format instead.
+ EOF
+ test_cmp expect err
+ fi
'
test_expect_success 'symref transaction supports false symlink config' '
diff --git a/t/t0601-reffiles-pack-refs.sh b/t/t0601-reffiles-pack-refs.sh
index aa7f6ecd81..12cf5d1dcb 100755
--- a/t/t0601-reffiles-pack-refs.sh
+++ b/t/t0601-reffiles-pack-refs.sh
@@ -17,432 +17,4 @@ export GIT_TEST_DEFAULT_REF_FORMAT
. ./test-lib.sh
-test_expect_success 'enable reflogs' '
- git config core.logallrefupdates true
-'
-
-test_expect_success 'prepare a trivial repository' '
- echo Hello > A &&
- git update-index --add A &&
- git commit -m "Initial commit." &&
- HEAD=$(git rev-parse --verify HEAD)
-'
-
-test_expect_success 'pack-refs --prune --all' '
- test_path_is_missing .git/packed-refs &&
- git pack-refs --no-prune --all &&
- test_path_is_file .git/packed-refs &&
- N=$(find .git/refs -type f | wc -l) &&
- test "$N" != 0 &&
-
- git pack-refs --prune --all &&
- test_path_is_file .git/packed-refs &&
- N=$(find .git/refs -type f) &&
- test -z "$N"
-'
-
-SHA1=
-
-test_expect_success 'see if git show-ref works as expected' '
- git branch a &&
- SHA1=$(cat .git/refs/heads/a) &&
- echo "$SHA1 refs/heads/a" >expect &&
- git show-ref a >result &&
- test_cmp expect result
-'
-
-test_expect_success 'see if a branch still exists when packed' '
- git branch b &&
- git pack-refs --all &&
- rm -f .git/refs/heads/b &&
- echo "$SHA1 refs/heads/b" >expect &&
- git show-ref b >result &&
- test_cmp expect result
-'
-
-test_expect_success 'git branch c/d should barf if branch c exists' '
- git branch c &&
- git pack-refs --all &&
- rm -f .git/refs/heads/c &&
- test_must_fail git branch c/d
-'
-
-test_expect_success 'see if a branch still exists after git pack-refs --prune' '
- git branch e &&
- git pack-refs --all --prune &&
- echo "$SHA1 refs/heads/e" >expect &&
- git show-ref e >result &&
- test_cmp expect result
-'
-
-test_expect_success 'see if git pack-refs --prune remove ref files' '
- git branch f &&
- git pack-refs --all --prune &&
- ! test -f .git/refs/heads/f
-'
-
-test_expect_success 'see if git pack-refs --prune removes empty dirs' '
- git branch r/s/t &&
- git pack-refs --all --prune &&
- ! test -e .git/refs/heads/r
-'
-
-test_expect_success 'git branch g should work when git branch g/h has been deleted' '
- git branch g/h &&
- git pack-refs --all --prune &&
- git branch -d g/h &&
- git branch g &&
- git pack-refs --all &&
- git branch -d g
-'
-
-test_expect_success 'git branch i/j/k should barf if branch i exists' '
- git branch i &&
- git pack-refs --all --prune &&
- test_must_fail git branch i/j/k
-'
-
-test_expect_success 'test git branch k after branch k/l/m and k/lm have been deleted' '
- git branch k/l &&
- git branch k/lm &&
- git branch -d k/l &&
- git branch k/l/m &&
- git branch -d k/l/m &&
- git branch -d k/lm &&
- git branch k
-'
-
-test_expect_success 'test git branch n after some branch deletion and pruning' '
- git branch n/o &&
- git branch n/op &&
- git branch -d n/o &&
- git branch n/o/p &&
- git branch -d n/op &&
- git pack-refs --all --prune &&
- git branch -d n/o/p &&
- git branch n
-'
-
-test_expect_success 'test excluded refs are not packed' '
- git branch dont_pack1 &&
- git branch dont_pack2 &&
- git branch pack_this &&
- git pack-refs --all --exclude "refs/heads/dont_pack*" &&
- test -f .git/refs/heads/dont_pack1 &&
- test -f .git/refs/heads/dont_pack2 &&
- ! test -f .git/refs/heads/pack_this'
-
-test_expect_success 'test --no-exclude refs clears excluded refs' '
- git branch dont_pack3 &&
- git branch dont_pack4 &&
- git pack-refs --all --exclude "refs/heads/dont_pack*" --no-exclude &&
- ! test -f .git/refs/heads/dont_pack3 &&
- ! test -f .git/refs/heads/dont_pack4'
-
-test_expect_success 'test only included refs are packed' '
- git branch pack_this1 &&
- git branch pack_this2 &&
- git tag dont_pack5 &&
- git pack-refs --include "refs/heads/pack_this*" &&
- test -f .git/refs/tags/dont_pack5 &&
- ! test -f .git/refs/heads/pack_this1 &&
- ! test -f .git/refs/heads/pack_this2'
-
-test_expect_success 'test --no-include refs clears included refs' '
- git branch pack1 &&
- git branch pack2 &&
- git pack-refs --include "refs/heads/pack*" --no-include &&
- test -f .git/refs/heads/pack1 &&
- test -f .git/refs/heads/pack2'
-
-test_expect_success 'test --exclude takes precedence over --include' '
- git branch dont_pack5 &&
- git pack-refs --include "refs/heads/pack*" --exclude "refs/heads/pack*" &&
- test -f .git/refs/heads/dont_pack5'
-
-test_expect_success 'see if up-to-date packed refs are preserved' '
- git branch q &&
- git pack-refs --all --prune &&
- git update-ref refs/heads/q refs/heads/q &&
- ! test -f .git/refs/heads/q
-'
-
-test_expect_success 'pack, prune and repack' '
- git tag foo &&
- git pack-refs --all --prune &&
- git show-ref >all-of-them &&
- git pack-refs &&
- git show-ref >again &&
- test_cmp all-of-them again
-'
-
-test_expect_success 'explicit pack-refs with dangling packed reference' '
- git commit --allow-empty -m "soon to be garbage-collected" &&
- git pack-refs --all &&
- git reset --hard HEAD^ &&
- git reflog expire --expire=all --all &&
- git prune --expire=all &&
- git pack-refs --all 2>result &&
- test_must_be_empty result
-'
-
-test_expect_success 'delete ref with dangling packed version' '
- git checkout -b lamb &&
- git commit --allow-empty -m "future garbage" &&
- git pack-refs --all &&
- git reset --hard HEAD^ &&
- git checkout main &&
- git reflog expire --expire=all --all &&
- git prune --expire=all &&
- git branch -d lamb 2>result &&
- test_must_be_empty result
-'
-
-test_expect_success 'delete ref while another dangling packed ref' '
- git branch lamb &&
- git commit --allow-empty -m "future garbage" &&
- git pack-refs --all &&
- git reset --hard HEAD^ &&
- git reflog expire --expire=all --all &&
- git prune --expire=all &&
- git branch -d lamb 2>result &&
- test_must_be_empty result
-'
-
-test_expect_success 'pack ref directly below refs/' '
- git update-ref refs/top HEAD &&
- git pack-refs --all --prune &&
- grep refs/top .git/packed-refs &&
- test_path_is_missing .git/refs/top
-'
-
-test_expect_success 'do not pack ref in refs/bisect' '
- git update-ref refs/bisect/local HEAD &&
- git pack-refs --all --prune &&
- ! grep refs/bisect/local .git/packed-refs >/dev/null &&
- test_path_is_file .git/refs/bisect/local
-'
-
-test_expect_success 'disable reflogs' '
- git config core.logallrefupdates false &&
- rm -rf .git/logs
-'
-
-test_expect_success 'create packed foo/bar/baz branch' '
- git branch foo/bar/baz &&
- git pack-refs --all --prune &&
- test_path_is_missing .git/refs/heads/foo/bar/baz &&
- test_must_fail git reflog exists refs/heads/foo/bar/baz
-'
-
-test_expect_success 'notice d/f conflict with existing directory' '
- test_must_fail git branch foo &&
- test_must_fail git branch foo/bar
-'
-
-test_expect_success 'existing directory reports concrete ref' '
- test_must_fail git branch foo 2>stderr &&
- test_grep refs/heads/foo/bar/baz stderr
-'
-
-test_expect_success 'notice d/f conflict with existing ref' '
- test_must_fail git branch foo/bar/baz/extra &&
- test_must_fail git branch foo/bar/baz/lots/of/extra/components
-'
-
-test_expect_success 'reject packed-refs with unterminated line' '
- cp .git/packed-refs .git/packed-refs.bak &&
- test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
- printf "%s" "$HEAD refs/zzzzz" >>.git/packed-refs &&
- echo "fatal: unterminated line in .git/packed-refs: $HEAD refs/zzzzz" >expected_err &&
- test_must_fail git for-each-ref >out 2>err &&
- test_cmp expected_err err
-'
-
-test_expect_success 'reject packed-refs containing junk' '
- cp .git/packed-refs .git/packed-refs.bak &&
- test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
- printf "%s\n" "bogus content" >>.git/packed-refs &&
- echo "fatal: unexpected line in .git/packed-refs: bogus content" >expected_err &&
- test_must_fail git for-each-ref >out 2>err &&
- test_cmp expected_err err
-'
-
-test_expect_success 'reject packed-refs with a short SHA-1' '
- cp .git/packed-refs .git/packed-refs.bak &&
- test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
- printf "%.7s %s\n" $HEAD refs/zzzzz >>.git/packed-refs &&
- printf "fatal: unexpected line in .git/packed-refs: %.7s %s\n" $HEAD refs/zzzzz >expected_err &&
- test_must_fail git for-each-ref >out 2>err &&
- test_cmp expected_err err
-'
-
-test_expect_success 'timeout if packed-refs.lock exists' '
- LOCK=.git/packed-refs.lock &&
- >"$LOCK" &&
- test_when_finished "rm -f $LOCK" &&
- test_must_fail git pack-refs --all --prune
-'
-
-test_expect_success 'retry acquiring packed-refs.lock' '
- LOCK=.git/packed-refs.lock &&
- >"$LOCK" &&
- test_when_finished "wait && rm -f $LOCK" &&
- {
- ( sleep 1 && rm -f $LOCK ) &
- } &&
- git -c core.packedrefstimeout=3000 pack-refs --all --prune
-'
-
-test_expect_success SYMLINKS 'pack symlinked packed-refs' '
- # First make sure that symlinking works when reading:
- git update-ref refs/heads/lossy refs/heads/main &&
- git for-each-ref >all-refs-before &&
- mv .git/packed-refs .git/my-deviant-packed-refs &&
- ln -s my-deviant-packed-refs .git/packed-refs &&
- git for-each-ref >all-refs-linked &&
- test_cmp all-refs-before all-refs-linked &&
- git pack-refs --all --prune &&
- git for-each-ref >all-refs-packed &&
- test_cmp all-refs-before all-refs-packed &&
- test -h .git/packed-refs &&
- test "$(test_readlink .git/packed-refs)" = "my-deviant-packed-refs"
-'
-
-# The 'packed-refs' file is stored directly in .git/. This means it is global
-# to the repository, and can only contain refs that are shared across all
-# worktrees.
-test_expect_success 'refs/worktree must not be packed' '
- test_commit initial &&
- test_commit wt1 &&
- test_commit wt2 &&
- git worktree add wt1 wt1 &&
- git worktree add wt2 wt2 &&
- git checkout initial &&
- git update-ref refs/worktree/foo HEAD &&
- git -C wt1 update-ref refs/worktree/foo HEAD &&
- git -C wt2 update-ref refs/worktree/foo HEAD &&
- git pack-refs --all &&
- test_path_is_missing .git/refs/tags/wt1 &&
- test_path_is_file .git/refs/worktree/foo &&
- test_path_is_file .git/worktrees/wt1/refs/worktree/foo &&
- test_path_is_file .git/worktrees/wt2/refs/worktree/foo
-'
-
-# we do not want to count on running pack-refs to
-# actually pack it, as it is perfectly reasonable to
-# skip processing a broken ref
-test_expect_success 'create packed-refs file with broken ref' '
- test_tick && git commit --allow-empty -m one &&
- recoverable=$(git rev-parse HEAD) &&
- test_tick && git commit --allow-empty -m two &&
- missing=$(git rev-parse HEAD) &&
- rm -f .git/refs/heads/main &&
- cat >.git/packed-refs <<-EOF &&
- $missing refs/heads/main
- $recoverable refs/heads/other
- EOF
- echo $missing >expect &&
- git rev-parse refs/heads/main >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'pack-refs does not silently delete broken packed ref' '
- git pack-refs --all --prune &&
- git rev-parse refs/heads/main >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'pack-refs does not drop broken refs during deletion' '
- git update-ref -d refs/heads/other &&
- git rev-parse refs/heads/main >actual &&
- test_cmp expect actual
-'
-
-for command in "git pack-refs --all --auto" "git maintenance run --task=pack-refs --auto"
-do
- test_expect_success "$command does not repack below 16 refs without packed-refs" '
- test_when_finished "rm -rf repo" &&
- git init repo &&
- (
- cd repo &&
- git config set maintenance.auto false &&
- git commit --allow-empty --message "initial" &&
-
- # Create 14 additional references, which brings us to
- # 15 together with the default branch.
- printf "create refs/heads/loose-%d HEAD\n" $(test_seq 14) >stdin &&
- git update-ref --stdin <stdin &&
- test_path_is_missing .git/packed-refs &&
- git pack-refs --auto --all &&
- test_path_is_missing .git/packed-refs &&
-
- # Create the 16th reference, which should cause us to repack.
- git update-ref refs/heads/loose-15 HEAD &&
- git pack-refs --auto --all &&
- test_path_is_file .git/packed-refs
- )
- '
-
- test_expect_success "$command does not repack below 16 refs with small packed-refs" '
- test_when_finished "rm -rf repo" &&
- git init repo &&
- (
- cd repo &&
- git config set maintenance.auto false &&
- git commit --allow-empty --message "initial" &&
-
- git pack-refs --all &&
- test_line_count = 2 .git/packed-refs &&
-
- # Create 15 loose references.
- printf "create refs/heads/loose-%d HEAD\n" $(test_seq 15) >stdin &&
- git update-ref --stdin <stdin &&
- git pack-refs --auto --all &&
- test_line_count = 2 .git/packed-refs &&
-
- # Create the 16th loose reference, which should cause us to repack.
- git update-ref refs/heads/loose-17 HEAD &&
- git pack-refs --auto --all &&
- test_line_count = 18 .git/packed-refs
- )
- '
-
- test_expect_success "$command scales with size of packed-refs" '
- test_when_finished "rm -rf repo" &&
- git init repo &&
- (
- cd repo &&
- git config set maintenance.auto false &&
- git commit --allow-empty --message "initial" &&
-
- # Create 99 packed refs. This should cause the heuristic
- # to require more than the minimum amount of loose refs.
- test_seq 99 |
- while read i
- do
- printf "create refs/heads/packed-%d HEAD\n" $i || return 1
- done >stdin &&
- git update-ref --stdin <stdin &&
- git pack-refs --all &&
- test_line_count = 101 .git/packed-refs &&
-
- # Create 24 loose refs, which should not yet cause us to repack.
- printf "create refs/heads/loose-%d HEAD\n" $(test_seq 24) >stdin &&
- git update-ref --stdin <stdin &&
- git pack-refs --auto --all &&
- test_line_count = 101 .git/packed-refs &&
-
- # Create another handful of refs to cross the border.
- # Note that we explicitly do not check for strict
- # boundaries here, as this also depends on the size of
- # the object hash.
- printf "create refs/heads/addn-%d HEAD\n" $(test_seq 10) >stdin &&
- git update-ref --stdin <stdin &&
- git pack-refs --auto --all &&
- test_line_count = 135 .git/packed-refs
- )
- '
-done
-
-test_done
+. "$TEST_DIRECTORY"/pack-refs-tests.sh
diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh
index d77e601111..e334751759 100755
--- a/t/t0613-reftable-write-options.sh
+++ b/t/t0613-reftable-write-options.sh
@@ -11,16 +11,18 @@ export GIT_TEST_REFTABLE_AUTOCOMPACTION
# Block sizes depend on the hash function, so we force SHA1 here.
GIT_TEST_DEFAULT_HASH=sha1
export GIT_TEST_DEFAULT_HASH
-# Block sizes also depend on the actual refs we write, so we force "master" to
-# be the default initial branch name.
-GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
-export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
+# Block sizes depend on the actual refs we write, so, for tests
+# that check block size, we force the initial branch name to be "master".
+init_repo () {
+ git init --initial-branch master repo
+}
+
test_expect_success 'default write options' '
test_when_finished "rm -rf repo" &&
- git init repo &&
+ init_repo &&
(
cd repo &&
test_commit initial &&
@@ -43,7 +45,7 @@ test_expect_success 'default write options' '
test_expect_success 'disabled reflog writes no log blocks' '
test_config_global core.logAllRefUpdates false &&
test_when_finished "rm -rf repo" &&
- git init repo &&
+ init_repo &&
(
cd repo &&
test_commit initial &&
@@ -62,7 +64,7 @@ test_expect_success 'disabled reflog writes no log blocks' '
test_expect_success 'many refs results in multiple blocks' '
test_when_finished "rm -rf repo" &&
- git init repo &&
+ init_repo &&
(
cd repo &&
test_commit initial &&
@@ -115,7 +117,7 @@ test_expect_success 'tiny block size leads to error' '
test_expect_success 'small block size leads to multiple ref blocks' '
test_config_global core.logAllRefUpdates false &&
test_when_finished "rm -rf repo" &&
- git init repo &&
+ init_repo &&
(
cd repo &&
test_commit A &&
@@ -172,7 +174,7 @@ test_expect_success 'block size exceeding maximum supported size' '
test_expect_success 'restart interval at every single record' '
test_when_finished "rm -rf repo" &&
- git init repo &&
+ init_repo &&
(
cd repo &&
test_commit initial &&
@@ -212,7 +214,7 @@ test_expect_success 'restart interval exceeding maximum supported interval' '
test_expect_success 'object index gets written by default with ref index' '
test_config_global core.logAllRefUpdates false &&
test_when_finished "rm -rf repo" &&
- git init repo &&
+ init_repo &&
(
cd repo &&
test_commit initial &&
@@ -247,7 +249,7 @@ test_expect_success 'object index gets written by default with ref index' '
test_expect_success 'object index can be disabled' '
test_config_global core.logAllRefUpdates false &&
test_when_finished "rm -rf repo" &&
- git init repo &&
+ init_repo &&
(
cd repo &&
test_commit initial &&
diff --git a/t/t0614-reftable-fsck.sh b/t/t0614-reftable-fsck.sh
new file mode 100755
index 0000000000..85cc47d67e
--- /dev/null
+++ b/t/t0614-reftable-fsck.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+test_description='Test reftable backend consistency check'
+
+GIT_TEST_DEFAULT_REF_FORMAT=reftable
+export GIT_TEST_DEFAULT_REF_FORMAT
+
+. ./test-lib.sh
+
+test_expect_success "no errors reported on a well formed repository" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git commit --allow-empty -m initial &&
+
+ for i in $(test_seq 20)
+ do
+ git update-ref refs/heads/branch-$i HEAD || return 1
+ done &&
+
+ # The repository should end up with multiple tables.
+ test_line_count ">" 1 .git/reftable/tables.list &&
+
+ git refs verify 2>err &&
+ test_must_be_empty err
+ )
+'
+
+for TABLE_NAME in "foo-bar-e4d12d59.ref" \
+ "0x00000000zzzz-0x00000000zzzz-e4d12d59.ref" \
+ "0x000000000001-0x000000000002-e4d12d59.abc" \
+ "0x000000000001-0x000000000002-e4d12d59.refabc"; do
+ test_expect_success "table name $TABLE_NAME should be checked" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git commit --allow-empty -m initial &&
+
+ git refs verify 2>err &&
+ test_must_be_empty err &&
+
+ EXISTING_TABLE=$(head -n1 .git/reftable/tables.list) &&
+ mv ".git/reftable/$EXISTING_TABLE" ".git/reftable/$TABLE_NAME" &&
+ sed "s/${EXISTING_TABLE}/${TABLE_NAME}/g" .git/reftable/tables.list > tables.list &&
+ mv tables.list .git/reftable/tables.list &&
+
+ git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ warning: ${TABLE_NAME}: badReftableTableName: invalid reftable table name
+ EOF
+ test_cmp expect err
+ )
+ '
+done
+
+test_done
diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh
index e9973f7494..312fe6717a 100755
--- a/t/t1010-mktree.sh
+++ b/t/t1010-mktree.sh
@@ -11,10 +11,13 @@ test_expect_success setup '
git add "$d" || return 1
done &&
echo zero >one &&
- git update-index --add --info-only one &&
- git write-tree --missing-ok >tree.missing &&
- git ls-tree $(cat tree.missing) >top.missing &&
- git ls-tree -r $(cat tree.missing) >all.missing &&
+ if test_have_prereq BROKEN_OBJECTS
+ then
+ git update-index --add --info-only one &&
+ git write-tree --missing-ok >tree.missing &&
+ git ls-tree $(cat tree.missing) >top.missing &&
+ git ls-tree -r $(cat tree.missing) >all.missing
+ fi &&
echo one >one &&
git add one &&
git write-tree >tree &&
@@ -53,7 +56,7 @@ test_expect_success 'ls-tree output in wrong order given to mktree (2)' '
test_cmp tree.withsub actual
'
-test_expect_success 'allow missing object with --missing' '
+test_expect_success BROKEN_OBJECTS 'allow missing object with --missing' '
git mktree --missing <top.missing >actual &&
test_cmp tree.missing actual
'
diff --git a/t/t1016-compatObjectFormat.sh b/t/t1016-compatObjectFormat.sh
index e88362fbe4..a9af8b2396 100755
--- a/t/t1016-compatObjectFormat.sh
+++ b/t/t1016-compatObjectFormat.sh
@@ -114,7 +114,7 @@ do
git config core.repositoryformatversion 1 &&
git config extensions.objectformat $hash &&
git config extensions.compatobjectformat $(compat_hash $hash) &&
- test_config gpg.program $TEST_DIRECTORY/t1016/gpg &&
+ git config gpg.program $TEST_DIRECTORY/t1016/gpg &&
echo "Hello World!" >hello &&
eval hello_${hash}_oid=$(git hash-object hello) &&
git update-index --add hello &&
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index ab3a105fff..b2da4feaef 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -1050,5 +1050,180 @@ test_expect_success 'check-rules null termination' '
test_cmp expect actual
'
+test_expect_success 'clean' '
+ git -C repo sparse-checkout set --cone deep/deeper1 &&
+ git -C repo sparse-checkout reapply &&
+ mkdir -p repo/deep/deeper2 repo/folder1/extra/inside &&
+
+ # Add untracked files
+ touch repo/deep/deeper2/file &&
+ touch repo/folder1/extra/inside/file &&
+
+ test_must_fail git -C repo sparse-checkout clean 2>err &&
+ grep "refusing to clean" err &&
+
+ git -C repo config clean.requireForce true &&
+ test_must_fail git -C repo sparse-checkout clean 2>err &&
+ grep "refusing to clean" err &&
+
+ cat >expect <<-\EOF &&
+ Would remove deep/deeper2/
+ Would remove folder1/
+ EOF
+
+ git -C repo sparse-checkout clean --dry-run >out &&
+ test_cmp expect out &&
+ test_path_exists repo/deep/deeper2 &&
+ test_path_exists repo/folder1/extra/inside/file &&
+
+ cat >expect <<-\EOF &&
+ Would remove deep/deeper2/file
+ Would remove folder1/extra/inside/file
+ EOF
+
+ git -C repo sparse-checkout clean --dry-run --verbose >out &&
+ test_cmp expect out &&
+
+ cat >expect <<-\EOF &&
+ Removing deep/deeper2/
+ Removing folder1/
+ EOF
+
+ git -C repo sparse-checkout clean -f >out &&
+ test_cmp expect out &&
+
+ test_path_is_missing repo/deep/deeper2 &&
+ test_path_is_missing repo/folder1
+'
+
+test_expect_success 'clean with sparse file states' '
+ test_when_finished git reset --hard &&
+ git -C repo sparse-checkout set --cone deep/deeper1 &&
+ mkdir repo/folder2 &&
+
+ # The previous test case checked the -f option, so
+ # test the config option in this one.
+ git -C repo config clean.requireForce false &&
+
+ # create an untracked file and a modified file
+ touch repo/folder2/file &&
+ echo dirty >repo/folder2/a &&
+
+ # First clean/reapply pass will do nothing.
+ git -C repo sparse-checkout clean >out &&
+ test_must_be_empty out &&
+ test_path_exists repo/folder2/a &&
+ test_path_exists repo/folder2/file &&
+
+ git -C repo sparse-checkout reapply 2>err &&
+ test_grep folder2 err &&
+ test_path_exists repo/folder2/a &&
+ test_path_exists repo/folder2/file &&
+
+ # Now, stage the change to the tracked file.
+ git -C repo add --sparse folder2/a &&
+
+ # Clean will continue not doing anything.
+ git -C repo sparse-checkout clean >out &&
+ test_line_count = 0 out &&
+ test_path_exists repo/folder2/a &&
+ test_path_exists repo/folder2/file &&
+
+ # But we can reapply to remove the staged change.
+ git -C repo sparse-checkout reapply 2>err &&
+ test_grep folder2 err &&
+ test_path_is_missing repo/folder2/a &&
+ test_path_exists repo/folder2/file &&
+
+ # We can clean now.
+ cat >expect <<-\EOF &&
+ Removing folder2/
+ EOF
+ git -C repo sparse-checkout clean >out &&
+ test_cmp expect out &&
+ test_path_is_missing repo/folder2 &&
+
+ # At the moment, the file is staged.
+ cat >expect <<-\EOF &&
+ M folder2/a
+ EOF
+
+ git -C repo status -s >out &&
+ test_cmp expect out &&
+
+ # Reapply persists the modified state.
+ git -C repo sparse-checkout reapply &&
+ cat >expect <<-\EOF &&
+ M folder2/a
+ EOF
+ git -C repo status -s >out &&
+ test_cmp expect out &&
+
+ # Committing the change leads to resolved status.
+ git -C repo commit -m "modified" &&
+ git -C repo status -s >out &&
+ test_must_be_empty out &&
+
+ # Repeat, but this time commit before reapplying.
+ mkdir repo/folder2/ &&
+ echo dirtier >repo/folder2/a &&
+ git -C repo add --sparse folder2/a &&
+ git -C repo sparse-checkout clean >out &&
+ test_must_be_empty out &&
+ test_path_exists repo/folder2/a &&
+
+ # Committing without reapplying makes it look like a deletion
+ # due to no skip-worktree bit.
+ git -C repo commit -m "dirtier" &&
+ git -C repo status -s >out &&
+ test_must_be_empty out &&
+
+ git -C repo sparse-checkout reapply &&
+ git -C repo status -s >out &&
+ test_must_be_empty out
+'
+
+test_expect_success 'sparse-checkout operations with merge conflicts' '
+ git clone repo merge &&
+
+ (
+ cd merge &&
+ mkdir -p folder1/even/more/dirs &&
+ echo base >folder1/even/more/dirs/file &&
+ git add folder1 &&
+ git commit -m "base" &&
+
+ git checkout -b right&&
+ echo right >folder1/even/more/dirs/file &&
+ git commit -a -m "right" &&
+
+ git checkout -b left HEAD~1 &&
+ echo left >folder1/even/more/dirs/file &&
+ git commit -a -m "left" &&
+
+ git checkout -b merge &&
+ git sparse-checkout set deep/deeper1 &&
+
+ test_must_fail git merge -m "will-conflict" right &&
+
+ test_must_fail git sparse-checkout clean -f 2>err &&
+ grep "failed to convert index to a sparse index" err &&
+
+ echo merged >folder1/even/more/dirs/file &&
+ git add --sparse folder1 &&
+ git merge --continue &&
+
+ test_path_exists folder1/even/more/dirs/file &&
+
+ # clean does not remove the file, because the
+ # SKIP_WORKTREE bit was not cleared by the merge command.
+ git sparse-checkout clean -f >out &&
+ test_line_count = 0 out &&
+ test_path_exists folder1/even/more/dirs/file &&
+
+ git sparse-checkout reapply &&
+ test_path_is_missing folder1
+ )
+'
test_done
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index f856821839..358d636379 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -9,6 +9,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
for mode in legacy subcommands
do
@@ -134,38 +135,39 @@ test_expect_success 'clear default config' '
rm -f .git/config
'
-cat > expect << EOF
+test_expect_success 'initial' '
+ cat >expect <<\EOF &&
[section]
penguin = little blue
EOF
-test_expect_success 'initial' '
git config ${mode_set} section.penguin "little blue" &&
test_cmp expect .git/config
'
-cat > expect << EOF
+test_expect_success 'mixed case' '
+ cat >expect <<\EOF &&
[section]
penguin = little blue
Movie = BadPhysics
EOF
-test_expect_success 'mixed case' '
git config ${mode_set} Section.Movie BadPhysics &&
test_cmp expect .git/config
'
-cat > expect << EOF
+test_expect_success 'similar section' '
+ cat >expect <<\EOF &&
[section]
penguin = little blue
Movie = BadPhysics
[Sections]
WhatEver = Second
EOF
-test_expect_success 'similar section' '
git config ${mode_set} Sections.WhatEver Second &&
test_cmp expect .git/config
'
-cat > expect << EOF
+test_expect_success 'uppercase section' '
+ cat >expect <<\EOF &&
[section]
penguin = little blue
Movie = BadPhysics
@@ -173,7 +175,6 @@ cat > expect << EOF
[Sections]
WhatEver = Second
EOF
-test_expect_success 'uppercase section' '
git config ${mode_set} SECTION.UPPERCASE true &&
test_cmp expect .git/config
'
@@ -186,7 +187,8 @@ test_expect_success 'replace with non-match (actually matching)' '
git config section.penguin "very blue" !kingpin
'
-cat > expect << EOF
+test_expect_success 'append comments' '
+ cat >expect <<\EOF &&
[section]
Movie = BadPhysics
UPPERCASE = true
@@ -198,8 +200,6 @@ cat > expect << EOF
[Sections]
WhatEver = Second
EOF
-
-test_expect_success 'append comments' '
git config --replace-all --comment="Pygoscelis papua" section.penguin gentoo &&
git config ${mode_set} --comment="find fish" section.disposition peckish &&
git config ${mode_set} --comment="#abc" section.foo bar &&
@@ -214,7 +214,9 @@ test_expect_success 'Prohibited LF in comment' '
test_must_fail git config ${mode_set} --comment="a${LF}b" section.k v
'
-test_expect_success 'non-match result' 'test_cmp expect .git/config'
+test_expect_success 'non-match result' '
+ test_cmp expect .git/config
+'
test_expect_success 'find mixed-case key by canonical name' '
test_cmp_config Second sections.whatever
@@ -265,14 +267,15 @@ test_expect_success 'unset with cont. lines' '
git config ${mode_unset} beta.baz
'
-cat > expect <<\EOF
-[alpha]
-bar = foo
-[beta]
-foo = bar
-EOF
-
-test_expect_success 'unset with cont. lines is correct' 'test_cmp expect .git/config'
+test_expect_success 'unset with cont. lines is correct' '
+ cat >expect <<-\EOF &&
+ [alpha]
+ bar = foo
+ [beta]
+ foo = bar
+ EOF
+ test_cmp expect .git/config
+'
cat > .git/config << EOF
[beta] ; silly comment # another comment
@@ -292,16 +295,15 @@ test_expect_success 'multiple unset' '
git config ${mode_unset_all} beta.haha
'
-cat > expect << EOF
+test_expect_success 'multiple unset is correct' '
+ cat >expect <<EOF &&
[beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
# empty line
; comment
[nextSection] noNewline = ouch
EOF
-
-test_expect_success 'multiple unset is correct' '
test_cmp expect .git/config
'
@@ -318,37 +320,37 @@ test_expect_success '--replace-all' '
git config ${mode_replace_all} beta.haha gamma
'
-cat > expect << EOF
+test_expect_success 'all replaced' '
+ cat >expect <<EOF &&
[beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
# empty line
; comment
haha = gamma
[nextSection] noNewline = ouch
EOF
-
-test_expect_success 'all replaced' '
test_cmp expect .git/config
'
-cat > expect << EOF
+test_expect_success 'really mean test' '
+ cat >expect <<EOF &&
[beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
# empty line
; comment
haha = alpha
[nextSection] noNewline = ouch
EOF
-test_expect_success 'really mean test' '
git config ${mode_set} beta.haha alpha &&
test_cmp expect .git/config
'
-cat > expect << EOF
+test_expect_success 'really really mean test' '
+ cat >expect <<EOF &&
[beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
# empty line
; comment
@@ -356,7 +358,6 @@ noIndent= sillyValue ; 'nother silly comment
[nextSection]
nonewline = wow
EOF
-test_expect_success 'really really mean test' '
git config ${mode_set} nextsection.nonewline wow &&
test_cmp expect .git/config
'
@@ -365,23 +366,24 @@ test_expect_success 'get value' '
test_cmp_config alpha beta.haha
'
-cat > expect << EOF
+test_expect_success 'unset' '
+ cat >expect <<EOF &&
[beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
# empty line
; comment
[nextSection]
nonewline = wow
EOF
-test_expect_success 'unset' '
git config ${mode_unset} beta.haha &&
test_cmp expect .git/config
'
-cat > expect << EOF
+test_expect_success 'multivar' '
+ cat >expect <<EOF &&
[beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
# empty line
; comment
@@ -389,7 +391,6 @@ noIndent= sillyValue ; 'nother silly comment
nonewline = wow
NoNewLine = wow2 for me
EOF
-test_expect_success 'multivar' '
git config nextsection.NoNewLine "wow2 for me" "for me$" &&
test_cmp expect .git/config
'
@@ -415,9 +416,10 @@ test_expect_success 'multi-valued get-all returns all' '
test_cmp expect actual
'
-cat > expect << EOF
+test_expect_success 'multivar replace' '
+ cat >expect <<EOF &&
[beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
# empty line
; comment
@@ -425,7 +427,6 @@ noIndent= sillyValue ; 'nother silly comment
nonewline = wow3
NoNewLine = wow2 for me
EOF
-test_expect_success 'multivar replace' '
git config nextsection.nonewline "wow3" "wow$" &&
test_cmp expect .git/config
'
@@ -438,17 +439,16 @@ test_expect_success 'invalid unset' '
test_must_fail git config ${mode_unset} somesection.nonewline
'
-cat > expect << EOF
+test_expect_success 'multivar unset' '
+ cat >expect <<EOF &&
[beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
# empty line
; comment
[nextSection]
NoNewLine = wow2 for me
EOF
-
-test_expect_success 'multivar unset' '
case "$mode" in
legacy)
git config --unset nextsection.nonewline "wow3$";;
@@ -458,17 +458,22 @@ test_expect_success 'multivar unset' '
test_cmp expect .git/config
'
-test_expect_success 'invalid key' 'test_must_fail git config inval.2key blabla'
+test_expect_success 'invalid key' '
+ test_must_fail git config inval.2key blabla
+'
-test_expect_success 'correct key' 'git config 123456.a123 987'
+test_expect_success 'correct key' '
+ git config 123456.a123 987
+'
test_expect_success 'hierarchical section' '
git config Version.1.2.3eX.Alpha beta
'
-cat > expect << EOF
+test_expect_success 'hierarchical section value' '
+ cat >expect <<EOF &&
[beta] ; silly comment # another comment
-noIndent= sillyValue ; 'nother silly comment
+noIndent= sillyValue ; ${SQ}nother silly comment
# empty line
; comment
@@ -479,65 +484,59 @@ noIndent= sillyValue ; 'nother silly comment
[Version "1.2.3eX"]
Alpha = beta
EOF
-
-test_expect_success 'hierarchical section value' '
test_cmp expect .git/config
'
-cat > expect << EOF
-beta.noindent=sillyValue
-nextsection.nonewline=wow2 for me
-123456.a123=987
-version.1.2.3eX.alpha=beta
-EOF
-
test_expect_success 'working --list' '
+ cat >expect <<-\EOF &&
+ beta.noindent=sillyValue
+ nextsection.nonewline=wow2 for me
+ 123456.a123=987
+ version.1.2.3eX.alpha=beta
+ EOF
git config ${mode_prefix}list > output &&
test_cmp expect output
'
+
test_expect_success '--list without repo produces empty output' '
git --git-dir=nonexistent config ${mode_prefix}list >output &&
test_must_be_empty output
'
-cat > expect << EOF
-beta.noindent
-nextsection.nonewline
-123456.a123
-version.1.2.3eX.alpha
-EOF
-
test_expect_success '--name-only --list' '
+ cat >expect <<-\EOF &&
+ beta.noindent
+ nextsection.nonewline
+ 123456.a123
+ version.1.2.3eX.alpha
+ EOF
git config ${mode_prefix}list --name-only >output &&
test_cmp expect output
'
-cat > expect << EOF
-beta.noindent sillyValue
-nextsection.nonewline wow2 for me
-EOF
-
test_expect_success '--get-regexp' '
+ cat >expect <<-\EOF &&
+ beta.noindent sillyValue
+ nextsection.nonewline wow2 for me
+ EOF
git config ${mode_get_regexp} in >output &&
test_cmp expect output
'
-cat > expect << EOF
-beta.noindent
-nextsection.nonewline
-EOF
-
test_expect_success '--name-only --get-regexp' '
+ cat >expect <<-\EOF &&
+ beta.noindent
+ nextsection.nonewline
+ EOF
git config ${mode_get_regexp} --name-only in >output &&
test_cmp expect output
'
-cat > expect << EOF
-wow2 for me
-wow4 for you
-EOF
-
test_expect_success '--add' '
+ cat >expect <<-\EOF &&
+ wow2 for me
+ wow4 for you
+ EOF
git config --add nextsection.nonewline "wow4 for you" &&
git config ${mode_get_all} nextsection.nonewline > output &&
test_cmp expect output
@@ -558,37 +557,32 @@ test_expect_success 'get variable with empty value' '
git config --get emptyvalue.variable ^$
'
-echo novalue.variable > expect
-
test_expect_success 'get-regexp variable with no value' '
+ echo novalue.variable >expect &&
git config ${mode_get_regexp} novalue > output &&
test_cmp expect output
'
-echo 'novalue.variable true' > expect
-
test_expect_success 'get-regexp --bool variable with no value' '
+ echo "novalue.variable true" >expect &&
git config ${mode_get_regexp} --bool novalue > output &&
test_cmp expect output
'
-echo 'emptyvalue.variable ' > expect
-
test_expect_success 'get-regexp variable with empty value' '
+ echo "emptyvalue.variable " >expect &&
git config ${mode_get_regexp} emptyvalue > output &&
test_cmp expect output
'
-echo true > expect
-
test_expect_success 'get bool variable with no value' '
+ echo true >expect &&
git config --bool novalue.variable > output &&
test_cmp expect output
'
-echo false > expect
-
test_expect_success 'get bool variable with empty value' '
+ echo false >expect &&
git config --bool emptyvalue.variable > output &&
test_cmp expect output
'
@@ -604,19 +598,19 @@ cat > .git/config << EOF
c = d
EOF
-cat > expect << EOF
+test_expect_success 'new section is partial match of another' '
+ cat >expect <<\EOF &&
[a.b]
c = d
[a]
x = y
EOF
-
-test_expect_success 'new section is partial match of another' '
git config a.x y &&
test_cmp expect .git/config
'
-cat > expect << EOF
+test_expect_success 'new variable inserts into proper section' '
+ cat >expect <<\EOF &&
[a.b]
c = d
[a]
@@ -625,8 +619,6 @@ cat > expect << EOF
[b]
x = y
EOF
-
-test_expect_success 'new variable inserts into proper section' '
git config b.x y &&
git config a.b c &&
test_cmp expect .git/config
@@ -642,11 +634,10 @@ cat > other-config << EOF
bahn = strasse
EOF
-cat > expect << EOF
-ein.bahn=strasse
-EOF
-
test_expect_success 'alternative GIT_CONFIG' '
+ cat >expect <<-\EOF &&
+ ein.bahn=strasse
+ EOF
GIT_CONFIG=other-config git config ${mode_prefix}list >output &&
test_cmp expect output
'
@@ -675,14 +666,13 @@ test_expect_success 'refer config from subdirectory' '
test_cmp_config -C x strasse --file=../other-config --get ein.bahn
'
-cat > expect << EOF
+test_expect_success '--set in alternative file' '
+ cat >expect <<\EOF &&
[ein]
bahn = strasse
[anwohner]
park = ausweis
EOF
-
-test_expect_success '--set in alternative file' '
git config --file=other-config anwohner.park ausweis &&
test_cmp expect other-config
'
@@ -730,7 +720,8 @@ test_expect_success 'rename another section' '
git config ${mode_prefix}rename-section branch."1 234 blabl/a" branch.drei
'
-cat > expect << EOF
+test_expect_success 'rename succeeded' '
+ cat >expect <<\EOF &&
# Hallo
#Bello
[branch "zwei"]
@@ -740,8 +731,6 @@ cat > expect << EOF
[branch "drei"]
weird
EOF
-
-test_expect_success 'rename succeeded' '
test_cmp expect .git/config
'
@@ -753,7 +742,8 @@ test_expect_success 'rename a section with a var on the same line' '
git config ${mode_prefix}rename-section branch.vier branch.zwei
'
-cat > expect << EOF
+test_expect_success 'rename succeeded' '
+ cat >expect <<\EOF &&
# Hallo
#Bello
[branch "zwei"]
@@ -765,8 +755,6 @@ weird
[branch "zwei"]
z = 1
EOF
-
-test_expect_success 'rename succeeded' '
test_cmp expect .git/config
'
@@ -816,32 +804,29 @@ test_expect_success 'remove section' '
git config ${mode_prefix}remove-section branch.zwei
'
-cat > expect << EOF
+test_expect_success 'section was removed properly' '
+ cat >expect <<\EOF &&
# Hallo
#Bello
[branch "drei"]
weird
EOF
-
-test_expect_success 'section was removed properly' '
test_cmp expect .git/config
'
-cat > expect << EOF
+test_expect_success 'section ending' '
+ cat >expect <<\EOF &&
[gitcvs]
enabled = true
dbname = %Ggitcvs2.%a.%m.sqlite
[gitcvs "ext"]
dbname = %Ggitcvs1.%a.%m.sqlite
EOF
-
-test_expect_success 'section ending' '
rm -f .git/config &&
git config ${mode_set} gitcvs.enabled true &&
git config ${mode_set} gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite &&
git config ${mode_set} gitcvs.dbname %Ggitcvs2.%a.%m.sqlite &&
test_cmp expect .git/config
-
'
test_expect_success numbers '
@@ -885,19 +870,17 @@ test_expect_success 'invalid stdin config' '
test_grep "bad config line 1 in standard input" output
'
-cat > expect << EOF
-true
-false
-true
-false
-true
-false
-true
-false
-EOF
-
test_expect_success bool '
-
+ cat >expect <<-\EOF &&
+ true
+ false
+ true
+ false
+ true
+ false
+ true
+ false
+ EOF
git config ${mode_set} bool.true1 01 &&
git config ${mode_set} bool.true2 -1 &&
git config ${mode_set} bool.true3 YeS &&
@@ -912,18 +895,20 @@ test_expect_success bool '
git config --bool --get bool.true$i >>result &&
git config --bool --get bool.false$i >>result || return 1
done &&
- test_cmp expect result'
+ test_cmp expect result
+'
test_expect_success 'invalid bool (--get)' '
-
git config ${mode_set} bool.nobool foobar &&
- test_must_fail git config --bool --get bool.nobool'
+ test_must_fail git config --bool --get bool.nobool
+'
test_expect_success 'invalid bool (set)' '
+ test_must_fail git config --bool bool.nobool foobar
+'
- test_must_fail git config --bool bool.nobool foobar'
-
-cat > expect <<\EOF
+test_expect_success 'set --bool' '
+ cat >expect <<\EOF &&
[bool]
true1 = true
true2 = true
@@ -934,9 +919,6 @@ cat > expect <<\EOF
false3 = false
false4 = false
EOF
-
-test_expect_success 'set --bool' '
-
rm -f .git/config &&
git config --bool bool.true1 01 &&
git config --bool bool.true2 -1 &&
@@ -948,15 +930,13 @@ test_expect_success 'set --bool' '
git config --bool bool.false4 FALSE &&
test_cmp expect .git/config'
-cat > expect <<\EOF
+test_expect_success 'set --int' '
+ cat >expect <<\EOF &&
[int]
val1 = 1
val2 = -1
val3 = 5242880
EOF
-
-test_expect_success 'set --int' '
-
rm -f .git/config &&
git config --int int.val1 01 &&
git config --int int.val2 -1 &&
@@ -994,7 +974,8 @@ test_expect_success 'get --bool-or-int' '
test_cmp expect actual
'
-cat >expect <<\EOF
+test_expect_success 'set --bool-or-int' '
+ cat >expect <<\EOF &&
[bool]
true1 = true
false1 = false
@@ -1005,8 +986,6 @@ cat >expect <<\EOF
int2 = 1
int3 = -1
EOF
-
-test_expect_success 'set --bool-or-int' '
rm -f .git/config &&
git config --bool-or-int bool.true1 true &&
git config --bool-or-int bool.false1 false &&
@@ -1018,44 +997,42 @@ test_expect_success 'set --bool-or-int' '
test_cmp expect .git/config
'
-cat >expect <<\EOF
+test_expect_success !MINGW 'set --path' '
+ cat >expect <<\EOF &&
[path]
home = ~/
normal = /dev/null
trailingtilde = foo~
EOF
-
-test_expect_success !MINGW 'set --path' '
rm -f .git/config &&
git config --path path.home "~/" &&
git config --path path.normal "/dev/null" &&
git config --path path.trailingtilde "foo~" &&
- test_cmp expect .git/config'
+ test_cmp expect .git/config
+'
if test_have_prereq !MINGW && test "${HOME+set}"
then
test_set_prereq HOMEVAR
fi
-cat >expect <<EOF
-$HOME/
-/dev/null
-foo~
-EOF
-
test_expect_success HOMEVAR 'get --path' '
+ cat >expect <<-EOF &&
+ $HOME/
+ /dev/null
+ foo~
+ EOF
git config --get --path path.home > result &&
git config --get --path path.normal >> result &&
git config --get --path path.trailingtilde >> result &&
test_cmp expect result
'
-cat >expect <<\EOF
-/dev/null
-foo~
-EOF
-
test_expect_success !MINGW 'get --path copes with unset $HOME' '
+ cat >expect <<-\EOF &&
+ /dev/null
+ foo~
+ EOF
(
sane_unset HOME &&
test_must_fail git config --get --path path.home \
@@ -1107,17 +1084,35 @@ test_expect_success 'get --type=color' '
rm .git/config &&
git config ${mode_set} foo.color "red" &&
git config --get --type=color foo.color >actual.raw &&
+ git config get --type=color foo.color >actual-subcommand.raw &&
+ test_cmp actual.raw actual-subcommand.raw &&
+ test_decode_color <actual.raw >actual &&
+ echo "<RED>" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'get --type=color with default value only' '
+ git config --get-color "" "red" >actual.raw &&
+ test_decode_color <actual.raw >actual &&
+ echo "<RED>" >expect &&
+ test_cmp expect actual &&
+ git config get --type=color --default="red" "" >actual-subcommand.raw &&
+ test_cmp actual.raw actual-subcommand.raw
+'
+
+test_expect_success TTY 'get --type=color does not use a pager' '
+ test_config core.pager "echo foobar" &&
+ test_terminal git config get --type=color --default="red" "" >actual.raw &&
test_decode_color <actual.raw >actual &&
echo "<RED>" >expect &&
test_cmp expect actual
'
-cat >expect << EOF
+test_expect_success 'set --type=color' '
+ cat >expect <<\EOF &&
[foo]
color = red
EOF
-
-test_expect_success 'set --type=color' '
rm .git/config &&
git config --type=color foo.color "red" &&
test_cmp expect .git/config
@@ -1133,14 +1128,14 @@ test_expect_success 'set --type=color barfs on non-color' '
test_grep "cannot parse color" error
'
-cat > expect << EOF
+test_expect_success 'quoting' '
+ cat >expect <<\EOF &&
[quote]
leading = " test"
ending = "test "
semicolon = "test;test"
hash = "test#test"
EOF
-test_expect_success 'quoting' '
rm -f .git/config &&
git config ${mode_set} quote.leading " test" &&
git config ${mode_set} quote.ending "test " &&
@@ -1151,10 +1146,13 @@ test_expect_success 'quoting' '
test_expect_success 'key with newline' '
test_must_fail git config ${mode_get} "key.with
-newline" 123'
+newline" 123
+'
-test_expect_success 'value with newline' 'git config ${mode_set} key.sub value.with\\\
-newline'
+test_expect_success 'value with newline' '
+ git config ${mode_set} key.sub value.with\\\
+newline
+'
cat > .git/config <<\EOF
[section]
@@ -1166,13 +1164,12 @@ inued
inued"
EOF
-cat > expect <<\EOF
-section.continued=continued
-section.noncont=not continued
-section.quotecont=cont;inued
-EOF
-
test_expect_success 'value continued on next line' '
+ cat >expect <<-\EOF &&
+ section.continued=continued
+ section.noncont=not continued
+ section.quotecont=cont;inued
+ EOF
git config ${mode_prefix}list > result &&
test_cmp expect result
'
@@ -1365,7 +1362,6 @@ test_expect_success 'multiple git -c appends config' '
'
test_expect_success 'last one wins: two level vars' '
-
# sec.var and sec.VAR are the same variable, as the first
# and the last level of a configuration variable name is
# case insensitive.
@@ -1384,7 +1380,6 @@ test_expect_success 'last one wins: two level vars' '
'
test_expect_success 'last one wins: three level vars' '
-
# v.a.r and v.A.r are not the same variable, as the middle
# level of a three-level configuration variable name is
# case sensitive.
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index b7415ec9d5..db7f5444da 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -2294,6 +2294,59 @@ do
)
'
+ test_expect_success CASE_INSENSITIVE_FS,REFFILES "stdin $type batch-updates existing reference" '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit one &&
+ old_head=$(git rev-parse HEAD) &&
+ test_commit two &&
+ head=$(git rev-parse HEAD) &&
+
+ {
+ format_command $type "create refs/heads/foo" "$head" &&
+ format_command $type "create refs/heads/ref" "$old_head" &&
+ format_command $type "create refs/heads/Foo" "$old_head"
+ } >stdin &&
+ git update-ref $type --stdin --batch-updates <stdin >stdout &&
+
+ echo $head >expect &&
+ git rev-parse refs/heads/foo >actual &&
+ echo $old_head >expect &&
+ git rev-parse refs/heads/ref >actual &&
+ test_cmp expect actual &&
+ test_grep -q "reference conflict due to case-insensitive filesystem" stdout
+ )
+ '
+
+ test_expect_success CASE_INSENSITIVE_FS "stdin $type batch-updates existing reference" '
+ git init --ref-format=reftable repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit one &&
+ old_head=$(git rev-parse HEAD) &&
+ test_commit two &&
+ head=$(git rev-parse HEAD) &&
+
+ {
+ format_command $type "create refs/heads/foo" "$head" &&
+ format_command $type "create refs/heads/ref" "$old_head" &&
+ format_command $type "create refs/heads/Foo" "$old_head"
+ } >stdin &&
+ git update-ref $type --stdin --batch-updates <stdin >stdout &&
+
+ echo $head >expect &&
+ git rev-parse refs/heads/foo >actual &&
+ echo $old_head >expect &&
+ git rev-parse refs/heads/ref >actual &&
+ test_cmp expect actual &&
+ git rev-parse refs/heads/Foo >actual &&
+ test_cmp expect actual
+ )
+ '
+
test_expect_success "stdin $type batch-updates delete incorrect symbolic ref" '
git init repo &&
test_when_finished "rm -fr repo" &&
diff --git a/t/t1421-reflog-write.sh b/t/t1421-reflog-write.sh
index 46df64c176..603ec3f6ed 100755
--- a/t/t1421-reflog-write.sh
+++ b/t/t1421-reflog-write.sh
@@ -108,6 +108,42 @@ test_expect_success 'simple writes' '
)
'
+test_expect_success 'uses user.name and user.email config' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ COMMIT_OID=$(git rev-parse HEAD) &&
+
+ sane_unset GIT_COMMITTER_NAME &&
+ sane_unset GIT_COMMITTER_EMAIL &&
+ git config --local user.name "Author" &&
+ git config --local user.email "a@uth.or" &&
+ git reflog write refs/heads/something $ZERO_OID $COMMIT_OID first &&
+ test_reflog_matches . refs/heads/something <<-EOF
+ $ZERO_OID $COMMIT_OID Author <a@uth.or> $GIT_COMMITTER_DATE first
+ EOF
+ )
+'
+
+test_expect_success 'environment variables take precedence over config' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ COMMIT_OID=$(git rev-parse HEAD) &&
+
+ git config --local user.name "Author" &&
+ git config --local user.email "a@uth.or" &&
+ git reflog write refs/heads/something $ZERO_OID $COMMIT_OID first &&
+ test_reflog_matches . refs/heads/something <<-EOF
+ $ZERO_OID $COMMIT_OID $SIGNATURE first
+ EOF
+ )
+'
+
test_expect_success 'can write to root ref' '
test_when_finished "rm -rf repo" &&
git init repo &&
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 5ae86c42be..c4b651c2dc 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -454,6 +454,60 @@ test_expect_success 'tag with NUL in header' '
test_grep "error in tag $tag.*unterminated header: NUL at offset" out
'
+test_expect_success 'tag accepts gpgsig header even if not validly signed' '
+ test_oid_cache <<-\EOF &&
+ header sha1:gpgsig-sha256
+ header sha256:gpgsig
+ EOF
+ header=$(test_oid header) &&
+ sha=$(git rev-parse HEAD) &&
+ cat >good-tag <<-EOF &&
+ object $sha
+ type commit
+ tag good
+ tagger T A Gger <tagger@example.com> 1234567890 -0000
+ $header -----BEGIN PGP SIGNATURE-----
+ Not a valid signature
+ -----END PGP SIGNATURE-----
+
+ This is a good tag.
+ EOF
+
+ tag=$(git hash-object --literally -t tag -w --stdin <good-tag) &&
+ test_when_finished "remove_object $tag" &&
+ git update-ref refs/tags/good $tag &&
+ test_when_finished "git update-ref -d refs/tags/good" &&
+ git -c fsck.extraHeaderEntry=error fsck --tags
+'
+
+test_expect_success 'tag rejects invalid headers' '
+ test_oid_cache <<-\EOF &&
+ header sha1:gpgsig-sha256
+ header sha256:gpgsig
+ EOF
+ header=$(test_oid header) &&
+ sha=$(git rev-parse HEAD) &&
+ cat >bad-tag <<-EOF &&
+ object $sha
+ type commit
+ tag good
+ tagger T A Gger <tagger@example.com> 1234567890 -0000
+ $header -----BEGIN PGP SIGNATURE-----
+ Not a valid signature
+ -----END PGP SIGNATURE-----
+ junk
+
+ This is a bad tag with junk at the end of the headers.
+ EOF
+
+ tag=$(git hash-object --literally -t tag -w --stdin <bad-tag) &&
+ test_when_finished "remove_object $tag" &&
+ git update-ref refs/tags/bad $tag &&
+ test_when_finished "git update-ref -d refs/tags/bad" &&
+ test_must_fail git -c fsck.extraHeaderEntry=error fsck --tags 2>out &&
+ test_grep "error in tag $tag.*invalid format - extra header" out
+'
+
test_expect_success 'cleaned up' '
git fsck >actual 2>&1 &&
test_must_be_empty actual
diff --git a/t/t1463-refs-optimize.sh b/t/t1463-refs-optimize.sh
new file mode 100755
index 0000000000..c11c905d79
--- /dev/null
+++ b/t/t1463-refs-optimize.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+test_description='git refs optimize should not change the branch semantic
+
+This test runs git refs optimize and git show-ref and checks that the branch
+semantic is still the same.
+'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_DEFAULT_REF_FORMAT=files
+export GIT_TEST_DEFAULT_REF_FORMAT
+
+. ./test-lib.sh
+
+pack_refs='refs optimize'
+. "$TEST_DIRECTORY"/pack-refs-tests.sh
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 58a4583088..7739ab611b 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -207,6 +207,40 @@ test_expect_success 'rev-parse --show-object-format in repo' '
grep "unknown mode for --show-object-format: squeamish-ossifrage" err
'
+
+test_expect_success 'rev-parse --show-object-format in repo with compat mode' '
+ mkdir repo &&
+ (
+ sane_unset GIT_DEFAULT_HASH &&
+ cd repo &&
+ git init --object-format=sha256 &&
+ git config extensions.compatobjectformat sha1 &&
+ echo sha256 >expect &&
+ git rev-parse --show-object-format >actual &&
+ test_cmp expect actual &&
+ git rev-parse --show-object-format=storage >actual &&
+ test_cmp expect actual &&
+ git rev-parse --show-object-format=input >actual &&
+ test_cmp expect actual &&
+ git rev-parse --show-object-format=output >actual &&
+ test_cmp expect actual &&
+ echo sha1 >expect &&
+ git rev-parse --show-object-format=compat >actual &&
+ test_cmp expect actual &&
+ test_must_fail git rev-parse --show-object-format=squeamish-ossifrage 2>err &&
+ grep "unknown mode for --show-object-format: squeamish-ossifrage" err
+ ) &&
+ mkdir repo2 &&
+ (
+ sane_unset GIT_DEFAULT_HASH &&
+ cd repo2 &&
+ git init --object-format=sha256 &&
+ echo >expect &&
+ git rev-parse --show-object-format=compat >actual &&
+ test_cmp expect actual
+ )
+'
+
test_expect_success 'rev-parse --show-ref-format' '
test_detect_ref_format >expect &&
git rev-parse --show-ref-format >actual &&
diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
index fe671d4197..f8f28c76ee 100755
--- a/t/t2401-worktree-prune.sh
+++ b/t/t2401-worktree-prune.sh
@@ -24,8 +24,8 @@ test_expect_success 'prune files inside $GIT_DIR/worktrees' '
Removing worktrees/abc: not a valid directory
EOF
test_cmp expect actual &&
- ! test -f .git/worktrees/abc &&
- ! test -d .git/worktrees
+ test_path_is_missing .git/worktrees/abc &&
+ test_path_is_missing .git/worktrees
'
test_expect_success 'prune directories without gitdir' '
@@ -36,8 +36,8 @@ Removing worktrees/def: gitdir file does not exist
EOF
git worktree prune --verbose 2>actual &&
test_cmp expect actual &&
- ! test -d .git/worktrees/def &&
- ! test -d .git/worktrees
+ test_path_is_missing .git/worktrees/def &&
+ test_path_is_missing .git/worktrees
'
test_expect_success SANITY 'prune directories with unreadable gitdir' '
@@ -47,8 +47,8 @@ test_expect_success SANITY 'prune directories with unreadable gitdir' '
chmod u-r .git/worktrees/def/gitdir &&
git worktree prune --verbose 2>actual &&
test_grep "Removing worktrees/def: unable to read gitdir file" actual &&
- ! test -d .git/worktrees/def &&
- ! test -d .git/worktrees
+ test_path_is_missing .git/worktrees/def &&
+ test_path_is_missing .git/worktrees
'
test_expect_success 'prune directories with invalid gitdir' '
@@ -57,8 +57,8 @@ test_expect_success 'prune directories with invalid gitdir' '
: >.git/worktrees/def/gitdir &&
git worktree prune --verbose 2>actual &&
test_grep "Removing worktrees/def: invalid gitdir file" actual &&
- ! test -d .git/worktrees/def &&
- ! test -d .git/worktrees
+ test_path_is_missing .git/worktrees/def &&
+ test_path_is_missing .git/worktrees
'
test_expect_success 'prune directories with gitdir pointing to nowhere' '
@@ -67,8 +67,8 @@ test_expect_success 'prune directories with gitdir pointing to nowhere' '
echo "$(pwd)"/nowhere >.git/worktrees/def/gitdir &&
git worktree prune --verbose 2>actual &&
test_grep "Removing worktrees/def: gitdir file points to non-existent location" actual &&
- ! test -d .git/worktrees/def &&
- ! test -d .git/worktrees
+ test_path_is_missing .git/worktrees/def &&
+ test_path_is_missing .git/worktrees
'
test_expect_success 'not prune locked checkout' '
@@ -76,23 +76,23 @@ test_expect_success 'not prune locked checkout' '
mkdir -p .git/worktrees/ghi &&
: >.git/worktrees/ghi/locked &&
git worktree prune &&
- test -d .git/worktrees/ghi
+ test_path_is_dir .git/worktrees/ghi
'
test_expect_success 'not prune recent checkouts' '
test_when_finished rm -r .git/worktrees &&
git worktree add jlm HEAD &&
- test -d .git/worktrees/jlm &&
+ test_path_is_dir .git/worktrees/jlm &&
rm -rf jlm &&
git worktree prune --verbose --expire=2.days.ago &&
- test -d .git/worktrees/jlm
+ test_path_is_dir .git/worktrees/jlm
'
test_expect_success 'not prune proper checkouts' '
test_when_finished rm -r .git/worktrees &&
git worktree add --detach "$PWD/nop" main &&
git worktree prune &&
- test -d .git/worktrees/nop
+ test_path_is_dir .git/worktrees/nop
'
test_expect_success 'prune duplicate (linked/linked)' '
@@ -103,8 +103,8 @@ test_expect_success 'prune duplicate (linked/linked)' '
mv .git/worktrees/w2/gitdir.new .git/worktrees/w2/gitdir &&
git worktree prune --verbose 2>actual &&
test_grep "duplicate entry" actual &&
- test -d .git/worktrees/w1 &&
- ! test -d .git/worktrees/w2
+ test_path_is_dir .git/worktrees/w1 &&
+ test_path_is_missing .git/worktrees/w2
'
test_expect_success 'prune duplicate (main/linked)' '
@@ -116,7 +116,7 @@ test_expect_success 'prune duplicate (main/linked)' '
mv repo wt &&
git -C wt worktree prune --verbose 2>actual &&
test_grep "duplicate entry" actual &&
- ! test -d .git/worktrees/wt
+ test_path_is_missing .git/worktrees/wt
'
test_expect_success 'not prune proper worktrees inside linked worktree with relative paths' '
diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh
index e091df6d01..1e812df806 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -707,7 +707,7 @@ test_expect_success 'format-patch --range-diff does not compare notes by default
! grep "note" 0000-*
'
-test_expect_success 'format-patch --notes=custom --range-diff only compares custom notes' '
+test_expect_success 'format-patch --notes=custom --range-diff --cover-letter only compares custom notes' '
test_when_finished "git notes remove topic unmodified || :" &&
git notes add -m "topic note" topic &&
git notes add -m "unmodified note" unmodified &&
@@ -721,6 +721,20 @@ test_expect_success 'format-patch --notes=custom --range-diff only compares cust
! grep "## Notes ##" 0000-*
'
+# --range-diff on a single commit requires --no-cover-letter
+test_expect_success 'format-patch --notes=custom --range-diff on single commit only compares custom notes' '
+ test_when_finished "git notes remove HEAD unmodified || :" &&
+ git notes add -m "topic note" HEAD &&
+ test_when_finished "git notes --ref=custom remove HEAD unmodified || :" &&
+ git notes add -m "unmodified note" unmodified &&
+ git notes --ref=custom add -m "topic note (custom)" HEAD &&
+ git notes --ref=custom add -m "unmodified note (custom)" unmodified &&
+ git format-patch --notes=custom --range-diff=$prev \
+ -1 --stdout >actual &&
+ test_grep "## Notes (custom) ##" actual &&
+ test_grep ! "## Notes ##" actual
+'
+
test_expect_success 'format-patch --range-diff with --no-notes' '
test_when_finished "git notes remove topic unmodified || :" &&
git notes add -m "topic note" topic &&
diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
index 5d093e3a7a..5033411a43 100755
--- a/t/t3415-rebase-autosquash.sh
+++ b/t/t3415-rebase-autosquash.sh
@@ -486,12 +486,28 @@ test_expect_success 'fixup a fixup' '
test XZWY = $(git show | tr -cd W-Z)
'
-test_expect_success 'fixup does not clean up commit message' '
- oneline="#818" &&
- git commit --allow-empty -m "$oneline" &&
- git commit --fixup HEAD --allow-empty &&
- git -c commit.cleanup=strip rebase -ki --autosquash HEAD~2 &&
- test "$oneline" = "$(git show -s --format=%s)"
+test_expect_success 'pick and fixup respect commit.cleanup' '
+ git reset --hard base &&
+ test_commit --no-tag "fixup! second commit" file1 fixup &&
+ test_commit something &&
+ write_script .git/hooks/prepare-commit-msg <<-\EOF &&
+ printf "\n# Prepared\n" >> "$1"
+ EOF
+ git rebase -i --autosquash HEAD~3 &&
+ test_commit_message HEAD~1 <<-\EOF &&
+ second commit
+
+ # Prepared
+ EOF
+ test_commit_message HEAD <<-\EOF &&
+ something
+
+ # Prepared
+ EOF
+ git reset --hard something &&
+ git -c commit.cleanup=strip rebase -i --autosquash HEAD~3 &&
+ test_commit_message HEAD~1 -m "second commit" &&
+ test_commit_message HEAD -m "something"
'
test_done
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index d9fe289a7a..4285314f35 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -48,8 +48,8 @@ test_expect_success 'unknown command' '
git add -N command &&
git diff command >expect &&
cat >>expect <<-EOF &&
- (1/1) Stage addition [y,n,q,a,d,e,p,?]? Unknown command ${SQ}W${SQ} (use ${SQ}?${SQ} for help)
- (1/1) Stage addition [y,n,q,a,d,e,p,?]?$SP
+ (1/1) Stage addition [y,n,q,a,d,e,p,P,?]? Unknown command ${SQ}W${SQ} (use ${SQ}?${SQ} for help)
+ (1/1) Stage addition [y,n,q,a,d,e,p,P,?]?$SP
EOF
git add -p -- command <command >actual 2>&1 &&
test_cmp expect actual
@@ -332,9 +332,9 @@ test_expect_success 'different prompts for mode change/deleted' '
git -c core.filemode=true add -p >actual &&
sed -n "s/^\(([0-9/]*) Stage .*?\).*/\1/p" actual >actual.filtered &&
cat >expect <<-\EOF &&
- (1/1) Stage deletion [y,n,q,a,d,p,?]?
- (1/2) Stage mode change [y,n,q,a,d,j,J,g,/,p,?]?
- (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]?
+ (1/1) Stage deletion [y,n,q,a,d,p,P,?]?
+ (1/2) Stage mode change [y,n,q,a,d,k,K,j,J,g,/,p,P,?]?
+ (2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,P,?]?
EOF
test_cmp expect actual.filtered
'
@@ -521,13 +521,13 @@ test_expect_success 'split hunk setup' '
test_expect_success 'goto hunk 1 with "g 1"' '
test_when_finished "git reset" &&
tr _ " " >expect <<-EOF &&
- (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? + 1: -1,2 +1,3 +15
+ (2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,P,?]? + 1: -1,2 +1,3 +15
_ 2: -2,4 +3,8 +21
go to which hunk? @@ -1,2 +1,3 @@
_10
+15
_20
- (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+ (1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?_
EOF
test_write_lines s y g 1 | git add -p >actual &&
tail -n 7 <actual >actual.trimmed &&
@@ -540,7 +540,7 @@ test_expect_success 'goto hunk 1 with "g1"' '
_10
+15
_20
- (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+ (1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?_
EOF
test_write_lines s y g1 | git add -p >actual &&
tail -n 4 <actual >actual.trimmed &&
@@ -550,11 +550,11 @@ test_expect_success 'goto hunk 1 with "g1"' '
test_expect_success 'navigate to hunk via regex /pattern' '
test_when_finished "git reset" &&
tr _ " " >expect <<-EOF &&
- (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? @@ -1,2 +1,3 @@
+ (2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,P,?]? @@ -1,2 +1,3 @@
_10
+15
_20
- (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+ (1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?_
EOF
test_write_lines s y /1,2 | git add -p >actual &&
tail -n 5 <actual >actual.trimmed &&
@@ -567,7 +567,7 @@ test_expect_success 'navigate to hunk via regex / pattern' '
_10
+15
_20
- (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+ (1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?_
EOF
test_write_lines s y / 1,2 | git add -p >actual &&
tail -n 4 <actual >actual.trimmed &&
@@ -579,11 +579,11 @@ test_expect_success 'print again the hunk' '
tr _ " " >expect <<-EOF &&
+15
20
- (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? @@ -1,2 +1,3 @@
+ (1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? @@ -1,2 +1,3 @@
10
+15
20
- (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+ (1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?_
EOF
test_write_lines s y g 1 p | git add -p >actual &&
tail -n 7 <actual >actual.trimmed &&
@@ -595,11 +595,11 @@ test_expect_success TTY 'print again the hunk (PAGER)' '
cat >expect <<-EOF &&
<GREEN>+<RESET><GREEN>15<RESET>
20<RESET>
- <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>PAGER <CYAN>@@ -1,2 +1,3 @@<RESET>
+ <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? <RESET>PAGER <CYAN>@@ -1,2 +1,3 @@<RESET>
PAGER 10<RESET>
PAGER <GREEN>+<RESET><GREEN>15<RESET>
PAGER 20<RESET>
- <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>
+ <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? <RESET>
EOF
test_write_lines s y g 1 P |
(
@@ -796,21 +796,21 @@ test_expect_success 'colors can be overridden' '
<BLUE>+<RESET><BLUE>new<RESET>
<CYAN> more-context<RESET>
<BLUE>+<RESET><BLUE>another-one<RESET>
- <YELLOW>(1/1) Stage this hunk [y,n,q,a,d,s,e,p,?]? <RESET><BOLD>Split into 2 hunks.<RESET>
+ <YELLOW>(1/1) Stage this hunk [y,n,q,a,d,s,e,p,P,?]? <RESET><BOLD>Split into 2 hunks.<RESET>
<MAGENTA>@@ -1,3 +1,3 @@<RESET>
<CYAN> context<RESET>
<BOLD>-old<RESET>
<BLUE>+<RESET><BLUE>new<RESET>
<CYAN> more-context<RESET>
- <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET><MAGENTA>@@ -3 +3,2 @@<RESET>
+ <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? <RESET><MAGENTA>@@ -3 +3,2 @@<RESET>
<CYAN> more-context<RESET>
<BLUE>+<RESET><BLUE>another-one<RESET>
- <YELLOW>(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? <RESET><MAGENTA>@@ -1,3 +1,3 @@<RESET>
+ <YELLOW>(2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,P,?]? <RESET><MAGENTA>@@ -1,3 +1,3 @@<RESET>
<CYAN> context<RESET>
<BOLD>-old<RESET>
<BLUE>+new<RESET>
<CYAN> more-context<RESET>
- <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>
+ <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? <RESET>
EOF
test_cmp expect actual
'
@@ -1354,4 +1354,92 @@ do
'
done
+test_expect_success 'splitting previous hunk marks split hunks as undecided' '
+ test_write_lines a " " b c d e f g h i j k >file &&
+ git add file &&
+ test_write_lines x " " b y d e f g h i j x >file &&
+ test_write_lines n K s n y q | git add -p file &&
+ git cat-file blob :file >actual &&
+ test_write_lines a " " b y d e f g h i j k >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'splitting edited hunk' '
+ # Before the first hunk is edited it can be split into two
+ # hunks, after editing it can be split into three hunks.
+
+ write_script fake-editor.sh <<-\EOF &&
+ sed "s/^ c/-c/" "$1" >"$1.tmp" &&
+ mv "$1.tmp" "$1"
+ EOF
+
+ test_write_lines a b c d e f g h i j k l m n >file &&
+ git add file &&
+ test_write_lines A b c d E f g h i j k l M n >file &&
+ (
+ test_set_editor "$(pwd)/fake-editor.sh" &&
+ test_write_lines e K s j y n y q | git add -p file
+ ) &&
+ git cat-file blob :file >actual &&
+ test_write_lines a b d e f g h i j k l M n >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'options J, K roll over' '
+ test_write_lines a b c d e f g h i >file &&
+ git add file &&
+ test_write_lines X b c d e f g h X >file &&
+ test_write_lines J J K q | git add -p >out &&
+ test_write_lines 1 2 1 2 >expect &&
+ sed -n -e "s-/.*--" -e "s/^(//p" <out >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'options y, n, a, d, j, k, e roll over to next undecided (1)' '
+ test_write_lines a b c d e f g h i j k l m n o p q >file &&
+ git add file &&
+ test_write_lines X b c d e f g h X j k l m n o p X >file &&
+ test_set_editor : &&
+ test_write_lines g3 y g3 n g3 a g3 d g3 j g3 e k q | git add -p >out &&
+ test_write_lines 1 3 1 3 1 3 1 3 1 3 1 3 1 2 >expect &&
+ sed -n -e "s-/.*--" -e "s/^(//p" <out >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'options y, n, a, d, j, k, e roll over to next undecided (2)' '
+ test_write_lines a b c d e f g h i j k l m n o p q >file &&
+ git add file &&
+ test_write_lines X b c d e f g h X j k l m n o p X >file &&
+ test_set_editor : &&
+ test_write_lines y g3 y g3 n g3 a g3 d g3 j g3 e g1 k q | git add -p >out &&
+ test_write_lines 1 2 3 2 3 2 3 2 3 2 3 2 3 2 1 2 >expect &&
+ sed -n -e "s-/.*--" -e "s/^(//p" <out >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'invalid option s is rejected' '
+ test_write_lines a b c d e f g h i j k >file &&
+ git add file &&
+ test_write_lines X b X d e f g h i j X >file &&
+ test_write_lines j s q | git add -p >out &&
+ sed -ne "s/ @@.*//" -e "s/ \$//" -e "/^(/p" <out >actual &&
+ cat >expect <<-EOF &&
+ (1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,s,e,p,P,?]?
+ (2/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? Sorry, cannot split this hunk
+ (2/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]?
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'EOF quits' '
+ echo a >file &&
+ echo a >file2 &&
+ git add file file2 &&
+ echo X >file &&
+ echo X >file2 &&
+ git add -p </dev/null >out &&
+ test_grep file out &&
+ test_grep ! file2 out
+'
+
test_done
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 0bb4648e36..70879941c2 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -902,6 +902,7 @@ test_expect_success 'branch: should not drop the stash if the apply fails' '
test_expect_success 'apply: show same status as git status (relative to ./)' '
git stash clear &&
+ mkdir -p subdir &&
echo 1 >subdir/subfile1 &&
echo 2 >subdir/subfile2 &&
git add subdir/subfile1 &&
@@ -1356,6 +1357,7 @@ test_expect_success 'stash -k -- <pathspec> leaves unstaged files intact' '
test_expect_success 'stash -- <subdir> leaves untracked files in subdir intact' '
git reset &&
+ mkdir -p subdir &&
>subdir/untracked &&
>subdir/tracked1 &&
>subdir/tracked2 &&
@@ -1372,6 +1374,7 @@ test_expect_success 'stash -- <subdir> leaves untracked files in subdir intact'
test_expect_success 'stash -- <subdir> works with binary files' '
git reset &&
+ mkdir -p subdir &&
>subdir/untracked &&
>subdir/tracked &&
cp "$TEST_DIRECTORY"/test-binary-1.png subdir/tracked-binary &&
@@ -1741,4 +1744,50 @@ test_expect_success 'submodules does not affect the branch recorded in stash mes
)
'
+test_expect_success SANITIZE_LEAK 'stash show handles -- without leaking' '
+ git stash show --
+'
+
+test_expect_success 'controlled error return on unrecognized option' '
+ test_expect_code 129 git stash show -p --invalid 2>usage &&
+ grep -e "^usage: git stash show" usage
+'
+
+test_expect_success 'stash.index=true implies --index' '
+ # setup for a few related tests
+ test_commit file base &&
+ echo index >file &&
+ git add file &&
+ echo working >file &&
+ git stash &&
+
+ test_when_finished "git reset --hard" &&
+ git -c stash.index=true stash apply &&
+ echo index >expect &&
+ git show :0:file >actual &&
+ test_cmp expect actual &&
+ echo working >expect &&
+ test_cmp expect file
+'
+
+test_expect_success 'stash.index=true overridden by --no-index' '
+ test_when_finished "git reset --hard" &&
+ git -c stash.index=true stash apply --no-index &&
+ echo base >expect &&
+ git show :0:file >actual &&
+ test_cmp expect actual &&
+ echo working >expect &&
+ test_cmp expect file
+'
+
+test_expect_success 'stash.index=false overridden by --index' '
+ test_when_finished "git reset --hard" &&
+ git -c stash.index=false stash apply --index &&
+ echo index >expect &&
+ git show :0:file >actual &&
+ test_cmp expect actual &&
+ echo working >expect &&
+ test_cmp expect file
+'
+
test_done
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
index 1289ae3e07..7704709054 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -87,7 +87,6 @@ test_expect_success 'stash save --patch --all fails' '
test_expect_success 'clean up untracked/untracked file to prepare for next tests' '
git clean --force --quiet
-
'
test_expect_success 'stash pop after save --include-untracked leaves files untracked again' '
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index cfeec239e0..d35695f5b0 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -5,7 +5,7 @@
test_description='Various diff formatting options'
-GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
@@ -70,7 +70,7 @@ test_expect_success setup '
GIT_COMMITTER_DATE="2006-06-26 00:04:00 +0000" &&
export GIT_AUTHOR_DATE GIT_COMMITTER_DATE &&
- git checkout master &&
+ git checkout main &&
git pull -s ours --no-rebase . side &&
GIT_AUTHOR_DATE="2006-06-26 00:05:00 +0000" &&
@@ -95,7 +95,7 @@ test_expect_success setup '
test_write_lines B A >dir/sub &&
git add dir/sub &&
git commit -m "Rearranged lines in dir/sub" &&
- git checkout master &&
+ git checkout main &&
GIT_AUTHOR_DATE="2006-06-26 00:06:00 +0000" &&
GIT_COMMITTER_DATE="2006-06-26 00:06:00 +0000" &&
@@ -103,7 +103,7 @@ test_expect_success setup '
git checkout -b mode initial &&
git update-index --chmod=+x file0 &&
git commit -m "update mode" &&
- git checkout -f master &&
+ git checkout -f main &&
GIT_AUTHOR_DATE="2006-06-26 00:06:00 +0000" &&
GIT_COMMITTER_DATE="2006-06-26 00:06:00 +0000" &&
@@ -112,12 +112,12 @@ test_expect_success setup '
git update-index --chmod=+x file2 &&
git commit -m "update mode (file2)" &&
git notes add -m "note" &&
- git checkout -f master &&
+ git checkout -f main &&
- # Same merge as master, but with parents reversed. Hide it in a
+ # Same merge as main, but with parents reversed. Hide it in a
# pseudo-ref to avoid impacting tests with --all.
commit=$(echo reverse |
- git commit-tree -p master^2 -p master^1 master^{tree}) &&
+ git commit-tree -p main^2 -p main^1 main^{tree}) &&
git update-ref REVERSE $commit &&
git config diff.renames false &&
@@ -127,15 +127,15 @@ test_expect_success setup '
: <<\EOF
! [initial] Initial
- * [master] Merge branch 'side'
+ * [main] Merge branch 'side'
! [rearrange] Rearranged lines in dir/sub
! [side] Side
----
+ [rearrange] Rearranged lines in dir/sub
- - [master] Merge branch 'side'
+ - [main] Merge branch 'side'
* + [side] Side
- * [master^] Third
- * [master~2] Second
+ * [main^] Third
+ * [main~2] Second
+*++ [initial] Initial
EOF
@@ -311,64 +311,64 @@ diff-tree initial mode
diff-tree --stat initial mode
diff-tree --summary initial mode
-diff-tree master
-diff-tree -m master
-diff-tree -p master
-diff-tree -p -m master
-diff-tree -c master
-diff-tree -c --abbrev master
-:noellipses diff-tree -c --abbrev master
-diff-tree --cc master
+diff-tree main
+diff-tree -m main
+diff-tree -p main
+diff-tree -p -m main
+diff-tree -c main
+diff-tree -c --abbrev main
+:noellipses diff-tree -c --abbrev main
+diff-tree --cc main
# stat only should show the diffstat with the first parent
-diff-tree -c --stat master
-diff-tree --cc --stat master
-diff-tree -c --stat --summary master
-diff-tree --cc --stat --summary master
+diff-tree -c --stat main
+diff-tree --cc --stat main
+diff-tree -c --stat --summary main
+diff-tree --cc --stat --summary main
# stat summary should show the diffstat and summary with the first parent
diff-tree -c --stat --summary side
diff-tree --cc --stat --summary side
-diff-tree --cc --shortstat master
+diff-tree --cc --shortstat main
diff-tree --cc --summary REVERSE
# improved by Timo's patch
-diff-tree --cc --patch-with-stat master
+diff-tree --cc --patch-with-stat main
# improved by Timo's patch
-diff-tree --cc --patch-with-stat --summary master
+diff-tree --cc --patch-with-stat --summary main
# this is correct
diff-tree --cc --patch-with-stat --summary side
-log master
-log -p master
-log --root master
-log --root -p master
-log --patch-with-stat master
-log --root --patch-with-stat master
-log --root --patch-with-stat --summary master
+log main
+log -p main
+log --root main
+log --root -p main
+log --patch-with-stat main
+log --root --patch-with-stat main
+log --root --patch-with-stat --summary main
# improved by Timo's patch
-log --root -c --patch-with-stat --summary master
+log --root -c --patch-with-stat --summary main
# improved by Timo's patch
-log --root --cc --patch-with-stat --summary master
-log --no-diff-merges -p --first-parent master
-log --diff-merges=off -p --first-parent master
-log --first-parent --diff-merges=off -p master
-log -p --first-parent master
-log -p --diff-merges=first-parent master
-log --diff-merges=first-parent master
-log -m -p --first-parent master
-log -m -p master
-log --cc -m -p master
-log -c -m -p master
-log -m --raw master
-log -m --stat master
-log -SF master
-log -S F master
-log -SF -p master
-log -SF master --max-count=0
-log -SF master --max-count=1
-log -SF master --max-count=2
-log -GF master
-log -GF -p master
-log -GF -p --pickaxe-all master
-log -IA -IB -I1 -I2 -p master
+log --root --cc --patch-with-stat --summary main
+log --no-diff-merges -p --first-parent main
+log --diff-merges=off -p --first-parent main
+log --first-parent --diff-merges=off -p main
+log -p --first-parent main
+log -p --diff-merges=first-parent main
+log --diff-merges=first-parent main
+log -m -p --first-parent main
+log -m -p main
+log --cc -m -p main
+log -c -m -p main
+log -m --raw main
+log -m --stat main
+log -SF main
+log -S F main
+log -SF -p main
+log -SF main --max-count=0
+log -SF main --max-count=1
+log -SF main --max-count=2
+log -GF main
+log -GF -p main
+log -GF -p --pickaxe-all main
+log -IA -IB -I1 -I2 -p main
log --decorate --all
log --decorate=full --all
log --decorate --clear-decorations --all
@@ -377,35 +377,35 @@ log --decorate=full --clear-decorations --all
rev-list --parents HEAD
rev-list --children HEAD
-whatchanged master
-:noellipses whatchanged master
-whatchanged -p master
-whatchanged --root master
-:noellipses whatchanged --root master
-whatchanged --root -p master
-whatchanged --patch-with-stat master
-whatchanged --root --patch-with-stat master
-whatchanged --root --patch-with-stat --summary master
+whatchanged main
+:noellipses whatchanged main
+whatchanged -p main
+whatchanged --root main
+:noellipses whatchanged --root main
+whatchanged --root -p main
+whatchanged --patch-with-stat main
+whatchanged --root --patch-with-stat main
+whatchanged --root --patch-with-stat --summary main
# improved by Timo's patch
-whatchanged --root -c --patch-with-stat --summary master
+whatchanged --root -c --patch-with-stat --summary main
# improved by Timo's patch
-whatchanged --root --cc --patch-with-stat --summary master
-whatchanged -SF master
-:noellipses whatchanged -SF master
-whatchanged -SF -p master
+whatchanged --root --cc --patch-with-stat --summary main
+whatchanged -SF main
+:noellipses whatchanged -SF main
+whatchanged -SF -p main
-log --patch-with-stat master -- dir/
-whatchanged --patch-with-stat master -- dir/
-log --patch-with-stat --summary master -- dir/
-whatchanged --patch-with-stat --summary master -- dir/
+log --patch-with-stat main -- dir/
+whatchanged --patch-with-stat main -- dir/
+log --patch-with-stat --summary main -- dir/
+whatchanged --patch-with-stat --summary main -- dir/
show initial
show --root initial
show side
-show master
-show -c master
-show -m master
-show --first-parent master
+show main
+show -c main
+show -m main
+show --first-parent main
show --stat side
show --stat --summary side
show --patch-with-stat side
@@ -414,22 +414,22 @@ show --patch-with-raw side
show --patch-with-stat --summary side
format-patch --stdout initial..side
-format-patch --stdout initial..master^
-format-patch --stdout initial..master
-format-patch --stdout --no-numbered initial..master
-format-patch --stdout --numbered initial..master
+format-patch --stdout initial..main^
+format-patch --stdout initial..main
+format-patch --stdout --no-numbered initial..main
+format-patch --stdout --numbered initial..main
format-patch --attach --stdout initial..side
format-patch --attach --stdout --suffix=.diff initial..side
-format-patch --attach --stdout initial..master^
-format-patch --attach --stdout initial..master
+format-patch --attach --stdout initial..main^
+format-patch --attach --stdout initial..main
format-patch --inline --stdout initial..side
-format-patch --inline --stdout initial..master^
-format-patch --inline --stdout --numbered-files initial..master
-format-patch --inline --stdout initial..master
-format-patch --inline --stdout --subject-prefix=TESTCASE initial..master
+format-patch --inline --stdout initial..main^
+format-patch --inline --stdout --numbered-files initial..main
+format-patch --inline --stdout initial..main
+format-patch --inline --stdout --subject-prefix=TESTCASE initial..main
config format.subjectprefix DIFFERENT_PREFIX
-format-patch --inline --stdout initial..master^^
-format-patch --stdout --cover-letter -n initial..master^
+format-patch --inline --stdout initial..main^^
+format-patch --stdout --cover-letter -n initial..main^
diff --abbrev initial..side
diff -U initial..side
@@ -448,13 +448,13 @@ diff --name-status dir2 dir
diff --no-index --name-status dir2 dir
diff --no-index --name-status -- dir2 dir
diff --no-index dir dir3
-diff master master^ side
+diff main main^ side
# Can't use spaces...
-diff --line-prefix=abc master master^ side
-diff --dirstat master~1 master~2
+diff --line-prefix=abc main main^ side
+diff --dirstat main~1 main~2
diff --dirstat initial rearrange
diff --dirstat-by-file initial rearrange
-diff --dirstat --cc master~1 master
+diff --dirstat --cc main~1 main
# No-index --abbrev and --no-abbrev
diff --raw initial
:noellipses diff --raw initial
@@ -482,7 +482,7 @@ test_expect_success !WITH_BREAKING_CHANGES 'whatchanged needs --i-still-use-this
'
test_expect_success 'log -m matches pure log' '
- git log master >result &&
+ git log main >result &&
process_diffs result >expected &&
git log -m >result &&
process_diffs result >actual &&
@@ -490,17 +490,17 @@ test_expect_success 'log -m matches pure log' '
'
test_expect_success 'log --diff-merges=on matches --diff-merges=separate' '
- git log -p --diff-merges=separate master >result &&
+ git log -p --diff-merges=separate main >result &&
process_diffs result >expected &&
- git log -p --diff-merges=on master >result &&
+ git log -p --diff-merges=on main >result &&
process_diffs result >actual &&
test_cmp expected actual
'
test_expect_success 'log --dd matches --diff-merges=1 -p' '
- git log --diff-merges=1 -p master >result &&
+ git log --diff-merges=1 -p main >result &&
process_diffs result >expected &&
- git log --dd master >result &&
+ git log --dd main >result &&
process_diffs result >actual &&
test_cmp expected actual
'
@@ -511,19 +511,19 @@ test_expect_success 'deny wrong log.diffMerges config' '
'
test_expect_success 'git config log.diffMerges first-parent' '
- git log -p --diff-merges=first-parent master >result &&
+ git log -p --diff-merges=first-parent main >result &&
process_diffs result >expected &&
test_config log.diffMerges first-parent &&
- git log -p --diff-merges=on master >result &&
+ git log -p --diff-merges=on main >result &&
process_diffs result >actual &&
test_cmp expected actual
'
test_expect_success 'git config log.diffMerges first-parent vs -m' '
- git log -p --diff-merges=first-parent master >result &&
+ git log -p --diff-merges=first-parent main >result &&
process_diffs result >expected &&
test_config log.diffMerges first-parent &&
- git log -p -m master >result &&
+ git log -p -m main >result &&
process_diffs result >actual &&
test_cmp expected actual
'
@@ -572,7 +572,7 @@ test_expect_success 'diff-tree --stdin with log formatting' '
Third
Second
EOF
- git rev-list master | git diff-tree --stdin --format=%s -s >actual &&
+ git rev-list main | git diff-tree --stdin --format=%s -s >actual &&
test_cmp expect actual
'
@@ -585,16 +585,16 @@ test_expect_success 'diff-tree --stdin with pathspec' '
dir/sub
EOF
- git rev-list master^ |
+ git rev-list main^ |
git diff-tree -r --stdin --name-only --format=%s dir >actual &&
test_cmp expect actual
'
test_expect_success 'show A B ... -- <pathspec>' '
# side touches dir/sub, file0, and file3
- # master^ touches dir/sub, and file1
- # master^^ touches dir/sub, file0, and file2
- git show --name-only --format="<%s>" side master^ master^^ -- dir >actual &&
+ # main^ touches dir/sub, and file1
+ # main^^ touches dir/sub, file0, and file2
+ git show --name-only --format="<%s>" side main^ main^^ -- dir >actual &&
cat >expect <<-\EOF &&
<Side>
@@ -610,7 +610,7 @@ test_expect_success 'show A B ... -- <pathspec>' '
'
test_expect_success 'diff -I<regex>: setup' '
- git checkout master &&
+ git checkout main &&
test_seq 50 >file0 &&
git commit -m "Set up -I<regex> test file" file0 &&
test_seq 50 | sed -e "s/13/ten and three/" -e "/7\$/d" >file0 &&
@@ -661,6 +661,43 @@ test_expect_success 'diff -I<regex>: ignore matching file' '
test_grep ! "file1" actual
'
+test_expect_success 'diff -I<regex>: ignore all content changes' '
+ test_when_finished "git rm -f file1 file2 file3" &&
+ : >file1 &&
+ git add file1 &&
+ : >file2 &&
+ git add file2 &&
+ : >file3 &&
+ git add file3 &&
+
+ rm -f file1 file2 &&
+ mkdir file2 &&
+ echo "A" >file3 &&
+ A_hash=$(git hash-object -w file3) &&
+ echo "B" >file3 &&
+ B_hash=$(git hash-object -w file3) &&
+ cat <<-EOF | git update-index --index-info &&
+ 100644 $A_hash 1 file3
+ 100644 $B_hash 2 file3
+ EOF
+
+ test_diff_no_content_changes () {
+ git diff $1 --ignore-blank-lines -I".*" >actual &&
+ test_line_count = 3 actual &&
+ test_grep "file1" actual &&
+ test_grep "file2" actual &&
+ test_grep "file3" actual &&
+ test_grep ! "diff --git" actual
+ } &&
+ test_diff_no_content_changes "--raw" &&
+ test_diff_no_content_changes "--name-only" &&
+ test_diff_no_content_changes "--name-status" &&
+
+ : >actual &&
+ test_must_fail git diff --quiet -I".*" >actual &&
+ test_must_be_empty actual
+'
+
# check_prefix <patch> <src> <dst>
# check only lines with paths to avoid dependency on exact oid/contents
check_prefix () {
diff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_main
index 9951e3677d..af1cf20f4c 100644
--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc --patch-with-stat --summary master
+$ git diff-tree --cc --patch-with-stat --summary main
59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_main
index db3c0a7b2c..0ec6042097 100644
--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master
+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc --patch-with-stat master
+$ git diff-tree --cc --patch-with-stat main
59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.diff-tree_--cc_--shortstat_master b/t/t4013/diff.diff-tree_--cc_--shortstat_main
index a4ca42df2a..9a4ef03197 100644
--- a/t/t4013/diff.diff-tree_--cc_--shortstat_master
+++ b/t/t4013/diff.diff-tree_--cc_--shortstat_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc --shortstat master
+$ git diff-tree --cc --shortstat main
59d314ad6f356dd08601a4cd5e530381da3e3c64
2 files changed, 5 insertions(+)
$
diff --git a/t/t4013/diff.diff-tree_-c_--stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--stat_--summary_main
index 81c3021541..9db08a4aa9 100644
--- a/t/t4013/diff.diff-tree_-c_--stat_--summary_master
+++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_main
@@ -1,4 +1,4 @@
-$ git diff-tree -c --stat --summary master
+$ git diff-tree --cc --stat --summary main
59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.diff-tree_-c_--stat_master b/t/t4013/diff.diff-tree_--cc_--stat_main
index 89d59b1548..7ecc67a524 100644
--- a/t/t4013/diff.diff-tree_-c_--stat_master
+++ b/t/t4013/diff.diff-tree_--cc_--stat_main
@@ -1,4 +1,4 @@
-$ git diff-tree -c --stat master
+$ git diff-tree --cc --stat main
59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.diff-tree_--cc_master b/t/t4013/diff.diff-tree_--cc_main
index 5ecb4e14ae..1a962856ad 100644
--- a/t/t4013/diff.diff-tree_--cc_master
+++ b/t/t4013/diff.diff-tree_--cc_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc master
+$ git diff-tree --cc main
59d314ad6f356dd08601a4cd5e530381da3e3c64
diff --cc dir/sub
index cead32e,7289e35..992913c
diff --git a/t/t4013/diff.diff-tree_-c_--abbrev_master b/t/t4013/diff.diff-tree_-c_--abbrev_main
index b8e4aa2530..039d127cf2 100644
--- a/t/t4013/diff.diff-tree_-c_--abbrev_master
+++ b/t/t4013/diff.diff-tree_-c_--abbrev_main
@@ -1,4 +1,4 @@
-$ git diff-tree -c --abbrev master
+$ git diff-tree -c --abbrev main
59d314ad6f356dd08601a4cd5e530381da3e3c64
::100644 100644 100644 cead32e... 7289e35... 992913c... MM dir/sub
::100644 100644 100644 b414108... f4615da... 10a8a9f... MM file0
diff --git a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master b/t/t4013/diff.diff-tree_-c_--stat_--summary_main
index d019867dd9..05a8d16ba7 100644
--- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master
+++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc --stat --summary master
+$ git diff-tree -c --stat --summary main
59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.diff-tree_--cc_--stat_master b/t/t4013/diff.diff-tree_-c_--stat_main
index 40b91796b3..61d9f450df 100644
--- a/t/t4013/diff.diff-tree_--cc_--stat_master
+++ b/t/t4013/diff.diff-tree_-c_--stat_main
@@ -1,4 +1,4 @@
-$ git diff-tree --cc --stat master
+$ git diff-tree -c --stat main
59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.diff-tree_-c_master b/t/t4013/diff.diff-tree_-c_main
index e2d2bb2611..a84e1185cf 100644
--- a/t/t4013/diff.diff-tree_-c_master
+++ b/t/t4013/diff.diff-tree_-c_main
@@ -1,4 +1,4 @@
-$ git diff-tree -c master
+$ git diff-tree -c main
59d314ad6f356dd08601a4cd5e530381da3e3c64
::100644 100644 100644 cead32e925b1420c84c14cbf7cf755e7e45af8ad 7289e35bff32727c08dda207511bec138fdb9ea5 992913c5aa0a5476d10c49ed0f21fc0c6d1aedf3 MM dir/sub
::100644 100644 100644 b414108e81e5091fe0974a1858b4d0d22b107f70 f4615da674c09df322d6ba8d6b21ecfb1b1ba510 10a8a9f3657f91a156b9f0184ed79a20adef9f7f MM file0
diff --git a/t/t4013/diff.diff-tree_-m_master b/t/t4013/diff.diff-tree_-m_main
index 6d0a2207fb..5da1f7f525 100644
--- a/t/t4013/diff.diff-tree_-m_master
+++ b/t/t4013/diff.diff-tree_-m_main
@@ -1,4 +1,4 @@
-$ git diff-tree -m master
+$ git diff-tree -m main
59d314ad6f356dd08601a4cd5e530381da3e3c64
:040000 040000 65f5c9dd60ce3b2b3324b618ac7accf8d912c113 0564e026437809817a64fff393079714b6dd4628 M dir
:100644 100644 b414108e81e5091fe0974a1858b4d0d22b107f70 10a8a9f3657f91a156b9f0184ed79a20adef9f7f M file0
diff --git a/t/t4013/diff.diff-tree_-p_-m_master b/t/t4013/diff.diff-tree_-p_-m_main
index b60bea039d..29c9fc20b8 100644
--- a/t/t4013/diff.diff-tree_-p_-m_master
+++ b/t/t4013/diff.diff-tree_-p_-m_main
@@ -1,4 +1,4 @@
-$ git diff-tree -p -m master
+$ git diff-tree -p -m main
59d314ad6f356dd08601a4cd5e530381da3e3c64
diff --git a/dir/sub b/dir/sub
index cead32e..992913c 100644
diff --git a/t/t4013/diff.diff-tree_-p_main b/t/t4013/diff.diff-tree_-p_main
new file mode 100644
index 0000000000..c658062422
--- /dev/null
+++ b/t/t4013/diff.diff-tree_-p_main
@@ -0,0 +1,2 @@
+$ git diff-tree -p main
+$
diff --git a/t/t4013/diff.diff-tree_-p_master b/t/t4013/diff.diff-tree_-p_master
deleted file mode 100644
index b182875fb2..0000000000
--- a/t/t4013/diff.diff-tree_-p_master
+++ /dev/null
@@ -1,2 +0,0 @@
-$ git diff-tree -p master
-$
diff --git a/t/t4013/diff.diff-tree_main b/t/t4013/diff.diff-tree_main
new file mode 100644
index 0000000000..dc5b9fdeb6
--- /dev/null
+++ b/t/t4013/diff.diff-tree_main
@@ -0,0 +1,2 @@
+$ git diff-tree main
+$
diff --git a/t/t4013/diff.diff-tree_master b/t/t4013/diff.diff-tree_master
deleted file mode 100644
index fe9226f8a1..0000000000
--- a/t/t4013/diff.diff-tree_master
+++ /dev/null
@@ -1,2 +0,0 @@
-$ git diff-tree master
-$
diff --git a/t/t4013/diff.diff_--dirstat_--cc_main~1_main b/t/t4013/diff.diff_--dirstat_--cc_main~1_main
new file mode 100644
index 0000000000..168a357a02
--- /dev/null
+++ b/t/t4013/diff.diff_--dirstat_--cc_main~1_main
@@ -0,0 +1,3 @@
+$ git diff --dirstat --cc main~1 main
+ 40.0% dir/
+$
diff --git a/t/t4013/diff.diff_--dirstat_--cc_master~1_master b/t/t4013/diff.diff_--dirstat_--cc_master~1_master
deleted file mode 100644
index fba4e34175..0000000000
--- a/t/t4013/diff.diff_--dirstat_--cc_master~1_master
+++ /dev/null
@@ -1,3 +0,0 @@
-$ git diff --dirstat --cc master~1 master
- 40.0% dir/
-$
diff --git a/t/t4013/diff.diff_--dirstat_main~1_main~2 b/t/t4013/diff.diff_--dirstat_main~1_main~2
new file mode 100644
index 0000000000..6809733708
--- /dev/null
+++ b/t/t4013/diff.diff_--dirstat_main~1_main~2
@@ -0,0 +1,3 @@
+$ git diff --dirstat main~1 main~2
+ 40.0% dir/
+$
diff --git a/t/t4013/diff.diff_--dirstat_master~1_master~2 b/t/t4013/diff.diff_--dirstat_master~1_master~2
deleted file mode 100644
index b672e1ca63..0000000000
--- a/t/t4013/diff.diff_--dirstat_master~1_master~2
+++ /dev/null
@@ -1,3 +0,0 @@
-$ git diff --dirstat master~1 master~2
- 40.0% dir/
-$
diff --git a/t/t4013/diff.diff_--line-prefix=abc_master_master^_side b/t/t4013/diff.diff_--line-prefix=abc_main_main^_side
index 99f91e7f0e..67a2145a36 100644
--- a/t/t4013/diff.diff_--line-prefix=abc_master_master^_side
+++ b/t/t4013/diff.diff_--line-prefix=abc_main_main^_side
@@ -1,4 +1,4 @@
-$ git diff --line-prefix=abc master master^ side
+$ git diff --line-prefix=abc main main^ side
abcdiff --cc dir/sub
abcindex cead32e,7289e35..992913c
abc--- a/dir/sub
diff --git a/t/t4013/diff.diff_master_master^_side b/t/t4013/diff.diff_main_main^_side
index 50ec9cadd6..ab81ec9e47 100644
--- a/t/t4013/diff.diff_master_master^_side
+++ b/t/t4013/diff.diff_main_main^_side
@@ -1,4 +1,4 @@
-$ git diff master master^ side
+$ git diff main main^ side
diff --cc dir/sub
index cead32e,7289e35..992913c
--- a/dir/sub
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..main
index 52fedc179e..9f56380350 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --attach --stdout initial..master
+$ git format-patch --attach --stdout initial..main
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..main^
index 1c3cde251b..80132ea99e 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..main^
@@ -1,4 +1,4 @@
-$ git format-patch --attach --stdout initial..master^
+$ git format-patch --attach --stdout initial..main^
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..main
index 02c4db7ec5..8e889090fb 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --inline --stdout --numbered-files initial..master
+$ git format-patch --inline --stdout --numbered-files initial..main
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..main
index c7677c5951..d7d2b12d15 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --inline --stdout --subject-prefix=TESTCASE initial..master
+$ git format-patch --inline --stdout --subject-prefix=TESTCASE initial..main
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..main
index 5b3e34e2c0..c49c423f82 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --inline --stdout initial..master
+$ git format-patch --inline --stdout initial..main
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..main^
index d13f8a8128..8669dbfe6c 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..main^
@@ -1,4 +1,4 @@
-$ git format-patch --inline --stdout initial..master^
+$ git format-patch --inline --stdout initial..main^
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..main^^
index caec5537de..b749be58b0 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..main^^
@@ -1,4 +1,4 @@
-$ git format-patch --inline --stdout initial..master^^
+$ git format-patch --inline --stdout initial..main^^
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..main^
index 244d964fc6..567f222198 100644
--- a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^
+++ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..main^
@@ -1,4 +1,4 @@
-$ git format-patch --stdout --cover-letter -n initial..master^
+$ git format-patch --stdout --cover-letter -n initial..main^
From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: C O Mitter <committer@example.com>
Date: Mon, 26 Jun 2006 00:06:00 +0000
diff --git a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..main
index bfc287a147..195b62ea4f 100644
--- a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master
+++ b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --stdout --no-numbered initial..master
+$ git format-patch --stdout --no-numbered initial..main
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--numbered_initial..main
index 568f6f584e..0678a38515 100644
--- a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master
+++ b/t/t4013/diff.format-patch_--stdout_--numbered_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --stdout --numbered initial..master
+$ git format-patch --stdout --numbered initial..main
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--stdout_initial..master b/t/t4013/diff.format-patch_--stdout_initial..main
index 5f0352f9f7..b4a6302e7c 100644
--- a/t/t4013/diff.format-patch_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--stdout_initial..main
@@ -1,4 +1,4 @@
-$ git format-patch --stdout initial..master
+$ git format-patch --stdout initial..main
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.format-patch_--stdout_initial..master^ b/t/t4013/diff.format-patch_--stdout_initial..main^
index 2ae454d807..36b3221582 100644
--- a/t/t4013/diff.format-patch_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--stdout_initial..main^
@@ -1,4 +1,4 @@
-$ git format-patch --stdout initial..master^
+$ git format-patch --stdout initial..main^
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
diff --git a/t/t4013/diff.log_-c_-m_-p_master b/t/t4013/diff.log_--cc_-m_-p_main
index b660f3d5f2..f32746ea3e 100644
--- a/t/t4013/diff.log_-c_-m_-p_master
+++ b/t/t4013/diff.log_--cc_-m_-p_main
@@ -1,4 +1,4 @@
-$ git log -c -m -p master
+$ git log --cc -m -p main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all
index 6b0b334a5d..c099399525 100644
--- a/t/t4013/diff.log_--decorate=full_--all
+++ b/t/t4013/diff.log_--decorate=full_--all
@@ -26,7 +26,7 @@ Date: Mon Jun 26 00:06:00 2006 +0000
Notes added by 'git notes add'
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/main)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate=full_--clear-decorations_--all b/t/t4013/diff.log_--decorate=full_--clear-decorations_--all
index 1c030a6554..c43684e536 100644
--- a/t/t4013/diff.log_--decorate=full_--clear-decorations_--all
+++ b/t/t4013/diff.log_--decorate=full_--clear-decorations_--all
@@ -26,7 +26,7 @@ Date: Mon Jun 26 00:06:00 2006 +0000
Notes added by 'git notes add'
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/main)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate=full_--decorate-all_--all b/t/t4013/diff.log_--decorate=full_--decorate-all_--all
index d6e7928784..48dca61681 100644
--- a/t/t4013/diff.log_--decorate=full_--decorate-all_--all
+++ b/t/t4013/diff.log_--decorate=full_--decorate-all_--all
@@ -26,7 +26,7 @@ Date: Mon Jun 26 00:06:00 2006 +0000
Notes added by 'git notes add'
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/main)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all
index c7df1f5814..8bbf891f65 100644
--- a/t/t4013/diff.log_--decorate_--all
+++ b/t/t4013/diff.log_--decorate_--all
@@ -26,7 +26,7 @@ Date: Mon Jun 26 00:06:00 2006 +0000
Notes added by 'git notes add'
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> main)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate_--clear-decorations_--all b/t/t4013/diff.log_--decorate_--clear-decorations_--all
index 88be82cce3..86b1353f51 100644
--- a/t/t4013/diff.log_--decorate_--clear-decorations_--all
+++ b/t/t4013/diff.log_--decorate_--clear-decorations_--all
@@ -26,7 +26,7 @@ Date: Mon Jun 26 00:06:00 2006 +0000
Notes added by 'git notes add'
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> main)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--decorate_--decorate-all_--all b/t/t4013/diff.log_--decorate_--decorate-all_--all
index 5d22618bb6..59fb17bfc5 100644
--- a/t/t4013/diff.log_--decorate_--decorate-all_--all
+++ b/t/t4013/diff.log_--decorate_--decorate-all_--all
@@ -26,7 +26,7 @@ Date: Mon Jun 26 00:06:00 2006 +0000
Notes added by 'git notes add'
-commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> main)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--diff-merges=first-parent_master b/t/t4013/diff.log_--diff-merges=first-parent_main
index fa63a557dd..bacee621e5 100644
--- a/t/t4013/diff.log_--diff-merges=first-parent_master
+++ b/t/t4013/diff.log_--diff-merges=first-parent_main
@@ -1,4 +1,4 @@
-$ git log --diff-merges=first-parent master
+$ git log --diff-merges=first-parent main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master b/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_main
index 597002232e..fe180fda3b 100644
--- a/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master
+++ b/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_main
@@ -1,4 +1,4 @@
-$ git log --no-diff-merges -p --first-parent master
+$ git log --diff-merges=off -p --first-parent main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--first-parent_--diff-merges=off_-p_master b/t/t4013/diff.log_--first-parent_--diff-merges=off_-p_main
index 5d7461a167..dca62d4e60 100644
--- a/t/t4013/diff.log_--first-parent_--diff-merges=off_-p_master
+++ b/t/t4013/diff.log_--first-parent_--diff-merges=off_-p_main
@@ -1,4 +1,4 @@
-$ git log --first-parent --diff-merges=off -p master
+$ git log --first-parent --diff-merges=off -p main
commit 80e25ffa65bcdbe82ef654b4d06dbbde7945c37f
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_master b/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_main
index 194e893c94..0b54118088 100644
--- a/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_master
+++ b/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_main
@@ -1,4 +1,4 @@
-$ git log --diff-merges=off -p --first-parent master
+$ git log --no-diff-merges -p --first-parent main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_main_--_dir_
index a18f1472a9..3ed46cc867 100644
--- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_--summary_main_--_dir_
@@ -1,4 +1,4 @@
-$ git log --patch-with-stat --summary master -- dir/
+$ git log --patch-with-stat --summary main -- dir/
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_master b/t/t4013/diff.log_--patch-with-stat_main
index ae425c4672..2e12b557cb 100644
--- a/t/t4013/diff.log_--patch-with-stat_master
+++ b/t/t4013/diff.log_--patch-with-stat_main
@@ -1,4 +1,4 @@
-$ git log --patch-with-stat master
+$ git log --patch-with-stat main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_main_--_dir_
index d5207cadf4..d511ea7f6b 100644
--- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_main_--_dir_
@@ -1,4 +1,4 @@
-$ git log --patch-with-stat master -- dir/
+$ git log --patch-with-stat main -- dir/
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_main
index 0fc1e8cd71..3cfd0e6422 100644
--- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git log --root --cc --patch-with-stat --summary master
+$ git log --root --cc --patch-with-stat --summary main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--patch-with-stat_--summary_main
index dffc09dde9..9f4d6dfa44 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git log --root --patch-with-stat --summary master
+$ git log --root --patch-with-stat --summary main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_master b/t/t4013/diff.log_--root_--patch-with-stat_main
index 55aa98012d..0d69ae2e11 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_main
@@ -1,4 +1,4 @@
-$ git log --root --patch-with-stat master
+$ git log --root --patch-with-stat main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_main
index 019d85f7de..1b71add9de 100644
--- a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git log --root -c --patch-with-stat --summary master
+$ git log --root -c --patch-with-stat --summary main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_-p_master b/t/t4013/diff.log_--root_-p_main
index b42c334439..04581296ed 100644
--- a/t/t4013/diff.log_--root_-p_master
+++ b/t/t4013/diff.log_--root_-p_main
@@ -1,4 +1,4 @@
-$ git log --root -p master
+$ git log --root -p main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--root_master b/t/t4013/diff.log_--root_main
index e8f46159da..d5e90fd6b4 100644
--- a/t/t4013/diff.log_--root_master
+++ b/t/t4013/diff.log_--root_main
@@ -1,4 +1,4 @@
-$ git log --root master
+$ git log --root main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-GF_-p_--pickaxe-all_master b/t/t4013/diff.log_-GF_-p_--pickaxe-all_main
index d36f88098b..1f7a497c2d 100644
--- a/t/t4013/diff.log_-GF_-p_--pickaxe-all_master
+++ b/t/t4013/diff.log_-GF_-p_--pickaxe-all_main
@@ -1,4 +1,4 @@
-$ git log -GF -p --pickaxe-all master
+$ git log -GF -p --pickaxe-all main
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-GF_-p_master b/t/t4013/diff.log_-GF_-p_main
index 9d93f2c23a..c80dda41e9 100644
--- a/t/t4013/diff.log_-GF_-p_master
+++ b/t/t4013/diff.log_-GF_-p_main
@@ -1,4 +1,4 @@
-$ git log -GF -p master
+$ git log -GF -p main
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-SF_master b/t/t4013/diff.log_-GF_main
index c1599f2f52..b94a7f7839 100644
--- a/t/t4013/diff.log_-SF_master
+++ b/t/t4013/diff.log_-GF_main
@@ -1,4 +1,4 @@
-$ git log -SF master
+$ git log -GF main
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_master b/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_main
index 929f35a05b..67e26b4e54 100644
--- a/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_master
+++ b/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_main
@@ -1,4 +1,4 @@
-$ git log -IA -IB -I1 -I2 -p master
+$ git log -IA -IB -I1 -I2 -p main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-SF_-p_master b/t/t4013/diff.log_-SF_-p_main
index 5e32438972..fa82ac1490 100644
--- a/t/t4013/diff.log_-SF_-p_master
+++ b/t/t4013/diff.log_-SF_-p_main
@@ -1,4 +1,4 @@
-$ git log -SF -p master
+$ git log -SF -p main
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-GF_master b/t/t4013/diff.log_-SF_main
index 4c6708d2d0..dbf770db49 100644
--- a/t/t4013/diff.log_-GF_master
+++ b/t/t4013/diff.log_-SF_main
@@ -1,4 +1,4 @@
-$ git log -GF master
+$ git log -SF main
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-SF_main_--max-count=0 b/t/t4013/diff.log_-SF_main_--max-count=0
new file mode 100644
index 0000000000..683b17eb99
--- /dev/null
+++ b/t/t4013/diff.log_-SF_main_--max-count=0
@@ -0,0 +1,2 @@
+$ git log -SF main --max-count=0
+$
diff --git a/t/t4013/diff.log_-SF_master_--max-count=2 b/t/t4013/diff.log_-SF_main_--max-count=1
index a6c55fd482..2102426f8c 100644
--- a/t/t4013/diff.log_-SF_master_--max-count=2
+++ b/t/t4013/diff.log_-SF_main_--max-count=1
@@ -1,4 +1,4 @@
-$ git log -SF master --max-count=2
+$ git log -SF main --max-count=1
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-SF_main_--max-count=2 b/t/t4013/diff.log_-SF_main_--max-count=2
new file mode 100644
index 0000000000..23e12a4cbb
--- /dev/null
+++ b/t/t4013/diff.log_-SF_main_--max-count=2
@@ -0,0 +1,7 @@
+$ git log -SF main --max-count=2
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:02:00 2006 +0000
+
+ Third
+$
diff --git a/t/t4013/diff.log_-SF_master_--max-count=0 b/t/t4013/diff.log_-SF_master_--max-count=0
deleted file mode 100644
index c1fc6c8731..0000000000
--- a/t/t4013/diff.log_-SF_master_--max-count=0
+++ /dev/null
@@ -1,2 +0,0 @@
-$ git log -SF master --max-count=0
-$
diff --git a/t/t4013/diff.log_-SF_master_--max-count=1 b/t/t4013/diff.log_-SF_master_--max-count=1
deleted file mode 100644
index c981a03814..0000000000
--- a/t/t4013/diff.log_-SF_master_--max-count=1
+++ /dev/null
@@ -1,7 +0,0 @@
-$ git log -SF master --max-count=1
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
-Author: A U Thor <author@example.com>
-Date: Mon Jun 26 00:02:00 2006 +0000
-
- Third
-$
diff --git a/t/t4013/diff.log_-S_F_master b/t/t4013/diff.log_-S_F_main
index 978d2b4118..a75a42e143 100644
--- a/t/t4013/diff.log_-S_F_master
+++ b/t/t4013/diff.log_-S_F_main
@@ -1,4 +1,4 @@
-$ git log -S F master
+$ git log -S F main
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_--cc_-m_-p_master b/t/t4013/diff.log_-c_-m_-p_main
index 7c217cf348..427f732456 100644
--- a/t/t4013/diff.log_--cc_-m_-p_master
+++ b/t/t4013/diff.log_-c_-m_-p_main
@@ -1,4 +1,4 @@
-$ git log --cc -m -p master
+$ git log -c -m -p main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-m_--raw_master b/t/t4013/diff.log_-m_--raw_main
index cd2ecc4628..31d9bc7707 100644
--- a/t/t4013/diff.log_-m_--raw_master
+++ b/t/t4013/diff.log_-m_--raw_main
@@ -1,4 +1,4 @@
-$ git log -m --raw master
+$ git log -m --raw main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-m_--stat_master b/t/t4013/diff.log_-m_--stat_main
index c7db084fd9..4c8909229b 100644
--- a/t/t4013/diff.log_-m_--stat_master
+++ b/t/t4013/diff.log_-m_--stat_main
@@ -1,4 +1,4 @@
-$ git log -m --stat master
+$ git log -m --stat main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-m_-p_--first-parent_master b/t/t4013/diff.log_-m_-p_--first-parent_main
index 7a0073f529..459e10786b 100644
--- a/t/t4013/diff.log_-m_-p_--first-parent_master
+++ b/t/t4013/diff.log_-m_-p_--first-parent_main
@@ -1,4 +1,4 @@
-$ git log -m -p --first-parent master
+$ git log -m -p --first-parent main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-m_-p_master b/t/t4013/diff.log_-m_-p_main
index 9ca62a01ed..07453c5698 100644
--- a/t/t4013/diff.log_-m_-p_master
+++ b/t/t4013/diff.log_-m_-p_main
@@ -1,4 +1,4 @@
-$ git log -m -p master
+$ git log -m -p main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-p_--diff-merges=first-parent_master b/t/t4013/diff.log_-p_--diff-merges=first-parent_main
index 9538a27511..264a2f373e 100644
--- a/t/t4013/diff.log_-p_--diff-merges=first-parent_master
+++ b/t/t4013/diff.log_-p_--diff-merges=first-parent_main
@@ -1,4 +1,4 @@
-$ git log -p --diff-merges=first-parent master
+$ git log -p --diff-merges=first-parent main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-p_--first-parent_master b/t/t4013/diff.log_-p_--first-parent_main
index 28840ebea1..247980817b 100644
--- a/t/t4013/diff.log_-p_--first-parent_master
+++ b/t/t4013/diff.log_-p_--first-parent_main
@@ -1,4 +1,4 @@
-$ git log -p --first-parent master
+$ git log -p --first-parent main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-p_master b/t/t4013/diff.log_-p_main
index bf1326dc36..c82b4dbf16 100644
--- a/t/t4013/diff.log_-p_master
+++ b/t/t4013/diff.log_-p_main
@@ -1,4 +1,4 @@
-$ git log -p master
+$ git log -p main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_master b/t/t4013/diff.log_main
index a8f6ce5abd..50401f73e6 100644
--- a/t/t4013/diff.log_master
+++ b/t/t4013/diff.log_main
@@ -1,4 +1,4 @@
-$ git log master
+$ git log main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.noellipses-diff-tree_-c_--abbrev_master b/t/t4013/diff.noellipses-diff-tree_-c_--abbrev_main
index bb80f013b3..3aa1f80af3 100644
--- a/t/t4013/diff.noellipses-diff-tree_-c_--abbrev_master
+++ b/t/t4013/diff.noellipses-diff-tree_-c_--abbrev_main
@@ -1,4 +1,4 @@
-$ git diff-tree -c --abbrev master
+$ git diff-tree -c --abbrev main
59d314ad6f356dd08601a4cd5e530381da3e3c64
::100644 100644 100644 cead32e 7289e35 992913c MM dir/sub
::100644 100644 100644 b414108 f4615da 10a8a9f MM file0
diff --git a/t/t4013/diff.noellipses-whatchanged_--root_master b/t/t4013/diff.noellipses-whatchanged_--root_main
index c2cfd4e729..2bec055835 100644
--- a/t/t4013/diff.noellipses-whatchanged_--root_master
+++ b/t/t4013/diff.noellipses-whatchanged_--root_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root master
+$ git whatchanged --root main
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.noellipses-whatchanged_-SF_master b/t/t4013/diff.noellipses-whatchanged_-SF_main
index b36ce5886e..0c1476d19e 100644
--- a/t/t4013/diff.noellipses-whatchanged_-SF_master
+++ b/t/t4013/diff.noellipses-whatchanged_-SF_main
@@ -1,4 +1,4 @@
-$ git whatchanged -SF master
+$ git whatchanged -SF main
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.noellipses-whatchanged_master b/t/t4013/diff.noellipses-whatchanged_main
index 55e500f2ed..c48d2851aa 100644
--- a/t/t4013/diff.noellipses-whatchanged_master
+++ b/t/t4013/diff.noellipses-whatchanged_main
@@ -1,4 +1,4 @@
-$ git whatchanged master
+$ git whatchanged main
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.show_--first-parent_master b/t/t4013/diff.show_--first-parent_main
index 3dcbe473a0..480502d65c 100644
--- a/t/t4013/diff.show_--first-parent_master
+++ b/t/t4013/diff.show_--first-parent_main
@@ -1,4 +1,4 @@
-$ git show --first-parent master
+$ git show --first-parent main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.show_-c_master b/t/t4013/diff.show_-c_main
index 81aba8da96..74ef8bc96b 100644
--- a/t/t4013/diff.show_-c_master
+++ b/t/t4013/diff.show_-c_main
@@ -1,4 +1,4 @@
-$ git show -c master
+$ git show -c main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.show_-m_master b/t/t4013/diff.show_-m_main
index 4ea2ee453d..8fd56736d9 100644
--- a/t/t4013/diff.show_-m_master
+++ b/t/t4013/diff.show_-m_main
@@ -1,4 +1,4 @@
-$ git show -m master
+$ git show -m main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0)
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.show_master b/t/t4013/diff.show_main
index fb08ce0e46..630b52a95e 100644
--- a/t/t4013/diff.show_master
+++ b/t/t4013/diff.show_main
@@ -1,4 +1,4 @@
-$ git show master
+$ git show main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_main_--_dir_
index c8b6af2f43..ce0754d556 100644
--- a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_
+++ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_main_--_dir_
@@ -1,4 +1,4 @@
-$ git whatchanged --patch-with-stat --summary master -- dir/
+$ git whatchanged --patch-with-stat --summary main -- dir/
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master b/t/t4013/diff.whatchanged_--patch-with-stat_main
index 1ac431ba92..aabccf39a5 100644
--- a/t/t4013/diff.whatchanged_--patch-with-stat_master
+++ b/t/t4013/diff.whatchanged_--patch-with-stat_main
@@ -1,4 +1,4 @@
-$ git whatchanged --patch-with-stat master
+$ git whatchanged --patch-with-stat main
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_main_--_dir_
index b30c28588f..c05a0e8149 100644
--- a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.whatchanged_--patch-with-stat_main_--_dir_
@@ -1,4 +1,4 @@
-$ git whatchanged --patch-with-stat master -- dir/
+$ git whatchanged --patch-with-stat main -- dir/
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_main
index 30aae7817b..1f74b1b548 100644
--- a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root --cc --patch-with-stat --summary master
+$ git whatchanged --root --cc --patch-with-stat --summary main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_main
index db90e51525..80d9812151 100644
--- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root --patch-with-stat --summary master
+$ git whatchanged --root --patch-with-stat --summary main
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_main
index 9a6cc92ce7..c0b9082a2c 100644
--- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master
+++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root --patch-with-stat master
+$ git whatchanged --root --patch-with-stat main
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_main
index d1d32bd34c..0002c6912e 100644
--- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root -c --patch-with-stat --summary master
+$ git whatchanged --root -c --patch-with-stat --summary main
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.whatchanged_--root_-p_master b/t/t4013/diff.whatchanged_--root_-p_main
index ebf1f0661e..39f3e2be74 100644
--- a/t/t4013/diff.whatchanged_--root_-p_master
+++ b/t/t4013/diff.whatchanged_--root_-p_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root -p master
+$ git whatchanged --root -p main
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--root_master b/t/t4013/diff.whatchanged_--root_main
index a405cb6138..36f4d6697f 100644
--- a/t/t4013/diff.whatchanged_--root_master
+++ b/t/t4013/diff.whatchanged_--root_main
@@ -1,4 +1,4 @@
-$ git whatchanged --root master
+$ git whatchanged --root main
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_-SF_-p_master b/t/t4013/diff.whatchanged_-SF_-p_main
index f39da84822..0e2e67c0df 100644
--- a/t/t4013/diff.whatchanged_-SF_-p_master
+++ b/t/t4013/diff.whatchanged_-SF_-p_main
@@ -1,4 +1,4 @@
-$ git whatchanged -SF -p master
+$ git whatchanged -SF -p main
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_-SF_master b/t/t4013/diff.whatchanged_-SF_main
index 0499321d0e..34c6bf6b95 100644
--- a/t/t4013/diff.whatchanged_-SF_master
+++ b/t/t4013/diff.whatchanged_-SF_main
@@ -1,4 +1,4 @@
-$ git whatchanged -SF master
+$ git whatchanged -SF main
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_-p_master b/t/t4013/diff.whatchanged_-p_main
index f18d43209c..18f3bdeef4 100644
--- a/t/t4013/diff.whatchanged_-p_master
+++ b/t/t4013/diff.whatchanged_-p_main
@@ -1,4 +1,4 @@
-$ git whatchanged -p master
+$ git whatchanged -p main
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_master b/t/t4013/diff.whatchanged_main
index cd3bcc2c72..d6c83ed8b0 100644
--- a/t/t4013/diff.whatchanged_master
+++ b/t/t4013/diff.whatchanged_main
@@ -1,4 +1,4 @@
-$ git whatchanged master
+$ git whatchanged main
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index c8a23d5148..7ec5854f74 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -44,6 +44,16 @@ test_expect_success 'GIT_EXTERNAL_DIFF environment and --no-ext-diff' '
'
+test_expect_success 'GIT_EXTERNAL_DIFF and --output' '
+ cat >expect <<-EOF &&
+ file $(git rev-parse --verify HEAD:file) 100644 file $(test_oid zero) 100644
+ EOF
+ GIT_EXTERNAL_DIFF=echo git diff --output=out >stdout &&
+ cut -d" " -f1,3- <out >actual &&
+ test_must_be_empty stdout &&
+ test_cmp expect actual
+'
+
test_expect_success SYMLINKS 'typechange diff' '
rm -f file &&
ln -s elif file &&
diff --git a/t/t4035-diff-quiet.sh b/t/t4035-diff-quiet.sh
index 0352bf81a9..35eaf0855f 100755
--- a/t/t4035-diff-quiet.sh
+++ b/t/t4035-diff-quiet.sh
@@ -50,6 +50,10 @@ test_expect_success 'git diff-tree HEAD HEAD' '
test_expect_code 0 git diff-tree --quiet HEAD HEAD >cnt &&
test_line_count = 0 cnt
'
+test_expect_success 'git diff-tree -w HEAD^ HEAD' '
+ test_expect_code 1 git diff-tree --quiet -w HEAD^ HEAD >cnt &&
+ test_line_count = 0 cnt
+'
test_expect_success 'git diff-files' '
test_expect_code 0 git diff-files --quiet >cnt &&
test_line_count = 0 cnt
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
index 44b4b13f5d..69599279e9 100755
--- a/t/t4053-diff-no-index.sh
+++ b/t/t4053-diff-no-index.sh
@@ -339,6 +339,22 @@ test_expect_success 'diff --no-index with pathspec' '
test_cmp expect actual
'
+test_expect_success 'diff --no-index first path ending in slash with pathspec' '
+ test_expect_code 1 git diff --name-status --no-index a/ b 1 >actual &&
+ cat >expect <<-EOF &&
+ D a/1
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'diff --no-index second path ending in slash with pathspec' '
+ test_expect_code 1 git diff --name-status --no-index a b/ 1 >actual &&
+ cat >expect <<-EOF &&
+ D a/1
+ EOF
+ test_cmp expect actual
+'
+
test_expect_success 'diff --no-index with pathspec no matches' '
test_expect_code 0 git diff --name-status --no-index a b missing
'
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index 0b3404f58f..98c6910963 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -946,4 +946,48 @@ test_expect_success 'stale commit cannot be parsed when traversing graph' '
)
'
+test_expect_success 'config commitGraph.changedPaths acts like --changed-paths' '
+ git init config-changed-paths &&
+ (
+ cd config-changed-paths &&
+
+ # commitGraph.changedPaths is not set and it should not write Bloom filters
+ test_commit first &&
+ GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
+ test_grep ! "Bloom filters" error &&
+
+ # Set commitGraph.changedPaths to true and it should write Bloom filters
+ test_commit second &&
+ git config commitGraph.changedPaths true &&
+ GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
+ test_grep "Bloom filters" error &&
+
+ # Add one more config commitGraph.changedPaths as false to disable the previous true config value
+ # It should still write Bloom filters due to existing filters
+ test_commit third &&
+ git config --add commitGraph.changedPaths false &&
+ GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
+ test_grep "Bloom filters" error &&
+
+ # commitGraph.changedPaths is still false and command line options should take precedence
+ test_commit fourth &&
+ GIT_PROGRESS_DELAY=0 git commit-graph write --no-changed-paths --reachable --progress 2>error &&
+ test_grep ! "Bloom filters" error &&
+ GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
+ test_grep ! "Bloom filters" error &&
+
+ # commitGraph.changedPaths is all cleared and then set to false again, command line options should take precedence
+ test_commit fifth &&
+ git config --unset-all commitGraph.changedPaths &&
+ git config commitGraph.changedPaths false &&
+ GIT_PROGRESS_DELAY=0 git commit-graph write --changed-paths --reachable --progress 2>error &&
+ test_grep "Bloom filters" error &&
+
+ # commitGraph.changedPaths is still false and it should write Bloom filters due to existing filters
+ test_commit sixth &&
+ GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
+ test_grep "Bloom filters" error
+ )
+'
+
test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 83d1aadf9f..b7059cccaa 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -45,7 +45,25 @@ test_expect_success "clone and setup child repos" '
git config set branch.main.merge refs/heads/one
) &&
git clone . bundle &&
- git clone . seven
+ git clone . seven &&
+ git clone --ref-format=reftable . case_sensitive &&
+ (
+ cd case_sensitive &&
+ git branch branch1 &&
+ git branch bRanch1
+ ) &&
+ git clone --ref-format=reftable . case_sensitive_fd &&
+ (
+ cd case_sensitive_fd &&
+ git branch foo/bar &&
+ git branch Foo
+ ) &&
+ git clone --ref-format=reftable . case_sensitive_df &&
+ (
+ cd case_sensitive_df &&
+ git branch Foo/bar &&
+ git branch foo
+ )
'
test_expect_success "fetch test" '
@@ -1465,6 +1483,100 @@ test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' '
test_path_is_missing whoops
'
+test_expect_success CASE_INSENSITIVE_FS,REFFILES 'existing references in a case insensitive filesystem' '
+ test_when_finished rm -rf case_insensitive &&
+ (
+ git init --bare case_insensitive &&
+ cd case_insensitive &&
+ git remote add origin -- ../case_sensitive &&
+ test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
+ test_grep "You${SQ}re on a case-insensitive filesystem" err &&
+ git rev-parse refs/heads/main >expect &&
+ git rev-parse refs/heads/branch1 >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success REFFILES 'existing reference lock in repo' '
+ test_when_finished rm -rf base repo &&
+ (
+ git init --ref-format=reftable base &&
+ cd base &&
+ echo >file update &&
+ git add . &&
+ git commit -m "updated" &&
+ git branch -M main &&
+
+ git update-ref refs/heads/foo @ &&
+ git update-ref refs/heads/branch @ &&
+ cd .. &&
+
+ git init --ref-format=files --bare repo &&
+ cd repo &&
+ git remote add origin ../base &&
+ touch refs/heads/foo.lock &&
+ test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
+ test_grep "error: fetching ref refs/heads/foo failed: reference already exists" err &&
+ git rev-parse refs/heads/main >expect &&
+ git rev-parse refs/heads/branch >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success CASE_INSENSITIVE_FS,REFFILES 'F/D conflict on case insensitive filesystem' '
+ test_when_finished rm -rf case_insensitive &&
+ (
+ git init --bare case_insensitive &&
+ cd case_insensitive &&
+ git remote add origin -- ../case_sensitive_fd &&
+ test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
+ test_grep "failed: refname conflict" err &&
+ git rev-parse refs/heads/main >expect &&
+ git rev-parse refs/heads/foo/bar >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success CASE_INSENSITIVE_FS,REFFILES 'D/F conflict on case insensitive filesystem' '
+ test_when_finished rm -rf case_insensitive &&
+ (
+ git init --bare case_insensitive &&
+ cd case_insensitive &&
+ git remote add origin -- ../case_sensitive_df &&
+ test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
+ test_grep "failed: refname conflict" err &&
+ git rev-parse refs/heads/main >expect &&
+ git rev-parse refs/heads/Foo/bar >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success REFFILES 'D/F conflict on case sensitive filesystem with lock' '
+ (
+ git init --ref-format=reftable base &&
+ cd base &&
+ echo >file update &&
+ git add . &&
+ git commit -m "updated" &&
+ git branch -M main &&
+
+ git update-ref refs/heads/foo @ &&
+ git update-ref refs/heads/branch @ &&
+ cd .. &&
+
+ git init --ref-format=files --bare repo &&
+ cd repo &&
+ git remote add origin ../base &&
+ mkdir refs/heads/foo &&
+ touch refs/heads/foo/random.lock &&
+ test_must_fail git fetch origin "refs/heads/*:refs/heads/*" 2>err &&
+ test_grep "some local refs could not be updated; try running" err &&
+ git rev-parse refs/heads/main >expect &&
+ git rev-parse refs/heads/branch >actual &&
+ test_cmp expect actual
+ )
+'
+
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 9b80ea1e3b..7f060d97bf 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -754,4 +754,69 @@ test_expect_success 'start after used with custom sort order' '
test_cmp expect actual
'
+test_expect_success 'start after with packed refs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit default &&
+
+ git update-ref --stdin <<-\EOF &&
+ create refs/heads/branch @
+ create refs/heads/side @
+ create refs/odd/spot @
+ create refs/tags/one @
+ create refs/tags/two @
+ commit
+ EOF
+
+ cat >expect <<-\EOF &&
+ refs/tags/default
+ refs/tags/one
+ refs/tags/two
+ EOF
+
+ git pack-refs --all &&
+ git for-each-ref --format="%(refname)" --start-after=refs/odd/spot >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'start after with packed refs and some loose refs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit default &&
+
+ git update-ref --stdin <<-\EOF &&
+ create refs/heads/branch @
+ create refs/heads/side @
+ create refs/odd/spot @
+ create refs/tags/one @
+ create refs/tags/two @
+ commit
+ EOF
+
+ git pack-refs --all &&
+
+ git update-ref --stdin <<-\EOF &&
+ create refs/heads/foo @
+ create refs/odd/tee @
+ commit
+ EOF
+
+ cat >expect <<-\EOF &&
+ refs/odd/tee
+ refs/tags/default
+ refs/tags/one
+ refs/tags/two
+ EOF
+
+
+ git for-each-ref --format="%(refname)" --start-after=refs/odd/spot >actual &&
+ test_cmp expect actual
+ )
+'
+
test_done
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 4dca8d97a7..66aff8e097 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -31,56 +31,83 @@ test_expect_success 'nonexistent template file should return error' '
echo changes >> foo &&
git add foo &&
(
+ GIT_EDITOR="echo hello >" &&
+ export GIT_EDITOR &&
+ test_must_fail git commit --template "$(pwd)"/notexist
+ )
+'
+
+test_expect_success 'nonexistent optional template file on command line' '
+ echo changes >> foo &&
+ git add foo &&
+ (
GIT_EDITOR="echo hello >\"\$1\"" &&
export GIT_EDITOR &&
- test_must_fail git commit --template "$PWD"/notexist
+ git commit --template ":(optional)$(pwd)/notexist"
)
'
test_expect_success 'nonexistent template file in config should return error' '
- test_config commit.template "$PWD"/notexist &&
+ test_config commit.template "$(pwd)"/notexist &&
(
- GIT_EDITOR="echo hello >\"\$1\"" &&
+ GIT_EDITOR="echo hello >" &&
export GIT_EDITOR &&
- test_must_fail git commit
+ test_must_fail git commit --allow-empty
)
'
+test_expect_success 'nonexistent optional template file in config' '
+ test_config commit.template ":(optional)$(pwd)"/notexist &&
+ GIT_EDITOR="echo hello >" git commit --allow-empty &&
+ git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
+ echo hello >expect &&
+ test_cmp expect actual
+'
+
# From now on we'll use a template file that exists.
-TEMPLATE="$PWD"/template
+TEMPLATE="$(pwd)"/template
test_expect_success 'unedited template should not commit' '
- echo "template line" > "$TEMPLATE" &&
- test_must_fail git commit --template "$TEMPLATE"
+ echo "template line" >"$TEMPLATE" &&
+ test_must_fail git commit --allow-empty --template "$TEMPLATE"
'
test_expect_success 'unedited template with comments should not commit' '
- echo "# comment in template" >> "$TEMPLATE" &&
- test_must_fail git commit --template "$TEMPLATE"
+ echo "# comment in template" >>"$TEMPLATE" &&
+ test_must_fail git commit --allow-empty --template "$TEMPLATE"
'
test_expect_success 'a Signed-off-by line by itself should not commit' '
(
test_set_editor "$TEST_DIRECTORY"/t7500/add-signed-off &&
- test_must_fail git commit --template "$TEMPLATE"
+ test_must_fail git commit --allow-empty --template "$TEMPLATE"
)
'
test_expect_success 'adding comments to a template should not commit' '
(
test_set_editor "$TEST_DIRECTORY"/t7500/add-comments &&
- test_must_fail git commit --template "$TEMPLATE"
+ test_must_fail git commit --allow-empty --template "$TEMPLATE"
)
'
test_expect_success 'adding real content to a template should commit' '
(
test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
- git commit --template "$TEMPLATE"
+ git commit --allow-empty --template "$TEMPLATE"
) &&
commit_msg_is "template linecommit message"
'
+test_expect_success 'existent template marked optional should commit' '
+ echo "existent template" >"$TEMPLATE" &&
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+ git commit --allow-empty --template ":(optional)$TEMPLATE"
+ ) &&
+ commit_msg_is "existent templatecommit message"
+'
+
test_expect_success '-t option should be short for --template' '
echo "short template" > "$TEMPLATE" &&
echo "new content" >> foo &&
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index cdc1d6fcc7..abad229e9d 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -717,6 +717,17 @@ test_expect_success TTY 'status -s with color.status' '
'
+test_expect_success TTY 'status -s keeps colors with -z' '
+ test_when_finished "rm -f output.*" &&
+ test_terminal git status -s -z >output.raw &&
+ # convert back to newlines to avoid portability issues with
+ # test_decode_color and test_cmp, and to let us use the same expected
+ # output as earlier tests
+ tr "\0" "\n" <output.raw >output.nl &&
+ test_decode_color <output.nl >output &&
+ test_cmp expect output
+'
+
cat >expect <<\EOF
## <YELLOW>main<RESET>...<CYAN>upstream<RESET> [ahead <YELLOW>1<RESET>, behind <CYAN>2<RESET>]
<RED>M<RESET> dir1/modified
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
index 0f887a3ebe..b50306b9b3 100755
--- a/t/t7528-signed-commit-ssh.sh
+++ b/t/t7528-signed-commit-ssh.sh
@@ -82,7 +82,7 @@ test_expect_success GPGSSH 'create signed commits' '
test_expect_success GPGSSH 'sign commits using literal public keys with ssh-agent' '
test_when_finished "test_unconfig commit.gpgsign" &&
test_config gpg.format ssh &&
- eval $(ssh-agent) &&
+ eval $(ssh-agent -T || ssh-agent) &&
test_when_finished "kill ${SSH_AGENT_PID}" &&
test_when_finished "test_unconfig user.signingkey" &&
mkdir tmpdir &&
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index ddd273d8dc..614184a097 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -465,6 +465,176 @@ test_expect_success 'maintenance.incremental-repack.auto (when config is unset)'
)
'
+run_and_verify_geometric_pack () {
+ EXPECTED_PACKS="$1" &&
+
+ # Verify that we perform a geometric repack.
+ rm -f "trace2.txt" &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git maintenance run --task=geometric-repack 2>/dev/null &&
+ test_subcommand git repack -d -l --geometric=2 \
+ --quiet --write-midx <trace2.txt &&
+
+ # Verify that the number of packfiles matches our expectation.
+ ls -l .git/objects/pack/*.pack >packfiles &&
+ test_line_count = "$EXPECTED_PACKS" packfiles &&
+
+ # And verify that there are no loose objects anymore.
+ git count-objects -v >count &&
+ test_grep '^count: 0$' count
+}
+
+test_expect_success 'geometric repacking task' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config set maintenance.auto false &&
+ test_commit initial &&
+
+ # The initial repack causes an all-into-one repack.
+ GIT_TRACE2_EVENT="$(pwd)/initial-repack.txt" \
+ git maintenance run --task=geometric-repack 2>/dev/null &&
+ test_subcommand git repack -d -l --cruft --cruft-expiration=2.weeks.ago \
+ --quiet --write-midx <initial-repack.txt &&
+
+ # Repacking should now cause a no-op geometric repack because
+ # no packfiles need to be combined.
+ ls -l .git/objects/pack/*.pack >before &&
+ run_and_verify_geometric_pack 1 &&
+ ls -l .git/objects/pack/*.pack >after &&
+ test_cmp before after &&
+
+ # This incremental change creates a new packfile that only
+ # soaks up loose objects. The packfiles are not getting merged
+ # at this point.
+ test_commit loose &&
+ run_and_verify_geometric_pack 2 &&
+
+ # Both packfiles have 3 objects, so the next run would cause us
+ # to merge all packfiles together. This should be turned into
+ # an all-into-one-repack.
+ GIT_TRACE2_EVENT="$(pwd)/all-into-one-repack.txt" \
+ git maintenance run --task=geometric-repack 2>/dev/null &&
+ test_subcommand git repack -d -l --cruft --cruft-expiration=2.weeks.ago \
+ --quiet --write-midx <all-into-one-repack.txt &&
+
+ # The geometric repack soaks up unreachable objects.
+ echo blob-1 | git hash-object -w --stdin -t blob &&
+ run_and_verify_geometric_pack 2 &&
+
+ # A second unreachable object should be written into another packfile.
+ echo blob-2 | git hash-object -w --stdin -t blob &&
+ run_and_verify_geometric_pack 3 &&
+
+ # And these two small packs should now be merged via the
+ # geometric repack. The large packfile should remain intact.
+ run_and_verify_geometric_pack 2 &&
+
+ # If we now add two more objects and repack twice we should
+ # then see another all-into-one repack. This time around
+ # though, as we have unreachable objects, we should also see a
+ # cruft pack.
+ echo blob-3 | git hash-object -w --stdin -t blob &&
+ echo blob-4 | git hash-object -w --stdin -t blob &&
+ run_and_verify_geometric_pack 3 &&
+ GIT_TRACE2_EVENT="$(pwd)/cruft-repack.txt" \
+ git maintenance run --task=geometric-repack 2>/dev/null &&
+ test_subcommand git repack -d -l --cruft --cruft-expiration=2.weeks.ago \
+ --quiet --write-midx <cruft-repack.txt &&
+ ls .git/objects/pack/*.pack >packs &&
+ test_line_count = 2 packs &&
+ ls .git/objects/pack/*.mtimes >cruft &&
+ test_line_count = 1 cruft
+ )
+'
+
+test_geometric_repack_needed () {
+ NEEDED="$1"
+ GEOMETRIC_CONFIG="$2" &&
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git ${GEOMETRIC_CONFIG:+-c maintenance.geometric-repack.$GEOMETRIC_CONFIG} \
+ maintenance run --auto --task=geometric-repack 2>/dev/null &&
+ case "$NEEDED" in
+ true)
+ test_grep "\[\"git\",\"repack\"," trace2.txt;;
+ false)
+ ! test_grep "\[\"git\",\"repack\"," trace2.txt;;
+ *)
+ BUG "invalid parameter: $NEEDED";;
+ esac
+}
+
+test_expect_success 'geometric repacking with --auto' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ # An empty repository does not need repacking, except when
+ # explicitly told to do it.
+ test_geometric_repack_needed false &&
+ test_geometric_repack_needed false auto=0 &&
+ test_geometric_repack_needed false auto=1 &&
+ test_geometric_repack_needed true auto=-1 &&
+
+ test_oid_init &&
+
+ # Loose objects cause a repack when crossing the limit. Note
+ # that the number of objects gets extrapolated by having a look
+ # at the "objects/17/" shard.
+ test_commit "$(test_oid blob17_1)" &&
+ test_geometric_repack_needed false &&
+ test_commit "$(test_oid blob17_2)" &&
+ test_geometric_repack_needed false auto=257 &&
+ test_geometric_repack_needed true auto=256 &&
+
+ # Force another repack.
+ test_commit first &&
+ test_commit second &&
+ test_geometric_repack_needed true auto=-1 &&
+
+ # We now have two packfiles that would be merged together. As
+ # such, the repack should always happen unless the user has
+ # disabled the auto task.
+ test_geometric_repack_needed false auto=0 &&
+ test_geometric_repack_needed true auto=9000
+ )
+'
+
+test_expect_success 'geometric repacking honors configured split factor' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config set maintenance.auto false &&
+
+ # Create three different packs with 9, 2 and 1 object, respectively.
+ # This is done so that only a subset of packs would be merged
+ # together so that we can verify that `git repack` receives the
+ # correct geometric factor.
+ for i in $(test_seq 9)
+ do
+ echo first-$i | git hash-object -w --stdin -t blob || return 1
+ done &&
+ git repack --geometric=2 -d &&
+
+ for i in $(test_seq 2)
+ do
+ echo second-$i | git hash-object -w --stdin -t blob || return 1
+ done &&
+ git repack --geometric=2 -d &&
+
+ echo third | git hash-object -w --stdin -t blob &&
+ git repack --geometric=2 -d &&
+
+ test_geometric_repack_needed false splitFactor=2 &&
+ test_geometric_repack_needed true splitFactor=3 &&
+ test_subcommand git repack -d -l --geometric=3 --quiet --write-midx <trace2.txt
+ )
+'
+
test_expect_success 'pack-refs task' '
for n in $(test_seq 1 5)
do
@@ -716,6 +886,76 @@ test_expect_success 'maintenance.strategy inheritance' '
<modified-daily.txt
'
+test_strategy () {
+ STRATEGY="$1"
+ shift
+
+ cat >expect &&
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -c maintenance.strategy=$STRATEGY maintenance run --quiet "$@" &&
+ sed -n 's/{"event":"child_start","sid":"[^/"]*",.*,"argv":\["\(.*\)\"]}/\1/p' <trace2.txt |
+ sed 's/","/ /g' >actual
+ test_cmp expect actual
+}
+
+test_expect_success 'maintenance.strategy is respected' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+
+ test_must_fail git -c maintenance.strategy=unknown maintenance run 2>err &&
+ test_grep "unknown maintenance strategy: .unknown." err &&
+
+ test_strategy incremental <<-\EOF &&
+ git pack-refs --all --prune
+ git reflog expire --all
+ git gc --quiet --no-detach --skip-foreground-tasks
+ EOF
+
+ test_strategy incremental --schedule=weekly <<-\EOF &&
+ git pack-refs --all --prune
+ git prune-packed --quiet
+ git multi-pack-index write --no-progress
+ git multi-pack-index expire --no-progress
+ git multi-pack-index repack --no-progress --batch-size=1
+ git commit-graph write --split --reachable --no-progress
+ EOF
+
+ test_strategy gc <<-\EOF &&
+ git pack-refs --all --prune
+ git reflog expire --all
+ git gc --quiet --no-detach --skip-foreground-tasks
+ EOF
+
+ test_strategy gc --schedule=weekly <<-\EOF &&
+ git pack-refs --all --prune
+ git reflog expire --all
+ git gc --quiet --no-detach --skip-foreground-tasks
+ EOF
+
+ test_strategy geometric <<-\EOF &&
+ git pack-refs --all --prune
+ git reflog expire --all
+ git repack -d -l --geometric=2 --quiet --write-midx
+ git commit-graph write --split --reachable --no-progress
+ git worktree prune --expire 3.months.ago
+ git rerere gc
+ EOF
+
+ test_strategy geometric --schedule=weekly <<-\EOF
+ git pack-refs --all --prune
+ git reflog expire --all
+ git repack -d -l --geometric=2 --quiet --write-midx
+ git commit-graph write --split --reachable --no-progress
+ git worktree prune --expire 3.months.ago
+ git rerere gc
+ EOF
+ )
+'
+
test_expect_success 'register and unregister' '
test_when_finished git config --global --unset-all maintenance.repo &&
@@ -1093,6 +1333,11 @@ test_expect_success 'fails when running outside of a repository' '
nongit test_must_fail git maintenance unregister
'
+test_expect_success 'fails when configured to use an invalid strategy' '
+ test_must_fail git -c maintenance.strategy=invalid maintenance run --schedule=hourly 2>err &&
+ test_grep "unknown maintenance strategy: .invalid." err
+'
+
test_expect_success 'register and unregister bare repo' '
test_when_finished "git config --global --unset-all maintenance.repo || :" &&
test_might_fail git config --global --unset-all maintenance.repo &&
diff --git a/t/t8020-last-modified.sh b/t/t8020-last-modified.sh
index 5eb4cef035..61f00bc15c 100755
--- a/t/t8020-last-modified.sh
+++ b/t/t8020-last-modified.sh
@@ -33,7 +33,6 @@ check_last_modified() {
done &&
cat >expect &&
- test_when_finished "rm -f tmp.*" &&
git ${indir:+-C "$indir"} last-modified "$@" >tmp.1 &&
git name-rev --annotate-stdin --name-only --tags \
<tmp.1 >tmp.2 &&
@@ -128,6 +127,27 @@ test_expect_success 'only last-modified files in the current tree' '
EOF
'
+test_expect_success 'subdirectory modified via merge' '
+ test_when_finished rm -rf repo &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit base &&
+ git switch --create left &&
+ mkdir subdir &&
+ test_commit left subdir/left &&
+ git switch --create right base &&
+ mkdir subdir &&
+ test_commit right subdir/right &&
+ git switch - &&
+ test_merge merge right &&
+ check_last_modified <<-\EOF
+ merge subdir
+ base base.t
+ EOF
+ )
+'
+
test_expect_success 'cross merge boundaries in blaming' '
git checkout HEAD^0 &&
git rm -rf . &&
diff --git a/t/t9305-fast-import-signatures.sh b/t/t9305-fast-import-signatures.sh
new file mode 100755
index 0000000000..c2b4271658
--- /dev/null
+++ b/t/t9305-fast-import-signatures.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+test_description='git fast-import --signed-commits=<mode>'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-gpg.sh"
+
+test_expect_success 'set up unsigned initial commit and import repo' '
+ test_commit first &&
+ git init new
+'
+
+test_expect_success GPG 'set up OpenPGP signed commit' '
+ git checkout -b openpgp-signing main &&
+ echo "Content for OpenPGP signing." >file-sign &&
+ git add file-sign &&
+ git commit -S -m "OpenPGP signed commit" &&
+ OPENPGP_SIGNING=$(git rev-parse --verify openpgp-signing)
+'
+
+test_expect_success GPG 'import OpenPGP signature with --signed-commits=verbatim' '
+ git fast-export --signed-commits=verbatim openpgp-signing >output &&
+ git -C new fast-import --quiet --signed-commits=verbatim <output >log 2>&1 &&
+ IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
+ test $OPENPGP_SIGNING = $IMPORTED &&
+ test_must_be_empty log
+'
+
+test_expect_success GPGSM 'set up X.509 signed commit' '
+ git checkout -b x509-signing main &&
+ test_config gpg.format x509 &&
+ test_config user.signingkey $GIT_COMMITTER_EMAIL &&
+ echo "Content for X.509 signing." >file-sign &&
+ git add file-sign &&
+ git commit -S -m "X.509 signed commit" &&
+ X509_SIGNING=$(git rev-parse HEAD)
+'
+
+test_expect_success GPGSM 'import X.509 signature fails with --signed-commits=abort' '
+ git fast-export --signed-commits=verbatim x509-signing >output &&
+ test_must_fail git -C new fast-import --quiet --signed-commits=abort <output
+'
+
+test_expect_success GPGSM 'import X.509 signature with --signed-commits=warn-verbatim' '
+ git -C new fast-import --quiet --signed-commits=warn-verbatim <output >log 2>&1 &&
+ IMPORTED=$(git -C new rev-parse --verify refs/heads/x509-signing) &&
+ test $X509_SIGNING = $IMPORTED &&
+ test_grep "importing a commit signature" log
+'
+
+test_expect_success GPGSSH 'set up SSH signed commit' '
+ git checkout -b ssh-signing main &&
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+ echo "Content for SSH signing." >file-sign &&
+ git add file-sign &&
+ git commit -S -m "SSH signed commit" &&
+ SSH_SIGNING=$(git rev-parse HEAD)
+'
+
+test_expect_success GPGSSH 'strip SSH signature with --signed-commits=strip' '
+ git fast-export --signed-commits=verbatim ssh-signing >output &&
+ git -C new fast-import --quiet --signed-commits=strip <output >log 2>&1 &&
+ IMPORTED=$(git -C new rev-parse --verify refs/heads/ssh-signing) &&
+ test $SSH_SIGNING != $IMPORTED &&
+ git -C new cat-file commit "$IMPORTED" >actual &&
+ test_grep ! -E "^gpgsig" actual &&
+ test_must_be_empty log
+'
+
+test_expect_success GPG 'setup a commit with dual OpenPGP signatures on its SHA-1 and SHA-256 formats' '
+ # Create a signed SHA-256 commit
+ git init --object-format=sha256 explicit-sha256 &&
+ git -C explicit-sha256 config extensions.compatObjectFormat sha1 &&
+ git -C explicit-sha256 checkout -b dual-signed &&
+ test_commit -C explicit-sha256 A &&
+ echo B >explicit-sha256/B &&
+ git -C explicit-sha256 add B &&
+ test_tick &&
+ git -C explicit-sha256 commit -S -m "signed" B &&
+ SHA256_B=$(git -C explicit-sha256 rev-parse dual-signed) &&
+
+ # Create the corresponding SHA-1 commit
+ SHA1_B=$(git -C explicit-sha256 rev-parse --output-object-format=sha1 dual-signed) &&
+
+ # Check that the resulting SHA-1 commit has both signatures
+ git -C explicit-sha256 cat-file -p $SHA1_B >out &&
+ test_grep -E "^gpgsig " out &&
+ test_grep -E "^gpgsig-sha256 " out
+'
+
+test_expect_success GPG 'strip both OpenPGP signatures with --signed-commits=warn-strip' '
+ git -C explicit-sha256 fast-export --signed-commits=verbatim dual-signed >output &&
+ test_grep -E "^gpgsig sha1 openpgp" output &&
+ test_grep -E "^gpgsig sha256 openpgp" output &&
+ git -C new fast-import --quiet --signed-commits=warn-strip <output >log 2>&1 &&
+ git -C new cat-file commit refs/heads/dual-signed >actual &&
+ test_grep ! -E "^gpgsig " actual &&
+ test_grep ! -E "^gpgsig-sha256 " actual &&
+ test_grep "stripping a commit signature" log >out &&
+ test_line_count = 2 out
+'
+
+test_done
diff --git a/t/t9306-fast-import-signed-tags.sh b/t/t9306-fast-import-signed-tags.sh
new file mode 100755
index 0000000000..363619e7d1
--- /dev/null
+++ b/t/t9306-fast-import-signed-tags.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+
+test_description='git fast-import --signed-tags=<mode>'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-gpg.sh"
+
+test_expect_success 'set up unsigned initial commit and import repo' '
+ test_commit first &&
+ git init new
+'
+
+test_expect_success 'import no signed tag with --signed-tags=abort' '
+ git fast-export --signed-tags=verbatim >output &&
+ git -C new fast-import --quiet --signed-tags=abort <output
+'
+
+test_expect_success GPG 'set up OpenPGP signed tag' '
+ git tag -s -m "OpenPGP signed tag" openpgp-signed first &&
+ OPENPGP_SIGNED=$(git rev-parse --verify refs/tags/openpgp-signed) &&
+ git fast-export --signed-tags=verbatim openpgp-signed >output
+'
+
+test_expect_success GPG 'import OpenPGP signed tag with --signed-tags=abort' '
+ test_must_fail git -C new fast-import --quiet --signed-tags=abort <output
+'
+
+test_expect_success GPG 'import OpenPGP signed tag with --signed-tags=verbatim' '
+ git -C new fast-import --quiet --signed-tags=verbatim <output >log 2>&1 &&
+ IMPORTED=$(git -C new rev-parse --verify refs/tags/openpgp-signed) &&
+ test $OPENPGP_SIGNED = $IMPORTED &&
+ test_must_be_empty log
+'
+
+test_expect_success GPGSM 'setup X.509 signed tag' '
+ test_config gpg.format x509 &&
+ test_config user.signingkey $GIT_COMMITTER_EMAIL &&
+
+ git tag -s -m "X.509 signed tag" x509-signed first &&
+ X509_SIGNED=$(git rev-parse --verify refs/tags/x509-signed) &&
+ git fast-export --signed-tags=verbatim x509-signed >output
+'
+
+test_expect_success GPGSM 'import X.509 signed tag with --signed-tags=warn-strip' '
+ git -C new fast-import --quiet --signed-tags=warn-strip <output >log 2>&1 &&
+ test_grep "stripping a tag signature for tag '\''x509-signed'\''" log &&
+ IMPORTED=$(git -C new rev-parse --verify refs/tags/x509-signed) &&
+ test $X509_SIGNED != $IMPORTED &&
+ git -C new cat-file -p x509-signed >out &&
+ test_grep ! "SIGNED MESSAGE" out
+'
+
+test_expect_success GPGSSH 'setup SSH signed tag' '
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+
+ git tag -s -m "SSH signed tag" ssh-signed first &&
+ SSH_SIGNED=$(git rev-parse --verify refs/tags/ssh-signed) &&
+ git fast-export --signed-tags=verbatim ssh-signed >output
+'
+
+test_expect_success GPGSSH 'import SSH signed tag with --signed-tags=warn-verbatim' '
+ git -C new fast-import --quiet --signed-tags=warn-verbatim <output >log 2>&1 &&
+ test_grep "importing a tag signature verbatim for tag '\''ssh-signed'\''" log &&
+ IMPORTED=$(git -C new rev-parse --verify refs/tags/ssh-signed) &&
+ test $SSH_SIGNED = $IMPORTED
+'
+
+test_expect_success GPGSSH 'import SSH signed tag with --signed-tags=strip' '
+ git -C new fast-import --quiet --signed-tags=strip <output >log 2>&1 &&
+ test_must_be_empty log &&
+ IMPORTED=$(git -C new rev-parse --verify refs/tags/ssh-signed) &&
+ test $SSH_SIGNED != $IMPORTED &&
+ git -C new cat-file -p ssh-signed >out &&
+ test_grep ! "SSH SIGNATURE" out
+'
+
+test_done
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 8f85c69d62..3d153a4805 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -35,6 +35,7 @@ test_expect_success 'setup' '
git commit -m sitzt file2 &&
test_tick &&
git tag -a -m valentin muss &&
+ ANNOTATED_TAG_COUNT=1 &&
git merge -s ours main
'
@@ -229,7 +230,8 @@ EOF
test_expect_success 'set up faked signed tag' '
- git fast-import <signed-tag-import
+ git fast-import <signed-tag-import &&
+ ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1))
'
@@ -277,6 +279,42 @@ test_expect_success 'signed-tags=warn-strip' '
test -s err
'
+test_expect_success GPGSM 'setup X.509 signed tag' '
+ test_config gpg.format x509 &&
+ test_config user.signingkey $GIT_COMMITTER_EMAIL &&
+
+ git tag -s -m "X.509 signed tag" x509-signed $(git rev-parse HEAD) &&
+ ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1))
+'
+
+test_expect_success GPGSM 'signed-tags=verbatim with X.509' '
+ git fast-export --signed-tags=verbatim x509-signed > output &&
+ test_grep "SIGNED MESSAGE" output
+'
+
+test_expect_success GPGSM 'signed-tags=strip with X.509' '
+ git fast-export --signed-tags=strip x509-signed > output &&
+ test_grep ! "SIGNED MESSAGE" output
+'
+
+test_expect_success GPGSSH 'setup SSH signed tag' '
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+
+ git tag -s -m "SSH signed tag" ssh-signed $(git rev-parse HEAD) &&
+ ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1))
+'
+
+test_expect_success GPGSSH 'signed-tags=verbatim with SSH' '
+ git fast-export --signed-tags=verbatim ssh-signed > output &&
+ test_grep "SSH SIGNATURE" output
+'
+
+test_expect_success GPGSSH 'signed-tags=strip with SSH' '
+ git fast-export --signed-tags=strip ssh-signed > output &&
+ test_grep ! "SSH SIGNATURE" output
+'
+
test_expect_success GPG 'set up signed commit' '
# Generate a commit with both "gpgsig" and "encoding" set, so
@@ -491,8 +529,9 @@ test_expect_success 'fast-export -C -C | fast-import' '
test_expect_success 'fast-export | fast-import when main is tagged' '
git tag -m msg last &&
+ ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1)) &&
git fast-export -C -C --signed-tags=strip --all > output &&
- test $(grep -c "^tag " output) = 3
+ test $(grep -c "^tag " output) = $ANNOTATED_TAG_COUNT
'
@@ -506,12 +545,13 @@ test_expect_success 'cope with tagger-less tags' '
TAG=$(git hash-object --literally -t tag -w tag-content) &&
git update-ref refs/tags/sonnenschein $TAG &&
+ ANNOTATED_TAG_COUNT=$((ANNOTATED_TAG_COUNT + 1)) &&
git fast-export -C -C --signed-tags=strip --all > output &&
- test $(grep -c "^tag " output) = 4 &&
+ test $(grep -c "^tag " output) = $ANNOTATED_TAG_COUNT &&
! grep "Unspecified Tagger" output &&
git fast-export -C -C --signed-tags=strip --all \
--fake-missing-tagger > output &&
- test $(grep -c "^tag " output) = 4 &&
+ test $(grep -c "^tag " output) = $ANNOTATED_TAG_COUNT &&
grep "Unspecified Tagger" output
'
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 6650d33fba..964e1f1569 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -11,9 +11,9 @@ test_description='test bash completion'
# untraceable with such ancient Bash versions.
test_untraceable=UnfortunatelyYes
-# Override environment and always use master for the default initial branch
+# Override environment and always use main for the default initial branch
# name for these tests, so that rev completion candidates are as expected.
-GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./lib-bash.sh
@@ -1453,7 +1453,7 @@ test_expect_success 'git bisect - start subcommand arguments before double-dash
HEAD Z
final Z
initial Z
- master Z
+ main Z
EOF
)
'
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index a28de7b19b..52d7759bf5 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1708,11 +1708,16 @@ test_set_hash () {
# Detect the hash algorithm in use.
test_detect_hash () {
case "${GIT_TEST_DEFAULT_HASH:-$GIT_TEST_BUILTIN_HASH}" in
- "sha256")
+ *:*)
+ test_hash_algo="${GIT_TEST_DEFAULT_HASH%%:*}"
+ test_compat_hash_algo="${GIT_TEST_DEFAULT_HASH##*:}"
+ test_repo_compat_hash_algo="$test_compat_hash_algo"
+ ;;
+ sha256)
test_hash_algo=sha256
test_compat_hash_algo=sha1
;;
- *)
+ sha1)
test_hash_algo=sha1
test_compat_hash_algo=sha256
;;
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 621cd31ae1..ef0ab7ec2d 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -127,11 +127,18 @@ then
export GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS
fi
-# Explicitly set the default branch name for testing, to avoid the
-# transitory "git init" warning under --verbose.
-: ${GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME:=master}
+# Explicitly set the default branch name for testing, to squelch hints
+# from "git init" during the transition period. Should be removed
+# after we decide to remove ADVICE_DEFAULT_BRANCH_NAME
+if test -z "$WITH_BREAKING_CHANGES"
+then
+ : ${GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME:=master}
+else
+ : ${GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME:=main}
+fi
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
################################################################
# It appears that people try to run tests without building...
GIT_BINARY="${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X"
@@ -1917,6 +1924,19 @@ test_lazy_prereq DEFAULT_HASH_ALGORITHM '
test_lazy_prereq DEFAULT_REPO_FORMAT '
test_have_prereq SHA1,REFFILES
'
+# BROKEN_OBJECTS is a test whether we can write deliberately broken objects and
+# expect them to work. When running using SHA-256 mode with SHA-1
+# compatibility, we cannot write such objects because there's no SHA-1
+# compatibility value for a nonexistent object.
+test_lazy_prereq BROKEN_OBJECTS '
+ ! test_have_prereq COMPAT_HASH
+'
+
+# COMPAT_HASH is a test if we're operating in a repository with SHA-256 with
+# SHA-1 compatibility.
+test_lazy_prereq COMPAT_HASH '
+ test -n "$test_repo_compat_hash_algo"
+'
# Ensure that no test accidentally triggers a Git command
# that runs the actual maintenance scheduler, affecting a user's
diff --git a/t/unit-tests/clar/.github/workflows/ci.yml b/t/unit-tests/clar/.github/workflows/ci.yml
index 0065843d17..4d4724222c 100644
--- a/t/unit-tests/clar/.github/workflows/ci.yml
+++ b/t/unit-tests/clar/.github/workflows/ci.yml
@@ -13,23 +13,56 @@ jobs:
platform:
- os: ubuntu-latest
generator: Unix Makefiles
+ env:
+ CFLAGS: "-Werror -Wall -Wextra"
+ - os: ubuntu-latest
+ generator: Unix Makefiles
+ env:
+ CC: "clang"
+ CFLAGS: "-Werror -Wall -Wextra -fsanitize=leak"
+ - os: ubuntu-latest
+ generator: Unix Makefiles
+ image: i386/debian:latest
+ env:
+ CFLAGS: "-Werror -Wall -Wextra"
- os: macos-latest
generator: Unix Makefiles
+ env:
+ CFLAGS: "-Werror -Wall -Wextra"
- os: windows-latest
generator: Visual Studio 17 2022
- os: windows-latest
generator: MSYS Makefiles
+ env:
+ CFLAGS: "-Werror -Wall -Wextra"
- os: windows-latest
generator: MinGW Makefiles
+ env:
+ CFLAGS: "-Werror -Wall -Wextra"
+ fail-fast: false
runs-on: ${{ matrix.platform.os }}
+ container: ${{matrix.platform.image}}
+
+ env:
+ CC: ${{matrix.platform.env.CC}}
+ CFLAGS: ${{matrix.platform.env.CFLAGS}}
steps:
+ - name: Prepare 32 bit container image
+ if: matrix.platform.image == 'i386/debian:latest'
+ run: apt -q update && apt -q -y install cmake gcc libc6-amd64 lib64stdc++6 make python3
- name: Check out
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Build
+ shell: bash
run: |
mkdir build
cd build
cmake .. -G "${{matrix.platform.generator}}"
- cmake --build .
+ cmake --build . --verbose
+ - name: Test
+ shell: bash
+ run: |
+ cd build
+ CTEST_OUTPUT_ON_FAILURE=1 ctest --build-config Debug
diff --git a/t/unit-tests/clar/CMakeLists.txt b/t/unit-tests/clar/CMakeLists.txt
index 12d4af114f..125db05bc1 100644
--- a/t/unit-tests/clar/CMakeLists.txt
+++ b/t/unit-tests/clar/CMakeLists.txt
@@ -1,8 +1,15 @@
+include(CheckFunctionExists)
+
cmake_minimum_required(VERSION 3.16..3.29)
project(clar LANGUAGES C)
-option(BUILD_TESTS "Build test executable" ON)
+option(BUILD_EXAMPLE "Build the example." ON)
+
+check_function_exists(realpath CLAR_HAS_REALPATH)
+if(CLAR_HAS_REALPATH)
+ add_compile_definitions(-DCLAR_HAS_REALPATH)
+endif()
add_library(clar INTERFACE)
target_sources(clar INTERFACE
@@ -25,4 +32,8 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
if(BUILD_TESTING)
add_subdirectory(test)
endif()
+
+ if(BUILD_EXAMPLE)
+ add_subdirectory(example)
+ endif()
endif()
diff --git a/t/unit-tests/clar/README.md b/t/unit-tests/clar/README.md
index a8961c5f10..41595989ca 100644
--- a/t/unit-tests/clar/README.md
+++ b/t/unit-tests/clar/README.md
@@ -26,8 +26,7 @@ Can you count to funk?
~~~~ sh
$ mkdir tests
$ cp -r $CLAR_ROOT/clar* tests
- $ cp $CLAR_ROOT/test/clar_test.h tests
- $ cp $CLAR_ROOT/test/main.c.sample tests/main.c
+ $ cp $CLAR_ROOT/example/*.c tests
~~~~
- **One: Write some tests**
@@ -147,7 +146,7 @@ To use Clar:
1. copy the Clar boilerplate to your test directory
2. copy (and probably modify) the sample `main.c` (from
- `$CLAR_PATH/test/main.c.sample`)
+ `$CLAR_PATH/example/main.c`)
3. run the Clar mixer (a.k.a. `generate.py`) to scan your test directory and
write out the test suite metadata.
4. compile your test files and the Clar boilerplate into a single test
@@ -159,7 +158,7 @@ The Clar boilerplate gives you a set of useful test assertions and features
the `clar.c` and `clar.h` files, plus the code in the `clar/` subdirectory.
You should not need to edit these files.
-The sample `main.c` (i.e. `$CLAR_PATH/test/main.c.sample`) file invokes
+The sample `main.c` (i.e. `$CLAR_PATH/example/main.c`) file invokes
`clar_test(argc, argv)` to run the tests. Usually, you will edit this file
to perform any framework specific initialization and teardown that you need.
@@ -251,11 +250,16 @@ suite.
- `cl_fixture(const char *)`: Gets the full path to a fixture file.
-Please do note that these methods are *always* available whilst running a
-test, even when calling auxiliary/static functions inside the same file.
+### Auxiliary / helper functions
-It's strongly encouraged to perform test assertions in auxiliary methods,
-instead of returning error values. This is considered good Clar style.
+The clar API is always available while running a test, even when calling
+"auxiliary" (helper) functions.
+
+You're encouraged to perform test assertions in those auxiliary
+methods, instead of returning error values. This is considered good
+Clar style. _However_, when you do this, you need to call `cl_invoke`
+to preserve the current state; this ensures that failures are reported
+as coming from the actual test, instead of the auxiliary method.
Style Example:
@@ -310,20 +314,19 @@ static void check_string(const char *str)
void test_example__a_test_with_auxiliary_methods(void)
{
- check_string("foo");
- check_string("bar");
+ cl_invoke(check_string("foo"));
+ cl_invoke(check_string("bar"));
}
~~~~
About Clar
==========
-Clar has been written from scratch by [Vicent Martí](https://github.com/vmg),
-to replace the old testing framework in [libgit2][libgit2].
-
-Do you know what languages are *in* on the SF startup scene? Node.js *and*
-Latin. Follow [@vmg](https://www.twitter.com/vmg) on Twitter to
-receive more lessons on word etymology. You can be hip too.
-
+Clar was originally written by [Vicent Martí](https://github.com/vmg),
+to replace the old testing framework in [libgit2][libgit2]. It is
+currently maintained by [Edward Thomson](https://github.com/ethomson),
+and used by the [libgit2][libgit2] and [git][git] projects, amongst
+others.
[libgit2]: https://github.com/libgit2/libgit2
+[git]: https://github.com/git/git
diff --git a/t/unit-tests/clar/clar.c b/t/unit-tests/clar/clar.c
index 03a3aa8e87..d6176e50b2 100644
--- a/t/unit-tests/clar/clar.c
+++ b/t/unit-tests/clar/clar.c
@@ -79,6 +79,8 @@
# else
# define p_snprintf snprintf
# endif
+
+# define localtime_r(timer, buf) (localtime_s(buf, timer) == 0 ? buf : NULL)
#else
# include <sys/wait.h> /* waitpid(2) */
# include <unistd.h>
@@ -150,7 +152,6 @@ static struct {
enum cl_output_format output_format;
- int report_errors_only;
int exit_on_error;
int verbosity;
@@ -164,6 +165,10 @@ static struct {
struct clar_report *reports;
struct clar_report *last_report;
+ const char *invoke_file;
+ const char *invoke_func;
+ size_t invoke_line;
+
void (*local_cleanup)(void *);
void *local_cleanup_payload;
@@ -190,7 +195,7 @@ struct clar_suite {
};
/* From clar_print_*.c */
-static void clar_print_init(int test_count, int suite_count, const char *suite_names);
+static void clar_print_init(int test_count, int suite_count);
static void clar_print_shutdown(int test_count, int suite_count, int error_count);
static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error);
static void clar_print_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status failed);
@@ -199,8 +204,10 @@ static void clar_print_onabortv(const char *msg, va_list argp);
static void clar_print_onabort(const char *msg, ...);
/* From clar_sandbox.c */
-static void clar_unsandbox(void);
-static void clar_sandbox(void);
+static void clar_tempdir_init(void);
+static void clar_tempdir_shutdown(void);
+static int clar_sandbox_create(const char *suite_name, const char *test_name);
+static int clar_sandbox_cleanup(void);
/* From summary.h */
static struct clar_summary *clar_summary_init(const char *filename);
@@ -304,6 +311,8 @@ clar_run_test(
CL_TRACE(CL_TRACE__TEST__BEGIN);
+ clar_sandbox_create(suite->name, test->name);
+
_clar.last_report->start = time(NULL);
clar_time_now(&start);
@@ -328,9 +337,13 @@ clar_run_test(
if (_clar.local_cleanup != NULL)
_clar.local_cleanup(_clar.local_cleanup_payload);
+ clar__clear_invokepoint();
+
if (cleanup->ptr != NULL)
cleanup->ptr();
+ clar_sandbox_cleanup();
+
CL_TRACE(CL_TRACE__TEST__END);
_clar.tests_ran++;
@@ -339,11 +352,7 @@ clar_run_test(
_clar.local_cleanup = NULL;
_clar.local_cleanup_payload = NULL;
- if (_clar.report_errors_only) {
- clar_report_errors(_clar.last_report);
- } else {
- clar_print_ontest(suite->name, test->name, _clar.tests_ran, _clar.last_report->status);
- }
+ clar_print_ontest(suite->name, test->name, _clar.tests_ran, _clar.last_report->status);
}
static void
@@ -360,8 +369,7 @@ clar_run_suite(const struct clar_suite *suite, const char *filter)
if (_clar.exit_on_error && _clar.total_errors)
return;
- if (!_clar.report_errors_only)
- clar_print_onsuite(suite->name, ++_clar.suites_ran);
+ clar_print_onsuite(suite->name, ++_clar.suites_ran);
_clar.active_suite = suite->name;
_clar.active_test = NULL;
@@ -428,12 +436,12 @@ clar_usage(const char *arg)
printf(" -iname Include the suite with `name`\n");
printf(" -xname Exclude the suite with `name`\n");
printf(" -v Increase verbosity (show suite names)\n");
- printf(" -q Only report tests that had an error\n");
+ printf(" -q Decrease verbosity, inverse to -v\n");
printf(" -Q Quit as soon as a test fails\n");
printf(" -t Display results in tap format\n");
printf(" -l Print suite names\n");
printf(" -r[filename] Write summary file (to the optional filename)\n");
- exit(-1);
+ exit(1);
}
static void
@@ -441,18 +449,11 @@ clar_parse_args(int argc, char **argv)
{
int i;
- /* Verify options before execute */
for (i = 1; i < argc; ++i) {
char *argument = argv[i];
- if (argument[0] != '-' || argument[1] == '\0'
- || strchr("sixvqQtlr", argument[1]) == NULL) {
+ if (argument[0] != '-' || argument[1] == '\0')
clar_usage(argv[0]);
- }
- }
-
- for (i = 1; i < argc; ++i) {
- char *argument = argv[i];
switch (argument[1]) {
case 's':
@@ -465,8 +466,13 @@ clar_parse_args(int argc, char **argv)
argument += offset;
arglen = strlen(argument);
- if (arglen == 0)
- clar_usage(argv[0]);
+ if (arglen == 0) {
+ if (i + 1 == argc)
+ clar_usage(argv[0]);
+
+ argument = argv[++i];
+ arglen = strlen(argument);
+ }
for (j = 0; j < _clar_suite_count; ++j) {
suitelen = strlen(_clar_suites[j].name);
@@ -483,9 +489,6 @@ clar_parse_args(int argc, char **argv)
++found;
- if (!exact)
- _clar.verbosity = MAX(_clar.verbosity, 1);
-
switch (action) {
case 's': {
struct clar_explicit *explicit;
@@ -517,23 +520,37 @@ clar_parse_args(int argc, char **argv)
if (!found)
clar_abort("No suite matching '%s' found.\n", argument);
+
break;
}
case 'q':
- _clar.report_errors_only = 1;
+ if (argument[2] != '\0')
+ clar_usage(argv[0]);
+
+ _clar.verbosity--;
break;
case 'Q':
+ if (argument[2] != '\0')
+ clar_usage(argv[0]);
+
_clar.exit_on_error = 1;
break;
case 't':
+ if (argument[2] != '\0')
+ clar_usage(argv[0]);
+
_clar.output_format = CL_OUTPUT_TAP;
break;
case 'l': {
size_t j;
+
+ if (argument[2] != '\0')
+ clar_usage(argv[0]);
+
printf("Test suites (use -s<name> to run just one):\n");
for (j = 0; j < _clar_suite_count; ++j)
printf(" %3d: %s\n", (int)j, _clar_suites[j].name);
@@ -542,23 +559,27 @@ clar_parse_args(int argc, char **argv)
}
case 'v':
+ if (argument[2] != '\0')
+ clar_usage(argv[0]);
+
_clar.verbosity++;
break;
case 'r':
_clar.write_summary = 1;
free(_clar.summary_filename);
+
if (*(argument + 2)) {
if ((_clar.summary_filename = strdup(argument + 2)) == NULL)
clar_abort("Failed to allocate summary filename.\n");
} else {
_clar.summary_filename = NULL;
}
+
break;
default:
- clar_abort("Unexpected commandline argument '%s'.\n",
- argument[1]);
+ clar_usage(argv[0]);
}
}
}
@@ -571,11 +592,7 @@ clar_test_init(int argc, char **argv)
if (argc > 1)
clar_parse_args(argc, argv);
- clar_print_init(
- (int)_clar_callback_count,
- (int)_clar_suite_count,
- ""
- );
+ clar_print_init((int)_clar_callback_count, (int)_clar_suite_count);
if (!_clar.summary_filename &&
(summary_env = getenv("CLAR_SUMMARY")) != NULL) {
@@ -591,7 +608,7 @@ clar_test_init(int argc, char **argv)
if (_clar.write_summary)
_clar.summary = clar_summary_init(_clar.summary_filename);
- clar_sandbox();
+ clar_tempdir_init();
}
int
@@ -623,7 +640,7 @@ clar_test_shutdown(void)
_clar.total_errors
);
- clar_unsandbox();
+ clar_tempdir_shutdown();
if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0)
clar_abort("Failed to write the summary file '%s: %s.\n",
@@ -635,6 +652,14 @@ clar_test_shutdown(void)
}
for (report = _clar.reports; report; report = report_next) {
+ struct clar_error *error, *error_next;
+
+ for (error = report->errors; error; error = error_next) {
+ free(error->description);
+ error_next = error->next;
+ free(error);
+ }
+
report_next = report->next;
free(report);
}
@@ -660,7 +685,7 @@ static void abort_test(void)
clar_print_onabort(
"Fatal error: a cleanup method raised an exception.\n");
clar_report_errors(_clar.last_report);
- exit(-1);
+ exit(1);
}
CL_TRACE(CL_TRACE__TEST__LONGJMP);
@@ -695,9 +720,9 @@ void clar__fail(
_clar.last_report->last_error = error;
- error->file = file;
- error->function = function;
- error->line_number = line;
+ error->file = _clar.invoke_file ? _clar.invoke_file : file;
+ error->function = _clar.invoke_func ? _clar.invoke_func : function;
+ error->line_number = _clar.invoke_line ? _clar.invoke_line : line;
error->error_msg = error_msg;
if (description != NULL &&
@@ -754,7 +779,12 @@ void clar__assert_equal(
p_snprintf(buf, sizeof(buf), "'%s' != '%s' (at byte %d)",
s1, s2, pos);
} else {
- p_snprintf(buf, sizeof(buf), "'%s' != '%s'", s1, s2);
+ const char *q1 = s1 ? "'" : "";
+ const char *q2 = s2 ? "'" : "";
+ s1 = s1 ? s1 : "NULL";
+ s2 = s2 ? s2 : "NULL";
+ p_snprintf(buf, sizeof(buf), "%s%s%s != %s%s%s",
+ q1, s1, q1, q2, s2, q2);
}
}
}
@@ -767,12 +797,17 @@ void clar__assert_equal(
if (!is_equal) {
if (s1 && s2) {
int pos;
- for (pos = 0; s1[pos] == s2[pos] && pos < len; ++pos)
+ for (pos = 0; pos < len && s1[pos] == s2[pos]; ++pos)
/* find differing byte offset */;
p_snprintf(buf, sizeof(buf), "'%.*s' != '%.*s' (at byte %d)",
len, s1, len, s2, pos);
} else {
- p_snprintf(buf, sizeof(buf), "'%.*s' != '%.*s'", len, s1, len, s2);
+ const char *q1 = s1 ? "'" : "";
+ const char *q2 = s2 ? "'" : "";
+ s1 = s1 ? s1 : "NULL";
+ s2 = s2 ? s2 : "NULL";
+ p_snprintf(buf, sizeof(buf), "%s%.*s%s != %s%.*s%s",
+ q1, len, s1, q1, q2, len, s2, q2);
}
}
}
@@ -790,7 +825,12 @@ void clar__assert_equal(
p_snprintf(buf, sizeof(buf), "'%ls' != '%ls' (at byte %d)",
wcs1, wcs2, pos);
} else {
- p_snprintf(buf, sizeof(buf), "'%ls' != '%ls'", wcs1, wcs2);
+ const char *q1 = wcs1 ? "'" : "";
+ const char *q2 = wcs2 ? "'" : "";
+ wcs1 = wcs1 ? wcs1 : L"NULL";
+ wcs2 = wcs2 ? wcs2 : L"NULL";
+ p_snprintf(buf, sizeof(buf), "%s%ls%s != %s%ls%s",
+ q1, wcs1, q1, q2, wcs2, q2);
}
}
}
@@ -803,12 +843,17 @@ void clar__assert_equal(
if (!is_equal) {
if (wcs1 && wcs2) {
int pos;
- for (pos = 0; wcs1[pos] == wcs2[pos] && pos < len; ++pos)
+ for (pos = 0; pos < len && wcs1[pos] == wcs2[pos]; ++pos)
/* find differing byte offset */;
p_snprintf(buf, sizeof(buf), "'%.*ls' != '%.*ls' (at byte %d)",
len, wcs1, len, wcs2, pos);
} else {
- p_snprintf(buf, sizeof(buf), "'%.*ls' != '%.*ls'", len, wcs1, len, wcs2);
+ const char *q1 = wcs1 ? "'" : "";
+ const char *q2 = wcs2 ? "'" : "";
+ wcs1 = wcs1 ? wcs1 : L"NULL";
+ wcs2 = wcs2 ? wcs2 : L"NULL";
+ p_snprintf(buf, sizeof(buf), "%s%.*ls%s != %s%.*ls%s",
+ q1, len, wcs1, q1, q2, len, wcs2, q2);
}
}
}
@@ -850,6 +895,23 @@ void cl_set_cleanup(void (*cleanup)(void *), void *opaque)
_clar.local_cleanup_payload = opaque;
}
+void clar__set_invokepoint(
+ const char *file,
+ const char *func,
+ size_t line)
+{
+ _clar.invoke_file = file;
+ _clar.invoke_func = func;
+ _clar.invoke_line = line;
+}
+
+void clar__clear_invokepoint(void)
+{
+ _clar.invoke_file = NULL;
+ _clar.invoke_func = NULL;
+ _clar.invoke_line = 0;
+}
+
#include "clar/sandbox.h"
#include "clar/fixtures.h"
#include "clar/fs.h"
diff --git a/t/unit-tests/clar/clar.h b/t/unit-tests/clar/clar.h
index 8c22382bd5..ca72292ae9 100644
--- a/t/unit-tests/clar/clar.h
+++ b/t/unit-tests/clar/clar.h
@@ -8,6 +8,25 @@
#define __CLAR_TEST_H__
#include <stdlib.h>
+#include <limits.h>
+
+#if defined(_WIN32) && defined(CLAR_WIN32_LONGPATHS)
+# define CLAR_MAX_PATH 4096
+#elif defined(_WIN32)
+# define CLAR_MAX_PATH MAX_PATH
+#else
+# define CLAR_MAX_PATH PATH_MAX
+#endif
+
+#ifndef CLAR_SELFTEST
+# define CLAR_CURRENT_FILE __FILE__
+# define CLAR_CURRENT_LINE __LINE__
+# define CLAR_CURRENT_FUNC __func__
+#else
+# define CLAR_CURRENT_FILE "file"
+# define CLAR_CURRENT_LINE 42
+# define CLAR_CURRENT_FUNC "func"
+#endif
enum cl_test_status {
CL_TEST_OK,
@@ -30,6 +49,7 @@ void clar_test_shutdown(void);
int clar_test(int argc, char *argv[]);
const char *clar_sandbox_path(void);
+const char *clar_tempdir_path(void);
void cl_set_cleanup(void (*cleanup)(void *), void *opaque);
void cl_fs_cleanup(void);
@@ -84,18 +104,32 @@ const char *cl_fixture_basename(const char *fixture_name);
#endif
/**
+ * Invoke a helper function, which itself will use `cl_assert`
+ * constructs. This will preserve the stack information of the
+ * current call point, so that function name and line number
+ * information is shown from the line of the test, instead of
+ * the helper function.
+ */
+#define cl_invoke(expr) \
+ do { \
+ clar__set_invokepoint(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE); \
+ expr; \
+ clar__clear_invokepoint(); \
+ } while(0)
+
+/**
* Assertion macros with explicit error message
*/
-#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 1)
-#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 1)
-#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 1)
+#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Function call failed: " #expr, desc, 1)
+#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expected function call to fail: " #expr, desc, 1)
+#define cl_assert_(expr, desc) clar__assert((expr) != 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expression is not true: " #expr, desc, 1)
/**
* Check macros with explicit error message
*/
-#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 0)
-#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 0)
-#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 0)
+#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Function call failed: " #expr, desc, 0)
+#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expected function call to fail: " #expr, desc, 0)
+#define cl_check_(expr, desc) clar__assert((expr) != 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expression is not true: " #expr, desc, 0)
/**
* Assertion macros with no error message
@@ -114,33 +148,33 @@ const char *cl_fixture_basename(const char *fixture_name);
/**
* Forced failure/warning
*/
-#define cl_fail(desc) clar__fail(__FILE__, __func__, __LINE__, "Test failed.", desc, 1)
-#define cl_warning(desc) clar__fail(__FILE__, __func__, __LINE__, "Warning during test execution:", desc, 0)
+#define cl_fail(desc) clar__fail(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Test failed.", desc, 1)
+#define cl_warning(desc) clar__fail(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Warning during test execution:", desc, 0)
#define cl_skip() clar__skip()
/**
* Typed assertion macros
*/
-#define cl_assert_equal_s(s1,s2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2))
-#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2))
+#define cl_assert_equal_s(s1,s2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2))
+#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2))
-#define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2))
-#define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2))
+#define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2))
+#define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2))
-#define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len))
-#define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len))
+#define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len))
+#define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len))
-#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len))
-#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len))
+#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len))
+#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len))
-#define cl_assert_equal_i(i1,i2) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2))
-#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2))
-#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2))
+#define cl_assert_equal_i(i1,i2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2))
+#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2))
+#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2))
-#define cl_assert_equal_b(b1,b2) clar__assert_equal(__FILE__,__func__,__LINE__,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0))
+#define cl_assert_equal_b(b1,b2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0))
-#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__func__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2))
+#define cl_assert_equal_p(p1,p2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2))
void clar__skip(void);
@@ -170,4 +204,11 @@ void clar__assert_equal(
const char *fmt,
...);
+void clar__set_invokepoint(
+ const char *file,
+ const char *func,
+ size_t line);
+
+void clar__clear_invokepoint(void);
+
#endif
diff --git a/t/unit-tests/clar/clar/fixtures.h b/t/unit-tests/clar/clar/fixtures.h
index 6ec6423484..9f1023df59 100644
--- a/t/unit-tests/clar/clar/fixtures.h
+++ b/t/unit-tests/clar/clar/fixtures.h
@@ -2,7 +2,7 @@
static const char *
fixture_path(const char *base, const char *fixture_name)
{
- static char _path[4096];
+ static char _path[CLAR_MAX_PATH];
size_t root_len;
root_len = strlen(base);
@@ -28,7 +28,7 @@ const char *cl_fixture(const char *fixture_name)
void cl_fixture_sandbox(const char *fixture_name)
{
- fs_copy(cl_fixture(fixture_name), _clar_path);
+ fs_copy(cl_fixture(fixture_name), clar_sandbox_path());
}
const char *cl_fixture_basename(const char *fixture_name)
@@ -45,6 +45,6 @@ const char *cl_fixture_basename(const char *fixture_name)
void cl_fixture_cleanup(const char *fixture_name)
{
- fs_rm(fixture_path(_clar_path, cl_fixture_basename(fixture_name)));
+ fs_rm(fixture_path(clar_sandbox_path(), cl_fixture_basename(fixture_name)));
}
#endif
diff --git a/t/unit-tests/clar/clar/fs.h b/t/unit-tests/clar/clar/fs.h
index 2203743fb4..f1311d91e8 100644
--- a/t/unit-tests/clar/clar/fs.h
+++ b/t/unit-tests/clar/clar/fs.h
@@ -8,12 +8,6 @@
#ifdef _WIN32
-#ifdef CLAR_WIN32_LONGPATHS
-# define CLAR_MAX_PATH 4096
-#else
-# define CLAR_MAX_PATH MAX_PATH
-#endif
-
#define RM_RETRY_COUNT 5
#define RM_RETRY_DELAY 10
@@ -296,7 +290,7 @@ void
cl_fs_cleanup(void)
{
#ifdef CLAR_FIXTURE_PATH
- fs_rm(fixture_path(_clar_path, "*"));
+ fs_rm(fixture_path(clar_tempdir_path(), "*"));
#else
((void)fs_copy); /* unused */
#endif
@@ -371,17 +365,19 @@ static void
fs_copydir_helper(const char *source, const char *dest, int dest_mode)
{
DIR *source_dir;
- struct dirent *d;
mkdir(dest, dest_mode);
cl_assert_(source_dir = opendir(source), "Could not open source dir");
- for (;;) {
+ while (1) {
+ struct dirent *d;
char *child;
errno = 0;
- if ((d = readdir(source_dir)) == NULL)
+ d = readdir(source_dir);
+ if (!d)
break;
+
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
@@ -479,15 +475,18 @@ static void
fs_rmdir_helper(const char *path)
{
DIR *dir;
- struct dirent *d;
cl_assert_(dir = opendir(path), "Could not open dir");
- for (;;) {
+
+ while (1) {
+ struct dirent *d;
char *child;
errno = 0;
- if ((d = readdir(dir)) == NULL)
+ d = readdir(dir);
+ if (!d)
break;
+
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
@@ -524,7 +523,7 @@ fs_rm(const char *path)
void
cl_fs_cleanup(void)
{
- clar_unsandbox();
- clar_sandbox();
+ clar_tempdir_shutdown();
+ clar_tempdir_init();
}
#endif
diff --git a/t/unit-tests/clar/clar/print.h b/t/unit-tests/clar/clar/print.h
index 69d0ee967e..89b66591d7 100644
--- a/t/unit-tests/clar/clar/print.h
+++ b/t/unit-tests/clar/clar/print.h
@@ -1,9 +1,13 @@
/* clap: clar protocol, the traditional clar output format */
-static void clar_print_clap_init(int test_count, int suite_count, const char *suite_names)
+static void clar_print_clap_init(int test_count, int suite_count)
{
(void)test_count;
- printf("Loaded %d suites: %s\n", (int)suite_count, suite_names);
+
+ if (_clar.verbosity < 0)
+ return;
+
+ printf("Loaded %d suites:\n", (int)suite_count);
printf("Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')\n");
}
@@ -13,10 +17,27 @@ static void clar_print_clap_shutdown(int test_count, int suite_count, int error_
(void)suite_count;
(void)error_count;
- printf("\n\n");
+ if (_clar.verbosity >= 0)
+ printf("\n\n");
clar_report_all();
}
+
+static void clar_print_indented(const char *str, int indent)
+{
+ const char *bol, *eol;
+
+ for (bol = str; *bol; bol = eol) {
+ eol = strchr(bol, '\n');
+ if (eol)
+ eol++;
+ else
+ eol = bol + strlen(bol);
+ printf("%*s%.*s", indent, "", (int)(eol - bol), bol);
+ }
+ putc('\n', stdout);
+}
+
static void clar_print_clap_error(int num, const struct clar_report *report, const struct clar_error *error)
{
printf(" %d) Failure:\n", num);
@@ -27,10 +48,10 @@ static void clar_print_clap_error(int num, const struct clar_report *report, con
error->file,
error->line_number);
- printf(" %s\n", error->error_msg);
+ clar_print_indented(error->error_msg, 2);
if (error->description != NULL)
- printf(" %s\n", error->description);
+ clar_print_indented(error->description, 2);
printf("\n");
fflush(stdout);
@@ -41,14 +62,17 @@ static void clar_print_clap_ontest(const char *suite_name, const char *test_name
(void)test_name;
(void)test_number;
+ if (_clar.verbosity < 0)
+ return;
+
if (_clar.verbosity > 1) {
printf("%s::%s: ", suite_name, test_name);
switch (status) {
case CL_TEST_OK: printf("ok\n"); break;
case CL_TEST_FAILURE: printf("fail\n"); break;
- case CL_TEST_SKIP: printf("skipped"); break;
- case CL_TEST_NOTRUN: printf("notrun"); break;
+ case CL_TEST_SKIP: printf("skipped\n"); break;
+ case CL_TEST_NOTRUN: printf("notrun\n"); break;
}
} else {
switch (status) {
@@ -64,6 +88,8 @@ static void clar_print_clap_ontest(const char *suite_name, const char *test_name
static void clar_print_clap_onsuite(const char *suite_name, int suite_index)
{
+ if (_clar.verbosity < 0)
+ return;
if (_clar.verbosity == 1)
printf("\n%s", suite_name);
@@ -77,11 +103,10 @@ static void clar_print_clap_onabort(const char *fmt, va_list arg)
/* tap: test anywhere protocol format */
-static void clar_print_tap_init(int test_count, int suite_count, const char *suite_names)
+static void clar_print_tap_init(int test_count, int suite_count)
{
(void)test_count;
(void)suite_count;
- (void)suite_names;
printf("TAP version 13\n");
}
@@ -127,18 +152,20 @@ static void clar_print_tap_ontest(const char *suite_name, const char *test_name,
case CL_TEST_FAILURE:
printf("not ok %d - %s::%s\n", test_number, suite_name, test_name);
- printf(" ---\n");
- printf(" reason: |\n");
- printf(" %s\n", error->error_msg);
+ if (_clar.verbosity >= 0) {
+ printf(" ---\n");
+ printf(" reason: |\n");
+ clar_print_indented(error->error_msg, 6);
- if (error->description)
- printf(" %s\n", error->description);
+ if (error->description)
+ clar_print_indented(error->description, 6);
- printf(" at:\n");
- printf(" file: '"); print_escaped(error->file); printf("'\n");
- printf(" line: %" PRIuMAX "\n", error->line_number);
- printf(" function: '%s'\n", error->function);
- printf(" ---\n");
+ printf(" at:\n");
+ printf(" file: '"); print_escaped(error->file); printf("'\n");
+ printf(" line: %" PRIuMAX "\n", error->line_number);
+ printf(" function: '%s'\n", error->function);
+ printf(" ---\n");
+ }
break;
case CL_TEST_SKIP:
@@ -152,6 +179,8 @@ static void clar_print_tap_ontest(const char *suite_name, const char *test_name,
static void clar_print_tap_onsuite(const char *suite_name, int suite_index)
{
+ if (_clar.verbosity < 0)
+ return;
printf("# start of suite %d: %s\n", suite_index, suite_name);
}
@@ -177,9 +206,9 @@ static void clar_print_tap_onabort(const char *fmt, va_list arg)
} \
} while (0)
-static void clar_print_init(int test_count, int suite_count, const char *suite_names)
+static void clar_print_init(int test_count, int suite_count)
{
- PRINT(init, test_count, suite_count, suite_names);
+ PRINT(init, test_count, suite_count);
}
static void clar_print_shutdown(int test_count, int suite_count, int error_count)
diff --git a/t/unit-tests/clar/clar/sandbox.h b/t/unit-tests/clar/clar/sandbox.h
index bc960f50e0..52add8aceb 100644
--- a/t/unit-tests/clar/clar/sandbox.h
+++ b/t/unit-tests/clar/clar/sandbox.h
@@ -2,7 +2,17 @@
#include <sys/syslimits.h>
#endif
-static char _clar_path[4096 + 1];
+/*
+ * The tempdir is the temporary directory for the entirety of the clar
+ * process execution. The sandbox is an individual temporary directory
+ * for the execution of an individual test. Sandboxes are deleted
+ * entirely after test execution to avoid pollution across tests.
+ */
+
+static char _clar_tempdir[CLAR_MAX_PATH];
+static size_t _clar_tempdir_len;
+
+static char _clar_sandbox[CLAR_MAX_PATH];
static int
is_valid_tmp_path(const char *path)
@@ -15,7 +25,10 @@ is_valid_tmp_path(const char *path)
if (!S_ISDIR(st.st_mode))
return 0;
- return (access(path, W_OK) == 0);
+ if (access(path, W_OK) != 0)
+ return 0;
+
+ return (strlen(path) < CLAR_MAX_PATH);
}
static int
@@ -31,14 +44,11 @@ find_tmp_path(char *buffer, size_t length)
for (i = 0; i < var_count; ++i) {
const char *env = getenv(env_vars[i]);
+
if (!env)
continue;
if (is_valid_tmp_path(env)) {
-#ifdef __APPLE__
- if (length >= PATH_MAX && realpath(env, buffer) != NULL)
- return 0;
-#endif
strncpy(buffer, env, length - 1);
buffer[length - 1] = '\0';
return 0;
@@ -47,21 +57,18 @@ find_tmp_path(char *buffer, size_t length)
/* If the environment doesn't say anything, try to use /tmp */
if (is_valid_tmp_path("/tmp")) {
-#ifdef __APPLE__
- if (length >= PATH_MAX && realpath("/tmp", buffer) != NULL)
- return 0;
-#endif
strncpy(buffer, "/tmp", length - 1);
buffer[length - 1] = '\0';
return 0;
}
#else
- DWORD env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length);
- if (env_len > 0 && env_len < (DWORD)length)
+ DWORD len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length);
+ if (len > 0 && len < (DWORD)length)
return 0;
- if (GetTempPath((DWORD)length, buffer))
+ len = GetTempPath((DWORD)length, buffer);
+ if (len > 0 && len < (DWORD)length)
return 0;
#endif
@@ -75,17 +82,53 @@ find_tmp_path(char *buffer, size_t length)
return -1;
}
-static void clar_unsandbox(void)
+static int canonicalize_tmp_path(char *buffer)
+{
+#ifdef _WIN32
+ char tmp[CLAR_MAX_PATH], *p;
+ DWORD ret;
+
+ ret = GetFullPathName(buffer, CLAR_MAX_PATH, tmp, NULL);
+
+ if (ret == 0 || ret > CLAR_MAX_PATH)
+ return -1;
+
+ ret = GetLongPathName(tmp, buffer, CLAR_MAX_PATH);
+
+ if (ret == 0 || ret > CLAR_MAX_PATH)
+ return -1;
+
+ /* normalize path to POSIX forward slashes */
+ for (p = buffer; *p; p++)
+ if (*p == '\\')
+ *p = '/';
+
+ return 0;
+#elif defined(CLAR_HAS_REALPATH)
+ char tmp[CLAR_MAX_PATH];
+
+ if (realpath(buffer, tmp) == NULL)
+ return -1;
+
+ strcpy(buffer, tmp);
+ return 0;
+#else
+ (void)buffer;
+ return 0;
+#endif
+}
+
+static void clar_tempdir_shutdown(void)
{
- if (_clar_path[0] == '\0')
+ if (_clar_tempdir[0] == '\0')
return;
cl_must_pass(chdir(".."));
- fs_rm(_clar_path);
+ fs_rm(_clar_tempdir);
}
-static int build_sandbox_path(void)
+static int build_tempdir_path(void)
{
#ifdef CLAR_TMPDIR
const char path_tail[] = CLAR_TMPDIR "_XXXXXX";
@@ -95,64 +138,153 @@ static int build_sandbox_path(void)
size_t len;
- if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0)
+ if (find_tmp_path(_clar_tempdir, sizeof(_clar_tempdir)) < 0 ||
+ canonicalize_tmp_path(_clar_tempdir) < 0)
return -1;
- len = strlen(_clar_path);
+ len = strlen(_clar_tempdir);
-#ifdef _WIN32
- { /* normalize path to POSIX forward slashes */
- size_t i;
- for (i = 0; i < len; ++i) {
- if (_clar_path[i] == '\\')
- _clar_path[i] = '/';
- }
- }
-#endif
+ if (len + strlen(path_tail) + 2 > CLAR_MAX_PATH)
+ return -1;
- if (_clar_path[len - 1] != '/') {
- _clar_path[len++] = '/';
- }
+ if (_clar_tempdir[len - 1] != '/')
+ _clar_tempdir[len++] = '/';
- strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len);
+ strncpy(_clar_tempdir + len, path_tail, sizeof(_clar_tempdir) - len);
#if defined(__MINGW32__)
- if (_mktemp(_clar_path) == NULL)
+ if (_mktemp(_clar_tempdir) == NULL)
return -1;
- if (mkdir(_clar_path, 0700) != 0)
+ if (mkdir(_clar_tempdir, 0700) != 0)
return -1;
#elif defined(_WIN32)
- if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0)
+ if (_mktemp_s(_clar_tempdir, sizeof(_clar_tempdir)) != 0)
return -1;
- if (mkdir(_clar_path, 0700) != 0)
+ if (mkdir(_clar_tempdir, 0700) != 0)
return -1;
-#elif defined(__sun) || defined(__TANDEM)
- if (mktemp(_clar_path) == NULL)
+#elif defined(__sun) || defined(__TANDEM) || defined(__hpux)
+ if (mktemp(_clar_tempdir) == NULL)
return -1;
- if (mkdir(_clar_path, 0700) != 0)
+ if (mkdir(_clar_tempdir, 0700) != 0)
return -1;
#else
- if (mkdtemp(_clar_path) == NULL)
+ if (mkdtemp(_clar_tempdir) == NULL)
return -1;
#endif
+ _clar_tempdir_len = strlen(_clar_tempdir);
return 0;
}
-static void clar_sandbox(void)
+static void clar_tempdir_init(void)
{
- if (_clar_path[0] == '\0' && build_sandbox_path() < 0)
- clar_abort("Failed to build sandbox path.\n");
+ if (_clar_tempdir[0] == '\0' && build_tempdir_path() < 0)
+ clar_abort("Failed to build tempdir path.\n");
- if (chdir(_clar_path) != 0)
- clar_abort("Failed to change into sandbox directory '%s': %s.\n",
- _clar_path, strerror(errno));
+ if (chdir(_clar_tempdir) != 0)
+ clar_abort("Failed to change into tempdir '%s': %s.\n",
+ _clar_tempdir, strerror(errno));
+
+#if !defined(CLAR_SANDBOX_TEST_NAMES) && defined(_WIN32)
+ srand(clock() ^ (unsigned int)time(NULL) ^ GetCurrentProcessId() ^ GetCurrentThreadId());
+#elif !defined(CLAR_SANDBOX_TEST_NAMES)
+ srand(clock() ^ time(NULL) ^ ((unsigned)getpid() << 16));
+#endif
+}
+
+static void append(char *dst, const char *src)
+{
+ char *d;
+ const char *s;
+
+ for (d = dst; *d; d++)
+ ;
+
+ for (s = src; *s; d++, s++)
+ if (*s == ':')
+ *d = '_';
+ else
+ *d = *s;
+
+ *d = '\0';
+}
+
+static int clar_sandbox_create(const char *suite_name, const char *test_name)
+{
+#ifndef CLAR_SANDBOX_TEST_NAMES
+ char alpha[] = "0123456789abcdef";
+ int num = rand();
+#endif
+
+ cl_assert(_clar_sandbox[0] == '\0');
+
+ /*
+ * We may want to use test names as sandbox directory names for
+ * readability, _however_ on platforms with restrictions for short
+ * file / folder names (eg, Windows), this may be too long.
+ */
+#ifdef CLAR_SANDBOX_TEST_NAMES
+ cl_assert(strlen(_clar_tempdir) + strlen(suite_name) + strlen(test_name) + 3 < CLAR_MAX_PATH);
+
+ strcpy(_clar_sandbox, _clar_tempdir);
+ _clar_sandbox[_clar_tempdir_len] = '/';
+ _clar_sandbox[_clar_tempdir_len + 1] = '\0';
+
+ append(_clar_sandbox, suite_name);
+ append(_clar_sandbox, "__");
+ append(_clar_sandbox, test_name);
+#else
+ ((void)suite_name);
+ ((void)test_name);
+ ((void)append);
+
+ cl_assert(strlen(_clar_tempdir) + 9 < CLAR_MAX_PATH);
+
+ strcpy(_clar_sandbox, _clar_tempdir);
+ _clar_sandbox[_clar_tempdir_len] = '/';
+
+ _clar_sandbox[_clar_tempdir_len + 1] = alpha[(num & 0xf0000000) >> 28];
+ _clar_sandbox[_clar_tempdir_len + 2] = alpha[(num & 0x0f000000) >> 24];
+ _clar_sandbox[_clar_tempdir_len + 3] = alpha[(num & 0x00f00000) >> 20];
+ _clar_sandbox[_clar_tempdir_len + 4] = alpha[(num & 0x000f0000) >> 16];
+ _clar_sandbox[_clar_tempdir_len + 5] = alpha[(num & 0x0000f000) >> 12];
+ _clar_sandbox[_clar_tempdir_len + 6] = alpha[(num & 0x00000f00) >> 8];
+ _clar_sandbox[_clar_tempdir_len + 7] = alpha[(num & 0x000000f0) >> 4];
+ _clar_sandbox[_clar_tempdir_len + 8] = alpha[(num & 0x0000000f) >> 0];
+ _clar_sandbox[_clar_tempdir_len + 9] = '\0';
+#endif
+
+ if (mkdir(_clar_sandbox, 0700) != 0)
+ return -1;
+
+ if (chdir(_clar_sandbox) != 0)
+ return -1;
+
+ return 0;
+}
+
+static int clar_sandbox_cleanup(void)
+{
+ cl_assert(_clar_sandbox[0] != '\0');
+
+ if (chdir(_clar_tempdir) != 0)
+ return -1;
+
+ fs_rm(_clar_sandbox);
+ _clar_sandbox[0] = '\0';
+
+ return 0;
+}
+
+const char *clar_tempdir_path(void)
+{
+ return _clar_tempdir;
}
const char *clar_sandbox_path(void)
{
- return _clar_path;
+ return _clar_sandbox;
}
diff --git a/t/unit-tests/clar/clar/summary.h b/t/unit-tests/clar/clar/summary.h
index 0d0b646fe7..7b85f162d8 100644
--- a/t/unit-tests/clar/clar/summary.h
+++ b/t/unit-tests/clar/clar/summary.h
@@ -23,10 +23,11 @@ static int clar_summary_testsuite(struct clar_summary *summary,
int idn, const char *name, time_t timestamp,
int test_count, int fail_count, int error_count)
{
- struct tm *tm = localtime(&timestamp);
+ struct tm tm;
char iso_dt[20];
- if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", tm) == 0)
+ localtime_r(&timestamp, &tm);
+ if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", &tm) == 0)
return -1;
return fprintf(summary->fp, "\t<testsuite"
diff --git a/t/unit-tests/clar/example/CMakeLists.txt b/t/unit-tests/clar/example/CMakeLists.txt
new file mode 100644
index 0000000000..b72f187523
--- /dev/null
+++ b/t/unit-tests/clar/example/CMakeLists.txt
@@ -0,0 +1,28 @@
+find_package(Python COMPONENTS Interpreter REQUIRED)
+
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
+ COMMAND "${Python_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/generate.py" --output "${CMAKE_CURRENT_BINARY_DIR}"
+ DEPENDS main.c example.c
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+)
+
+add_executable(example)
+set_target_properties(example PROPERTIES
+ C_STANDARD 90
+ C_STANDARD_REQUIRED ON
+ C_EXTENSIONS OFF
+)
+target_sources(example PRIVATE
+ main.c
+ example.c
+ "${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
+)
+target_compile_definitions(example PRIVATE)
+target_compile_options(example PRIVATE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,/W4,-Wall>
+)
+target_include_directories(example PRIVATE
+ "${CMAKE_SOURCE_DIR}"
+ "${CMAKE_CURRENT_BINARY_DIR}"
+)
+target_link_libraries(example clar)
diff --git a/t/unit-tests/clar/example/example.c b/t/unit-tests/clar/example/example.c
new file mode 100644
index 0000000000..c07d6bf68e
--- /dev/null
+++ b/t/unit-tests/clar/example/example.c
@@ -0,0 +1,6 @@
+#include "clar.h"
+
+void test_example__simple_assert(void)
+{
+ cl_assert_equal_i(1, 1);
+}
diff --git a/t/unit-tests/clar/test/main.c.sample b/t/unit-tests/clar/example/main.c
index a4d91b72fa..f8def7fa6e 100644
--- a/t/unit-tests/clar/test/main.c.sample
+++ b/t/unit-tests/clar/example/main.c
@@ -5,7 +5,7 @@
* For full terms see the included COPYING file.
*/
-#include "clar_test.h"
+#include "clar.h"
/*
* Minimal main() for clar tests.
diff --git a/t/unit-tests/clar/generate.py b/t/unit-tests/clar/generate.py
index 80996ac3e7..fd2f0ee83b 100755
--- a/t/unit-tests/clar/generate.py
+++ b/t/unit-tests/clar/generate.py
@@ -158,17 +158,24 @@ class TestSuite(object):
def find_modules(self):
modules = []
- for root, _, files in os.walk(self.path):
- module_root = root[len(self.path):]
- module_root = [c for c in module_root.split(os.sep) if c]
- tests_in_module = fnmatch.filter(files, "*.c")
+ if os.path.isfile(self.path):
+ full_path = os.path.abspath(self.path)
+ module_name = os.path.basename(self.path)
+ module_name = os.path.splitext(module_name)[0]
+ modules.append((full_path, module_name))
+ else:
+ for root, _, files in os.walk(self.path):
+ module_root = root[len(self.path):]
+ module_root = [c for c in module_root.split(os.sep) if c]
- for test_file in tests_in_module:
- full_path = os.path.join(root, test_file)
- module_name = "_".join(module_root + [test_file[:-2]]).replace("-", "_")
+ tests_in_module = fnmatch.filter(files, "*.c")
- modules.append((full_path, module_name))
+ for test_file in tests_in_module:
+ full_path = os.path.join(root, test_file)
+ module_name = "_".join(module_root + [test_file[:-2]]).replace("-", "_")
+
+ modules.append((full_path, module_name))
return modules
@@ -217,6 +224,7 @@ class TestSuite(object):
def write(self):
output = os.path.join(self.output, 'clar.suite')
+ os.makedirs(self.output, exist_ok=True)
if not self.should_generate(output):
return False
@@ -258,7 +266,11 @@ if __name__ == '__main__':
sys.exit(1)
path = args.pop() if args else '.'
+ if os.path.isfile(path) and not options.output:
+ print("Must provide --output when specifying a file")
+ sys.exit(1)
output = options.output or path
+
suite = TestSuite(path, output)
suite.load(options.force)
suite.disable(options.excluded)
diff --git a/t/unit-tests/clar/test/CMakeLists.txt b/t/unit-tests/clar/test/CMakeLists.txt
index 7f2c1dc17a..f240166439 100644
--- a/t/unit-tests/clar/test/CMakeLists.txt
+++ b/t/unit-tests/clar/test/CMakeLists.txt
@@ -2,12 +2,12 @@ find_package(Python COMPONENTS Interpreter REQUIRED)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
COMMAND "${Python_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/generate.py" --output "${CMAKE_CURRENT_BINARY_DIR}"
- DEPENDS main.c sample.c clar_test.h
+ DEPENDS main.c selftest.c
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
-add_executable(clar_test)
-set_target_properties(clar_test PROPERTIES
+add_executable(selftest)
+set_target_properties(selftest PROPERTIES
C_STANDARD 90
C_STANDARD_REQUIRED ON
C_EXTENSIONS OFF
@@ -15,25 +15,35 @@ set_target_properties(clar_test PROPERTIES
# MSVC generates all kinds of warnings. We may want to fix these in the future
# and then unconditionally treat warnings as errors.
-if(NOT MSVC)
- set_target_properties(clar_test PROPERTIES
+if (NOT MSVC)
+ set_target_properties(selftest PROPERTIES
COMPILE_WARNING_AS_ERROR ON
)
endif()
-target_sources(clar_test PRIVATE
+target_sources(selftest PRIVATE
main.c
- sample.c
+ selftest.c
"${CMAKE_CURRENT_BINARY_DIR}/clar.suite"
)
-target_compile_definitions(clar_test PRIVATE
- CLAR_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/"
+target_compile_definitions(selftest PRIVATE
+ CLAR_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/expected/"
)
-target_compile_options(clar_test PRIVATE
+target_compile_options(selftest PRIVATE
$<IF:$<CXX_COMPILER_ID:MSVC>,/W4,-Wall>
)
-target_include_directories(clar_test PRIVATE
+target_include_directories(selftest PRIVATE
"${CMAKE_SOURCE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}"
)
-target_link_libraries(clar_test clar)
+target_link_libraries(selftest clar)
+
+add_test(NAME build_selftest
+ COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --config "$<CONFIG>" --target selftest
+)
+set_tests_properties(build_selftest PROPERTIES FIXTURES_SETUP clar_test_fixture)
+
+add_subdirectory(suites)
+
+add_test(NAME selftest COMMAND "${CMAKE_CURRENT_BINARY_DIR}/selftest" $<TARGET_FILE_DIR:combined_suite>)
+set_tests_properties(selftest PROPERTIES FIXTURES_REQUIRED clar_test_fixture)
diff --git a/t/unit-tests/clar/test/clar_test.h b/t/unit-tests/clar/test/clar_test.h
deleted file mode 100644
index 0fcaa639aa..0000000000
--- a/t/unit-tests/clar/test/clar_test.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) Vicent Marti. All rights reserved.
- *
- * This file is part of clar, distributed under the ISC license.
- * For full terms see the included COPYING file.
- */
-#ifndef __CLAR_TEST__
-#define __CLAR_TEST__
-
-/* Import the standard clar helper functions */
-#include "clar.h"
-
-/* Your custom shared includes / defines here */
-extern int global_test_counter;
-
-#endif
diff --git a/t/unit-tests/clar/test/expected/help b/t/unit-tests/clar/test/expected/help
new file mode 100644
index 0000000000..9428def2d7
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/help
@@ -0,0 +1,12 @@
+Usage: combined [options]
+
+Options:
+ -sname Run only the suite with `name` (can go to individual test name)
+ -iname Include the suite with `name`
+ -xname Exclude the suite with `name`
+ -v Increase verbosity (show suite names)
+ -q Decrease verbosity, inverse to -v
+ -Q Quit as soon as a test fails
+ -t Display results in tap format
+ -l Print suite names
+ -r[filename] Write summary file (to the optional filename)
diff --git a/t/unit-tests/clar/test/expected/quiet b/t/unit-tests/clar/test/expected/quiet
new file mode 100644
index 0000000000..280c99d8ad
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/quiet
@@ -0,0 +1,44 @@
+ 1) Failure:
+combined::1 [file:42]
+ Function call failed: -1
+
+ 2) Failure:
+combined::2 [file:42]
+ Expression is not true: 100 == 101
+
+ 3) Failure:
+combined::strings [file:42]
+ String mismatch: "mismatched" != actual ("this one fails")
+ 'mismatched' != 'expected' (at byte 0)
+
+ 4) Failure:
+combined::strings_with_length [file:42]
+ String mismatch: "exactly" != actual ("this one fails")
+ 'exa' != 'exp' (at byte 2)
+
+ 5) Failure:
+combined::int [file:42]
+ 101 != value ("extra note on failing test")
+ 101 != 100
+
+ 6) Failure:
+combined::int_fmt [file:42]
+ 022 != value
+ 0022 != 0144
+
+ 7) Failure:
+combined::bool [file:42]
+ 0 != value
+ 0 != 1
+
+ 8) Failure:
+combined::multiline_description [file:42]
+ Function call failed: -1
+ description line 1
+ description line 2
+
+ 9) Failure:
+combined::null_string [file:42]
+ String mismatch: "expected" != actual ("this one fails")
+ 'expected' != NULL
+
diff --git a/t/unit-tests/clar/test/expected/specific_test b/t/unit-tests/clar/test/expected/specific_test
new file mode 100644
index 0000000000..6c22e9f507
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/specific_test
@@ -0,0 +1,9 @@
+Loaded 1 suites:
+Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
+F
+
+ 1) Failure:
+combined::bool [file:42]
+ 0 != value
+ 0 != 1
+
diff --git a/t/unit-tests/clar/test/expected/stop_on_failure b/t/unit-tests/clar/test/expected/stop_on_failure
new file mode 100644
index 0000000000..c23610754f
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/stop_on_failure
@@ -0,0 +1,8 @@
+Loaded 1 suites:
+Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
+F
+
+ 1) Failure:
+combined::1 [file:42]
+ Function call failed: -1
+
diff --git a/t/unit-tests/clar/test/expected/suite_names b/t/unit-tests/clar/test/expected/suite_names
new file mode 100644
index 0000000000..10d1538427
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/suite_names
@@ -0,0 +1,2 @@
+Test suites (use -s<name> to run just one):
+ 0: combined
diff --git a/t/unit-tests/clar/test/expected/summary.xml b/t/unit-tests/clar/test/expected/summary.xml
new file mode 100644
index 0000000000..9a89d43a59
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/summary.xml
@@ -0,0 +1,41 @@
+<testsuites>
+ <testsuite id="0" name="selftest" hostname="localhost" timestamp="2024-09-06T10:04:08" tests="8" failures="8" errors="0">
+ <testcase name="1" classname="selftest" time="0.00">
+ <failure type="assert"><![CDATA[Function call failed: -1
+(null)]]></failure>
+ </testcase>
+ <testcase name="2" classname="selftest" time="0.00">
+ <failure type="assert"><![CDATA[Expression is not true: 100 == 101
+(null)]]></failure>
+ </testcase>
+ <testcase name="strings" classname="selftest" time="0.00">
+ <failure type="assert"><![CDATA[String mismatch: "mismatched" != actual ("this one fails")
+'mismatched' != 'expected' (at byte 0)]]></failure>
+ </testcase>
+ <testcase name="strings_with_length" classname="selftest" time="0.00">
+ <failure type="assert"><![CDATA[String mismatch: "exactly" != actual ("this one fails")
+'exa' != 'exp' (at byte 2)]]></failure>
+ </testcase>
+ <testcase name="int" classname="selftest" time="0.00">
+ <failure type="assert"><![CDATA[101 != value ("extra note on failing test")
+101 != 100]]></failure>
+ </testcase>
+ <testcase name="int_fmt" classname="selftest" time="0.00">
+ <failure type="assert"><![CDATA[022 != value
+0022 != 0144]]></failure>
+ </testcase>
+ <testcase name="bool" classname="selftest" time="0.00">
+ <failure type="assert"><![CDATA[0 != value
+0 != 1]]></failure>
+ </testcase>
+ <testcase name="multiline_description" classname="selftest" time="0.00">
+ <failure type="assert"><![CDATA[Function call failed: −1
+description line 1
+description line 2]]></failure>
+ </testcase>
+ <testcase name="null_string" classname="selftest" time="0.00">
+ <failure type="assert"><![CDATA[String mismatch: "expected" != actual ("this one fails")
+'expected' != NULL]]></failure>
+ </testcase>
+ </testsuite>
+</testsuites>
diff --git a/t/unit-tests/clar/test/expected/summary_with_filename b/t/unit-tests/clar/test/expected/summary_with_filename
new file mode 100644
index 0000000000..460160791d
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/summary_with_filename
@@ -0,0 +1,49 @@
+Loaded 1 suites:
+Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
+FFFFFFFFF
+
+ 1) Failure:
+combined::1 [file:42]
+ Function call failed: -1
+
+ 2) Failure:
+combined::2 [file:42]
+ Expression is not true: 100 == 101
+
+ 3) Failure:
+combined::strings [file:42]
+ String mismatch: "mismatched" != actual ("this one fails")
+ 'mismatched' != 'expected' (at byte 0)
+
+ 4) Failure:
+combined::strings_with_length [file:42]
+ String mismatch: "exactly" != actual ("this one fails")
+ 'exa' != 'exp' (at byte 2)
+
+ 5) Failure:
+combined::int [file:42]
+ 101 != value ("extra note on failing test")
+ 101 != 100
+
+ 6) Failure:
+combined::int_fmt [file:42]
+ 022 != value
+ 0022 != 0144
+
+ 7) Failure:
+combined::bool [file:42]
+ 0 != value
+ 0 != 1
+
+ 8) Failure:
+combined::multiline_description [file:42]
+ Function call failed: -1
+ description line 1
+ description line 2
+
+ 9) Failure:
+combined::null_string [file:42]
+ String mismatch: "expected" != actual ("this one fails")
+ 'expected' != NULL
+
+written summary file to different.xml
diff --git a/t/unit-tests/clar/test/expected/summary_without_filename b/t/unit-tests/clar/test/expected/summary_without_filename
new file mode 100644
index 0000000000..7874c1d98b
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/summary_without_filename
@@ -0,0 +1,49 @@
+Loaded 1 suites:
+Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
+FFFFFFFFF
+
+ 1) Failure:
+combined::1 [file:42]
+ Function call failed: -1
+
+ 2) Failure:
+combined::2 [file:42]
+ Expression is not true: 100 == 101
+
+ 3) Failure:
+combined::strings [file:42]
+ String mismatch: "mismatched" != actual ("this one fails")
+ 'mismatched' != 'expected' (at byte 0)
+
+ 4) Failure:
+combined::strings_with_length [file:42]
+ String mismatch: "exactly" != actual ("this one fails")
+ 'exa' != 'exp' (at byte 2)
+
+ 5) Failure:
+combined::int [file:42]
+ 101 != value ("extra note on failing test")
+ 101 != 100
+
+ 6) Failure:
+combined::int_fmt [file:42]
+ 022 != value
+ 0022 != 0144
+
+ 7) Failure:
+combined::bool [file:42]
+ 0 != value
+ 0 != 1
+
+ 8) Failure:
+combined::multiline_description [file:42]
+ Function call failed: -1
+ description line 1
+ description line 2
+
+ 9) Failure:
+combined::null_string [file:42]
+ String mismatch: "expected" != actual ("this one fails")
+ 'expected' != NULL
+
+written summary file to summary.xml
diff --git a/t/unit-tests/clar/test/expected/tap b/t/unit-tests/clar/test/expected/tap
new file mode 100644
index 0000000000..bddbd5dfe9
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/tap
@@ -0,0 +1,92 @@
+TAP version 13
+# start of suite 1: combined
+not ok 1 - combined::1
+ ---
+ reason: |
+ Function call failed: -1
+ at:
+ file: 'file'
+ line: 42
+ function: 'func'
+ ---
+not ok 2 - combined::2
+ ---
+ reason: |
+ Expression is not true: 100 == 101
+ at:
+ file: 'file'
+ line: 42
+ function: 'func'
+ ---
+not ok 3 - combined::strings
+ ---
+ reason: |
+ String mismatch: "mismatched" != actual ("this one fails")
+ 'mismatched' != 'expected' (at byte 0)
+ at:
+ file: 'file'
+ line: 42
+ function: 'func'
+ ---
+not ok 4 - combined::strings_with_length
+ ---
+ reason: |
+ String mismatch: "exactly" != actual ("this one fails")
+ 'exa' != 'exp' (at byte 2)
+ at:
+ file: 'file'
+ line: 42
+ function: 'func'
+ ---
+not ok 5 - combined::int
+ ---
+ reason: |
+ 101 != value ("extra note on failing test")
+ 101 != 100
+ at:
+ file: 'file'
+ line: 42
+ function: 'func'
+ ---
+not ok 6 - combined::int_fmt
+ ---
+ reason: |
+ 022 != value
+ 0022 != 0144
+ at:
+ file: 'file'
+ line: 42
+ function: 'func'
+ ---
+not ok 7 - combined::bool
+ ---
+ reason: |
+ 0 != value
+ 0 != 1
+ at:
+ file: 'file'
+ line: 42
+ function: 'func'
+ ---
+not ok 8 - combined::multiline_description
+ ---
+ reason: |
+ Function call failed: -1
+ description line 1
+ description line 2
+ at:
+ file: 'file'
+ line: 42
+ function: 'func'
+ ---
+not ok 9 - combined::null_string
+ ---
+ reason: |
+ String mismatch: "expected" != actual ("this one fails")
+ 'expected' != NULL
+ at:
+ file: 'file'
+ line: 42
+ function: 'func'
+ ---
+1..9
diff --git a/t/unit-tests/clar/test/expected/without_arguments b/t/unit-tests/clar/test/expected/without_arguments
new file mode 100644
index 0000000000..1111d418a0
--- /dev/null
+++ b/t/unit-tests/clar/test/expected/without_arguments
@@ -0,0 +1,48 @@
+Loaded 1 suites:
+Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')
+FFFFFFFFF
+
+ 1) Failure:
+combined::1 [file:42]
+ Function call failed: -1
+
+ 2) Failure:
+combined::2 [file:42]
+ Expression is not true: 100 == 101
+
+ 3) Failure:
+combined::strings [file:42]
+ String mismatch: "mismatched" != actual ("this one fails")
+ 'mismatched' != 'expected' (at byte 0)
+
+ 4) Failure:
+combined::strings_with_length [file:42]
+ String mismatch: "exactly" != actual ("this one fails")
+ 'exa' != 'exp' (at byte 2)
+
+ 5) Failure:
+combined::int [file:42]
+ 101 != value ("extra note on failing test")
+ 101 != 100
+
+ 6) Failure:
+combined::int_fmt [file:42]
+ 022 != value
+ 0022 != 0144
+
+ 7) Failure:
+combined::bool [file:42]
+ 0 != value
+ 0 != 1
+
+ 8) Failure:
+combined::multiline_description [file:42]
+ Function call failed: -1
+ description line 1
+ description line 2
+
+ 9) Failure:
+combined::null_string [file:42]
+ String mismatch: "expected" != actual ("this one fails")
+ 'expected' != NULL
+
diff --git a/t/unit-tests/clar/test/main.c b/t/unit-tests/clar/test/main.c
index 59e56ad255..94af440643 100644
--- a/t/unit-tests/clar/test/main.c
+++ b/t/unit-tests/clar/test/main.c
@@ -1,23 +1,9 @@
-/*
- * Copyright (c) Vicent Marti. All rights reserved.
- *
- * This file is part of clar, distributed under the ISC license.
- * For full terms see the included COPYING file.
- */
+#include <stdio.h>
+#include <string.h>
-#include "clar_test.h"
+#include "selftest.h"
-/*
- * Sample main() for clar tests.
- *
- * You should write your own main routine for clar tests that does specific
- * setup and teardown as necessary for your application. The only required
- * line is the call to `clar_test(argc, argv)`, which will execute the test
- * suite. If you want to check the return value of the test application,
- * your main() should return the same value returned by clar_test().
- */
-
-int global_test_counter = 0;
+const char *selftest_suite_directory;
#ifdef _WIN32
int __cdecl main(int argc, char *argv[])
@@ -25,16 +11,15 @@ int __cdecl main(int argc, char *argv[])
int main(int argc, char *argv[])
#endif
{
- int ret;
-
- /* Your custom initialization here */
- global_test_counter = 0;
-
- /* Run the test suite */
- ret = clar_test(argc, argv);
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <selftest-suite-directory> <options>\n",
+ argv[0]);
+ exit(1);
+ }
- /* Your custom cleanup here */
- cl_assert_equal_i(8, global_test_counter);
+ selftest_suite_directory = argv[1];
+ memmove(argv + 1, argv + 2, argc - 1);
+ argc -= 1;
- return ret;
+ return clar_test(argc, argv);
}
diff --git a/t/unit-tests/clar/test/selftest.c b/t/unit-tests/clar/test/selftest.c
new file mode 100644
index 0000000000..eed83e4512
--- /dev/null
+++ b/t/unit-tests/clar/test/selftest.c
@@ -0,0 +1,370 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "selftest.h"
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+static char *read_full(HANDLE h, int is_pipe)
+{
+ char *data = NULL;
+ size_t data_size = 0;
+
+ while (1) {
+ CHAR buf[4096];
+ DWORD bytes_read;
+
+ if (!ReadFile(h, buf, sizeof(buf), &bytes_read, NULL)) {
+ if (!is_pipe)
+ cl_fail("Failed reading file handle.");
+ cl_assert_equal_i(GetLastError(), ERROR_BROKEN_PIPE);
+ break;
+ }
+ if (!bytes_read)
+ break;
+
+ data = realloc(data, data_size + bytes_read);
+ cl_assert(data);
+ memcpy(data + data_size, buf, bytes_read);
+ data_size += bytes_read;
+ }
+
+ data = realloc(data, data_size + 1);
+ cl_assert(data);
+ data[data_size] = '\0';
+
+ while (strstr(data, "\r\n")) {
+ char *ptr = strstr(data, "\r\n");
+ memmove(ptr, ptr + 1, strlen(ptr));
+ }
+
+ return data;
+}
+
+static char *read_file(const char *path)
+{
+ char *content;
+ HANDLE file;
+
+ file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ cl_assert(file != INVALID_HANDLE_VALUE);
+ content = read_full(file, 0);
+ cl_assert_equal_b(1, CloseHandle(file));
+
+ return content;
+}
+
+static char *execute(const char *suite, int expected_error_code, const char **args, size_t nargs)
+{
+ SECURITY_ATTRIBUTES security_attributes = { 0 };
+ PROCESS_INFORMATION process_info = { 0 };
+ STARTUPINFO startup_info = { 0 };
+ char binary_path[4096] = { 0 };
+ char cmdline[4096] = { 0 };
+ char *output = NULL;
+ HANDLE stdout_write;
+ HANDLE stdout_read;
+ DWORD exit_code;
+ size_t i;
+
+ snprintf(binary_path, sizeof(binary_path), "%s/%s_suite.exe",
+ selftest_suite_directory, suite);
+
+ /*
+ * Assemble command line arguments. In theory we'd have to properly
+ * quote them. In practice none of our tests actually care.
+ */
+ snprintf(cmdline, sizeof(cmdline), suite);
+ for (i = 0; i < nargs; i++) {
+ size_t cmdline_len = strlen(cmdline);
+ const char *arg = args[i];
+ cl_assert(cmdline_len + strlen(arg) < sizeof(cmdline));
+ snprintf(cmdline + cmdline_len, sizeof(cmdline) - cmdline_len,
+ " %s", arg);
+ }
+
+ /*
+ * Create a pipe that we will use to read data from the child process.
+ * The writing side needs to be inheritable such that the child can use
+ * it as stdout and stderr. The reading side should only be used by the
+ * parent.
+ */
+ security_attributes.nLength = sizeof(security_attributes);
+ security_attributes.bInheritHandle = TRUE;
+ cl_assert_equal_b(1, CreatePipe(&stdout_read, &stdout_write, &security_attributes, 0));
+ cl_assert_equal_b(1, SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0));
+
+ /*
+ * Create the child process with our pipe.
+ */
+ startup_info.cb = sizeof(startup_info);
+ startup_info.hStdError = stdout_write;
+ startup_info.hStdOutput = stdout_write;
+ startup_info.dwFlags |= STARTF_USESTDHANDLES;
+ cl_assert_equal_b(1, CreateProcess(binary_path, cmdline, NULL, NULL, TRUE,
+ 0, NULL, NULL, &startup_info, &process_info));
+ cl_assert_equal_b(1, CloseHandle(stdout_write));
+
+ output = read_full(stdout_read, 1);
+ cl_assert_equal_b(1, CloseHandle(stdout_read));
+ cl_assert_equal_b(1, GetExitCodeProcess(process_info.hProcess, &exit_code));
+ cl_assert_equal_i(exit_code, expected_error_code);
+
+ return output;
+}
+
+static void assert_output(const char *suite, const char *expected_output_file, int expected_error_code, ...)
+{
+ char *expected_output = NULL;
+ char *output = NULL;
+ const char *args[16];
+ va_list ap;
+ size_t i;
+
+ va_start(ap, expected_error_code);
+ for (i = 0; ; i++) {
+ const char *arg = va_arg(ap, const char *);
+ if (!arg)
+ break;
+ cl_assert(i < sizeof(args) / sizeof(*args));
+ args[i] = arg;
+ }
+ va_end(ap);
+
+ output = execute(suite, expected_error_code, args, i);
+ expected_output = read_file(cl_fixture(expected_output_file));
+ cl_assert_equal_s(output, expected_output);
+
+ free(expected_output);
+ free(output);
+}
+
+#else
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+# include <unistd.h>
+# include <sys/wait.h>
+
+static char *read_full(int fd)
+{
+ size_t data_bytes = 0;
+ char *data = NULL;
+
+ while (1) {
+ char buf[4096];
+ ssize_t n;
+
+ n = read(fd, buf, sizeof(buf));
+ if (n < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ cl_fail("Failed reading from child process.");
+ }
+ if (!n)
+ break;
+
+ data = realloc(data, data_bytes + n);
+ cl_assert(data);
+
+ memcpy(data + data_bytes, buf, n);
+ data_bytes += n;
+ }
+
+ data = realloc(data, data_bytes + 1);
+ cl_assert(data);
+ data[data_bytes] = '\0';
+
+ return data;
+}
+
+static char *read_file(const char *path)
+{
+ char *data;
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ cl_fail("Failed reading expected file.");
+
+ data = read_full(fd);
+ cl_must_pass(close(fd));
+
+ return data;
+}
+
+static char *execute(const char *suite, int expected_error_code, const char **args, size_t nargs)
+{
+ int pipe_fds[2];
+ pid_t pid;
+
+ cl_must_pass(pipe(pipe_fds));
+
+ pid = fork();
+ if (!pid) {
+ const char *final_args[17] = { NULL };
+ char binary_path[4096];
+ size_t len = 0;
+ size_t i;
+
+ cl_assert(nargs < sizeof(final_args) / sizeof(*final_args));
+ final_args[0] = suite;
+ for (i = 0; i < nargs; i++)
+ final_args[i + 1] = args[i];
+
+ if (dup2(pipe_fds[1], STDOUT_FILENO) < 0 ||
+ dup2(pipe_fds[1], STDERR_FILENO) < 0 ||
+ close(0) < 0 ||
+ close(pipe_fds[0]) < 0 ||
+ close(pipe_fds[1]) < 0)
+ exit(1);
+
+ cl_assert(len + strlen(selftest_suite_directory) < sizeof(binary_path));
+ strcpy(binary_path, selftest_suite_directory);
+ len += strlen(selftest_suite_directory);
+
+ cl_assert(len + 1 < sizeof(binary_path));
+ binary_path[len] = '/';
+ len += 1;
+
+ cl_assert(len + strlen(suite) < sizeof(binary_path));
+ strcpy(binary_path + len, suite);
+ len += strlen(suite);
+
+ cl_assert(len + strlen("_suite") < sizeof(binary_path));
+ strcpy(binary_path + len, "_suite");
+ len += strlen("_suite");
+
+ binary_path[len] = '\0';
+
+ execv(binary_path, (char **) final_args);
+ exit(1);
+ } else if (pid > 0) {
+ pid_t waited_pid;
+ char *output;
+ int stat;
+
+ cl_must_pass(close(pipe_fds[1]));
+
+ output = read_full(pipe_fds[0]);
+
+ waited_pid = waitpid(pid, &stat, 0);
+ cl_assert_equal_i(pid, waited_pid);
+ cl_assert(WIFEXITED(stat));
+ cl_assert_equal_i(WEXITSTATUS(stat), expected_error_code);
+
+ return output;
+ } else {
+ cl_fail("Fork failed.");
+ }
+
+ return NULL;
+}
+
+static void assert_output(const char *suite, const char *expected_output_file, int expected_error_code, ...)
+{
+ char *expected_output, *output;
+ const char *args[16];
+ va_list ap;
+ size_t i;
+
+ va_start(ap, expected_error_code);
+ for (i = 0; ; i++) {
+ cl_assert(i < sizeof(args) / sizeof(*args));
+ args[i] = va_arg(ap, const char *);
+ if (!args[i])
+ break;
+ }
+ va_end(ap);
+
+ output = execute(suite, expected_error_code, args, i);
+ expected_output = read_file(cl_fixture(expected_output_file));
+ cl_assert_equal_s(output, expected_output);
+
+ free(expected_output);
+ free(output);
+}
+#endif
+
+void test_selftest__help(void)
+{
+ cl_invoke(assert_output("combined", "help", 1, "-h", NULL));
+}
+
+void test_selftest__without_arguments(void)
+{
+ cl_invoke(assert_output("combined", "without_arguments", 9, NULL));
+}
+
+void test_selftest__specific_test(void)
+{
+ cl_invoke(assert_output("combined", "specific_test", 1, "-scombined::bool", NULL));
+}
+
+void test_selftest__stop_on_failure(void)
+{
+ cl_invoke(assert_output("combined", "stop_on_failure", 1, "-Q", NULL));
+}
+
+void test_selftest__quiet(void)
+{
+ cl_invoke(assert_output("combined", "quiet", 9, "-q", NULL));
+}
+
+void test_selftest__tap(void)
+{
+ cl_invoke(assert_output("combined", "tap", 9, "-t", NULL));
+}
+
+void test_selftest__suite_names(void)
+{
+ cl_invoke(assert_output("combined", "suite_names", 0, "-l", NULL));
+}
+
+void test_selftest__summary_without_filename(void)
+{
+ struct stat st;
+ cl_invoke(assert_output("combined", "summary_without_filename", 9, "-r", NULL));
+ /* The summary contains timestamps, so we cannot verify its contents. */
+ cl_must_pass(stat("summary.xml", &st));
+}
+
+void test_selftest__summary_with_filename(void)
+{
+ struct stat st;
+ cl_invoke(assert_output("combined", "summary_with_filename", 9, "-rdifferent.xml", NULL));
+ /* The summary contains timestamps, so we cannot verify its contents. */
+ cl_must_pass(stat("different.xml", &st));
+}
+
+void test_selftest__pointer_equal(void)
+{
+ const char *args[] = {
+ "-spointer::equal",
+ "-t"
+ };
+ char *output = execute("pointer", 0, args, 2);
+ cl_assert_equal_s(output,
+ "TAP version 13\n"
+ "# start of suite 1: pointer\n"
+ "ok 1 - pointer::equal\n"
+ "1..1\n"
+ );
+ free(output);
+}
+
+void test_selftest__pointer_unequal(void)
+{
+ const char *args[] = {
+ "-spointer::unequal",
+ };
+ char *output = execute("pointer", 1, args, 1);
+ cl_assert(output);
+ cl_assert(strstr(output, "Pointer mismatch: "));
+ free(output);
+}
diff --git a/t/unit-tests/clar/test/selftest.h b/t/unit-tests/clar/test/selftest.h
new file mode 100644
index 0000000000..c24e0c5af4
--- /dev/null
+++ b/t/unit-tests/clar/test/selftest.h
@@ -0,0 +1,3 @@
+#include "clar.h"
+
+extern const char *selftest_suite_directory;
diff --git a/t/unit-tests/clar/test/suites/CMakeLists.txt b/t/unit-tests/clar/test/suites/CMakeLists.txt
new file mode 100644
index 0000000000..fa8ab9416a
--- /dev/null
+++ b/t/unit-tests/clar/test/suites/CMakeLists.txt
@@ -0,0 +1,53 @@
+list(APPEND suites
+ "combined"
+ "pointer"
+)
+
+foreach(suite IN LISTS suites)
+ add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${suite}/clar.suite"
+ COMMAND "${Python_EXECUTABLE}"
+ "${CMAKE_SOURCE_DIR}/generate.py"
+ "${CMAKE_CURRENT_SOURCE_DIR}/${suite}.c"
+ --output "${CMAKE_CURRENT_BINARY_DIR}/${suite}"
+ DEPENDS ${suite}.c
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ )
+
+ add_executable(${suite}_suite)
+ set_target_properties(${suite}_suite PROPERTIES
+ C_STANDARD 90
+ C_STANDARD_REQUIRED ON
+ C_EXTENSIONS OFF
+ )
+
+ # MSVC generates all kinds of warnings. We may want to fix these in the future
+ # and then unconditionally treat warnings as errors.
+ if(NOT MSVC)
+ set_target_properties(${suite}_suite PROPERTIES
+ COMPILE_WARNING_AS_ERROR ON
+ )
+ endif()
+
+ target_sources(${suite}_suite PRIVATE
+ main.c
+ ${suite}.c
+ "${CMAKE_CURRENT_BINARY_DIR}/${suite}/clar.suite"
+ )
+ target_compile_definitions(${suite}_suite PRIVATE
+ CLAR_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/"
+ CLAR_SELFTEST
+ )
+ target_compile_options(${suite}_suite PRIVATE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,/W4,-Wall>
+ )
+ target_include_directories(${suite}_suite PRIVATE
+ "${CMAKE_SOURCE_DIR}"
+ "${CMAKE_CURRENT_BINARY_DIR}/${suite}"
+ )
+ target_link_libraries(${suite}_suite clar)
+
+ add_test(NAME build_${suite}_suite
+ COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --config "$<CONFIG>" --target selftest
+ )
+ set_tests_properties(build_${suite}_suite PROPERTIES FIXTURES_SETUP clar_test_fixture)
+endforeach()
diff --git a/t/unit-tests/clar/test/sample.c b/t/unit-tests/clar/test/suites/combined.c
index faa1209262..e8b41c98c3 100644
--- a/t/unit-tests/clar/test/sample.c
+++ b/t/unit-tests/clar/test/suites/combined.c
@@ -1,6 +1,7 @@
-#include "clar_test.h"
#include <sys/stat.h>
+#include "clar.h"
+
static int file_size(const char *filename)
{
struct stat st;
@@ -10,19 +11,14 @@ static int file_size(const char *filename)
return -1;
}
-void test_sample__initialize(void)
-{
- global_test_counter++;
-}
-
-void test_sample__cleanup(void)
+void test_combined__cleanup(void)
{
cl_fixture_cleanup("test");
cl_assert(file_size("test/file") == -1);
}
-void test_sample__1(void)
+void test_combined__1(void)
{
cl_assert(1);
cl_must_pass(0); /* 0 == success */
@@ -30,7 +26,7 @@ void test_sample__1(void)
cl_must_pass(-1); /* demonstrate a failing call */
}
-void test_sample__2(void)
+void test_combined__2(void)
{
cl_fixture_sandbox("test");
@@ -39,7 +35,7 @@ void test_sample__2(void)
cl_assert(100 == 101);
}
-void test_sample__strings(void)
+void test_combined__strings(void)
{
const char *actual = "expected";
cl_assert_equal_s("expected", actual);
@@ -47,7 +43,7 @@ void test_sample__strings(void)
cl_assert_equal_s_("mismatched", actual, "this one fails");
}
-void test_sample__strings_with_length(void)
+void test_combined__strings_with_length(void)
{
const char *actual = "expected";
cl_assert_equal_strn("expected_", actual, 8);
@@ -56,29 +52,34 @@ void test_sample__strings_with_length(void)
cl_assert_equal_strn_("exactly", actual, 3, "this one fails");
}
-void test_sample__int(void)
+void test_combined__int(void)
{
int value = 100;
cl_assert_equal_i(100, value);
cl_assert_equal_i_(101, value, "extra note on failing test");
}
-void test_sample__int_fmt(void)
+void test_combined__int_fmt(void)
{
int value = 100;
cl_assert_equal_i_fmt(022, value, "%04o");
}
-void test_sample__bool(void)
+void test_combined__bool(void)
{
int value = 100;
cl_assert_equal_b(1, value); /* test equality as booleans */
cl_assert_equal_b(0, value);
}
-void test_sample__ptr(void)
+void test_combined__multiline_description(void)
{
- const char *actual = "expected";
- cl_assert_equal_p(actual, actual); /* pointers to same object */
- cl_assert_equal_p(&actual, actual);
+ cl_must_pass_(-1, "description line 1\ndescription line 2");
+}
+
+void test_combined__null_string(void)
+{
+ const char *actual = NULL;
+ cl_assert_equal_s(actual, actual);
+ cl_assert_equal_s_("expected", actual, "this one fails");
}
diff --git a/t/unit-tests/clar/test/suites/main.c b/t/unit-tests/clar/test/suites/main.c
new file mode 100644
index 0000000000..3ab581d390
--- /dev/null
+++ b/t/unit-tests/clar/test/suites/main.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) Vicent Marti. All rights reserved.
+ *
+ * This file is part of clar, distributed under the ISC license.
+ * For full terms see the included COPYING file.
+ */
+
+#include "clar.h"
+
+/*
+ * Selftest main() for clar tests.
+ *
+ * You should write your own main routine for clar tests that does specific
+ * setup and teardown as necessary for your application. The only required
+ * line is the call to `clar_test(argc, argv)`, which will execute the test
+ * suite. If you want to check the return value of the test application,
+ * your main() should return the same value returned by clar_test().
+ */
+
+#ifdef _WIN32
+int __cdecl main(int argc, char *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+ return clar_test(argc, argv);
+}
diff --git a/t/unit-tests/clar/test/suites/pointer.c b/t/unit-tests/clar/test/suites/pointer.c
new file mode 100644
index 0000000000..20535b159e
--- /dev/null
+++ b/t/unit-tests/clar/test/suites/pointer.c
@@ -0,0 +1,13 @@
+#include "clar.h"
+
+void test_pointer__equal(void)
+{
+ void *p1 = (void *)0x1;
+ cl_assert_equal_p(p1, p1);
+}
+
+void test_pointer__unequal(void)
+{
+ void *p1 = (void *)0x1, *p2 = (void *)0x2;
+ cl_assert_equal_p(p1, p2);
+}
diff --git a/t/unit-tests/clar/test/resources/test/file b/t/unit-tests/clar/test/suites/resources/test/file
index 220f4aa98a..220f4aa98a 100644
--- a/t/unit-tests/clar/test/resources/test/file
+++ b/t/unit-tests/clar/test/suites/resources/test/file
diff --git a/t/unit-tests/u-reftable-basics.c b/t/unit-tests/u-reftable-basics.c
index a0471083e7..73566ed0eb 100644
--- a/t/unit-tests/u-reftable-basics.c
+++ b/t/unit-tests/u-reftable-basics.c
@@ -9,6 +9,7 @@ https://developers.google.com/open-source/licenses/bsd
#include "unit-test.h"
#include "lib-reftable.h"
#include "reftable/basics.h"
+#include "reftable/reftable-error.h"
struct integer_needle_lesseq_args {
int needle;
@@ -79,14 +80,18 @@ void test_reftable_basics__names_equal(void)
void test_reftable_basics__parse_names(void)
{
char in1[] = "line\n";
- char in2[] = "a\nb\nc";
- char **out = parse_names(in1, strlen(in1));
+ char in2[] = "a\nb\nc\n";
+ char **out = NULL;
+ int err = parse_names(in1, strlen(in1), &out);
+ cl_assert(err == 0);
cl_assert(out != NULL);
cl_assert_equal_s(out[0], "line");
cl_assert(!out[1]);
free_names(out);
- out = parse_names(in2, strlen(in2));
+ out = NULL;
+ err = parse_names(in2, strlen(in2), &out);
+ cl_assert(err == 0);
cl_assert(out != NULL);
cl_assert_equal_s(out[0], "a");
cl_assert_equal_s(out[1], "b");
@@ -95,10 +100,21 @@ void test_reftable_basics__parse_names(void)
free_names(out);
}
+void test_reftable_basics__parse_names_missing_newline(void)
+{
+ char in1[] = "line\nline2";
+ char **out = NULL;
+ int err = parse_names(in1, strlen(in1), &out);
+ cl_assert(err == REFTABLE_FORMAT_ERROR);
+ cl_assert(out == NULL);
+}
+
void test_reftable_basics__parse_names_drop_empty_string(void)
{
char in[] = "a\n\nb\n";
- char **out = parse_names(in, strlen(in));
+ char **out = NULL;
+ int err = parse_names(in, strlen(in), &out);
+ cl_assert(err == 0);
cl_assert(out != NULL);
cl_assert_equal_s(out[0], "a");
/* simply '\n' should be dropped as empty string */