diff options
Diffstat (limited to 't')
| -rw-r--r-- | t/helper/test-find-pack.c | 3 | ||||
| -rw-r--r-- | t/helper/test-pack-deltas.c | 10 | ||||
| -rw-r--r-- | t/helper/test-pack-mtimes.c | 2 | ||||
| -rw-r--r-- | t/lib-gpg.sh | 24 | ||||
| -rw-r--r-- | t/meson.build | 4 | ||||
| -rw-r--r-- | t/pack-refs-tests.sh | 431 | ||||
| -rwxr-xr-x | t/perf/p6010-merge-base.sh | 101 | ||||
| -rwxr-xr-x | t/t0001-init.sh | 16 | ||||
| -rwxr-xr-x | t/t0008-ignores.sh | 11 | ||||
| -rwxr-xr-x | t/t0014-alias.sh | 57 | ||||
| -rwxr-xr-x | t/t0300-credentials.sh | 19 | ||||
| -rwxr-xr-x | t/t0600-reffiles-backend.sh | 26 | ||||
| -rwxr-xr-x | t/t0601-reffiles-pack-refs.sh | 430 | ||||
| -rwxr-xr-x | t/t0613-reftable-write-options.sh | 24 | ||||
| -rwxr-xr-x | t/t0614-reftable-fsck.sh | 58 | ||||
| -rwxr-xr-x | t/t1010-mktree.sh | 13 | ||||
| -rwxr-xr-x | t/t1016-compatObjectFormat.sh | 2 | ||||
| -rwxr-xr-x | t/t1091-sparse-checkout-builtin.sh | 175 | ||||
| -rwxr-xr-x | t/t1300-config.sh | 349 | ||||
| -rwxr-xr-x | t/t1400-update-ref.sh | 53 | ||||
| -rwxr-xr-x | t/t1421-reflog-write.sh | 36 | ||||
| -rwxr-xr-x | t/t1450-fsck.sh | 54 | ||||
| -rwxr-xr-x | t/t1463-refs-optimize.sh | 17 | ||||
| -rwxr-xr-x | t/t1500-rev-parse.sh | 34 | ||||
| -rwxr-xr-x | t/t2401-worktree-prune.sh | 34 | ||||
| -rwxr-xr-x | t/t3206-range-diff.sh | 16 | ||||
| -rwxr-xr-x | t/t3415-rebase-autosquash.sh | 28 | ||||
| -rwxr-xr-x | t/t3701-add-interactive.sh | 126 | ||||
| -rwxr-xr-x | t/t3903-stash.sh | 49 | ||||
| -rwxr-xr-x | t/t3905-stash-include-untracked.sh | 1 | ||||
| -rwxr-xr-x | t/t4013-diff-various.sh | 257 | ||||
| -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_main | 2 | ||||
| -rw-r--r-- | t/t4013/diff.diff-tree_-p_master | 2 | ||||
| -rw-r--r-- | t/t4013/diff.diff-tree_main | 2 | ||||
| -rw-r--r-- | t/t4013/diff.diff-tree_master | 2 | ||||
| -rw-r--r-- | t/t4013/diff.diff_--dirstat_--cc_main~1_main | 3 | ||||
| -rw-r--r-- | t/t4013/diff.diff_--dirstat_--cc_master~1_master | 3 | ||||
| -rw-r--r-- | t/t4013/diff.diff_--dirstat_main~1_main~2 | 3 | ||||
| -rw-r--r-- | t/t4013/diff.diff_--dirstat_master~1_master~2 | 3 | ||||
| -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_--all | 2 | ||||
| -rw-r--r-- | t/t4013/diff.log_--decorate=full_--clear-decorations_--all | 2 | ||||
| -rw-r--r-- | t/t4013/diff.log_--decorate=full_--decorate-all_--all | 2 | ||||
| -rw-r--r-- | t/t4013/diff.log_--decorate_--all | 2 | ||||
| -rw-r--r-- | t/t4013/diff.log_--decorate_--clear-decorations_--all | 2 | ||||
| -rw-r--r-- | t/t4013/diff.log_--decorate_--decorate-all_--all | 2 | ||||
| -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=0 | 2 | ||||
| -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=2 | 7 | ||||
| -rw-r--r-- | t/t4013/diff.log_-SF_master_--max-count=0 | 2 | ||||
| -rw-r--r-- | t/t4013/diff.log_-SF_master_--max-count=1 | 7 | ||||
| -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-x | t/t4020-diff-external.sh | 10 | ||||
| -rwxr-xr-x | t/t4035-diff-quiet.sh | 4 | ||||
| -rwxr-xr-x | t/t4053-diff-no-index.sh | 16 | ||||
| -rwxr-xr-x | t/t5318-commit-graph.sh | 44 | ||||
| -rwxr-xr-x | t/t5510-fetch.sh | 114 | ||||
| -rwxr-xr-x | t/t6302-for-each-ref-filter.sh | 65 | ||||
| -rwxr-xr-x | t/t7500-commit-template-squash-signoff.sh | 51 | ||||
| -rwxr-xr-x | t/t7508-status.sh | 11 | ||||
| -rwxr-xr-x | t/t7528-signed-commit-ssh.sh | 2 | ||||
| -rwxr-xr-x | t/t7900-maintenance.sh | 245 | ||||
| -rwxr-xr-x | t/t8020-last-modified.sh | 22 | ||||
| -rwxr-xr-x | t/t9305-fast-import-signatures.sh | 106 | ||||
| -rwxr-xr-x | t/t9306-fast-import-signed-tags.sh | 80 | ||||
| -rwxr-xr-x | t/t9350-fast-export.sh | 48 | ||||
| -rwxr-xr-x | t/t9902-completion.sh | 6 | ||||
| -rw-r--r-- | t/test-lib-functions.sh | 9 | ||||
| -rw-r--r-- | t/test-lib.sh | 26 | ||||
| -rw-r--r-- | t/unit-tests/clar/.github/workflows/ci.yml | 37 | ||||
| -rw-r--r-- | t/unit-tests/clar/CMakeLists.txt | 13 | ||||
| -rw-r--r-- | t/unit-tests/clar/README.md | 37 | ||||
| -rw-r--r-- | t/unit-tests/clar/clar.c | 154 | ||||
| -rw-r--r-- | t/unit-tests/clar/clar.h | 83 | ||||
| -rw-r--r-- | t/unit-tests/clar/clar/fixtures.h | 6 | ||||
| -rw-r--r-- | t/unit-tests/clar/clar/fs.h | 29 | ||||
| -rw-r--r-- | t/unit-tests/clar/clar/print.h | 71 | ||||
| -rw-r--r-- | t/unit-tests/clar/clar/sandbox.h | 226 | ||||
| -rw-r--r-- | t/unit-tests/clar/clar/summary.h | 5 | ||||
| -rw-r--r-- | t/unit-tests/clar/example/CMakeLists.txt | 28 | ||||
| -rw-r--r-- | t/unit-tests/clar/example/example.c | 6 | ||||
| -rw-r--r-- | t/unit-tests/clar/example/main.c (renamed from t/unit-tests/clar/test/main.c.sample) | 2 | ||||
| -rwxr-xr-x | t/unit-tests/clar/generate.py | 28 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/CMakeLists.txt | 34 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/clar_test.h | 16 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/expected/help | 12 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/expected/quiet | 44 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/expected/specific_test | 9 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/expected/stop_on_failure | 8 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/expected/suite_names | 2 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/expected/summary.xml | 41 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/expected/summary_with_filename | 49 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/expected/summary_without_filename | 49 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/expected/tap | 92 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/expected/without_arguments | 48 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/main.c | 41 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/selftest.c | 370 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/selftest.h | 3 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/suites/CMakeLists.txt | 53 | ||||
| -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.c | 27 | ||||
| -rw-r--r-- | t/unit-tests/clar/test/suites/pointer.c | 13 | ||||
| -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.c | 24 |
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(×tamp); + struct tm tm; char iso_dt[20]; - if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", tm) == 0) + localtime_r(×tamp, &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 */ |
