diff options
| -rw-r--r-- | Documentation/BreakingChanges.adoc | 11 | ||||
| -rw-r--r-- | Documentation/CodingGuidelines | 6 | ||||
| -rw-r--r-- | Documentation/RelNotes/2.52.0.adoc | 44 | ||||
| -rw-r--r-- | Documentation/config.adoc | 9 | ||||
| -rw-r--r-- | Documentation/config/core.adoc | 20 | ||||
| -rw-r--r-- | Documentation/config/promisor.adoc | 61 | ||||
| -rw-r--r-- | Documentation/config/sendemail.adoc | 2 | ||||
| -rw-r--r-- | Documentation/config/stash.adoc | 5 | ||||
| -rw-r--r-- | Documentation/git-checkout.adoc | 151 | ||||
| -rw-r--r-- | Documentation/git-fast-import.adoc | 8 | ||||
| -rw-r--r-- | Documentation/git-init.adoc | 12 | ||||
| -rw-r--r-- | Documentation/git-send-email.adoc | 34 | ||||
| -rw-r--r-- | Documentation/gitprotocol-v2.adoc | 64 | ||||
| -rw-r--r-- | add-interactive.c | 89 | ||||
| -rw-r--r-- | add-interactive.h | 7 | ||||
| -rw-r--r-- | add-patch.c | 12 | ||||
| -rw-r--r-- | advice.c | 2 | ||||
| -rw-r--r-- | advice.h | 2 | ||||
| -rw-r--r-- | alloc.c | 10 | ||||
| -rw-r--r-- | alloc.h | 4 | ||||
| -rw-r--r-- | bisect.c | 5 | ||||
| -rw-r--r-- | builtin/add.c | 2 | ||||
| -rw-r--r-- | builtin/am.c | 4 | ||||
| -rw-r--r-- | builtin/branch.c | 2 | ||||
| -rw-r--r-- | builtin/clean.c | 2 | ||||
| -rw-r--r-- | builtin/commit.c | 11 | ||||
| -rw-r--r-- | builtin/config.c | 25 | ||||
| -rw-r--r-- | builtin/describe.c | 3 | ||||
| -rw-r--r-- | builtin/fetch.c | 21 | ||||
| -rw-r--r-- | builtin/grep.c | 2 | ||||
| -rw-r--r-- | builtin/log.c | 1 | ||||
| -rw-r--r-- | builtin/ls-tree.c | 7 | ||||
| -rw-r--r-- | builtin/merge.c | 3 | ||||
| -rw-r--r-- | builtin/pack-objects.c | 6 | ||||
| -rw-r--r-- | builtin/push.c | 2 | ||||
| -rw-r--r-- | builtin/range-diff.c | 24 | ||||
| -rw-r--r-- | builtin/rebase.c | 6 | ||||
| -rw-r--r-- | builtin/rev-parse.c | 7 | ||||
| -rw-r--r-- | builtin/revert.c | 7 | ||||
| -rw-r--r-- | builtin/show-branch.c | 2 | ||||
| -rw-r--r-- | builtin/stash.c | 40 | ||||
| -rw-r--r-- | builtin/submodule--helper.c | 10 | ||||
| -rwxr-xr-x | ci/run-build-and-tests.sh | 1 | ||||
| -rw-r--r-- | color.c | 24 | ||||
| -rw-r--r-- | color.h | 14 | ||||
| -rw-r--r-- | combine-diff.c | 2 | ||||
| -rw-r--r-- | config.c | 297 | ||||
| -rw-r--r-- | contrib/diff-highlight/README | 8 | ||||
| -rwxr-xr-x | contrib/subtree/git-subtree.sh | 36 | ||||
| -rwxr-xr-x | contrib/subtree/t/t7900-subtree.sh | 71 | ||||
| -rw-r--r-- | diff.c | 48 | ||||
| -rw-r--r-- | diff.h | 5 | ||||
| -rw-r--r-- | environment.c | 15 | ||||
| -rw-r--r-- | environment.h | 3 | ||||
| -rw-r--r-- | git-curl-compat.h | 7 | ||||
| -rwxr-xr-x | git-send-email.perl | 43 | ||||
| -rw-r--r-- | grep.c | 4 | ||||
| -rw-r--r-- | grep.h | 4 | ||||
| -rw-r--r-- | http-push.c | 2 | ||||
| -rw-r--r-- | http.c | 8 | ||||
| -rw-r--r-- | imap-send.c | 26 | ||||
| -rw-r--r-- | line-log.c | 15 | ||||
| -rw-r--r-- | list-objects-filter.c | 9 | ||||
| -rw-r--r-- | log-tree.c | 5 | ||||
| -rw-r--r-- | log-tree.h | 4 | ||||
| -rw-r--r-- | object-name.c | 32 | ||||
| -rw-r--r-- | object.c | 26 | ||||
| -rw-r--r-- | parse-options-cb.c | 4 | ||||
| -rw-r--r-- | pretty.c | 12 | ||||
| -rw-r--r-- | pretty.h | 3 | ||||
| -rw-r--r-- | promisor-remote.c | 424 | ||||
| -rw-r--r-- | range-diff.c | 20 | ||||
| -rw-r--r-- | range-diff.h | 5 | ||||
| -rw-r--r-- | ref-filter.h | 4 | ||||
| -rw-r--r-- | refs.c | 32 | ||||
| -rw-r--r-- | refs.h | 2 | ||||
| -rw-r--r-- | refs/files-backend.c | 78 | ||||
| -rw-r--r-- | remote.c | 5 | ||||
| -rw-r--r-- | repository.c | 1 | ||||
| -rw-r--r-- | repository.h | 3 | ||||
| -rw-r--r-- | revision.c | 49 | ||||
| -rw-r--r-- | revision.h | 2 | ||||
| -rw-r--r-- | sequencer.c | 19 | ||||
| -rw-r--r-- | sequencer.h | 4 | ||||
| -rw-r--r-- | shallow.c | 4 | ||||
| -rw-r--r-- | shallow.h | 5 | ||||
| -rw-r--r-- | sideband.c | 6 | ||||
| -rw-r--r-- | submodule.c | 2 | ||||
| -rwxr-xr-x | t/t0001-init.sh | 16 | ||||
| -rwxr-xr-x | t/t0613-reftable-write-options.sh | 24 | ||||
| -rwxr-xr-x | t/t1400-update-ref.sh | 53 | ||||
| -rwxr-xr-x | t/t3404-rebase-interactive.sh | 19 | ||||
| -rwxr-xr-x | t/t3415-rebase-autosquash.sh | 28 | ||||
| -rwxr-xr-x | t/t3418-rebase-continue.sh | 2 | ||||
| -rwxr-xr-x | t/t3701-add-interactive.sh | 53 | ||||
| -rwxr-xr-x | t/t3903-stash.sh | 49 | ||||
| -rwxr-xr-x | t/t3904-stash-patch.sh | 19 | ||||
| -rwxr-xr-x | t/t3905-stash-include-untracked.sh | 1 | ||||
| -rwxr-xr-x | t/t4013-diff-various.sh | 220 | ||||
| -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/t4211-line-log.sh | 2 | ||||
| -rw-r--r-- | t/t4211/sha1/expect.multiple | 6 | ||||
| -rw-r--r-- | t/t4211/sha1/expect.no-assertion-error | 90 | ||||
| -rw-r--r-- | t/t4211/sha1/expect.two-ranges | 6 | ||||
| -rw-r--r-- | t/t4211/sha256/expect.multiple | 6 | ||||
| -rw-r--r-- | t/t4211/sha256/expect.no-assertion-error | 90 | ||||
| -rw-r--r-- | t/t4211/sha256/expect.two-ranges | 6 | ||||
| -rwxr-xr-x | t/t5510-fetch.sh | 114 | ||||
| -rwxr-xr-x | t/t5564-http-proxy.sh | 4 | ||||
| -rwxr-xr-x | t/t5710-promisor-remote-capability.sh | 65 | ||||
| -rwxr-xr-x | t/t7502-commit-porcelain.sh | 52 | ||||
| -rwxr-xr-x | t/t9902-completion.sh | 6 | ||||
| -rw-r--r-- | t/test-lib.sh | 13 | ||||
| -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-- | transport.c | 2 | ||||
| -rw-r--r-- | upload-pack.c | 7 | ||||
| -rw-r--r-- | wt-status.c | 6 | ||||
| -rw-r--r-- | wt-status.h | 2 |
246 files changed, 3958 insertions, 1020 deletions
diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc index f8d2eba061..0cba20fadb 100644 --- a/Documentation/BreakingChanges.adoc +++ b/Documentation/BreakingChanges.adoc @@ -165,6 +165,12 @@ A prerequisite for this change is that the ecosystem is ready to support the "reftable" format. Most importantly, alternative implementations of Git like JGit, libgit2 and Gitoxide need to support it. +* In new repositories, the default branch name will be `main`. We have been + warning that the default name will change since 675704c74dd (init: + provide useful advice about init.defaultBranch, 2020-12-11). The new name + matches the default branch name used in new repositories by many of the + big Git forges. + === Removals * Support for grafting commits has long been superseded by git-replace(1). @@ -239,6 +245,11 @@ These features will be removed. + The command will be removed. +* Support for `core.commentString=auto` has been deprecated and will + be removed in Git 3.0. ++ +cf. <xmqqa59i45wc.fsf@gitster.g> + == Superseded features that will not be deprecated Some features have gained newer replacements that aim to improve the design in diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index 224f0978a8..df72fe0177 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -650,6 +650,12 @@ For C programs: cases. However, it is recommended to find a more descriptive name wherever possible to improve the readability and maintainability of the code. + - Bit fields should be defined without a space around the colon. E.g. + + unsigned my_field:1; + unsigned other_field:1; + unsigned field_with_longer_name:1; + For Perl programs: - Most of the C guidelines above apply. diff --git a/Documentation/RelNotes/2.52.0.adoc b/Documentation/RelNotes/2.52.0.adoc index 959c8afe15..c4fc561631 100644 --- a/Documentation/RelNotes/2.52.0.adoc +++ b/Documentation/RelNotes/2.52.0.adoc @@ -24,6 +24,17 @@ UI, Workflows & Features "--format=nul", and learns to report the objects format used in the repository. + * "core.commentChar=auto" that attempts to dynamically pick a + suitable comment character is non-workable, as it is too much + trouble to support for little benefit, and is marked as deprecated. + + * "git send-email" learned to drive "git imap-send" to store already + sent e-mails in an IMAP folder. + + * The "promisor-remote" capability mechanism has been updated to + allow the "partialCloneFilter" settings and the "token" value to be + communicated from the server side. + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -63,6 +74,19 @@ Performance, Internal Implementation, Development Support etc. singleton variable, which has been updated to pass an instance throughout the callchain. + * CodingGuidelines now spells out how bitfields are to be written. + + * Adjust to the way newer versions of cURL selectivel enables tracing + options, so that our tests can continue to work. + (merge 1b5a6bfff3 jk/curl-global-trace-components later to maint). + + * The clear_alloc_state() API function was not fully clearing the + structure for reuse, but since nobody reuses it, replace it with a + variant that frees the structure as well, making the callers simpler. + + * "git range-diff" learned a way to limit the memory consumed by + O(N*N) cost matrix. + Fixes since v2.51 ----------------- @@ -177,6 +201,22 @@ including security updates, are included in this release. exhaust memory storing them redundantly, which has been corrected. (merge 88a2dc68c8 ps/upload-pack-oom-protection later to maint). + * A corner case bug in "git log -L..." has been corrected. + (merge e3106998ff sg/line-log-boundary-fixes later to maint). + + * "git rev-parse --short" and friends failed to disambiguate two + objects with object names that share common prefix longer than 32 + characters, which has been fixed. + (merge 8655908b9e jc/longer-disambiguation-fix later to maint). + + * Some among "git add -p" and friends ignored color.diff and/or + color.ui configuration variables, which is an old regression, which + has been corrected. + (merge 1092cd6435 jk/add-i-color later to maint). + + * "git subtree" (in contrib/) did not work correctly when splitting + squashed subtrees, which has been improved. + * Other code cleanup, docfix, build fix, etc. (merge 823d537fa7 kh/doc-git-log-markup-fix later to maint). (merge cf7efa4f33 rj/t6137-cygwin-fix later to maint). @@ -198,3 +238,7 @@ including security updates, are included in this release. (merge c25651aefd ds/midx-write-fixes later to maint). (merge 069c15d256 rs/object-name-extend-abbrev-len-update later to maint). (merge bf5c224537 mm/worktree-doc-typofix later to maint). + (merge 31397bc4f7 kh/doc-fast-import-markup-fix later to maint). + (merge ac7096723b jc/doc-includeif-hasconfig-remote-url-fix later to maint). + (merge fafc9b08b8 ag/doc-sendmail-gmail-example-update later to maint). + (merge a66fc22bf9 rs/get-oid-with-flags-cleanup later to maint). diff --git a/Documentation/config.adoc b/Documentation/config.adoc index cc769251be..05f1ca7293 100644 --- a/Documentation/config.adoc +++ b/Documentation/config.adoc @@ -114,8 +114,7 @@ whose format and meaning depends on the keyword. Supported keywords are: `gitdir`:: - - The data that follows the keyword `gitdir:` is used as a glob + The data that follows the keyword `gitdir` and a colon is used as a glob pattern. If the location of the .git directory matches the pattern, the include condition is met. + @@ -148,7 +147,7 @@ refer to linkgit:gitignore[5] for details. For convenience: case-insensitively (e.g. on case-insensitive file systems) `onbranch`:: - The data that follows the keyword `onbranch:` is taken to be a + The data that follows the keyword `onbranch` and a colon is taken to be a pattern with standard globbing wildcards and two additional ones, `**/` and `/**`, that can match multiple path components. If we are in a worktree where the name of the branch that is @@ -161,8 +160,8 @@ all branches that begin with `foo/`. This is useful if your branches are organized hierarchically and you would like to apply a configuration to all the branches in that hierarchy. -`hasconfig:remote.*.url:`:: - The data that follows this keyword is taken to +`hasconfig:remote.*.url`:: + The data that follows this keyword and a colon is taken to be a pattern with standard globbing wildcards and two additional ones, `**/` and `/**`, that can match multiple components. The first time this keyword is seen, the rest of diff --git a/Documentation/config/core.adoc b/Documentation/config/core.adoc index 3fbe83eef1..08739bb9d4 100644 --- a/Documentation/config/core.adoc +++ b/Documentation/config/core.adoc @@ -531,9 +531,25 @@ core.commentString:: commented, and removes them after the editor returns (default '#'). + -If set to "auto", `git-commit` would select a character that is not +ifndef::with-breaking-changes[] +If set to "auto", `git-commit` will select a character that is not the beginning character of any line in existing commit messages. -+ +Support for this value is deprecated and will be removed in Git 3.0 +due to the following limitations: ++ +-- +* It is incompatible with adding comments in a commit message + template. This includes the conflicts comments added to + the commit message by `cherry-pick`, `merge`, `rebase` and + `revert`. +* It is incompatible with adding comments to the commit message + in the `prepare-commit-msg` hook. +* It is incompatible with the `fixup` and `squash` commands when + rebasing, +* It is not respected by `git notes` +-- ++ +endif::with-breaking-changes[] Note that these two variables are aliases of each other, and in modern versions of Git you are free to use a string (e.g., `//` or `⁑⁕⁑`) with `commentChar`. Versions of Git prior to v2.45.0 will ignore diff --git a/Documentation/config/promisor.adoc b/Documentation/config/promisor.adoc index 2638b01f83..93e5e0d9b5 100644 --- a/Documentation/config/promisor.adoc +++ b/Documentation/config/promisor.adoc @@ -9,6 +9,28 @@ promisor.advertise:: "false", which means the "promisor-remote" capability is not advertised. +promisor.sendFields:: + A comma or space separated list of additional remote related + field names. A server sends these field names and the + associated field values from its configuration when + advertising its promisor remotes using the "promisor-remote" + capability, see linkgit:gitprotocol-v2[5]. Currently, only the + "partialCloneFilter" and "token" field names are supported. ++ +`partialCloneFilter`:: contains the partial clone filter +used for the remote. ++ +`token`:: contains an authentication token for the remote. ++ +When a field name is part of this list and a corresponding +"remote.foo.<field-name>" config variable is set on the server to a +non-empty value, then the field name and value are sent when +advertising the promisor remote "foo". ++ +This list has no effect unless the "promisor.advertise" config +variable is set to "true", and the "name" and "url" fields are always +advertised regardless of this setting. + promisor.acceptFromServer:: If set to "all", a client will accept all the promisor remotes a server might advertise using the "promisor-remote" @@ -28,3 +50,42 @@ promisor.acceptFromServer:: lazily fetchable from this promisor remote from its responses to "fetch" and "clone" requests from the client. Name and URL comparisons are case sensitive. See linkgit:gitprotocol-v2[5]. + +promisor.checkFields:: + A comma or space separated list of additional remote related + field names. A client checks if the values of these fields + transmitted by a server correspond to the values of these + fields in its own configuration before accepting a promisor + remote. Currently, "partialCloneFilter" and "token" are the + only supported field names. ++ +If one of these field names (e.g., "token") is being checked for an +advertised promisor remote (e.g., "foo"), three conditions must be met +for the check of this specific field to pass: ++ +1. The corresponding local configuration (e.g., `remote.foo.token`) + must be set. +2. The server must advertise the "token" field for remote "foo". +3. The value of the locally configured `remote.foo.token` must exactly + match the value advertised by the server for the "token" field. ++ +If any of these conditions is not met for any field name listed in +`promisor.checkFields`, the advertised remote "foo" is rejected. ++ +For the "partialCloneFilter" field, this allows the client to ensure +that the server's filter matches what it expects locally, preventing +inconsistencies in filtering behavior. For the "token" field, this can +be used to verify that authentication credentials match expected +values. ++ +Field values are compared case-sensitively. ++ +The "name" and "url" fields are always checked according to the +`promisor.acceptFromServer` policy, independently of this setting. ++ +The field names and values should be passed by the server through the +"promisor-remote" capability by using the `promisor.sendFields` config +variable. The fields are checked only if the +`promisor.acceptFromServer` config variable is not set to "None". If +set to "None", this config variable has no effect. See +linkgit:gitprotocol-v2[5]. diff --git a/Documentation/config/sendemail.adoc b/Documentation/config/sendemail.adoc index 4722334657..90164c734d 100644 --- a/Documentation/config/sendemail.adoc +++ b/Documentation/config/sendemail.adoc @@ -88,6 +88,8 @@ sendemail.smtpServer:: sendemail.smtpServerPort:: sendemail.smtpServerOption:: sendemail.smtpUser:: +sendemail.imapSentFolder:: +sendemail.useImapOnly:: sendemail.thread:: sendemail.transferEncoding:: sendemail.validate:: diff --git a/Documentation/config/stash.adoc b/Documentation/config/stash.adoc index ec1edaeba6..e556105a15 100644 --- a/Documentation/config/stash.adoc +++ b/Documentation/config/stash.adoc @@ -1,3 +1,8 @@ +stash.index:: + If this is set to true, `git stash apply` and `git stash pop` will + behave as if `--index` was supplied. Defaults to false. See the + descriptions in linkgit:git-stash[1]. + stash.showIncludeUntracked:: If this is set to true, the `git stash show` command will show the untracked files of a stash entry. Defaults to false. See diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc index ff1cb29bc1..431185ca0b 100644 --- a/Documentation/git-checkout.adoc +++ b/Documentation/git-checkout.adoc @@ -12,25 +12,29 @@ git checkout [-q] [-f] [-m] [<branch>] git checkout [-q] [-f] [-m] --detach [<branch>] git checkout [-q] [-f] [-m] [--detach] <commit> git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new-branch>] [<start-point>] -git checkout [-f] <tree-ish> [--] <pathspec>... -git checkout [-f] <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul] +git checkout <tree-ish> [--] <pathspec>... +git checkout <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul] git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>... git checkout [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul] git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...] DESCRIPTION ----------- -Updates files in the working tree to match the version in the index -or the specified tree. If no pathspec was given, `git checkout` will -also update `HEAD` to set the specified branch as the current -branch. + +`git checkout` has two main modes: + +1. **Switch branches**, with `git checkout <branch>` +2. **Restore a different version of a file**, for example with + `git checkout <commit> <filename>` or `git checkout <filename>` + +See ARGUMENT DISAMBIGUATION below for how Git decides which one to do. `git checkout [<branch>]`:: - To prepare for working on _<branch>_, switch to it by updating - the index and the files in the working tree, and by pointing - `HEAD` at the branch. Local modifications to the files in the - working tree are kept, so that they can be committed to the - _<branch>_. + Switch to _<branch>_. This sets the current branch to _<branch>_ and + updates the files in your working directory. The checkout will fail + if there are uncommitted changes to any files where _<branch>_ and + your current commit have different content. Uncommitted changes will + otherwise be kept. + If _<branch>_ is not found but there does exist a tracking branch in exactly one remote (call it _<remote>_) with a matching name and @@ -40,68 +44,63 @@ exactly one remote (call it _<remote>_) with a matching name and $ git checkout -b <branch> --track <remote>/<branch> ------------ + -You could omit _<branch>_, in which case the command degenerates to -"check out the current branch", which is a glorified no-op with -rather expensive side-effects to show only the tracking information, -if it exists, for the current branch. - -`git checkout (-b|-B) <new-branch> [<start-point>]`:: - - Specifying `-b` causes a new branch to be created as if - linkgit:git-branch[1] were called and then checked out. In - this case you can use the `--track` or `--no-track` options, - which will be passed to `git branch`. As a convenience, - `--track` without `-b` implies branch creation; see the - description of `--track` below. -+ -If `-B` is given, _<new-branch>_ is created if it doesn't exist; otherwise, it -is reset. This is the transactional equivalent of -+ ------------- -$ git branch -f <branch> [<start-point>] -$ git checkout <branch> ------------- +Running `git checkout` without specifying a branch has no effect except +to print out the tracking information for the current branch. + +`git checkout -b <new-branch> [<start-point>]`:: + + Create a new branch named _<new-branch>_, start it at _<start-point>_ + (defaults to the current commit), and check out the new branch. + You can use the `--track` or `--no-track` options to set the branch's + upstream tracking information. + -that is to say, the branch is not reset/created unless "git checkout" is -successful (e.g., when the branch is in use in another worktree, not -just the current branch stays the same, but the branch is not reset to -the start-point, either). +This will fail if there's an error checking out _<new-branch>_, for +example if checking out the `<start-point>` commit would overwrite your +uncommitted changes. + +`git checkout -B <branch> [<start-point>]`:: + + The same as `-b`, except that if the branch already exists it + resets `_<branch>_` to the start point instead of failing. `git checkout --detach [<branch>]`:: `git checkout [--detach] <commit>`:: - Prepare to work on top of _<commit>_, by detaching `HEAD` at it - (see "DETACHED HEAD" section), and updating the index and the - files in the working tree. Local modifications to the files - in the working tree are kept, so that the resulting working - tree will be the state recorded in the commit plus the local - modifications. -+ -When the _<commit>_ argument is a branch name, the `--detach` option can -be used to detach `HEAD` at the tip of the branch (`git checkout -<branch>` would check out that branch without detaching `HEAD`). + The same as `git checkout <branch>`, except that instead of pointing + `HEAD` at the branch, it points `HEAD` at the commit ID. + See the "DETACHED HEAD" section below for more. + Omitting _<branch>_ detaches `HEAD` at the tip of the current branch. -`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>...`:: -`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] --pathspec-from-file=<file> [--pathspec-file-nul]`:: +`git checkout <tree-ish> [--] <pathspec>...`:: +`git checkout <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul]`:: - Overwrite the contents of the files that match the pathspec. - When the _<tree-ish>_ (most often a commit) is not given, - overwrite working tree with the contents in the index. - When the _<tree-ish>_ is given, overwrite both the index and - the working tree with the contents at the _<tree-ish>_. + Replace the specified files and/or directories with the version from + the given commit or tree and add them to the index + (also known as "staging area"). + -The index may contain unmerged entries because of a previous failed merge. -By default, if you try to check out such an entry from the index, the -checkout operation will fail and nothing will be checked out. -Using `-f` will ignore these unmerged entries. The contents from a -specific side of the merge can be checked out of the index by -using `--ours` or `--theirs`. With `-m`, changes made to the working tree -file can be discarded to re-create the original conflicted merge result. +For example, `git checkout main file.txt` will replace `file.txt` +with the version from `main`. + +`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>...`:: +`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul]`:: + + Replace the specified files and/or directories with the version from + the index. ++ +For example, if you check out a commit, edit `file.txt`, and then +decide those changes were a mistake, `git checkout file.txt` will +discard any unstaged changes to `file.txt`. ++ +This will fail if the file has a merge conflict and you haven't yet run +`git add file.txt` (or something equivalent) to mark it as resolved. +You can use `-f` to ignore the unmerged files instead of failing, use +`--ours` or `--theirs` to replace them with the version from a specific +side of the merge, or use `-m` to replace them with the original +conflicted merge result. `git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]`:: - This is similar to the previous mode, but lets you use the + This is similar to the previous two modes, but lets you use the interactive interface to show the "diff" output and choose which hunks to use in the result. See below for the description of `--patch` option. @@ -155,16 +154,14 @@ of it"). see linkgit:git-branch[1] for details. `-B <new-branch>`:: - Creates the branch _<new-branch>_, start it at _<start-point>_; - if it already exists, then reset it to _<start-point>_. And then - check the resulting branch out. This is equivalent to running - `git branch` with `-f` followed by `git checkout` of that branch; - see linkgit:git-branch[1] for details. + The same as `-b`, except that if the branch already exists it + resets `_<branch>_` to the start point instead of failing. `-t`:: `--track[=(direct|inherit)]`:: When creating a new branch, set up "upstream" configuration. See - `--track` in linkgit:git-branch[1] for details. + `--track` in linkgit:git-branch[1] for details. As a convenience, + --track without -b implies branch creation. + If no `-b` option is given, the name of the new branch will be derived from the remote-tracking branch, by looking at the local part of @@ -511,14 +508,18 @@ $ git log -g -2 HEAD ARGUMENT DISAMBIGUATION ----------------------- -When there is only one argument given and it is not `--` (e.g. `git -checkout abc`), and when the argument is both a valid _<tree-ish>_ -(e.g. a branch `abc` exists) and a valid _<pathspec>_ (e.g. a file -or a directory whose name is "abc" exists), Git would usually ask -you to disambiguate. Because checking out a branch is so common an -operation, however, `git checkout abc` takes "abc" as a _<tree-ish>_ -in such a situation. Use `git checkout -- <pathspec>` if you want -to checkout these paths out of the index. +When you run `git checkout <something>`, Git tries to guess whether +`<something>` is intended to be a branch, a commit, or a set of file(s), +and then either switches to that branch or commit, or restores the +specified files. + +If there's any ambiguity, Git will treat `<something>` as a branch or +commit, but you can use the double dash `--` to force Git to treat the +parameter as a list of files and/or directories, like this: + +---------- +git checkout -- file.txt +---------- EXAMPLES -------- diff --git a/Documentation/git-fast-import.adoc b/Documentation/git-fast-import.adoc index e7d1214d2d..6e095b02a1 100644 --- a/Documentation/git-fast-import.adoc +++ b/Documentation/git-fast-import.adoc @@ -61,10 +61,10 @@ OPTIONS currently impacts only the `export-marks`, `import-marks`, and `import-marks-if-exists` feature commands. + - Only enable this option if you trust the program generating the - fast-import stream! This option is enabled automatically for - remote-helpers that use the `import` capability, as they are - already trusted to run their own code. +Only enable this option if you trust the program generating the +fast-import stream! This option is enabled automatically for +remote-helpers that use the `import` capability, as they are +already trusted to run their own code. Options for Frontends ~~~~~~~~~~~~~~~~~~~~~ diff --git a/Documentation/git-init.adoc b/Documentation/git-init.adoc index a0dffba665..bab99b9b47 100644 --- a/Documentation/git-init.adoc +++ b/Documentation/git-init.adoc @@ -77,9 +77,15 @@ If this is a reinitialization, the repository will be moved to the specified pat `-b <branch-name>`:: `--initial-branch=<branch-name>`:: Use _<branch-name>_ for the initial branch in the newly created -repository. If not specified, fall back to the default name (currently -`master`, but this is subject to change in the future; the name can be -customized via the `init.defaultBranch` configuration variable). +repository. If not specified, fall back to the default name +ifndef::with-breaking-changes[] +(currently `master`, but this will change to `main` when Git 3.0 is released). +endif::with-breaking-changes[] +ifdef::with-breaking-changes[] +`main`. +endif::with-breaking-changes[] +The default name can be customized via the `init.defaultBranch` configuration +variable. `--shared[=(false|true|umask|group|all|world|everybody|<perm>)]`:: diff --git a/Documentation/git-send-email.adoc b/Documentation/git-send-email.adoc index 11b1ab1a07..263b977353 100644 --- a/Documentation/git-send-email.adoc +++ b/Documentation/git-send-email.adoc @@ -300,6 +300,32 @@ must be used for each option. commands and replies will be printed. Useful to debug TLS connection and authentication problems. +--imap-sent-folder=<folder>:: + Some email providers (e.g. iCloud) do not send a copy of the emails sent + using SMTP to the `Sent` folder or similar in your mailbox. Use this option + to use `git imap-send` to send a copy of the emails to the folder specified + using this option. You can run `git imap-send --list` to get a list of + valid folder names, including the correct name of the `Sent` folder in + your mailbox. You can also use this option to send emails to a dedicated + IMAP folder of your choice. ++ +This feature requires setting up `git imap-send`. See linkgit:git-imap-send[1] +for instructions. + +--use-imap-only:: +--no-use-imap-only:: + If this is set, all emails will only be copied to the IMAP folder specified + with `--imap-sent-folder` or `sendemail.imapSentFolder` and will not be sent + to the recipients. Useful if you just want to create a draft of the emails + and use another email client to send them. + If disabled with `--no-use-imap-only`, the emails will be sent like usual. + Disabled by default, but the `sendemail.useImapOnly` configuration + variable can be used to enable it. + ++ +This feature requires setting up `git imap-send`. See linkgit:git-imap-send[1] +for instructions. + --batch-size=<num>:: Some email servers (e.g. 'smtp.163.com') limit the number of emails to be sent per session (connection) and this will lead to a failure when @@ -531,10 +557,10 @@ edit `~/.gitconfig` to specify your account settings: ---- [sendemail] - smtpEncryption = tls + smtpEncryption = ssl smtpServer = smtp.gmail.com smtpUser = yourname@gmail.com - smtpServerPort = 587 + smtpServerPort = 465 ---- Gmail does not allow using your regular password for `git send-email`. @@ -552,10 +578,10 @@ if you want to use `OAUTHBEARER`, edit your `~/.gitconfig` file and add ---- [sendemail] - smtpEncryption = tls + smtpEncryption = ssl smtpServer = smtp.gmail.com smtpUser = yourname@gmail.com - smtpServerPort = 587 + smtpServerPort = 465 smtpAuth = OAUTHBEARER ---- diff --git a/Documentation/gitprotocol-v2.adoc b/Documentation/gitprotocol-v2.adoc index 9a57005d77..c7db103299 100644 --- a/Documentation/gitprotocol-v2.adoc +++ b/Documentation/gitprotocol-v2.adoc @@ -785,33 +785,64 @@ retrieving the header from a bundle at the indicated URI, and thus save themselves and the server(s) the request(s) needed to inspect the headers of that bundle or bundles. -promisor-remote=<pr-infos> -~~~~~~~~~~~~~~~~~~~~~~~~~~ +promisor-remote=<pr-info> +~~~~~~~~~~~~~~~~~~~~~~~~~ The server may advertise some promisor remotes it is using or knows about to a client which may want to use them as its promisor remotes, -instead of this repository. In this case <pr-infos> should be of the +instead of this repository. In this case <pr-info> should be of the form: - pr-infos = pr-info | pr-infos ";" pr-info + pr-info = pr-fields | pr-info ";" pr-fields - pr-info = "name=" pr-name | "name=" pr-name "," "url=" pr-url + pr-fields = pr-field | pr-fields "," pr-field -where `pr-name` is the urlencoded name of a promisor remote, and -`pr-url` the urlencoded URL of that promisor remote. + pr-field = field-name "=" field-value -In this case, if the client decides to use one or more promisor -remotes the server advertised, it can reply with -"promisor-remote=<pr-names>" where <pr-names> should be of the form: +where all the `field-name` and `field-value` in a given `pr-fields` +are field names and values related to a single promisor remote. A +given `field-name` MUST NOT appear more than once in given +`pr-fields`. + +The server MUST advertise at least the "name" and "url" field names +along with the associated field values, which are the name of a valid +remote and its URL, in each `pr-fields`. The "name" and "url" fields +MUST appear first in each pr-fields, in that order. + +After these mandatory fields, the server MAY advertise the following +optional fields in any order: + +`partialCloneFilter`:: The filter specification used by the remote. +Clients can use this to determine if the remote's filtering strategy +is compatible with their needs (e.g., checking if both use "blob:none"). +It corresponds to the "remote.<name>.partialCloneFilter" config setting. + +`token`:: An authentication token that clients can use when +connecting to the remote. It corresponds to the "remote.<name>.token" +config setting. + +No other fields are defined by the protocol at this time. Field names +are case-sensitive and MUST be transmitted exactly as specified +above. Clients MUST ignore fields they don't recognize to allow for +future protocol extensions. + +For now, the client can only use information transmitted through these +fields to decide if it accepts the advertised promisor remote. In the +future that information might be used for other purposes though. + +Field values MUST be urlencoded. + +If the client decides to use one or more promisor remotes the server +advertised, it can reply with "promisor-remote=<pr-names>" where +<pr-names> should be of the form: pr-names = pr-name | pr-names ";" pr-name where `pr-name` is the urlencoded name of a promisor remote the server advertised and the client accepts. -Note that, everywhere in this document, `pr-name` MUST be a valid -remote name, and the ';' and ',' characters MUST be encoded if they -appear in `pr-name` or `pr-url`. +Note that, everywhere in this document, the ';' and ',' characters +MUST be encoded if they appear in `pr-name` or `field-value`. If the server doesn't know any promisor remote that could be good for a client to use, or prefers a client not to use any promisor remote it @@ -822,9 +853,10 @@ In this case, or if the client doesn't want to use any promisor remote the server advertised, the client shouldn't advertise the "promisor-remote" capability at all in its reply. -The "promisor.advertise" and "promisor.acceptFromServer" configuration -options can be used on the server and client side to control what they -advertise or accept respectively. See the documentation of these +On the server side, the "promisor.advertise" and "promisor.sendFields" +configuration options can be used to control what it advertises. On +the client side, the "promisor.acceptFromServer" configuration option +can be used to control what it accepts. See the documentation of these configuration options for more information. Note that in the future it would be nice if the "promisor-remote" diff --git a/add-interactive.c b/add-interactive.c index 3e692b47ec..6ffe64c38d 100644 --- a/add-interactive.c +++ b/add-interactive.c @@ -20,14 +20,14 @@ #include "prompt.h" #include "tree.h" -static void init_color(struct repository *r, struct add_i_state *s, +static void init_color(struct repository *r, enum git_colorbool use_color, const char *section_and_slot, char *dst, const char *default_color) { char *key = xstrfmt("color.%s", section_and_slot); const char *value; - if (!s->use_color) + if (!want_color(use_color)) dst[0] = '\0'; else if (repo_config_get_value(r, key, &value) || color_parse(value, dst)) @@ -36,42 +36,64 @@ static void init_color(struct repository *r, struct add_i_state *s, free(key); } -void init_add_i_state(struct add_i_state *s, struct repository *r, - struct add_p_opt *add_p_opt) +static enum git_colorbool check_color_config(struct repository *r, const char *var) { const char *value; + enum git_colorbool ret; + + if (repo_config_get_value(r, var, &value)) + ret = GIT_COLOR_UNKNOWN; + else + ret = git_config_colorbool(var, value); + + /* + * Do not rely on want_color() to fall back to color.ui for us. It uses + * the value parsed by git_color_config(), which may not have been + * called by the main command. + */ + if (ret == GIT_COLOR_UNKNOWN && + !repo_config_get_value(r, "color.ui", &value)) + ret = git_config_colorbool("color.ui", value); + return ret; +} + +void init_add_i_state(struct add_i_state *s, struct repository *r, + struct add_p_opt *add_p_opt) +{ s->r = r; s->context = -1; s->interhunkcontext = -1; - if (repo_config_get_value(r, "color.interactive", &value)) - s->use_color = -1; - else - s->use_color = - git_config_colorbool("color.interactive", value); - s->use_color = want_color(s->use_color); - - init_color(r, s, "interactive.header", s->header_color, GIT_COLOR_BOLD); - init_color(r, s, "interactive.help", s->help_color, GIT_COLOR_BOLD_RED); - init_color(r, s, "interactive.prompt", s->prompt_color, - GIT_COLOR_BOLD_BLUE); - init_color(r, s, "interactive.error", s->error_color, - GIT_COLOR_BOLD_RED); - - init_color(r, s, "diff.frag", s->fraginfo_color, - diff_get_color(s->use_color, DIFF_FRAGINFO)); - init_color(r, s, "diff.context", s->context_color, "fall back"); + s->use_color_interactive = check_color_config(r, "color.interactive"); + + init_color(r, s->use_color_interactive, "interactive.header", + s->header_color, GIT_COLOR_BOLD); + init_color(r, s->use_color_interactive, "interactive.help", + s->help_color, GIT_COLOR_BOLD_RED); + init_color(r, s->use_color_interactive, "interactive.prompt", + s->prompt_color, GIT_COLOR_BOLD_BLUE); + init_color(r, s->use_color_interactive, "interactive.error", + s->error_color, GIT_COLOR_BOLD_RED); + strlcpy(s->reset_color_interactive, + want_color(s->use_color_interactive) ? GIT_COLOR_RESET : "", COLOR_MAXLEN); + + s->use_color_diff = check_color_config(r, "color.diff"); + + init_color(r, s->use_color_diff, "diff.frag", s->fraginfo_color, + diff_get_color(s->use_color_diff, DIFF_FRAGINFO)); + init_color(r, s->use_color_diff, "diff.context", s->context_color, + "fall back"); if (!strcmp(s->context_color, "fall back")) - init_color(r, s, "diff.plain", s->context_color, - diff_get_color(s->use_color, DIFF_CONTEXT)); - init_color(r, s, "diff.old", s->file_old_color, - diff_get_color(s->use_color, DIFF_FILE_OLD)); - init_color(r, s, "diff.new", s->file_new_color, - diff_get_color(s->use_color, DIFF_FILE_NEW)); - - strlcpy(s->reset_color, - s->use_color ? GIT_COLOR_RESET : "", COLOR_MAXLEN); + init_color(r, s->use_color_diff, "diff.plain", + s->context_color, + diff_get_color(s->use_color_diff, DIFF_CONTEXT)); + init_color(r, s->use_color_diff, "diff.old", s->file_old_color, + diff_get_color(s->use_color_diff, DIFF_FILE_OLD)); + init_color(r, s->use_color_diff, "diff.new", s->file_new_color, + diff_get_color(s->use_color_diff, DIFF_FILE_NEW)); + strlcpy(s->reset_color_diff, + want_color(s->use_color_diff) ? GIT_COLOR_RESET : "", COLOR_MAXLEN); FREE_AND_NULL(s->interactive_diff_filter); repo_config_get_string(r, "interactive.difffilter", @@ -109,7 +131,8 @@ void clear_add_i_state(struct add_i_state *s) FREE_AND_NULL(s->interactive_diff_filter); FREE_AND_NULL(s->interactive_diff_algorithm); memset(s, 0, sizeof(*s)); - s->use_color = -1; + s->use_color_interactive = GIT_COLOR_UNKNOWN; + s->use_color_diff = GIT_COLOR_UNKNOWN; } /* @@ -1188,9 +1211,9 @@ int run_add_i(struct repository *r, const struct pathspec *ps, * When color was asked for, use the prompt color for * highlighting, otherwise use square brackets. */ - if (s.use_color) { + if (want_color(s.use_color_interactive)) { data.color = s.prompt_color; - data.reset = s.reset_color; + data.reset = s.reset_color_interactive; } print_file_item_data.color = data.color; print_file_item_data.reset = data.reset; diff --git a/add-interactive.h b/add-interactive.h index 4213dcd67b..da49502b76 100644 --- a/add-interactive.h +++ b/add-interactive.h @@ -12,16 +12,19 @@ struct add_p_opt { struct add_i_state { struct repository *r; - int use_color; + enum git_colorbool use_color_interactive; + enum git_colorbool use_color_diff; char header_color[COLOR_MAXLEN]; char help_color[COLOR_MAXLEN]; char prompt_color[COLOR_MAXLEN]; char error_color[COLOR_MAXLEN]; - char reset_color[COLOR_MAXLEN]; + char reset_color_interactive[COLOR_MAXLEN]; + char fraginfo_color[COLOR_MAXLEN]; char context_color[COLOR_MAXLEN]; char file_old_color[COLOR_MAXLEN]; char file_new_color[COLOR_MAXLEN]; + char reset_color_diff[COLOR_MAXLEN]; int use_single_key; char *interactive_diff_filter, *interactive_diff_algorithm; diff --git a/add-patch.c b/add-patch.c index 302e6ba7d9..b0389c5d5b 100644 --- a/add-patch.c +++ b/add-patch.c @@ -300,7 +300,7 @@ static void err(struct add_p_state *s, const char *fmt, ...) va_start(args, fmt); fputs(s->s.error_color, stdout); vprintf(fmt, args); - puts(s->s.reset_color); + puts(s->s.reset_color_interactive); va_end(args); } @@ -457,7 +457,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) } strbuf_complete_line(plain); - if (want_color_fd(1, -1)) { + if (want_color_fd(1, s->s.use_color_diff)) { struct child_process colored_cp = CHILD_PROCESS_INIT; const char *diff_filter = s->s.interactive_diff_filter; @@ -714,7 +714,7 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk, if (len) strbuf_add(out, p, len); else if (colored) - strbuf_addf(out, "%s\n", s->s.reset_color); + strbuf_addf(out, "%s\n", s->s.reset_color_diff); else strbuf_addch(out, '\n'); } @@ -1107,7 +1107,7 @@ static void recolor_hunk(struct add_p_state *s, struct hunk *hunk) s->s.file_new_color : s->s.context_color); strbuf_add(&s->colored, plain + current, eol - current); - strbuf_addstr(&s->colored, s->s.reset_color); + strbuf_addstr(&s->colored, s->s.reset_color_diff); if (next > eol) strbuf_add(&s->colored, plain + eol, next - eol); current = next; @@ -1528,8 +1528,8 @@ static int patch_update_file(struct add_p_state *s, : 1)); printf(_(s->mode->prompt_mode[prompt_mode_type]), s->buf.buf); - if (*s->s.reset_color) - fputs(s->s.reset_color, stdout); + if (*s->s.reset_color_interactive) + fputs(s->s.reset_color_interactive, stdout); fflush(stdout); if (read_single_character(s) == EOF) break; @@ -7,7 +7,7 @@ #include "help.h" #include "string-list.h" -static int advice_use_color = -1; +static enum git_colorbool advice_use_color = GIT_COLOR_UNKNOWN; static char advice_colors[][COLOR_MAXLEN] = { GIT_COLOR_RESET, GIT_COLOR_YELLOW, /* HINT */ @@ -18,7 +18,7 @@ enum advice_type { ADVICE_AM_WORK_DIR, ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME, ADVICE_COMMIT_BEFORE_MERGE, - ADVICE_DEFAULT_BRANCH_NAME, + ADVICE_DEFAULT_BRANCH_NAME, /* To be retired sometime after Git 3.0 */ ADVICE_DETACHED_HEAD, ADVICE_DIVERGING, ADVICE_FETCH_SET_HEAD_WARN, @@ -36,19 +36,25 @@ struct alloc_state { int slab_nr, slab_alloc; }; -struct alloc_state *allocate_alloc_state(void) +struct alloc_state *alloc_state_alloc(void) { return xcalloc(1, sizeof(struct alloc_state)); } -void clear_alloc_state(struct alloc_state *s) +void alloc_state_free_and_null(struct alloc_state **s_) { + struct alloc_state *s = *s_; + + if (!s) + return; + while (s->slab_nr > 0) { s->slab_nr--; free(s->slabs[s->slab_nr]); } FREE_AND_NULL(s->slabs); + FREE_AND_NULL(*s_); } static inline void *alloc_node(struct alloc_state *s, size_t node_size) @@ -14,7 +14,7 @@ void *alloc_commit_node(struct repository *r); void *alloc_tag_node(struct repository *r); void *alloc_object_node(struct repository *r); -struct alloc_state *allocate_alloc_state(void); -void clear_alloc_state(struct alloc_state *s); +struct alloc_state *alloc_state_alloc(void); +void alloc_state_free_and_null(struct alloc_state **s_); #endif @@ -674,9 +674,6 @@ static void bisect_rev_setup(struct repository *r, struct rev_info *revs, const char *bad_format, const char *good_format, int read_paths) { - struct setup_revision_opt opt = { - .free_removed_argv_elements = 1, - }; int i; repo_init_revisions(r, revs, prefix); @@ -693,7 +690,7 @@ static void bisect_rev_setup(struct repository *r, struct rev_info *revs, if (read_paths) read_bisect_paths(rev_argv); - setup_revisions(rev_argv->nr, rev_argv->v, revs, &opt); + setup_revisions_from_strvec(rev_argv, revs, NULL); } static void bisect_common(struct rev_info *revs) diff --git a/builtin/add.c b/builtin/add.c index 740c7c4581..4cd3d183f9 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -200,7 +200,7 @@ static int edit_patch(struct repository *repo, argc = setup_revisions(argc, argv, &rev, NULL); rev.diffopt.output_format = DIFF_FORMAT_PATCH; - rev.diffopt.use_color = 0; + rev.diffopt.use_color = GIT_COLOR_NEVER; rev.diffopt.flags.ignore_dirty_submodules = 1; out = xopen(file, O_CREAT | O_WRONLY | O_TRUNC, 0666); rev.diffopt.file = xfdopen(out, "w"); diff --git a/builtin/am.c b/builtin/am.c index 6073d64ae9..277c2e7937 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -1408,7 +1408,7 @@ static void write_commit_patch(const struct am_state *state, struct commit *comm rev_info.no_commit_id = 1; rev_info.diffopt.flags.binary = 1; rev_info.diffopt.flags.full_index = 1; - rev_info.diffopt.use_color = 0; + rev_info.diffopt.use_color = GIT_COLOR_NEVER; rev_info.diffopt.file = fp; rev_info.diffopt.close_file = 1; add_pending_object(&rev_info, &commit->object, ""); @@ -1441,7 +1441,7 @@ static void write_index_patch(const struct am_state *state) rev_info.disable_stdin = 1; rev_info.no_commit_id = 1; rev_info.diffopt.output_format = DIFF_FORMAT_PATCH; - rev_info.diffopt.use_color = 0; + rev_info.diffopt.use_color = GIT_COLOR_NEVER; rev_info.diffopt.file = fp; rev_info.diffopt.close_file = 1; add_pending_object(&rev_info, &tree->object, ""); diff --git a/builtin/branch.c b/builtin/branch.c index fa5ced452e..9fcf04bebb 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -46,7 +46,7 @@ static struct object_id head_oid; static int recurse_submodules = 0; static int submodule_propagate_branches = 0; -static int branch_use_color = -1; +static enum git_colorbool branch_use_color = GIT_COLOR_UNKNOWN; static char branch_colors[][COLOR_MAXLEN] = { GIT_COLOR_RESET, GIT_COLOR_NORMAL, /* PLAIN */ diff --git a/builtin/clean.c b/builtin/clean.c index 38b67923a6..1d5e7e5366 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -64,7 +64,7 @@ static const char *color_interactive_slots[] = { [CLEAN_COLOR_RESET] = "reset", }; -static int clean_use_color = -1; +static enum git_colorbool clean_use_color = GIT_COLOR_UNKNOWN; static char clean_colors[][COLOR_MAXLEN] = { [CLEAN_COLOR_ERROR] = GIT_COLOR_BOLD_RED, [CLEAN_COLOR_HEADER] = GIT_COLOR_BOLD, diff --git a/builtin/commit.c b/builtin/commit.c index 8a5dee384d..0243f17d53 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -695,6 +695,7 @@ static int author_date_is_interesting(void) return author_message || force_date; } +#ifndef WITH_BREAKING_CHANGES static void adjust_comment_line_char(const struct strbuf *sb) { char candidates[] = "#;@!$%^&|:"; @@ -732,6 +733,7 @@ static void adjust_comment_line_char(const struct strbuf *sb) free(comment_line_str_to_free); comment_line_str = comment_line_str_to_free = xstrfmt("%c", *p); } +#endif /* !WITH_BREAKING_CHANGES */ static void prepare_amend_commit(struct commit *commit, struct strbuf *sb, struct pretty_print_context *ctx) @@ -928,15 +930,17 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len) die_errno(_("could not write commit template")); +#ifndef WITH_BREAKING_CHANGES if (auto_comment_line_char) adjust_comment_line_char(&sb); +#endif /* !WITH_BREAKING_CHANGES */ strbuf_release(&sb); /* This checks if committer ident is explicitly given */ strbuf_addstr(&committer_ident, git_committer_info(IDENT_STRICT)); if (use_editor && include_status) { int ident_shown = 0; - int saved_color_setting; + enum git_colorbool saved_color_setting; struct ident_split ci, ai; const char *hint_cleanup_all = allow_empty_message ? _("Please enter the commit message for your changes." @@ -1016,7 +1020,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, status_printf_ln(s, GIT_COLOR_NORMAL, "%s", ""); /* Add new line for clarity */ saved_color_setting = s->use_color; - s->use_color = 0; + s->use_color = GIT_COLOR_NEVER; committable = run_status(s->fp, index_file, prefix, 1, s); s->use_color = saved_color_setting; string_list_clear_func(&s->change, change_data_free); @@ -1793,6 +1797,9 @@ int cmd_commit(int argc, show_usage_with_options_if_asked(argc, argv, builtin_commit_usage, builtin_commit_options); +#ifndef WITH_BREAKING_CHANGES + warn_on_auto_comment_char = true; +#endif /* !WITH_BREAKING_CHANGES */ prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; diff --git a/builtin/config.c b/builtin/config.c index 59fb113b07..2348a99dd4 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -568,9 +568,9 @@ static void get_color(const struct config_location_options *opts, } struct get_colorbool_config_data { - int get_colorbool_found; - int get_diff_color_found; - int get_color_ui_found; + enum git_colorbool get_colorbool_found; + enum git_colorbool get_diff_color_found; + enum git_colorbool get_color_ui_found; const char *get_colorbool_slot; }; @@ -594,33 +594,34 @@ static int get_colorbool(const struct config_location_options *opts, { struct get_colorbool_config_data data = { .get_colorbool_slot = var, - .get_colorbool_found = -1, - .get_diff_color_found = -1, - .get_color_ui_found = -1, + .get_colorbool_found = GIT_COLOR_UNKNOWN, + .get_diff_color_found = GIT_COLOR_UNKNOWN, + .get_color_ui_found = GIT_COLOR_UNKNOWN, }; + bool result; config_with_options(git_get_colorbool_config, &data, &opts->source, the_repository, &opts->options); - if (data.get_colorbool_found < 0) { + if (data.get_colorbool_found == GIT_COLOR_UNKNOWN) { if (!strcmp(data.get_colorbool_slot, "color.diff")) data.get_colorbool_found = data.get_diff_color_found; - if (data.get_colorbool_found < 0) + if (data.get_colorbool_found == GIT_COLOR_UNKNOWN) data.get_colorbool_found = data.get_color_ui_found; } - if (data.get_colorbool_found < 0) + if (data.get_colorbool_found == GIT_COLOR_UNKNOWN) /* default value if none found in config */ data.get_colorbool_found = GIT_COLOR_AUTO; - data.get_colorbool_found = want_color(data.get_colorbool_found); + result = want_color(data.get_colorbool_found); if (print) { - printf("%s\n", data.get_colorbool_found ? "true" : "false"); + printf("%s\n", result ? "true" : "false"); return 0; } else - return data.get_colorbool_found ? 0 : 1; + return result ? 0 : 1; } static void check_write(const struct git_config_source *source) diff --git a/builtin/describe.c b/builtin/describe.c index 9f4e26d7ff..ffaf8d9f0a 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -580,7 +580,8 @@ static void describe_blob(const struct object_id *oid, struct strbuf *dst) NULL); repo_init_revisions(the_repository, &revs, NULL); - if (setup_revisions(args.nr, args.v, &revs, NULL) > 1) + setup_revisions_from_strvec(&args, &revs, NULL); + if (args.nr > 1) BUG("setup_revisions could not handle all args?"); if (prepare_revision_walk(&revs)) diff --git a/builtin/fetch.c b/builtin/fetch.c index 24645c4653..c7ff3480fb 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1643,7 +1643,8 @@ cleanup: struct ref_rejection_data { int *retcode; - int conflict_msg_shown; + bool conflict_msg_shown; + bool case_sensitive_msg_shown; const char *remote_name; }; @@ -1657,11 +1658,25 @@ static void ref_transaction_rejection_handler(const char *refname, { struct ref_rejection_data *data = cb_data; - if (err == REF_TRANSACTION_ERROR_NAME_CONFLICT && !data->conflict_msg_shown) { + if (err == REF_TRANSACTION_ERROR_CASE_CONFLICT && ignore_case && + !data->case_sensitive_msg_shown) { + error(_("You're on a case-insensitive filesystem, and the remote you are\n" + "trying to fetch from has references that only differ in casing. It\n" + "is impossible to store such references with the 'files' backend. You\n" + "can either accept this as-is, in which case you won't be able to\n" + "store all remote references on disk. Or you can alternatively\n" + "migrate your repository to use the 'reftable' backend with the\n" + "following command:\n\n git refs migrate --ref-format=reftable\n\n" + "Please keep in mind that not all implementations of Git support this\n" + "new format yet. So if you use tools other than Git to access this\n" + "repository it may not be an option to migrate to reftables.\n")); + data->case_sensitive_msg_shown = true; + } else if (err == REF_TRANSACTION_ERROR_NAME_CONFLICT && + !data->conflict_msg_shown) { error(_("some local refs could not be updated; try running\n" " 'git remote prune %s' to remove any old, conflicting " "branches"), data->remote_name); - data->conflict_msg_shown = 1; + data->conflict_msg_shown = true; } else { const char *reason = ref_transaction_error_msg(err); diff --git a/builtin/grep.c b/builtin/grep.c index 5df6537333..1d97eb2a2a 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -1091,7 +1091,7 @@ int cmd_grep(int argc, if (show_in_pager == default_pager) show_in_pager = git_pager(the_repository, 1); if (show_in_pager) { - opt.color = 0; + opt.color = GIT_COLOR_NEVER; opt.name_only = 1; opt.null_following_name = 1; opt.output_priv = &path_list; diff --git a/builtin/log.c b/builtin/log.c index c2f8bbf863..5f552d14c0 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1404,6 +1404,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, struct range_diff_options range_diff_opts = { .creation_factor = rev->creation_factor, .dual_color = 1, + .max_memory = RANGE_DIFF_MAX_MEMORY_DEFAULT, .diffopt = &opts, .other_arg = &other_arg }; diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 5d55731ca3..ec6940fc7c 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -373,7 +373,6 @@ int cmd_ls_tree(int argc, OPT_END() }; struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format; - struct object_context obj_context = {0}; int ret; repo_config(the_repository, git_default_config, NULL); @@ -405,9 +404,8 @@ int cmd_ls_tree(int argc, ls_tree_usage, ls_tree_options); if (argc < 1) usage_with_options(ls_tree_usage, ls_tree_options); - if (get_oid_with_context(the_repository, argv[0], - GET_OID_HASH_ANY, &oid, - &obj_context)) + if (repo_get_oid_with_flags(the_repository, argv[0], &oid, + GET_OID_HASH_ANY)) die("Not a valid object name %s", argv[0]); /* @@ -447,6 +445,5 @@ int cmd_ls_tree(int argc, ret = !!read_tree(the_repository, tree, &options.pathspec, fn, &options); clear_pathspec(&options.pathspec); - object_context_release(&obj_context); return ret; } diff --git a/builtin/merge.c b/builtin/merge.c index b235af730a..c421a11b0b 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -1379,6 +1379,9 @@ int cmd_merge(int argc, show_usage_with_options_if_asked(argc, argv, builtin_merge_usage, builtin_merge_options); +#ifndef WITH_BREAKING_CHANGES + warn_on_auto_comment_char = true; +#endif /* !WITH_BREAKING_CHANGES */ prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 1494afcf3d..5856b5f6bf 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -4650,7 +4650,7 @@ static void get_object_list_path_walk(struct rev_info *revs) die(_("failed to pack objects via path-walk")); } -static void get_object_list(struct rev_info *revs, int ac, const char **av) +static void get_object_list(struct rev_info *revs, struct strvec *argv) { struct setup_revision_opt s_r_opt = { .allow_exclude_promisor_objects = 1, @@ -4660,7 +4660,7 @@ static void get_object_list(struct rev_info *revs, int ac, const char **av) int save_warning; save_commit_buffer = 0; - setup_revisions(ac, av, revs, &s_r_opt); + setup_revisions_from_strvec(argv, revs, &s_r_opt); /* make sure shallows are read */ is_repository_shallow(the_repository); @@ -5229,7 +5229,7 @@ int cmd_pack_objects(int argc, revs.include_check = is_not_in_promisor_pack; revs.include_check_obj = is_not_in_promisor_pack_obj; } - get_object_list(&revs, rp.nr, rp.v); + get_object_list(&revs, &rp); release_revisions(&revs); } cleanup_preferred_base(); diff --git a/builtin/push.c b/builtin/push.c index d0794b7b30..5b6cebbb85 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -27,7 +27,7 @@ static const char * const push_usage[] = { NULL, }; -static int push_use_color = -1; +static enum git_colorbool push_use_color = GIT_COLOR_UNKNOWN; static char push_colors[][COLOR_MAXLEN] = { GIT_COLOR_RESET, GIT_COLOR_RED, /* ERROR */ diff --git a/builtin/range-diff.c b/builtin/range-diff.c index a563abff5f..1bc082a869 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -6,6 +6,8 @@ #include "parse-options.h" #include "range-diff.h" #include "config.h" +#include "parse.h" +#include "color.h" static const char * const builtin_range_diff_usage[] = { @@ -15,6 +17,21 @@ N_("git range-diff [<options>] <base> <old-tip> <new-tip>"), NULL }; +static int parse_max_memory(const struct option *opt, const char *arg, int unset) +{ + size_t *max_memory = opt->value; + uintmax_t val; + + if (unset) + return 0; + + if (!git_parse_unsigned(arg, &val, SIZE_MAX)) + return error(_("invalid max-memory value: %s"), arg); + + *max_memory = (size_t)val; + return 0; +} + int cmd_range_diff(int argc, const char **argv, const char *prefix, @@ -25,6 +42,7 @@ int cmd_range_diff(int argc, struct strvec diff_merges_arg = STRVEC_INIT; struct range_diff_options range_diff_opts = { .creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT, + .max_memory = RANGE_DIFF_MAX_MEMORY_DEFAULT, .diffopt = &diffopt, .other_arg = &other_arg }; @@ -40,6 +58,10 @@ int cmd_range_diff(int argc, PARSE_OPT_OPTARG), OPT_PASSTHRU_ARGV(0, "diff-merges", &diff_merges_arg, N_("style"), N_("passed to 'git log'"), 0), + OPT_CALLBACK(0, "max-memory", &range_diff_opts.max_memory, + N_("size"), + N_("maximum memory for cost matrix (default 4G)"), + parse_max_memory), OPT_PASSTHRU_ARGV(0, "remerge-diff", &diff_merges_arg, NULL, N_("passed to 'git log'"), PARSE_OPT_NOARG), OPT_BOOL(0, "left-only", &left_only, @@ -66,7 +88,7 @@ int cmd_range_diff(int argc, /* force color when --dual-color was used */ if (!simple_color) - diffopt.use_color = 1; + diffopt.use_color = GIT_COLOR_ALWAYS; /* If `--diff-merges` was specified, imply `--merges` */ if (diff_merges_arg.nr) { diff --git a/builtin/rebase.c b/builtin/rebase.c index 3c85768d29..c468828189 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -299,8 +299,7 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags) oid_to_hex(&opts->restrict_revision->object.oid)); ret = sequencer_make_script(the_repository, &todo_list.buf, - make_script_args.nr, make_script_args.v, - flags); + &make_script_args, flags); if (ret) { error(_("could not generate todo list")); goto cleanup; @@ -1242,6 +1241,9 @@ int cmd_rebase(int argc, builtin_rebase_usage, builtin_rebase_options); +#ifndef WITH_BREAKING_CHANGES + warn_on_auto_comment_char = true; +#endif /* !WITH_BREAKING_CHANGES */ prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 44ff1b8342..9da92b990d 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -708,7 +708,6 @@ int cmd_rev_parse(int argc, struct object_id oid; unsigned int flags = 0; const char *name = NULL; - struct object_context unused; struct strbuf buf = STRBUF_INIT; int seen_end_of_options = 0; enum format_type format = FORMAT_DEFAULT; @@ -1141,9 +1140,8 @@ int cmd_rev_parse(int argc, name++; type = REVERSED; } - if (!get_oid_with_context(the_repository, name, - flags, &oid, &unused)) { - object_context_release(&unused); + if (!repo_get_oid_with_flags(the_repository, name, &oid, + flags)) { if (output_algo) repo_oid_to_algop(the_repository, &oid, output_algo, &oid); @@ -1153,7 +1151,6 @@ int cmd_rev_parse(int argc, show_rev(type, &oid, name); continue; } - object_context_release(&unused); if (verify) die_no_single_rev(quiet); if (has_dashdash) diff --git a/builtin/revert.c b/builtin/revert.c index c3f92b585d..bedc40f368 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -4,6 +4,7 @@ #include "builtin.h" #include "parse-options.h" #include "diff.h" +#include "environment.h" #include "gettext.h" #include "revision.h" #include "rerere.h" @@ -285,6 +286,9 @@ int cmd_revert(int argc, struct replay_opts opts = REPLAY_OPTS_INIT; int res; +#ifndef WITH_BREAKING_CHANGES + warn_on_auto_comment_char = true; +#endif /* !WITH_BREAKING_CHANGES */ opts.action = REPLAY_REVERT; sequencer_init_config(&opts); res = run_sequencer(argc, argv, prefix, &opts); @@ -302,6 +306,9 @@ struct repository *repo UNUSED) struct replay_opts opts = REPLAY_OPTS_INIT; int res; +#ifndef WITH_BREAKING_CHANGES + warn_on_auto_comment_char = true; +#endif /* !WITH_BREAKING_CHANGES */ opts.action = REPLAY_PICK; sequencer_init_config(&opts); res = run_sequencer(argc, argv, prefix, &opts); diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 1ab7db9d2c..441babf2e3 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -29,7 +29,7 @@ static const char*const show_branch_usage[] = { NULL }; -static int showbranch_use_color = -1; +static enum git_colorbool showbranch_use_color = GIT_COLOR_UNKNOWN; static struct strvec default_args = STRVEC_INIT; diff --git a/builtin/stash.c b/builtin/stash.c index f5ddee5c7f..948eba06fb 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -146,6 +146,11 @@ static const char * const git_stash_import_usage[] = { static const char ref_stash[] = "refs/stash"; static struct strbuf stash_index_path = STRBUF_INIT; +static int show_stat = 1; +static int show_patch; +static int show_include_untracked; +static int use_index; + /* * w_commit is set to the commit containing the working tree * b_commit is set to the base commit @@ -377,7 +382,7 @@ static int diff_tree_binary(struct strbuf *out, struct object_id *w_commit) * however it should be done together with apply_cached. */ cp.git_cmd = 1; - strvec_pushl(&cp.args, "diff-tree", "--binary", NULL); + strvec_pushl(&cp.args, "diff-tree", "--binary", "--no-color", NULL); strvec_pushf(&cp.args, "%s^2^..%s^2", w_commit_hex, w_commit_hex); return pipe_command(&cp, NULL, 0, out, 0, NULL, 0); @@ -717,7 +722,7 @@ static int apply_stash(int argc, const char **argv, const char *prefix, { int ret = -1; int quiet = 0; - int index = 0; + int index = use_index; struct stash_info info = STASH_INFO_INIT; struct option options[] = { OPT__QUIET(&quiet, N_("be quiet, only report errors")), @@ -815,7 +820,7 @@ static int pop_stash(int argc, const char **argv, const char *prefix, struct repository *repo UNUSED) { int ret = -1; - int index = 0; + int index = use_index; int quiet = 0; struct stash_info info = STASH_INFO_INIT; struct option options[] = { @@ -905,10 +910,6 @@ static int list_stash(int argc, const char **argv, const char *prefix, return run_command(&cp); } -static int show_stat = 1; -static int show_patch; -static int show_include_untracked; - static int git_stash_config(const char *var, const char *value, const struct config_context *ctx, void *cb) { @@ -924,6 +925,10 @@ static int git_stash_config(const char *var, const char *value, show_include_untracked = git_config_bool(var, value); return 0; } + if (!strcmp(var, "stash.index")) { + use_index = git_config_bool(var, value); + return 0; + } return git_diff_basic_config(var, value, ctx, cb); } @@ -1015,8 +1020,8 @@ static int show_stash(int argc, const char **argv, const char *prefix, } } - argc = setup_revisions(revision_args.nr, revision_args.v, &rev, NULL); - if (argc > 1) + setup_revisions_from_strvec(&revision_args, &rev, NULL); + if (revision_args.nr > 1) goto usage; if (!rev.diffopt.output_format) { rev.diffopt.output_format = DIFF_FORMAT_PATCH; @@ -1089,7 +1094,6 @@ static int store_stash(int argc, const char **argv, const char *prefix, int quiet = 0; const char *stash_msg = NULL; struct object_id obj; - struct object_context dummy = {0}; struct option options[] = { OPT__QUIET(&quiet, N_("be quiet")), OPT_STRING('m', "message", &stash_msg, "message", @@ -1109,9 +1113,8 @@ static int store_stash(int argc, const char **argv, const char *prefix, return -1; } - if (get_oid_with_context(the_repository, - argv[0], quiet ? GET_OID_QUIETLY : 0, &obj, - &dummy)) { + if (repo_get_oid_with_flags(the_repository, argv[0], &obj, + quiet ? GET_OID_QUIETLY : 0)) { if (!quiet) fprintf_ln(stderr, _("Cannot update %s with %s"), ref_stash, argv[0]); @@ -1122,7 +1125,6 @@ static int store_stash(int argc, const char **argv, const char *prefix, ret = do_store_stash(&obj, stash_msg, quiet); out: - object_context_release(&dummy); return ret; } @@ -1284,6 +1286,7 @@ static int stash_staged(struct stash_info *info, struct strbuf *out_patch, cp_diff_tree.git_cmd = 1; strvec_pushl(&cp_diff_tree.args, "diff-tree", "-p", "--binary", + "--no-color", "-U1", "HEAD", oid_to_hex(&info->w_tree), "--", NULL); if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) { ret = -1; @@ -1346,6 +1349,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps, cp_diff_tree.git_cmd = 1; strvec_pushl(&cp_diff_tree.args, "diff-tree", "-p", "-U1", "HEAD", + "--no-color", oid_to_hex(&info->w_tree), "--", NULL); if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) { ret = -1; @@ -1720,6 +1724,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q cp_diff.git_cmd = 1; strvec_pushl(&cp_diff.args, "diff-index", "-p", + "--no-color", "--cached", "--binary", "HEAD", "--", NULL); add_pathspecs(&cp_diff.args, ps); @@ -2235,7 +2240,6 @@ static int do_export_stash(struct repository *r, const char **argv) { struct object_id base; - struct object_context unused; struct commit *prev; struct commit_list *items = NULL, **iter = &items, *cur; int res = 0; @@ -2269,9 +2273,9 @@ static int do_export_stash(struct repository *r, struct commit *stash; if (parse_stash_revision(&revision, argv[i], 1) || - get_oid_with_context(r, revision.buf, - GET_OID_QUIETLY | GET_OID_GENTLY, - &oid, &unused)) { + repo_get_oid_with_flags(r, revision.buf, &oid, + GET_OID_QUIETLY | + GET_OID_GENTLY)) { res = error(_("unable to find stash entry %s"), argv[i]); goto out; } diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 07a1935cbe..fcd73abe53 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -616,9 +616,6 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, struct rev_info rev = REV_INFO_INIT; struct strbuf buf = STRBUF_INIT; const char *git_dir; - struct setup_revision_opt opt = { - .free_removed_argv_elements = 1, - }; if (validate_submodule_path(path) < 0) die(NULL); @@ -655,7 +652,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, repo_init_revisions(the_repository, &rev, NULL); rev.abbrev = 0; - setup_revisions(diff_files_args.nr, diff_files_args.v, &rev, &opt); + setup_revisions_from_strvec(&diff_files_args, &rev, NULL); run_diff_files(&rev, 0); if (!diff_result_code(&rev)) { @@ -1094,9 +1091,6 @@ static int compute_summary_module_list(struct object_id *head_oid, { struct strvec diff_args = STRVEC_INIT; struct rev_info rev; - struct setup_revision_opt opt = { - .free_removed_argv_elements = 1, - }; struct module_cb_list list = MODULE_CB_LIST_INIT; int ret = 0; @@ -1114,7 +1108,7 @@ static int compute_summary_module_list(struct object_id *head_oid, repo_init_revisions(the_repository, &rev, info->prefix); rev.abbrev = 0; precompose_argv_prefix(diff_args.nr, diff_args.v, NULL); - setup_revisions(diff_args.nr, diff_args.v, &rev, &opt); + setup_revisions_from_strvec(&diff_args, &rev, NULL); rev.diffopt.output_format = DIFF_FORMAT_NO_OUTPUT | DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = submodule_summary_callback; rev.diffopt.format_callback_data = &list; diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh index 01823fd0f1..a21834043f 100755 --- a/ci/run-build-and-tests.sh +++ b/ci/run-build-and-tests.sh @@ -9,7 +9,6 @@ run_tests=t case "$jobname" in linux-breaking-changes) - export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export WITH_BREAKING_CHANGES=YesPlease ;; linux-TEST-vars) @@ -9,7 +9,7 @@ #include "pager.h" #include "strbuf.h" -static int git_use_color_default = GIT_COLOR_AUTO; +static enum git_colorbool git_use_color_default = GIT_COLOR_AUTO; int color_stdout_is_tty = -1; /* @@ -369,29 +369,29 @@ bad: #undef OUT } -int git_config_colorbool(const char *var, const char *value) +enum git_colorbool git_config_colorbool(const char *var, const char *value) { if (value) { if (!strcasecmp(value, "never")) - return 0; + return GIT_COLOR_NEVER; if (!strcasecmp(value, "always")) - return 1; + return GIT_COLOR_ALWAYS; if (!strcasecmp(value, "auto")) return GIT_COLOR_AUTO; } if (!var) - return -1; + return GIT_COLOR_UNKNOWN; /* Missing or explicit false to turn off colorization */ if (!git_config_bool(var, value)) - return 0; + return GIT_COLOR_NEVER; /* any normal truth value defaults to 'auto' */ return GIT_COLOR_AUTO; } -static int check_auto_color(int fd) +static bool check_auto_color(int fd) { static int color_stderr_is_tty = -1; int *is_tty_p = fd == 1 ? &color_stdout_is_tty : &color_stderr_is_tty; @@ -399,12 +399,12 @@ static int check_auto_color(int fd) *is_tty_p = isatty(fd); if (*is_tty_p || (fd == 1 && pager_in_use() && pager_use_color)) { if (!is_terminal_dumb()) - return 1; + return true; } - return 0; + return false; } -int want_color_fd(int fd, int var) +bool want_color_fd(int fd, enum git_colorbool var) { /* * NEEDSWORK: This function is sometimes used from multiple threads, and @@ -418,7 +418,7 @@ int want_color_fd(int fd, int var) if (fd < 1 || fd >= ARRAY_SIZE(want_auto)) BUG("file descriptor out of range: %d", fd); - if (var < 0) + if (var == GIT_COLOR_UNKNOWN) var = git_use_color_default; if (var == GIT_COLOR_AUTO) { @@ -426,7 +426,7 @@ int want_color_fd(int fd, int var) want_auto[fd] = check_auto_color(fd); return want_auto[fd]; } - return var; + return var == GIT_COLOR_ALWAYS; } int git_color_config(const char *var, const char *value, void *cb UNUSED) @@ -73,10 +73,12 @@ struct strbuf; * returned from git_config_colorbool. The "auto" value can be returned from * config_colorbool, and will be converted by want_color() into either 0 or 1. */ -#define GIT_COLOR_UNKNOWN -1 -#define GIT_COLOR_NEVER 0 -#define GIT_COLOR_ALWAYS 1 -#define GIT_COLOR_AUTO 2 +enum git_colorbool { + GIT_COLOR_UNKNOWN = -1, + GIT_COLOR_NEVER = 0, + GIT_COLOR_ALWAYS = 1, + GIT_COLOR_AUTO = 2, +}; /* A default list of colors to use for commit graphs and show-branch output */ extern const char *column_colors_ansi[]; @@ -98,13 +100,13 @@ int git_color_config(const char *var, const char *value, void *cb); * GIT_COLOR_ALWAYS for "always" or a positive boolean, * and GIT_COLOR_AUTO for "auto". */ -int git_config_colorbool(const char *var, const char *value); +enum git_colorbool git_config_colorbool(const char *var, const char *value); /* * Return a boolean whether to use color, where the argument 'var' is * one of GIT_COLOR_UNKNOWN, GIT_COLOR_NEVER, GIT_COLOR_ALWAYS, GIT_COLOR_AUTO. */ -int want_color_fd(int fd, int var); +bool want_color_fd(int fd, enum git_colorbool var); #define want_color(colorbool) want_color_fd(1, (colorbool)) #define want_color_stderr(colorbool) want_color_fd(2, (colorbool)) diff --git a/combine-diff.c b/combine-diff.c index e779b86e0b..b799862068 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -749,7 +749,7 @@ static void show_line_to_eol(const char *line, int len, const char *reset) static void dump_sline(struct sline *sline, const char *line_prefix, unsigned long cnt, int num_parent, - int use_color, int result_deleted) + enum git_colorbool use_color, int result_deleted) { unsigned long mark = (1UL<<num_parent); unsigned long no_pre_delete = (2UL<<num_parent); @@ -8,9 +8,11 @@ #include "git-compat-util.h" #include "abspath.h" +#include "advice.h" #include "date.h" #include "branch.h" #include "config.h" +#include "dir.h" #include "parse.h" #include "convert.h" #include "environment.h" @@ -1948,10 +1950,290 @@ int git_configset_get_pathname(struct config_set *set, const char *key, char **d return 1; } +struct comment_char_config { + unsigned last_key_id; + bool auto_set; + bool auto_set_in_file; + struct strintmap key_flags; + size_t alloc, nr; + struct comment_char_config_item { + unsigned key_id; + char *path; + enum config_scope scope; + } *item; +}; + +#define COMMENT_CHAR_CFG_INIT { \ + .key_flags = STRINTMAP_INIT, \ + } + +static void comment_char_config_release(struct comment_char_config *config) +{ + strintmap_clear(&config->key_flags); + for (size_t i = 0; i < config->nr; i++) + free(config->item[i].path); + free(config->item); +} + +/* Used to track whether the key occurs more than once in a given file */ +#define KEY_SEEN_ONCE 1u +#define KEY_SEEN_TWICE 2u +#define COMMENT_KEY_SHIFT(id) (2 * (id)) +#define COMMENT_KEY_MASK(id) (3u << COMMENT_KEY_SHIFT(id)) + +static void set_comment_key_flags(struct comment_char_config *config, + const char *path, unsigned id, unsigned value) +{ + unsigned old = strintmap_get(&config->key_flags, path); + unsigned new = (old & ~COMMENT_KEY_MASK(id)) | + value << COMMENT_KEY_SHIFT(id); + + strintmap_set(&config->key_flags, path, new); +} + +static unsigned get_comment_key_flags(struct comment_char_config *config, + const char *path, unsigned id) +{ + unsigned value = strintmap_get(&config->key_flags, path); + + return (value & COMMENT_KEY_MASK(id)) >> COMMENT_KEY_SHIFT(id); +} + +static const char *comment_key_name(unsigned id) +{ + static const char *name[] = { + "core.commentChar", + "core.commentString", + }; + + if (id >= ARRAY_SIZE(name)) + BUG("invalid comment key id"); + + return name[id]; +} + +static void comment_char_callback(const char *key, const char *value, + const struct config_context *ctx, void *data) +{ + struct comment_char_config *config = data; + const struct key_value_info *kvi = ctx->kvi; + unsigned key_id; + + if (!strcmp(key, "core.commentchar")) + key_id = 0; + else if (!strcmp(key, "core.commentstring")) + key_id = 1; + else + return; + + config->last_key_id = key_id; + config->auto_set = value && !strcmp(value, "auto"); + if (kvi->origin_type != CONFIG_ORIGIN_FILE) { + return; + } else if (get_comment_key_flags(config, kvi->filename, key_id)) { + set_comment_key_flags(config, kvi->filename, key_id, + KEY_SEEN_TWICE); + } else { + struct comment_char_config_item *item; + + ALLOC_GROW_BY(config->item, config->nr, 1, config->alloc); + item = &config->item[config->nr - 1]; + item->key_id = key_id; + item->scope = kvi->scope; + item->path = xstrdup(kvi->filename); + set_comment_key_flags(config, kvi->filename, key_id, + KEY_SEEN_ONCE); + } + config->auto_set_in_file = config->auto_set; +} + +static void add_config_scope_arg(struct repository *repo, struct strbuf *buf, + struct comment_char_config_item *item) +{ + char *global_config = git_global_config(); + char *system_config = git_system_config(); + + if (item->scope == CONFIG_SCOPE_SYSTEM && access(item->path, W_OK)) { + /* + * If the user cannot write to the system config recommend + * setting the global config instead. + */ + strbuf_addstr(buf, "--global "); + } else if (fspatheq(item->path, system_config)) { + strbuf_addstr(buf, "--system "); + } else if (fspatheq(item->path, global_config)) { + strbuf_addstr(buf, "--global "); + } else if (fspatheq(item->path, + mkpath("%s/config", + repo_get_git_dir(repo)))) { + ; /* --local is the default */ + } else if (fspatheq(item->path, + mkpath("%s/config.worktree", + repo_get_common_dir(repo)))) { + strbuf_addstr(buf, "--worktree "); + } else { + const char *path = item->path; + const char *home = getenv("HOME"); + + strbuf_addstr(buf, "--file "); + if (home && !fspathncmp(path, home, strlen(home))) { + path += strlen(home); + if (!fspathncmp(path, "/", 1)) + path++; + strbuf_addstr(buf, "~/"); + } + sq_quote_buf_pretty(buf, path); + strbuf_addch(buf, ' '); + } + + free(global_config); + free(system_config); +} + +static bool can_unset_comment_char_config(struct comment_char_config *config) +{ + for (size_t i = 0; i < config->nr; i++) { + struct comment_char_config_item *item = &config->item[i]; + + if (item->scope == CONFIG_SCOPE_SYSTEM && + access(item->path, W_OK)) + return false; + } + + return true; +} + +static void add_unset_auto_comment_char_advice(struct repository *repo, + struct comment_char_config *config) +{ + struct strbuf buf = STRBUF_INIT; + + if (!can_unset_comment_char_config(config)) + return; + + for (size_t i = 0; i < config->nr; i++) { + struct comment_char_config_item *item = &config->item[i]; + + strbuf_addstr(&buf, " git config unset "); + add_config_scope_arg(repo, &buf, item); + if (get_comment_key_flags(config, item->path, item->key_id) == KEY_SEEN_TWICE) + strbuf_addstr(&buf, "--all "); + strbuf_addf(&buf, "%s\n", comment_key_name(item->key_id)); + } + advise(_("\nTo use the default comment string (#) please run\n\n%s"), + buf.buf); + strbuf_release(&buf); +} + +static void add_comment_char_advice(struct repository *repo, + struct comment_char_config *config) +{ + struct strbuf buf = STRBUF_INIT; + struct comment_char_config_item *item; + /* TRANSLATORS this is a place holder for the value of core.commentString */ + const char *placeholder = _("<comment string>"); + + /* + * If auto is set in the last file that we saw advise the user how to + * update their config. + */ + if (!config->auto_set_in_file) + return; + + add_unset_auto_comment_char_advice(repo, config); + item = &config->item[config->nr - 1]; + strbuf_reset(&buf); + strbuf_addstr(&buf, " git config set "); + add_config_scope_arg(repo, &buf, item); + strbuf_addf(&buf, "%s %s\n", comment_key_name(item->key_id), + placeholder); + advise(_("\nTo set a custom comment string please run\n\n" + "%s\nwhere '%s' is the string you wish to use.\n"), + buf.buf, placeholder); + strbuf_release(&buf); +} + +#undef KEY_SEEN_ONCE +#undef KEY_SEEN_TWICE +#undef COMMENT_KEY_SHIFT +#undef COMMENT_KEY_MASK + +struct repo_config { + struct repository *repo; + struct comment_char_config comment_char_config; +}; + +#define REPO_CONFIG_INIT(repo_) { \ + .comment_char_config = COMMENT_CHAR_CFG_INIT, \ + .repo = repo_, \ + }; + +static void repo_config_release(struct repo_config *config) +{ + comment_char_config_release(&config->comment_char_config); +} + +#ifdef WITH_BREAKING_CHANGES +static void check_auto_comment_char_config(struct repository *repo, + struct comment_char_config *config) +{ + if (!config->auto_set) + return; + + die_message(_("Support for '%s=auto' has been removed in Git 3.0"), + comment_key_name(config->last_key_id)); + add_comment_char_advice(repo, config); + die(NULL); +} +#else +static void check_auto_comment_char_config(struct repository *repo, + struct comment_char_config *config) +{ + extern bool warn_on_auto_comment_char; + const char *DEPRECATED_CONFIG_ENV = + "GIT_AUTO_COMMENT_CHAR_CONFIG_WARNING_GIVEN"; + + if (!config->auto_set || !warn_on_auto_comment_char) + return; + + /* + * Use an environment variable to ensure that subprocesses do not repeat + * the warning. + */ + if (git_env_bool(DEPRECATED_CONFIG_ENV, false)) + return; + + setenv(DEPRECATED_CONFIG_ENV, "true", true); + + warning(_("Support for '%s=auto' is deprecated and will be removed in " + "Git 3.0"), comment_key_name(config->last_key_id)); + add_comment_char_advice(repo, config); +} +#endif /* WITH_BREAKING_CHANGES */ + +static void check_deprecated_config(struct repo_config *config) +{ + if (!config->repo->check_deprecated_config) + return; + + check_auto_comment_char_config(config->repo, + &config->comment_char_config); +} + +static int repo_config_callback(const char *key, const char *value, + const struct config_context *ctx, void *data) +{ + struct repo_config *config = data; + + comment_char_callback(key, value, ctx, &config->comment_char_config); + return config_set_callback(key, value, ctx, config->repo->config); +} + /* Functions use to read configuration from a repository */ static void repo_read_config(struct repository *repo) { struct config_options opts = { 0 }; + struct repo_config config = REPO_CONFIG_INIT(repo); opts.respect_includes = 1; opts.commondir = repo->commondir; @@ -1963,8 +2245,8 @@ static void repo_read_config(struct repository *repo) git_configset_clear(repo->config); git_configset_init(repo->config); - if (config_with_options(config_set_callback, repo->config, NULL, - repo, &opts) < 0) + if (config_with_options(repo_config_callback, &config, NULL, repo, + &opts) < 0) /* * config_with_options() normally returns only * zero, as most errors are fatal, and @@ -1977,6 +2259,8 @@ static void repo_read_config(struct repository *repo) * immediately. */ die(_("unknown error occurred while reading the configuration files")); + check_deprecated_config(&config); + repo_config_release(&config); } static void git_config_check_init(struct repository *repo) @@ -2664,6 +2948,14 @@ int repo_config_set_multivar_in_file_gently(struct repository *r, char *contents = NULL; size_t contents_sz; struct config_store_data store = CONFIG_STORE_INIT; + bool saved_check_deprecated_config = r->check_deprecated_config; + + /* + * Do not warn or die if there are deprecated config settings as + * we want the user to be able to change those settings by running + * "git config". + */ + r->check_deprecated_config = false; validate_comment_string(comment); @@ -2895,6 +3187,7 @@ out_free: if (in_fd >= 0) close(in_fd); config_store_data_clear(&store); + r->check_deprecated_config = saved_check_deprecated_config; return ret; write_err_out: diff --git a/contrib/diff-highlight/README b/contrib/diff-highlight/README index d4c2343175..1db4440e68 100644 --- a/contrib/diff-highlight/README +++ b/contrib/diff-highlight/README @@ -58,6 +58,14 @@ following in your git configuration: diff = diff-highlight | less --------------------------------------------- +If you use the interactive patch mode of `git add -p`, `git checkout +-p`, etc, you may also want to configure it to be used there: + +--------------------------------------------- +[interactive] + diffFilter = diff-highlight +--------------------------------------------- + Color Config ------------ diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh index 3fddba797c..17106d1a72 100755 --- a/contrib/subtree/git-subtree.sh +++ b/contrib/subtree/git-subtree.sh @@ -785,20 +785,40 @@ ensure_valid_ref_format () { die "fatal: '$1' does not look like a ref" } -# Usage: check if a commit from another subtree should be +# Usage: should_ignore_subtree_split_commit REV +# +# Check if REV is a commit from another subtree and should be # ignored from processing for splits should_ignore_subtree_split_commit () { assert test $# = 1 - local rev="$1" - if test -n "$(git log -1 --grep="git-subtree-dir:" $rev)" + + git show \ + --no-patch \ + --no-show-signature \ + --format='%(trailers:key=git-subtree-dir,key=git-subtree-mainline)' \ + "$1" | + ( + have_mainline= + subtree_dir= + + while read -r trailer val + do + case "$trailer" in + git-subtree-dir:) + subtree_dir="${val%/}" ;; + git-subtree-mainline:) + have_mainline=y ;; + esac + done + + if test -n "${subtree_dir}" && + test -z "${have_mainline}" && + test "${subtree_dir}" != "$arg_prefix" then - if test -z "$(git log -1 --grep="git-subtree-mainline:" $rev)" && - test -z "$(git log -1 --grep="git-subtree-dir: $arg_prefix$" $rev)" - then - return 0 - fi + return 0 fi return 1 + ) } # Usage: process_split_commit REV PARENTS diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 3edbb33af4..316dc5269e 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -9,6 +9,9 @@ This test verifies the basic operation of the add, merge, split, pull, and push subcommands of git subtree. ' +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + TEST_DIRECTORY=$(pwd)/../../../t . "$TEST_DIRECTORY"/test-lib.sh . "$TEST_DIRECTORY"/lib-gpg.sh @@ -68,6 +71,33 @@ test_create_pre2_32_repo () { git -C "$1-clone" replace HEAD^2 $new_commit } +# test_create_subtree_add REPO ORPHAN PREFIX FILENAME ... +# +# Create a simple subtree on a new branch named ORPHAN in REPO. +# The subtree is then merged into the current branch of REPO, +# under PREFIX. The generated subtree has has one commit +# with subject and tag FILENAME with a single file "FILENAME.t" +# +# When this method returns: +# - the current branch of REPO will have file PREFIX/FILENAME.t +# - REPO will have a branch named ORPHAN with subtree history +# +# additional arguments are forwarded to "subtree add" +test_create_subtree_add () { + ( + cd "$1" && + orphan="$2" && + prefix="$3" && + filename="$4" && + shift 4 && + last="$(git branch --show-current)" && + git switch --orphan "$orphan" && + test_commit "$filename" && + git checkout "$last" && + git subtree add --prefix="$prefix" "$@" "$orphan" + ) +} + test_expect_success 'shows short help text for -h' ' test_expect_code 129 git subtree -h >out 2>err && test_must_be_empty err && @@ -426,6 +456,47 @@ test_expect_success 'split with multiple subtrees' ' --squash --rejoin -d -m "Sub B Split 1" 2>&1 | grep -w "\[1\]")" = "" ' +# When subtree split-ing a directory that has other subtree +# *merges* underneath it, the split must include those subtrees. +# This test creates a nested subtree, `subA/subB`, and tests +# that the tree is correct after a subtree split of `subA/`. +# The test covers: +# - An initial `subtree add`; and +# - A follow-up `subtree merge` +# both with and without `--squashed`. +for is_squashed in '' 'y' +do + test_expect_success "split keeps nested ${is_squashed:+--squash }subtrees that are part of the split" ' + subtree_test_create_repo "$test_count" && + ( + cd "$test_count" && + mkdir subA && + test_commit subA/file1 && + test_create_subtree_add \ + . mksubtree subA/subB file2 ${is_squashed:+--squash} && + test_path_is_file subA/file1.t && + test_path_is_file subA/subB/file2.t && + git subtree split --prefix=subA --branch=bsplit && + git checkout bsplit && + test_path_is_file file1.t && + test_path_is_file subB/file2.t && + git checkout mksubtree && + git branch -D bsplit && + test_commit file3 && + git checkout main && + git subtree merge \ + ${is_squashed:+--squash} \ + --prefix=subA/subB mksubtree && + test_path_is_file subA/subB/file3.t && + git subtree split --prefix=subA --branch=bsplit && + git checkout bsplit && + test_path_is_file file1.t && + test_path_is_file subB/file2.t && + test_path_is_file subB/file3.t + ) + ' +done + test_expect_success 'split sub dir/ with --rejoin from scratch' ' subtree_test_create_repo "$test_count" && test_create_commit "$test_count" main1 && @@ -57,7 +57,7 @@ static int diff_detect_rename_default; static int diff_indent_heuristic = 1; static int diff_rename_limit_default = 1000; static int diff_suppress_blank_empty; -static int diff_use_color_default = -1; +static enum git_colorbool diff_use_color_default = GIT_COLOR_UNKNOWN; static int diff_color_moved_default; static int diff_color_moved_ws_default; static int diff_context_default = 3; @@ -1672,7 +1672,7 @@ static void emit_hunk_header(struct emit_callback *ecbdata, const char *frag = diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO); const char *func = diff_get_color(ecbdata->color_diff, DIFF_FUNCINFO); const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET); - const char *reverse = ecbdata->color_diff ? GIT_COLOR_REVERSE : ""; + const char *reverse = want_color(ecbdata->color_diff) ? GIT_COLOR_REVERSE : ""; static const char atat[2] = { '@', '@' }; const char *cp, *ep; struct strbuf msgbuf = STRBUF_INIT; @@ -1826,7 +1826,7 @@ static void emit_rewrite_diff(const char *name_a, size_two = fill_textconv(o->repo, textconv_two, two, &data_two); memset(&ecbdata, 0, sizeof(ecbdata)); - ecbdata.color_diff = want_color(o->use_color); + ecbdata.color_diff = o->use_color; ecbdata.ws_rule = whitespace_rule(o->repo->index, name_b); ecbdata.opt = o; if (ecbdata.ws_rule & WS_BLANK_AT_EOF) { @@ -2303,7 +2303,7 @@ static void free_diff_words_data(struct emit_callback *ecbdata) } } -const char *diff_get_color(int diff_use_color, enum color_diff ix) +const char *diff_get_color(enum git_colorbool diff_use_color, enum color_diff ix) { if (want_color(diff_use_color)) return diff_colors[ix]; @@ -3732,7 +3732,7 @@ static void builtin_diff(const char *name_a, if (o->flags.suppress_diff_headers) lbl[0] = NULL; ecbdata.label_path = lbl; - ecbdata.color_diff = want_color(o->use_color); + ecbdata.color_diff = o->use_color; ecbdata.ws_rule = whitespace_rule(o->repo->index, name_b); if (ecbdata.ws_rule & WS_BLANK_AT_EOF) check_blank_at_eof(&mf1, &mf2, &ecbdata); @@ -4497,7 +4497,7 @@ static void fill_metainfo(struct strbuf *msg, struct diff_options *o, struct diff_filepair *p, int *must_show_header, - int use_color) + enum git_colorbool use_color) { const char *set = diff_get_color(use_color, DIFF_METAINFO); const char *reset = diff_get_color(use_color, DIFF_RESET); @@ -4596,7 +4596,7 @@ static void run_diff_cmd(const struct external_diff *pgm, */ fill_metainfo(msg, name, other, one, two, o, p, &must_show_header, - want_color(o->use_color) && !pgm); + pgm ? GIT_COLOR_NEVER : o->use_color); xfrm_msg = msg->len ? msg->buf : NULL; } @@ -4995,8 +4995,7 @@ void diff_setup_done(struct diff_options *options) if (options->flags.follow_renames) diff_check_follow_pathspec(&options->pathspec, 1); - if (!options->use_color || - (options->flags.allow_external && external_diff())) + if (options->flags.allow_external && external_diff()) options->color_moved = 0; if (options->filter_not) { @@ -5278,7 +5277,7 @@ static int diff_opt_color_words(const struct option *opt, struct diff_options *options = opt->value; BUG_ON_OPT_NEG(unset); - options->use_color = 1; + options->use_color = GIT_COLOR_ALWAYS; options->word_diff = DIFF_WORDS_COLOR; options->word_regex = arg; return 0; @@ -5600,7 +5599,7 @@ static int diff_opt_word_diff(const struct option *opt, if (!strcmp(arg, "plain")) options->word_diff = DIFF_WORDS_PLAIN; else if (!strcmp(arg, "color")) { - options->use_color = 1; + options->use_color = GIT_COLOR_ALWAYS; options->word_diff = DIFF_WORDS_COLOR; } else if (!strcmp(arg, "porcelain")) @@ -6733,7 +6732,7 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o) if (WSEH_NEW & WS_RULE_MASK) BUG("WS rules bit mask overlaps with diff symbol flags"); - if (o->color_moved) + if (o->color_moved && want_color(o->use_color)) o->emitted_symbols = &esm; if (o->additional_path_headers) @@ -6746,20 +6745,17 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o) } if (o->emitted_symbols) { - if (o->color_moved) { - struct mem_pool entry_pool; - struct moved_entry_list *entry_list; - - mem_pool_init(&entry_pool, 1024 * 1024); - entry_list = add_lines_to_move_detection(o, - &entry_pool); - mark_color_as_moved(o, entry_list); - if (o->color_moved == COLOR_MOVED_ZEBRA_DIM) - dim_moved_lines(o); - - mem_pool_discard(&entry_pool, 0); - free(entry_list); - } + struct mem_pool entry_pool; + struct moved_entry_list *entry_list; + + mem_pool_init(&entry_pool, 1024 * 1024); + entry_list = add_lines_to_move_detection(o, &entry_pool); + mark_color_as_moved(o, entry_list); + if (o->color_moved == COLOR_MOVED_ZEBRA_DIM) + dim_moved_lines(o); + + mem_pool_discard(&entry_pool, 0); + free(entry_list); for (i = 0; i < esm.nr; i++) emit_diff_symbol_from_struct(o, &esm.buf[i]); @@ -7,6 +7,7 @@ #include "hash.h" #include "pathspec.h" #include "strbuf.h" +#include "color.h" struct oidset; @@ -290,7 +291,7 @@ struct diff_options { /* diff-filter bits */ unsigned int filter, filter_not; - int use_color; + enum git_colorbool use_color; /* Number of context lines to generate in patch output. */ int context; @@ -476,7 +477,7 @@ enum color_diff { DIFF_FILE_NEW_BOLD = 22, }; -const char *diff_get_color(int diff_use_color, enum color_diff ix); +const char *diff_get_color(enum git_colorbool diff_use_color, enum color_diff ix); #define diff_get_color_opt(o, ix) \ diff_get_color((o)->use_color, ix) diff --git a/environment.c b/environment.c index 0e72fdac85..a770b5921d 100644 --- a/environment.c +++ b/environment.c @@ -121,7 +121,10 @@ int protect_ntfs = PROTECT_NTFS_DEFAULT; */ const char *comment_line_str = "#"; char *comment_line_str_to_free; +#ifndef WITH_BREAKING_CHANGES int auto_comment_line_char; +bool warn_on_auto_comment_char; +#endif /* !WITH_BREAKING_CHANGES */ /* This is set by setup_git_directory_gently() and/or git_default_config() */ char *git_work_tree_cfg; @@ -463,16 +466,22 @@ static int git_default_core_config(const char *var, const char *value, if (!strcmp(var, "core.commentchar") || !strcmp(var, "core.commentstring")) { - if (!value) + if (!value) { return config_error_nonbool(var); - else if (!strcasecmp(value, "auto")) +#ifndef WITH_BREAKING_CHANGES + } else if (!strcasecmp(value, "auto")) { auto_comment_line_char = 1; - else if (value[0]) { + FREE_AND_NULL(comment_line_str_to_free); + comment_line_str = "#"; +#endif /* !WITH_BREAKING_CHANGES */ + } else if (value[0]) { if (strchr(value, '\n')) return error(_("%s cannot contain newline"), var); comment_line_str = value; FREE_AND_NULL(comment_line_str_to_free); +#ifndef WITH_BREAKING_CHANGES auto_comment_line_char = 0; +#endif /* !WITH_BREAKING_CHANGES */ } else return error(_("%s must have at least one character"), var); return 0; diff --git a/environment.h b/environment.h index 8cfce41015..51898c99cd 100644 --- a/environment.h +++ b/environment.h @@ -208,7 +208,10 @@ extern char *excludes_file; */ extern const char *comment_line_str; extern char *comment_line_str_to_free; +#ifndef WITH_BREAKING_CHANGES extern int auto_comment_line_char; +extern bool warn_on_auto_comment_char; +#endif /* !WITH_BREAKING_CHANGES */ # endif /* USE_THE_REPOSITORY_VARIABLE */ #endif /* ENVIRONMENT_H */ diff --git a/git-curl-compat.h b/git-curl-compat.h index aa8eed7ed2..659e5a3875 100644 --- a/git-curl-compat.h +++ b/git-curl-compat.h @@ -46,6 +46,13 @@ #endif /** + * curl_global_trace() was added in 8.3.0, released September 2023. + */ +#if LIBCURL_VERSION_NUM >= 0x080300 +#define GIT_CURL_HAVE_GLOBAL_TRACE 1 +#endif + +/** * CURLOPT_TCP_KEEPCNT was added in 8.9.0, released in July, 2024. */ #if LIBCURL_VERSION_NUM >= 0x080900 diff --git a/git-send-email.perl b/git-send-email.perl index 437f8ac46a..cd4b316ddc 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -62,7 +62,7 @@ git send-email --translate-aliases --smtp-user <str> * Username for SMTP-AUTH. --smtp-pass <str> * Password for SMTP-AUTH; not necessary. --smtp-encryption <str> * tls or ssl; anything else disables. - --smtp-ssl * Deprecated. Use '--smtp-encryption ssl'. + --smtp-ssl * Deprecated. Use `--smtp-encryption ssl`. --smtp-ssl-cert-path <str> * Path to ca-certificates (either directory or file). Pass an empty string to disable certificate verification. @@ -73,6 +73,10 @@ git send-email --translate-aliases --no-smtp-auth * Disable SMTP authentication. Shorthand for `--smtp-auth=none` --smtp-debug <0|1> * Disable, enable Net::SMTP debug. + --imap-sent-folder <str> * IMAP folder where a copy of the emails should be sent. + Make sure `git imap-send` is set up to use this feature. + --[no-]use-imap-only * Only copy emails to the IMAP folder specified by + `--imap-sent-folder` instead of actually sending them. --batch-size <int> * send max <int> message per connection. --relogin-delay <int> * delay <int> seconds between two successive login. @@ -200,7 +204,7 @@ my $re_encoded_word = qr/=\?($re_token)\?($re_token)\?($re_encoded_text)\?=/; # Variables we fill in automatically, or via prompting: my (@to,@cc,@xh,$envelope_sender, - $initial_in_reply_to,$reply_to,$initial_subject,@files, + $initial_in_reply_to,$reply_to,$initial_subject,@files,@imap_copy, $author,$sender,$smtp_authpass,$annotate,$compose,$time); # Things we either get from config, *or* are overridden on the # command-line. @@ -277,6 +281,7 @@ my ($smtp_server, $smtp_server_port, @smtp_server_options); my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path); my ($batch_size, $relogin_delay); my ($identity, $aliasfiletype, @alias_files, $smtp_domain, $smtp_auth); +my ($imap_sent_folder); my ($confirm); my (@suppress_cc); my ($auto_8bit_encoding); @@ -293,6 +298,7 @@ my $mailmap = 0; my $target_xfer_encoding = 'auto'; my $forbid_sendmail_variables = 1; my $outlook_id_fix = 'auto'; +my $use_imap_only = 0; my %config_bool_settings = ( "thread" => \$thread, @@ -309,6 +315,7 @@ my %config_bool_settings = ( "forbidsendmailvariables" => \$forbid_sendmail_variables, "mailmap" => \$mailmap, "outlookidfix" => \$outlook_id_fix, + "useimaponly" => \$use_imap_only, ); my %config_settings = ( @@ -322,6 +329,7 @@ my %config_settings = ( "smtpauth" => \$smtp_auth, "smtpbatchsize" => \$batch_size, "smtprelogindelay" => \$relogin_delay, + "imapsentfolder" => \$imap_sent_folder, "to" => \@config_to, "tocmd" => \$to_cmd, "cc" => \@config_cc, @@ -527,6 +535,8 @@ my %options = ( "smtp-domain:s" => \$smtp_domain, "smtp-auth=s" => \$smtp_auth, "no-smtp-auth" => sub {$smtp_auth = 'none'}, + "imap-sent-folder=s" => \$imap_sent_folder, + "use-imap-only!" => \$use_imap_only, "annotate!" => \$annotate, "compose" => \$compose, "quiet" => \$quiet, @@ -1678,6 +1688,8 @@ EOF if ($dry_run) { # We don't want to send the email. + } elsif ($use_imap_only) { + die __("The destination IMAP folder is not properly defined.") if !defined $imap_sent_folder; } elsif (defined $sendmail_cmd || file_name_is_absolute($smtp_server)) { my $pid = open my $sm, '|-'; defined $pid or die $!; @@ -1829,6 +1841,17 @@ EOF print "\n"; } + if ($imap_sent_folder && !$dry_run) { + my $imap_header = $header; + if (@initial_bcc) { + # Bcc is not a part of $header, so we add it here. + # This is only for the IMAP copy, not for the actual email + # sent to the recipients. + $imap_header .= "Bcc: " . join(", ", @initial_bcc) . "\n"; + } + push @imap_copy, "From git-send-email\n$imap_header\n$message"; + } + return 1; } @@ -1931,6 +1954,9 @@ sub pre_process_file { $in_reply_to = $1; } } + elsif (/^Reply-To: (.*)/i) { + $reply_to = $1; + } elsif (/^References: (.*)/i) { if (!$initial_in_reply_to || $thread) { $references = $1; @@ -2223,6 +2249,19 @@ sub cleanup_compose_files { $smtp->quit if $smtp; +if ($imap_sent_folder && @imap_copy && !$dry_run) { + my $imap_input = join("\n", @imap_copy); + eval { + print "\nStarting git imap-send...\n"; + my ($fh, $ctx) = Git::command_input_pipe(['imap-send', '-f', $imap_sent_folder]); + print $fh $imap_input; + Git::command_close_pipe($fh, $ctx); + 1; + } or do { + warn "Warning: failed to send messages to IMAP folder $imap_sent_folder: $@"; + }; +} + sub apply_transfer_encoding { my $message = shift; my $from = shift; @@ -1263,12 +1263,12 @@ static void show_line(struct grep_opt *opt, */ show_line_header(opt, name, lno, cno, sign); } - if (opt->color || opt->only_matching) { + if (want_color(opt->color) || opt->only_matching) { regmatch_t match; enum grep_context ctx = GREP_CONTEXT_BODY; int eflags = 0; - if (opt->color) { + if (want_color(opt->color)) { if (sign == ':') match_color = opt->colors[GREP_COLOR_MATCH_SELECTED]; else @@ -159,7 +159,7 @@ struct grep_opt { int pathname; int null_following_name; int only_matching; - int color; + enum git_colorbool color; int max_depth; int funcname; int funcbody; @@ -198,7 +198,7 @@ struct grep_opt { [GREP_COLOR_SEP] = GIT_COLOR_CYAN, \ }, \ .only_matching = 0, \ - .color = -1, \ + .color = GIT_COLOR_UNKNOWN, \ .output = std_output, \ } diff --git a/http-push.c b/http-push.c index 91a5465afb..4c43ba3bc7 100644 --- a/http-push.c +++ b/http-push.c @@ -1941,7 +1941,7 @@ int cmd_main(int argc, const char **argv) strvec_pushf(&commit_argv, "^%s", oid_to_hex(&ref->old_oid)); repo_init_revisions(the_repository, &revs, setup_git_directory()); - setup_revisions(commit_argv.nr, commit_argv.v, &revs, NULL); + setup_revisions_from_strvec(&commit_argv, &revs, NULL); revs.edge_hint = 0; /* just in case */ /* Generate a list of objects that need to be pushed */ @@ -1348,6 +1348,14 @@ void http_init(struct remote *remote, const char *url, int proactive_auth) if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) die("curl_global_init failed"); +#ifdef GIT_CURL_HAVE_GLOBAL_TRACE + { + const char *comp = getenv("GIT_TRACE_CURL_COMPONENTS"); + if (comp) + curl_global_trace(comp); + } +#endif + if (proactive_auth && http_proactive_auth == PROACTIVE_AUTH_NONE) http_proactive_auth = PROACTIVE_AUTH_IF_CREDENTIALS; diff --git a/imap-send.c b/imap-send.c index 254ec83ab7..4bd5b8aa0d 100644 --- a/imap-send.c +++ b/imap-send.c @@ -1442,14 +1442,24 @@ static int count_messages(struct strbuf *all_msgs) while (1) { if (starts_with(p, "From ")) { - p = strstr(p+5, "\nFrom: "); - if (!p) break; - p = strstr(p+7, "\nDate: "); - if (!p) break; - p = strstr(p+7, "\nSubject: "); - if (!p) break; - p += 10; - count++; + if (starts_with(p, "From git-send-email")) { + p = strstr(p+5, "\nFrom: "); + if (!p) break; + p += 7; + p = strstr(p, "\nTo: "); + if (!p) break; + p += 5; + count++; + } else { + p = strstr(p+5, "\nFrom: "); + if (!p) break; + p = strstr(p+7, "\nDate: "); + if (!p) break; + p = strstr(p+7, "\nSubject: "); + if (!p) break; + p += 10; + count++; + } } p = strstr(p+5, "\nFrom "); if (!p) diff --git a/line-log.c b/line-log.c index 188d387d40..8bd422148d 100644 --- a/line-log.c +++ b/line-log.c @@ -201,7 +201,7 @@ static void range_set_difference(struct range_set *out, * b: ------| */ j++; - if (j >= b->nr || end < b->ranges[j].start) { + if (j >= b->nr || end <= b->ranges[j].start) { /* * b exhausted, or * a: ----| @@ -408,7 +408,7 @@ static void diff_ranges_filter_touched(struct diff_ranges *out, assert(out->target.nr == 0); for (i = 0; i < diff->target.nr; i++) { - while (diff->target.ranges[i].start > rs->ranges[j].end) { + while (diff->target.ranges[i].start >= rs->ranges[j].end) { j++; if (j == rs->nr) return; @@ -939,9 +939,18 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang long t_cur = t_start; unsigned int j_last; + /* + * If a diff range touches multiple line ranges, then all + * those line ranges should be shown, so take a step back if + * the current line range is still in the previous diff range + * (even if only partially). + */ + if (j > 0 && diff->target.ranges[j-1].end > t_start) + j--; + while (j < diff->target.nr && diff->target.ranges[j].end < t_start) j++; - if (j == diff->target.nr || diff->target.ranges[j].start > t_end) + if (j == diff->target.nr || diff->target.ranges[j].start >= t_end) continue; /* Scan ahead to determine the last diff that falls in this range */ diff --git a/list-objects-filter.c b/list-objects-filter.c index 7ecd4d9ef5..acd65ebb73 100644 --- a/list-objects-filter.c +++ b/list-objects-filter.c @@ -524,12 +524,11 @@ static void filter_sparse_oid__init( struct filter *filter) { struct filter_sparse_data *d = xcalloc(1, sizeof(*d)); - struct object_context oc; struct object_id sparse_oid; - if (get_oid_with_context(the_repository, - filter_options->sparse_oid_name, - GET_OID_BLOB, &sparse_oid, &oc)) + if (repo_get_oid_with_flags(the_repository, + filter_options->sparse_oid_name, + &sparse_oid, GET_OID_BLOB)) die(_("unable to access sparse blob in '%s'"), filter_options->sparse_oid_name); if (add_patterns_from_blob_to_list(&sparse_oid, "", 0, &d->pl) < 0) @@ -544,8 +543,6 @@ static void filter_sparse_oid__init( filter->filter_data = d; filter->filter_object_fn = filter_sparse; filter->free_fn = filter_sparse_free; - - object_context_release(&oc); } /* diff --git a/log-tree.c b/log-tree.c index 233bf9f227..67d9ace596 100644 --- a/log-tree.c +++ b/log-tree.c @@ -57,7 +57,7 @@ static const char *color_decorate_slots[] = { [DECORATION_GRAFTED] = "grafted", }; -static const char *decorate_get_color(int decorate_use_color, enum decoration_type ix) +static const char *decorate_get_color(enum git_colorbool decorate_use_color, enum decoration_type ix) { if (want_color(decorate_use_color)) return decoration_colors[ix]; @@ -341,7 +341,7 @@ static void show_name(struct strbuf *sb, const struct name_decoration *decoratio */ void format_decorations(struct strbuf *sb, const struct commit *commit, - int use_color, + enum git_colorbool use_color, const struct decoration_options *opts) { const struct name_decoration *decoration; @@ -717,6 +717,7 @@ static void show_diff_of_diff(struct rev_info *opt) struct range_diff_options range_diff_opts = { .creation_factor = opt->creation_factor, .dual_color = 1, + .max_memory = RANGE_DIFF_MAX_MEMORY_DEFAULT, .diffopt = &opts }; diff --git a/log-tree.h b/log-tree.h index ebe491c543..07924be8bc 100644 --- a/log-tree.h +++ b/log-tree.h @@ -1,6 +1,8 @@ #ifndef LOG_TREE_H #define LOG_TREE_H +#include "color.h" + struct rev_info; struct log_info { @@ -26,7 +28,7 @@ int log_tree_diff_flush(struct rev_info *); int log_tree_commit(struct rev_info *, struct commit *); void show_log(struct rev_info *opt); void format_decorations(struct strbuf *sb, const struct commit *commit, - int use_color, const struct decoration_options *opts); + enum git_colorbool use_color, const struct decoration_options *opts); void show_decorations(struct rev_info *opt, struct commit *commit); void log_write_email_headers(struct rev_info *opt, struct commit *commit, char **extra_headers_p, diff --git a/object-name.c b/object-name.c index 1e0118e8a6..7774991d28 100644 --- a/object-name.c +++ b/object-name.c @@ -703,7 +703,7 @@ static int extend_abbrev_len(const struct object_id *oid, while (mad->hex[i] && mad->hex[i] == get_hex_char_from_oid(oid, i)) i++; - if (i < GIT_MAX_RAWSZ && i >= mad->cur_len) + if (mad->hex[i] && i >= mad->cur_len) mad->cur_len = i + 1; return 0; @@ -1857,55 +1857,35 @@ int repo_get_oid_committish(struct repository *r, const char *name, struct object_id *oid) { - struct object_context unused; - int ret = get_oid_with_context(r, name, GET_OID_COMMITTISH, - oid, &unused); - object_context_release(&unused); - return ret; + return repo_get_oid_with_flags(r, name, oid, GET_OID_COMMITTISH); } int repo_get_oid_treeish(struct repository *r, const char *name, struct object_id *oid) { - struct object_context unused; - int ret = get_oid_with_context(r, name, GET_OID_TREEISH, - oid, &unused); - object_context_release(&unused); - return ret; + return repo_get_oid_with_flags(r, name, oid, GET_OID_TREEISH); } int repo_get_oid_commit(struct repository *r, const char *name, struct object_id *oid) { - struct object_context unused; - int ret = get_oid_with_context(r, name, GET_OID_COMMIT, - oid, &unused); - object_context_release(&unused); - return ret; + return repo_get_oid_with_flags(r, name, oid, GET_OID_COMMIT); } int repo_get_oid_tree(struct repository *r, const char *name, struct object_id *oid) { - struct object_context unused; - int ret = get_oid_with_context(r, name, GET_OID_TREE, - oid, &unused); - object_context_release(&unused); - return ret; + return repo_get_oid_with_flags(r, name, oid, GET_OID_TREE); } int repo_get_oid_blob(struct repository *r, const char *name, struct object_id *oid) { - struct object_context unused; - int ret = get_oid_with_context(r, name, GET_OID_BLOB, - oid, &unused); - object_context_release(&unused); - return ret; + return repo_get_oid_with_flags(r, name, oid, GET_OID_BLOB); } /* Must be called only when object_name:filename doesn't exist. */ @@ -517,12 +517,11 @@ struct parsed_object_pool *parsed_object_pool_new(struct repository *repo) memset(o, 0, sizeof(*o)); o->repo = repo; - o->blob_state = allocate_alloc_state(); - o->tree_state = allocate_alloc_state(); - o->commit_state = allocate_alloc_state(); - o->tag_state = allocate_alloc_state(); - o->object_state = allocate_alloc_state(); - + o->blob_state = alloc_state_alloc(); + o->tree_state = alloc_state_alloc(); + o->commit_state = alloc_state_alloc(); + o->tag_state = alloc_state_alloc(); + o->object_state = alloc_state_alloc(); o->is_shallow = -1; CALLOC_ARRAY(o->shallow_stat, 1); @@ -573,16 +572,11 @@ void parsed_object_pool_clear(struct parsed_object_pool *o) o->buffer_slab = NULL; parsed_object_pool_reset_commit_grafts(o); - clear_alloc_state(o->blob_state); - clear_alloc_state(o->tree_state); - clear_alloc_state(o->commit_state); - clear_alloc_state(o->tag_state); - clear_alloc_state(o->object_state); + alloc_state_free_and_null(&o->blob_state); + alloc_state_free_and_null(&o->tree_state); + alloc_state_free_and_null(&o->commit_state); + alloc_state_free_and_null(&o->tag_state); + alloc_state_free_and_null(&o->object_state); stat_validity_clear(o->shallow_stat); - FREE_AND_NULL(o->blob_state); - FREE_AND_NULL(o->tree_state); - FREE_AND_NULL(o->commit_state); - FREE_AND_NULL(o->tag_state); - FREE_AND_NULL(o->object_state); FREE_AND_NULL(o->shallow_stat); } diff --git a/parse-options-cb.c b/parse-options-cb.c index 50c8afe412..976cc86385 100644 --- a/parse-options-cb.c +++ b/parse-options-cb.c @@ -50,12 +50,12 @@ int parse_opt_expiry_date_cb(const struct option *opt, const char *arg, int parse_opt_color_flag_cb(const struct option *opt, const char *arg, int unset) { - int value; + enum git_colorbool value; if (!arg) arg = unset ? "never" : (const char *)opt->defval; value = git_config_colorbool(NULL, arg); - if (value < 0) + if (value == GIT_COLOR_UNKNOWN) return error(_("option `%s' expects \"always\", \"auto\", or \"never\""), opt->long_name); *(int *)opt->value = value; @@ -470,7 +470,7 @@ static inline void strbuf_add_with_color(struct strbuf *sb, const char *color, static void append_line_with_color(struct strbuf *sb, struct grep_opt *opt, const char *line, size_t linelen, - int color, enum grep_context ctx, + enum git_colorbool color, enum grep_context ctx, enum grep_header_field field) { const char *buf, *eol, *line_color, *match_color; @@ -899,7 +899,7 @@ struct format_commit_context { const char *message; char *commit_encoding; size_t width, indent1, indent2; - int auto_color; + enum git_colorbool auto_color; int padding; /* These offsets are relative to the start of the commit message. */ @@ -1455,14 +1455,14 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ switch (placeholder[0]) { case 'C': if (starts_with(placeholder + 1, "(auto)")) { - c->auto_color = want_color(c->pretty_ctx->color); - if (c->auto_color && sb->len) + c->auto_color = c->pretty_ctx->color; + if (want_color(c->auto_color) && sb->len) strbuf_addstr(sb, GIT_COLOR_RESET); return 7; /* consumed 7 bytes, "C(auto)" */ } else { int ret = parse_color(sb, placeholder, c); if (ret) - c->auto_color = 0; + c->auto_color = GIT_COLOR_NEVER; /* * Otherwise, we decided to treat %C<unknown> * as a literal string, and the previous @@ -2167,7 +2167,7 @@ static int pp_utf8_width(const char *start, const char *end) } static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt, - int color, int tabwidth, const char *line, + enum git_colorbool color, int tabwidth, const char *line, int linelen) { const char *tab; @@ -3,6 +3,7 @@ #include "date.h" #include "string-list.h" +#include "color.h" struct commit; struct repository; @@ -46,7 +47,7 @@ struct pretty_print_context { struct rev_info *rev; const char *output_encoding; struct string_list *mailmap; - int color; + enum git_colorbool color; struct ident_split *from_ident; unsigned encode_email_headers:1; struct pretty_print_describe_status *describe_status; diff --git a/promisor-remote.c b/promisor-remote.c index 08b0da8962..77ebf537e2 100644 --- a/promisor-remote.c +++ b/promisor-remote.c @@ -314,9 +314,162 @@ static int allow_unsanitized(char ch) return ch > 32 && ch < 127; } -static void promisor_info_vecs(struct repository *repo, - struct strvec *names, - struct strvec *urls) +/* + * All the fields used in "promisor-remote" protocol capability, + * including the mandatory "name" and "url" ones. + */ +static const char promisor_field_name[] = "name"; +static const char promisor_field_url[] = "url"; +static const char promisor_field_filter[] = "partialCloneFilter"; +static const char promisor_field_token[] = "token"; + +/* + * List of optional field names that can be used in the + * "promisor-remote" protocol capability (others must be + * ignored). Each field should correspond to a configurable property + * of a remote that can be relevant for the client. + */ +static const char *known_fields[] = { + promisor_field_filter, /* Filter used for partial clone */ + promisor_field_token, /* Authentication token for the remote */ + NULL +}; + +/* + * Check if 'field' is in the list of the known field names for the + * "promisor-remote" protocol capability. + */ +static int is_known_field(const char *field) +{ + const char **p; + + for (p = known_fields; *p; p++) + if (!strcasecmp(*p, field)) + return 1; + return 0; +} + +static int is_valid_field(struct string_list_item *item, void *cb_data) +{ + const char *field = item->string; + const char *config_key = (const char *)cb_data; + + if (!is_known_field(field)) { + warning(_("unsupported field '%s' in '%s' config"), field, config_key); + return 0; + } + return 1; +} + +static char *fields_from_config(struct string_list *fields_list, const char *config_key) +{ + char *fields = NULL; + + if (!repo_config_get_string(the_repository, config_key, &fields) && *fields) { + string_list_split_in_place_f(fields_list, fields, ",", -1, + STRING_LIST_SPLIT_TRIM | + STRING_LIST_SPLIT_NONEMPTY); + filter_string_list(fields_list, 0, is_valid_field, (void *)config_key); + } + + return fields; +} + +static struct string_list *fields_sent(void) +{ + static struct string_list fields_list = STRING_LIST_INIT_NODUP; + static int initialized; + + if (!initialized) { + fields_list.cmp = strcasecmp; + fields_from_config(&fields_list, "promisor.sendFields"); + initialized = 1; + } + + return &fields_list; +} + +static struct string_list *fields_checked(void) +{ + static struct string_list fields_list = STRING_LIST_INIT_NODUP; + static int initialized; + + if (!initialized) { + fields_list.cmp = strcasecmp; + fields_from_config(&fields_list, "promisor.checkFields"); + initialized = 1; + } + + return &fields_list; +} + +/* + * Struct for promisor remotes involved in the "promisor-remote" + * protocol capability. + * + * Except for "name", each <member> in this struct and its <value> + * should correspond (either on the client side or on the server side) + * to a "remote.<name>.<member>" config variable set to <value> where + * "<name>" is a promisor remote name. + */ +struct promisor_info { + const char *name; + const char *url; + const char *filter; + const char *token; +}; + +static void promisor_info_free(struct promisor_info *p) +{ + free((char *)p->name); + free((char *)p->url); + free((char *)p->filter); + free((char *)p->token); + free(p); +} + +static void promisor_info_list_clear(struct string_list *list) +{ + for (size_t i = 0; i < list->nr; i++) + promisor_info_free(list->items[i].util); + string_list_clear(list, 0); +} + +static void set_one_field(struct promisor_info *p, + const char *field, const char *value) +{ + if (!strcasecmp(field, promisor_field_filter)) + p->filter = xstrdup(value); + else if (!strcasecmp(field, promisor_field_token)) + p->token = xstrdup(value); + else + BUG("invalid field '%s'", field); +} + +static void set_fields(struct promisor_info *p, + struct string_list *field_names) +{ + struct string_list_item *item; + + for_each_string_list_item(item, field_names) { + char *key = xstrfmt("remote.%s.%s", p->name, item->string); + const char *val; + if (!repo_config_get_string_tmp(the_repository, key, &val) && *val) + set_one_field(p, item->string, val); + free(key); + } +} + +/* + * Populate 'list' with promisor remote information from the config. + * The 'util' pointer of each list item will hold a 'struct + * promisor_info'. Except "name" and "url", only members of that + * struct specified by the 'field_names' list are set (using values + * from the configuration). + */ +static void promisor_config_info_list(struct repository *repo, + struct string_list *list, + struct string_list *field_names) { struct promisor_remote *r; @@ -328,8 +481,17 @@ static void promisor_info_vecs(struct repository *repo, /* Only add remotes with a non empty URL */ if (!repo_config_get_string_tmp(the_repository, url_key, &url) && *url) { - strvec_push(names, r->name); - strvec_push(urls, url); + struct promisor_info *new_info = xcalloc(1, sizeof(*new_info)); + struct string_list_item *item; + + new_info->name = xstrdup(r->name); + new_info->url = xstrdup(url); + + if (field_names) + set_fields(new_info, field_names); + + item = string_list_append(list, new_info->name); + item->util = new_info; } free(url_key); @@ -340,47 +502,45 @@ char *promisor_remote_info(struct repository *repo) { struct strbuf sb = STRBUF_INIT; int advertise_promisors = 0; - struct strvec names = STRVEC_INIT; - struct strvec urls = STRVEC_INIT; + struct string_list config_info = STRING_LIST_INIT_NODUP; + struct string_list_item *item; repo_config_get_bool(the_repository, "promisor.advertise", &advertise_promisors); if (!advertise_promisors) return NULL; - promisor_info_vecs(repo, &names, &urls); + promisor_config_info_list(repo, &config_info, fields_sent()); - if (!names.nr) + if (!config_info.nr) return NULL; - for (size_t i = 0; i < names.nr; i++) { - if (i) + for_each_string_list_item(item, &config_info) { + struct promisor_info *p = item->util; + + if (item != config_info.items) strbuf_addch(&sb, ';'); - strbuf_addstr(&sb, "name="); - strbuf_addstr_urlencode(&sb, names.v[i], allow_unsanitized); - strbuf_addstr(&sb, ",url="); - strbuf_addstr_urlencode(&sb, urls.v[i], allow_unsanitized); + + strbuf_addf(&sb, "%s=", promisor_field_name); + strbuf_addstr_urlencode(&sb, p->name, allow_unsanitized); + strbuf_addf(&sb, ",%s=", promisor_field_url); + strbuf_addstr_urlencode(&sb, p->url, allow_unsanitized); + + if (p->filter) { + strbuf_addf(&sb, ",%s=", promisor_field_filter); + strbuf_addstr_urlencode(&sb, p->filter, allow_unsanitized); + } + if (p->token) { + strbuf_addf(&sb, ",%s=", promisor_field_token); + strbuf_addstr_urlencode(&sb, p->token, allow_unsanitized); + } } - strvec_clear(&names); - strvec_clear(&urls); + promisor_info_list_clear(&config_info); return strbuf_detach(&sb, NULL); } -/* - * Find first index of 'nicks' where there is 'nick'. 'nick' is - * compared case sensitively to the strings in 'nicks'. If not found - * 'nicks->nr' is returned. - */ -static size_t remote_nick_find(struct strvec *nicks, const char *nick) -{ - for (size_t i = 0; i < nicks->nr; i++) - if (!strcmp(nicks->v[i], nick)) - return i; - return nicks->nr; -} - enum accept_promisor { ACCEPT_NONE = 0, ACCEPT_KNOWN_URL, @@ -388,23 +548,84 @@ enum accept_promisor { ACCEPT_ALL }; +static int match_field_against_config(const char *field, const char *value, + struct promisor_info *config_info) +{ + if (config_info->filter && !strcasecmp(field, promisor_field_filter)) + return !strcmp(config_info->filter, value); + else if (config_info->token && !strcasecmp(field, promisor_field_token)) + return !strcmp(config_info->token, value); + + return 0; +} + +static int all_fields_match(struct promisor_info *advertised, + struct string_list *config_info, + int in_list) +{ + struct string_list *fields = fields_checked(); + struct string_list_item *item_checked; + + for_each_string_list_item(item_checked, fields) { + int match = 0; + const char *field = item_checked->string; + const char *value = NULL; + struct string_list_item *item; + + if (!strcasecmp(field, promisor_field_filter)) + value = advertised->filter; + else if (!strcasecmp(field, promisor_field_token)) + value = advertised->token; + + if (!value) + return 0; + + if (in_list) { + for_each_string_list_item(item, config_info) { + struct promisor_info *p = item->util; + if (match_field_against_config(field, value, p)) { + match = 1; + break; + } + } + } else { + item = string_list_lookup(config_info, advertised->name); + if (item) { + struct promisor_info *p = item->util; + match = match_field_against_config(field, value, p); + } + } + + if (!match) + return 0; + } + + return 1; +} + static int should_accept_remote(enum accept_promisor accept, - const char *remote_name, const char *remote_url, - struct strvec *names, struct strvec *urls) + struct promisor_info *advertised, + struct string_list *config_info) { - size_t i; + struct promisor_info *p; + struct string_list_item *item; + const char *remote_name = advertised->name; + const char *remote_url = advertised->url; if (accept == ACCEPT_ALL) - return 1; + return all_fields_match(advertised, config_info, 1); - i = remote_nick_find(names, remote_name); + /* Get config info for that promisor remote */ + item = string_list_lookup(config_info, remote_name); - if (i >= names->nr) + if (!item) /* We don't know about that remote */ return 0; + p = item->util; + if (accept == ACCEPT_KNOWN_NAME) - return 1; + return all_fields_match(advertised, config_info, 0); if (accept != ACCEPT_KNOWN_URL) BUG("Unhandled 'enum accept_promisor' value '%d'", accept); @@ -414,24 +635,72 @@ static int should_accept_remote(enum accept_promisor accept, return 0; } - if (!strcmp(urls->v[i], remote_url)) - return 1; + if (!strcmp(p->url, remote_url)) + return all_fields_match(advertised, config_info, 0); warning(_("known remote named '%s' but with URL '%s' instead of '%s'"), - remote_name, urls->v[i], remote_url); + remote_name, p->url, remote_url); return 0; } +static int skip_field_name_prefix(const char *elem, const char *field_name, const char **value) +{ + const char *p; + if (!skip_prefix(elem, field_name, &p) || *p != '=') + return 0; + *value = p + 1; + return 1; +} + +static struct promisor_info *parse_one_advertised_remote(const char *remote_info) +{ + struct promisor_info *info = xcalloc(1, sizeof(*info)); + struct string_list elem_list = STRING_LIST_INIT_DUP; + struct string_list_item *item; + + string_list_split(&elem_list, remote_info, ",", -1); + + for_each_string_list_item(item, &elem_list) { + const char *elem = item->string; + const char *p = strchr(elem, '='); + + if (!p) { + warning(_("invalid element '%s' from remote info"), elem); + continue; + } + + if (skip_field_name_prefix(elem, promisor_field_name, &p)) + info->name = url_percent_decode(p); + else if (skip_field_name_prefix(elem, promisor_field_url, &p)) + info->url = url_percent_decode(p); + else if (skip_field_name_prefix(elem, promisor_field_filter, &p)) + info->filter = url_percent_decode(p); + else if (skip_field_name_prefix(elem, promisor_field_token, &p)) + info->token = url_percent_decode(p); + } + + string_list_clear(&elem_list, 0); + + if (!info->name || !info->url) { + warning(_("server advertised a promisor remote without a name or URL: %s"), + remote_info); + promisor_info_free(info); + return NULL; + } + + return info; +} + static void filter_promisor_remote(struct repository *repo, struct strvec *accepted, const char *info) { - struct strbuf **remotes; const char *accept_str; enum accept_promisor accept = ACCEPT_NONE; - struct strvec names = STRVEC_INIT; - struct strvec urls = STRVEC_INIT; + struct string_list config_info = STRING_LIST_INIT_NODUP; + struct string_list remote_info = STRING_LIST_INIT_DUP; + struct string_list_item *item; if (!repo_config_get_string_tmp(the_repository, "promisor.acceptfromserver", &accept_str)) { if (!*accept_str || !strcasecmp("None", accept_str)) @@ -450,49 +719,31 @@ static void filter_promisor_remote(struct repository *repo, if (accept == ACCEPT_NONE) return; - if (accept != ACCEPT_ALL) - promisor_info_vecs(repo, &names, &urls); - /* Parse remote info received */ - remotes = strbuf_split_str(info, ';', 0); - - for (size_t i = 0; remotes[i]; i++) { - struct strbuf **elems; - const char *remote_name = NULL; - const char *remote_url = NULL; - char *decoded_name = NULL; - char *decoded_url = NULL; - - strbuf_strip_suffix(remotes[i], ";"); - elems = strbuf_split(remotes[i], ','); - - for (size_t j = 0; elems[j]; j++) { - int res; - strbuf_strip_suffix(elems[j], ","); - res = skip_prefix(elems[j]->buf, "name=", &remote_name) || - skip_prefix(elems[j]->buf, "url=", &remote_url); - if (!res) - warning(_("unknown element '%s' from remote info"), - elems[j]->buf); - } + string_list_split(&remote_info, info, ";", -1); + + for_each_string_list_item(item, &remote_info) { + struct promisor_info *advertised; - if (remote_name) - decoded_name = url_percent_decode(remote_name); - if (remote_url) - decoded_url = url_percent_decode(remote_url); + advertised = parse_one_advertised_remote(item->string); + + if (!advertised) + continue; + + if (!config_info.nr) { + promisor_config_info_list(repo, &config_info, fields_checked()); + string_list_sort(&config_info); + } - if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &names, &urls)) - strvec_push(accepted, decoded_name); + if (should_accept_remote(accept, advertised, &config_info)) + strvec_push(accepted, advertised->name); - strbuf_list_free(elems); - free(decoded_name); - free(decoded_url); + promisor_info_free(advertised); } - strvec_clear(&names); - strvec_clear(&urls); - strbuf_list_free(remotes); + promisor_info_list_clear(&config_info); + string_list_clear(&remote_info, 0); } char *promisor_remote_reply(const char *info) @@ -518,16 +769,15 @@ char *promisor_remote_reply(const char *info) void mark_promisor_remotes_as_accepted(struct repository *r, const char *remotes) { - struct strbuf **accepted_remotes = strbuf_split_str(remotes, ';', 0); + struct string_list accepted_remotes = STRING_LIST_INIT_DUP; + struct string_list_item *item; - for (size_t i = 0; accepted_remotes[i]; i++) { - struct promisor_remote *p; - char *decoded_remote; + string_list_split(&accepted_remotes, remotes, ";", -1); - strbuf_strip_suffix(accepted_remotes[i], ";"); - decoded_remote = url_percent_decode(accepted_remotes[i]->buf); + for_each_string_list_item(item, &accepted_remotes) { + char *decoded_remote = url_percent_decode(item->string); + struct promisor_remote *p = repo_promisor_remote_find(r, decoded_remote); - p = repo_promisor_remote_find(r, decoded_remote); if (p) p->accepted = 1; else @@ -537,5 +787,5 @@ void mark_promisor_remotes_as_accepted(struct repository *r, const char *remotes free(decoded_remote); } - strbuf_list_free(accepted_remotes); + string_list_clear(&accepted_remotes, 0); } diff --git a/range-diff.c b/range-diff.c index 8a2dcbee32..ca449a0769 100644 --- a/range-diff.c +++ b/range-diff.c @@ -325,13 +325,24 @@ static int diffsize(const char *a, const char *b) } static void get_correspondences(struct string_list *a, struct string_list *b, - int creation_factor) + int creation_factor, size_t max_memory) { int n = a->nr + b->nr; int *cost, c, *a2b, *b2a; int i, j; - - ALLOC_ARRAY(cost, st_mult(n, n)); + size_t cost_size = st_mult(n, n); + size_t cost_bytes = st_mult(sizeof(int), cost_size); + if (cost_bytes >= max_memory) { + struct strbuf cost_str = STRBUF_INIT; + struct strbuf max_str = STRBUF_INIT; + strbuf_humanise_bytes(&cost_str, cost_bytes); + strbuf_humanise_bytes(&max_str, max_memory); + die(_("range-diff: unable to compute the range-diff, since it " + "exceeds the maximum memory for the cost matrix: %s " + "(%"PRIuMAX" bytes) needed, limited to %s (%"PRIuMAX" bytes)"), + cost_str.buf, (uintmax_t)cost_bytes, max_str.buf, (uintmax_t)max_memory); + } + ALLOC_ARRAY(cost, cost_size); ALLOC_ARRAY(a2b, n); ALLOC_ARRAY(b2a, n); @@ -591,7 +602,8 @@ int show_range_diff(const char *range1, const char *range2, if (!res) { find_exact_matches(&branch1, &branch2); get_correspondences(&branch1, &branch2, - range_diff_opts->creation_factor); + range_diff_opts->creation_factor, + range_diff_opts->max_memory); output(&branch1, &branch2, range_diff_opts); } diff --git a/range-diff.h b/range-diff.h index cd85000b5a..9d39818e34 100644 --- a/range-diff.h +++ b/range-diff.h @@ -5,6 +5,10 @@ #include "strvec.h" #define RANGE_DIFF_CREATION_FACTOR_DEFAULT 60 +#define RANGE_DIFF_MAX_MEMORY_DEFAULT \ + (sizeof(void*) >= 8 ? \ + ((size_t)(1024L * 1024L) * (size_t)(4L * 1024L)) : /* 4GB on 64-bit */ \ + ((size_t)(1024L * 1024L) * (size_t)(2L * 1024L))) /* 2GB on 32-bit */ /* * A much higher value than the default, when we KNOW we are comparing @@ -17,6 +21,7 @@ struct range_diff_options { unsigned dual_color:1; unsigned left_only:1, right_only:1; unsigned include_merges:1; + size_t max_memory; const struct diff_options *diffopt; /* may be NULL */ const struct strvec *other_arg; /* may be NULL */ }; diff --git a/ref-filter.h b/ref-filter.h index f22ca94b49..81f2c229a9 100644 --- a/ref-filter.h +++ b/ref-filter.h @@ -95,7 +95,7 @@ struct ref_format { const char *format; const char *rest; int quote_style; - int use_color; + enum git_colorbool use_color; /* Internal state to ref-filter */ int need_color_reset_at_eol; @@ -111,7 +111,7 @@ struct ref_format { .exclude = STRVEC_INIT, \ } #define REF_FORMAT_INIT { \ - .use_color = -1, \ + .use_color = GIT_COLOR_UNKNOWN, \ } /* Macros for checking --merged and --no-merged options */ @@ -627,10 +627,12 @@ void expand_ref_prefix(struct strvec *prefixes, const char *prefix) strvec_pushf(prefixes, *p, len, prefix); } +#ifndef WITH_BREAKING_CHANGES static const char default_branch_name_advice[] = N_( "Using '%s' as the name for the initial branch. This default branch name\n" -"is subject to change. To configure the initial branch name to use in all\n" -"of your new repositories, which will suppress this warning, call:\n" +"will change to \"main\" in Git 3.0. To configure the initial branch name\n" +"to use in all of your new repositories, which will suppress this warning,\n" +"call:\n" "\n" "\tgit config --global init.defaultBranch <name>\n" "\n" @@ -639,6 +641,15 @@ static const char default_branch_name_advice[] = N_( "\n" "\tgit branch -m <name>\n" ); +#else +static const char default_branch_name_advice[] = N_( +"Using '%s' as the name for the initial branch since Git 3.0.\n" +"If you expected Git to create 'master', the just-created\n" +"branch can be renamed via this command:\n" +"\n" +"\tgit branch -m master\n" +); +#endif /* WITH_BREAKING_CHANGES */ char *repo_default_branch_name(struct repository *r, int quiet) { @@ -649,11 +660,15 @@ char *repo_default_branch_name(struct repository *r, int quiet) if (env && *env) ret = xstrdup(env); - else if (repo_config_get_string(r, config_key, &ret) < 0) + if (!ret && repo_config_get_string(r, config_key, &ret) < 0) die(_("could not retrieve `%s`"), config_display_key); if (!ret) { +#ifdef WITH_BREAKING_CHANGES + ret = xstrdup("main"); +#else ret = xstrdup("master"); +#endif /* WITH_BREAKING_CHANGES */ if (!quiet) advise_if_enabled(ADVICE_DEFAULT_BRANCH_NAME, _(default_branch_name_advice), ret); @@ -1222,7 +1237,7 @@ int ref_transaction_maybe_set_rejected(struct ref_transaction *transaction, return 0; if (!transaction->rejections) - BUG("transaction not inititalized with failure support"); + BUG("transaction not initialized with failure support"); /* * Don't accept generic errors, since these errors are not user @@ -1231,6 +1246,13 @@ int ref_transaction_maybe_set_rejected(struct ref_transaction *transaction, if (err == REF_TRANSACTION_ERROR_GENERIC) return 0; + /* + * Rejected refnames shouldn't be considered in the availability + * checks, so remove them from the list. + */ + string_list_remove(&transaction->refnames, + transaction->updates[update_idx]->refname, 0); + transaction->updates[update_idx]->rejection_err = err; ALLOC_GROW(transaction->rejections->update_indices, transaction->rejections->nr + 1, @@ -3315,6 +3337,8 @@ const char *ref_transaction_error_msg(enum ref_transaction_error err) return "invalid new value provided"; case REF_TRANSACTION_ERROR_EXPECTED_SYMREF: return "expected symref but found regular ref"; + case REF_TRANSACTION_ERROR_CASE_CONFLICT: + return "reference conflict due to case-insensitive filesystem"; default: return "unknown failure"; } @@ -31,6 +31,8 @@ enum ref_transaction_error { REF_TRANSACTION_ERROR_INVALID_NEW_VALUE = -6, /* Expected ref to be symref, but is a regular ref */ REF_TRANSACTION_ERROR_EXPECTED_SYMREF = -7, + /* Cannot create ref due to case-insensitive filesystem */ + REF_TRANSACTION_ERROR_CASE_CONFLICT = -8, }; /* diff --git a/refs/files-backend.c b/refs/files-backend.c index 1b3bf26add..bc3347d18c 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -654,6 +654,26 @@ static void unlock_ref(struct ref_lock *lock) } /* + * Check if the transaction has another update with a case-insensitive refname + * match. + * + * If the update is part of the transaction, we only check up to that index. + * Further updates are expected to call this function to match previous indices. + */ +static bool transaction_has_case_conflicting_update(struct ref_transaction *transaction, + struct ref_update *update) +{ + for (size_t i = 0; i < transaction->nr; i++) { + if (transaction->updates[i] == update) + break; + + if (!strcasecmp(transaction->updates[i]->refname, update->refname)) + return true; + } + return false; +} + +/* * Lock refname, without following symrefs, and set *lock_p to point * at a newly-allocated lock object. Fill in lock->old_oid, referent, * and type similarly to read_raw_ref(). @@ -683,16 +703,17 @@ static void unlock_ref(struct ref_lock *lock) * - Generate informative error messages in the case of failure */ static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs, - struct ref_update *update, + struct ref_transaction *transaction, size_t update_idx, int mustexist, struct string_list *refnames_to_check, - const struct string_list *extras, struct ref_lock **lock_p, struct strbuf *referent, struct strbuf *err) { enum ref_transaction_error ret = REF_TRANSACTION_ERROR_GENERIC; + struct ref_update *update = transaction->updates[update_idx]; + const struct string_list *extras = &transaction->refnames; const char *refname = update->refname; unsigned int *type = &update->type; struct ref_lock *lock; @@ -782,6 +803,24 @@ retry: goto retry; } else { unable_to_lock_message(ref_file.buf, myerr, err); + if (myerr == EEXIST) { + if (ignore_case && + transaction_has_case_conflicting_update(transaction, update)) { + /* + * In case-insensitive filesystems, ensure that conflicts within a + * given transaction are handled. Pre-existing refs on a + * case-insensitive system will be overridden without any issue. + */ + ret = REF_TRANSACTION_ERROR_CASE_CONFLICT; + } else { + /* + * Pre-existing case-conflicting reference locks should also be + * specially categorized to avoid failing all batched updates. + */ + ret = REF_TRANSACTION_ERROR_CREATE_EXISTS; + } + } + goto error_return; } } @@ -837,6 +876,7 @@ retry: goto error_return; } else if (remove_dir_recursively(&ref_file, REMOVE_DIR_EMPTY_ONLY)) { + ret = REF_TRANSACTION_ERROR_NAME_CONFLICT; if (refs_verify_refname_available( &refs->base, refname, extras, NULL, 0, err)) { @@ -844,14 +884,14 @@ retry: * The error message set by * verify_refname_available() is OK. */ - ret = REF_TRANSACTION_ERROR_NAME_CONFLICT; goto error_return; } else { /* - * We can't delete the directory, - * but we also don't know of any - * references that it should - * contain. + * Directory conflicts can occur if there + * is an existing lock file in the directory + * or if the filesystem is case-insensitive + * and the directory contains a valid reference + * but conflicts with the update. */ strbuf_addf(err, "there is a non-empty directory '%s' " "blocking reference '%s'", @@ -873,8 +913,23 @@ retry: * If the ref did not exist and we are creating it, we have to * make sure there is no existing packed ref that conflicts * with refname. This check is deferred so that we can batch it. + * + * For case-insensitive filesystems, we should also check for F/D + * conflicts between 'foo' and 'Foo/bar'. So let's lowercase + * the refname. */ - item = string_list_append(refnames_to_check, refname); + if (ignore_case) { + struct strbuf lower = STRBUF_INIT; + + strbuf_addstr(&lower, refname); + strbuf_tolower(&lower); + + item = string_list_append_nodup(refnames_to_check, + strbuf_detach(&lower, NULL)); + } else { + item = string_list_append(refnames_to_check, refname); + } + item->util = xmalloc(sizeof(update_idx)); memcpy(item->util, &update_idx, sizeof(update_idx)); } @@ -2616,9 +2671,8 @@ static enum ref_transaction_error lock_ref_for_update(struct files_ref_store *re if (lock) { lock->count++; } else { - ret = lock_raw_ref(refs, update, update_idx, mustexist, - refnames_to_check, &transaction->refnames, - &lock, &referent, err); + ret = lock_raw_ref(refs, transaction, update_idx, mustexist, + refnames_to_check, &lock, &referent, err); if (ret) { char *reason; @@ -2858,7 +2912,7 @@ static int files_transaction_prepare(struct ref_store *ref_store, "ref_transaction_prepare"); size_t i; int ret = 0; - struct string_list refnames_to_check = STRING_LIST_INIT_NODUP; + struct string_list refnames_to_check = STRING_LIST_INIT_DUP; char *head_ref = NULL; int head_type; struct files_transaction_backend_data *backend_data; @@ -2143,9 +2143,6 @@ static int stat_branch_pair(const char *branch_name, const char *base, struct object_id oid; struct commit *ours, *theirs; struct rev_info revs; - struct setup_revision_opt opt = { - .free_removed_argv_elements = 1, - }; struct strvec argv = STRVEC_INIT; /* Cannot stat if what we used to build on no longer exists */ @@ -2180,7 +2177,7 @@ static int stat_branch_pair(const char *branch_name, const char *base, strvec_push(&argv, "--"); repo_init_revisions(the_repository, &revs, NULL); - setup_revisions(argv.nr, argv.v, &revs, &opt); + setup_revisions_from_strvec(&argv, &revs, NULL); if (prepare_revision_walk(&revs)) die(_("revision walk setup failed")); diff --git a/repository.c b/repository.c index 97f0578381..6faf5c7398 100644 --- a/repository.c +++ b/repository.c @@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo) repo->parsed_objects = parsed_object_pool_new(repo); ALLOC_ARRAY(repo->index, 1); index_state_init(repo->index, repo); + repo->check_deprecated_config = true; /* * When a command runs inside a repository, it learns what diff --git a/repository.h b/repository.h index 042dc93f0f..5808a5d610 100644 --- a/repository.h +++ b/repository.h @@ -161,6 +161,9 @@ struct repository { /* Indicate if a repository has a different 'commondir' from 'gitdir' */ unsigned different_commondir:1; + + /* Should repo_config() check for deprecated settings */ + bool check_deprecated_config; }; #ifdef USE_THE_REPOSITORY_VARIABLE diff --git a/revision.c b/revision.c index 6ba8f67054..806a1c4c24 100644 --- a/revision.c +++ b/revision.c @@ -2321,6 +2321,24 @@ static timestamp_t parse_age(const char *arg) return num; } +static void overwrite_argv(int *argc, const char **argv, + const char **value, + const struct setup_revision_opt *opt) +{ + /* + * Detect the case when we are overwriting ourselves. The assignment + * itself would be a noop either way, but this lets us avoid corner + * cases around the free() and NULL operations. + */ + if (*value != argv[*argc]) { + if (opt && opt->free_removed_argv_elements) + free((char *)argv[*argc]); + argv[*argc] = *value; + *value = NULL; + } + (*argc)++; +} + static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv, int *unkc, const char **unkv, const struct setup_revision_opt* opt) @@ -2342,7 +2360,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg starts_with(arg, "--branches=") || starts_with(arg, "--tags=") || starts_with(arg, "--remotes=") || starts_with(arg, "--no-walk=")) { - unkv[(*unkc)++] = arg; + overwrite_argv(unkc, unkv, &argv[0], opt); return 1; } @@ -2706,7 +2724,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg } else { int opts = diff_opt_parse(&revs->diffopt, argv, argc, revs->prefix); if (!opts) - unkv[(*unkc)++] = arg; + overwrite_argv(unkc, unkv, &argv[0], opt); return opts; } @@ -3018,7 +3036,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s if (!strcmp(arg, "--stdin")) { if (revs->disable_stdin) { - argv[left++] = arg; + overwrite_argv(&left, argv, &argv[i], opt); continue; } if (revs->read_from_stdin++) @@ -3174,9 +3192,34 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s revs->show_notes_given = 1; } + if (argv) { + if (opt && opt->free_removed_argv_elements) + free((char *)argv[left]); + argv[left] = NULL; + } + return left; } +void setup_revisions_from_strvec(struct strvec *argv, struct rev_info *revs, + struct setup_revision_opt *opt) +{ + struct setup_revision_opt fallback_opt; + int ret; + + if (!opt) { + memset(&fallback_opt, 0, sizeof(fallback_opt)); + opt = &fallback_opt; + } + opt->free_removed_argv_elements = 1; + + ret = setup_revisions(argv->nr, argv->v, revs, opt); + + for (size_t i = ret; i < argv->nr; i++) + free((char *)argv->v[i]); + argv->nr = ret; +} + static void release_revisions_cmdline(struct rev_cmdline_info *cmdline) { unsigned int i; diff --git a/revision.h b/revision.h index 21e288c5ba..a28e349044 100644 --- a/revision.h +++ b/revision.h @@ -441,6 +441,8 @@ struct setup_revision_opt { }; int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct setup_revision_opt *); +void setup_revisions_from_strvec(struct strvec *argv, struct rev_info *revs, + struct setup_revision_opt *); /** * Free data allocated in a "struct rev_info" after it's been diff --git a/sequencer.c b/sequencer.c index 9ae40a91b2..5476d39ba9 100644 --- a/sequencer.c +++ b/sequencer.c @@ -1087,7 +1087,6 @@ N_("you have staged changes in your working tree\n" #define CLEANUP_MSG (1<<3) #define VERIFY_MSG (1<<4) #define CREATE_ROOT_COMMIT (1<<5) -#define VERBATIM_MSG (1<<6) static int run_command_silent_on_success(struct child_process *cmd) { @@ -1125,9 +1124,6 @@ static int run_git_commit(const char *defmsg, { struct child_process cmd = CHILD_PROCESS_INIT; - if ((flags & CLEANUP_MSG) && (flags & VERBATIM_MSG)) - BUG("CLEANUP_MSG and VERBATIM_MSG are mutually exclusive"); - cmd.git_cmd = 1; if (is_rebase_i(opts) && @@ -1166,8 +1162,6 @@ static int run_git_commit(const char *defmsg, strvec_pushl(&cmd.args, "-C", "HEAD", NULL); if ((flags & CLEANUP_MSG)) strvec_push(&cmd.args, "--cleanup=strip"); - if ((flags & VERBATIM_MSG)) - strvec_push(&cmd.args, "--cleanup=verbatim"); if ((flags & EDIT_MSG)) strvec_push(&cmd.args, "-e"); else if (!(flags & CLEANUP_MSG) && @@ -1540,9 +1534,6 @@ static int try_to_commit(struct repository *r, enum commit_msg_cleanup_mode cleanup; int res = 0; - if ((flags & CLEANUP_MSG) && (flags & VERBATIM_MSG)) - BUG("CLEANUP_MSG and VERBATIM_MSG are mutually exclusive"); - if (parse_head(r, ¤t_head)) return -1; @@ -1618,8 +1609,6 @@ static int try_to_commit(struct repository *r, if (flags & CLEANUP_MSG) cleanup = COMMIT_MSG_CLEANUP_ALL; - else if (flags & VERBATIM_MSG) - cleanup = COMMIT_MSG_CLEANUP_NONE; else if ((opts->signoff || opts->record_origin) && !opts->explicit_cleanup) cleanup = COMMIT_MSG_CLEANUP_SPACE; @@ -2436,7 +2425,6 @@ static int do_pick_commit(struct repository *r, if (!final_fixup) msg_file = rebase_path_squash_msg(); else if (file_exists(rebase_path_fixup_msg())) { - flags |= VERBATIM_MSG; msg_file = rebase_path_fixup_msg(); } else { const char *dest = git_path_squash_msg(r); @@ -6064,8 +6052,8 @@ static int make_script_with_merges(struct pretty_print_context *pp, return 0; } -int sequencer_make_script(struct repository *r, struct strbuf *out, int argc, - const char **argv, unsigned flags) +int sequencer_make_script(struct repository *r, struct strbuf *out, + struct strvec *argv, unsigned flags) { char *format = NULL; struct pretty_print_context pp = {0}; @@ -6106,7 +6094,8 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc, pp.fmt = revs.commit_format; pp.output_encoding = get_log_output_encoding(); - if (setup_revisions(argc, argv, &revs, NULL) > 1) { + setup_revisions_from_strvec(argv, &revs, NULL); + if (argv->nr > 1) { ret = error(_("make_script: unhandled options")); goto cleanup; } diff --git a/sequencer.h b/sequencer.h index 304ba4b4d3..719684c8a9 100644 --- a/sequencer.h +++ b/sequencer.h @@ -186,8 +186,8 @@ int sequencer_remove_state(struct replay_opts *opts); #define TODO_LIST_REAPPLY_CHERRY_PICKS (1U << 7) #define TODO_LIST_WARN_SKIPPED_CHERRY_PICKS (1U << 8) -int sequencer_make_script(struct repository *r, struct strbuf *out, int argc, - const char **argv, unsigned flags); +int sequencer_make_script(struct repository *r, struct strbuf *out, + struct strvec *argv, unsigned flags); int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags, const char *shortrevisions, const char *onto_name, @@ -213,7 +213,7 @@ static void show_commit(struct commit *commit, void *data) * are marked with shallow_flag. The list of border/shallow commits * are also returned. */ -struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av, +struct commit_list *get_shallow_commits_by_rev_list(struct strvec *argv, int shallow_flag, int not_shallow_flag) { @@ -232,7 +232,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av, repo_init_revisions(the_repository, &revs, NULL); save_commit_buffer = 0; - setup_revisions(ac, av, &revs, NULL); + setup_revisions_from_strvec(argv, &revs, NULL); if (prepare_revision_walk(&revs)) die("revision walk setup failed"); @@ -7,6 +7,7 @@ #include "strbuf.h" struct oid_array; +struct strvec; void set_alternate_shallow_file(struct repository *r, const char *path, int override); int register_shallow(struct repository *r, const struct object_id *oid); @@ -36,8 +37,8 @@ void rollback_shallow_file(struct repository *r, struct shallow_lock *lk); struct commit_list *get_shallow_commits(struct object_array *heads, int depth, int shallow_flag, int not_shallow_flag); -struct commit_list *get_shallow_commits_by_rev_list( - int ac, const char **av, int shallow_flag, int not_shallow_flag); +struct commit_list *get_shallow_commits_by_rev_list(struct strvec *argv, + int shallow_flag, int not_shallow_flag); int write_shallow_commits(struct strbuf *out, int use_pack_protocol, const struct oid_array *extra); diff --git a/sideband.c b/sideband.c index 8f15b98a65..ea7c25211e 100644 --- a/sideband.c +++ b/sideband.c @@ -27,16 +27,16 @@ static struct keyword_entry keywords[] = { }; /* Returns a color setting (GIT_COLOR_NEVER, etc). */ -static int use_sideband_colors(void) +static enum git_colorbool use_sideband_colors(void) { - static int use_sideband_colors_cached = -1; + static enum git_colorbool use_sideband_colors_cached = GIT_COLOR_UNKNOWN; const char *key = "color.remote"; struct strbuf sb = STRBUF_INIT; const char *value; int i; - if (use_sideband_colors_cached >= 0) + if (use_sideband_colors_cached != GIT_COLOR_UNKNOWN) return use_sideband_colors_cached; if (!repo_config_get_string_tmp(the_repository, key, &value)) diff --git a/submodule.c b/submodule.c index fff3c75570..35c55155f7 100644 --- a/submodule.c +++ b/submodule.c @@ -900,7 +900,7 @@ static void collect_changed_submodules(struct repository *r, save_warning = warn_on_object_refname_ambiguity; warn_on_object_refname_ambiguity = 0; repo_init_revisions(r, &rev, NULL); - setup_revisions(argv->nr, argv->v, &rev, &s_r_opt); + setup_revisions_from_strvec(argv, &rev, &s_r_opt); warn_on_object_refname_ambiguity = save_warning; if (prepare_revision_walk(&rev)) die(_("revision walk setup failed")); 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/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/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/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 34d6ad0770..e778dd8ae4 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1176,7 +1176,7 @@ test_expect_success 'rebase -i respects core.commentchar' ' test B = $(git cat-file commit HEAD^ | sed -ne \$p) ' -test_expect_success 'rebase -i respects core.commentchar=auto' ' +test_expect_success !WITH_BREAKING_CHANGES 'rebase -i respects core.commentchar=auto' ' test_config core.commentchar auto && write_script copy-edit-script.sh <<-\EOF && cp "$1" edit-script @@ -1184,8 +1184,23 @@ test_expect_success 'rebase -i respects core.commentchar=auto' ' test_when_finished "git rebase --abort || :" && ( test_set_editor "$(pwd)/copy-edit-script.sh" && - git rebase -i HEAD^ + git rebase -i HEAD^ 2>err ) && + sed -n "s/^hint: *\$//p; s/^hint: //p; s/^warning: //p" err >actual && + cat >expect <<-EOF && + Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0 + + To use the default comment string (#) please run + + git config unset core.commentChar + + To set a custom comment string please run + + git config set core.commentChar <comment string> + + where ${SQ}<comment string>${SQ} is the string you wish to use. + EOF + test_cmp expect actual && test -z "$(grep -ve "^#" -e "^\$" -e "^pick" edit-script)" ' 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/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index b8a8dd77e7..f9b8999db5 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -328,7 +328,7 @@ test_expect_success 'there is no --no-reschedule-failed-exec in an ongoing rebas test_expect_code 129 git rebase --edit-todo --no-reschedule-failed-exec ' -test_expect_success 'no change in comment character due to conflicts markers with core.commentChar=auto' ' +test_expect_success !WITH_BREAKING_CHANGES 'no change in comment character due to conflicts markers with core.commentChar=auto' ' git checkout -b branch-a && test_commit A F1 && git checkout -b branch-b HEAD^ && diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 04d2a19835..d9fe289a7a 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -866,6 +866,44 @@ test_expect_success 'colorized diffs respect diff.wsErrorHighlight' ' test_grep "old<" output ' +test_expect_success 'diff color respects color.diff' ' + git reset --hard && + + echo old >test && + git add test && + echo new >test && + + printf n >n && + force_color git \ + -c color.interactive=auto \ + -c color.interactive.prompt=blue \ + -c color.diff=false \ + -c color.diff.old=red \ + add -p >output.raw 2>&1 <n && + test_decode_color <output.raw >output && + test_grep "BLUE.*Stage this hunk" output && + test_grep ! "RED" output +' + +test_expect_success 're-coloring diff without color.interactive' ' + git reset --hard && + + test_write_lines 1 2 3 >test && + git add test && + test_write_lines one 2 three >test && + + test_write_lines s n n | + force_color git \ + -c color.interactive=false \ + -c color.interactive.prompt=blue \ + -c color.diff=true \ + -c color.diff.frag="bold magenta" \ + add -p >output.raw 2>&1 && + test_decode_color <output.raw >output && + test_grep "<BOLD;MAGENTA>@@" output && + test_grep ! "BLUE" output +' + test_expect_success 'diffFilter filters diff' ' git reset --hard && @@ -1283,6 +1321,12 @@ test_expect_success 'stash accepts -U and --inter-hunk-context' ' test_grep "@@ -2,20 +2,20 @@" actual ' +test_expect_success 'set up base for -p color tests' ' + echo commit >file && + git commit -am "commit state" && + git tag patch-base +' + for cmd in add checkout commit reset restore "stash save" "stash push" do test_expect_success "$cmd rejects invalid context options" ' @@ -1299,6 +1343,15 @@ do test_must_fail git $cmd --inter-hunk-context 2 2>actual && test_grep -E ".--inter-hunk-context. requires .(--interactive/)?--patch." actual ' + + test_expect_success "$cmd falls back to color.ui" ' + git reset --hard patch-base && + echo working-tree >file && + test_write_lines y | + force_color git -c color.ui=false $cmd -p >output.raw 2>&1 && + test_decode_color <output.raw >output && + test_cmp output.raw output + ' done 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/t3904-stash-patch.sh b/t/t3904-stash-patch.sh index ae313e3c70..90a4ff2c10 100755 --- a/t/t3904-stash-patch.sh +++ b/t/t3904-stash-patch.sh @@ -107,4 +107,23 @@ test_expect_success 'stash -p with split hunk' ' ! grep "added line 2" test ' +test_expect_success 'stash -p not confused by GIT_PAGER_IN_USE' ' + echo to-stash >test && + # Set both GIT_PAGER_IN_USE and TERM. Our goal is to entice any + # diff subprocesses into thinking that they could output + # color, even though their stdout is not going into a tty. + echo y | + GIT_PAGER_IN_USE=1 TERM=vt100 git stash -p && + git diff --exit-code +' + +test_expect_success 'index push not confused by GIT_PAGER_IN_USE' ' + echo index >test && + git add test && + echo working-tree >test && + # As above, we try to entice the child diff into using color. + GIT_PAGER_IN_USE=1 TERM=vt100 git stash push test && + git diff --exit-code +' + 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..55a06eadb3 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 && 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/t4211-line-log.sh b/t/t4211-line-log.sh index 950451cf6a..0a7c3ca42f 100755 --- a/t/t4211-line-log.sh +++ b/t/t4211-line-log.sh @@ -78,6 +78,8 @@ canned_test "-L :main:a.c -L 4,18:a.c simple" multiple-overlapping canned_test "-L 4:a.c -L 8,12:a.c simple" multiple-superset canned_test "-L 8,12:a.c -L 4:a.c simple" multiple-superset +canned_test "-L 10,16:b.c -L 18,26:b.c main" no-assertion-error + test_bad_opts "-L" "switch.*requires a value" test_bad_opts "-L b.c" "argument not .start,end:file" test_bad_opts "-L 1:" "argument not .start,end:file" diff --git a/t/t4211/sha1/expect.multiple b/t/t4211/sha1/expect.multiple index 76ad5b598c..1eee8a7801 100644 --- a/t/t4211/sha1/expect.multiple +++ b/t/t4211/sha1/expect.multiple @@ -102,3 +102,9 @@ diff --git a/a.c b/a.c + s++; + } +} +@@ -0,0 +16,5 @@ ++int main () ++{ ++ printf("%d\n", f(15)); ++ return 0; ++} diff --git a/t/t4211/sha1/expect.no-assertion-error b/t/t4211/sha1/expect.no-assertion-error new file mode 100644 index 0000000000..994c37db1e --- /dev/null +++ b/t/t4211/sha1/expect.no-assertion-error @@ -0,0 +1,90 @@ +commit 0d8dcfc6b968e06a27d5215bad1fdde3de9d6235 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:50:24 2013 +0100 + + move within the file + +diff --git a/b.c b/b.c +--- a/b.c ++++ b/b.c +@@ -25,0 +18,9 @@ ++long f(long x) ++{ ++ int s = 0; ++ while (x) { ++ x /= 2; ++ s++; ++ } ++ return s; ++} + +commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:43 2013 +0100 + + change back to complete line + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,7 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} +\ No newline at end of file ++} ++ ++/* incomplete lines are bad! */ + +commit 100b61a6f2f720f812620a9d10afb3a960ccb73c +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:10 2013 +0100 + + change to an incomplete line at end + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,5 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} ++} +\ No newline at end of file + +commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -17,5 +17,5 @@ + int main () + { +- printf("%d\n", f(15)); ++ printf("%ld\n", f(15)); + return 0; + } + +commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +16,5 @@ ++int main () ++{ ++ printf("%d\n", f(15)); ++ return 0; ++} diff --git a/t/t4211/sha1/expect.two-ranges b/t/t4211/sha1/expect.two-ranges index 6109aa0dce..c5164f3be3 100644 --- a/t/t4211/sha1/expect.two-ranges +++ b/t/t4211/sha1/expect.two-ranges @@ -100,3 +100,9 @@ diff --git a/a.c b/a.c + s++; + } +} +@@ -0,0 +16,5 @@ ++int main () ++{ ++ printf("%d\n", f(15)); ++ return 0; ++} diff --git a/t/t4211/sha256/expect.multiple b/t/t4211/sha256/expect.multiple index ca00409b9a..dbd987b74a 100644 --- a/t/t4211/sha256/expect.multiple +++ b/t/t4211/sha256/expect.multiple @@ -102,3 +102,9 @@ diff --git a/a.c b/a.c + s++; + } +} +@@ -0,0 +16,5 @@ ++int main () ++{ ++ printf("%d\n", f(15)); ++ return 0; ++} diff --git a/t/t4211/sha256/expect.no-assertion-error b/t/t4211/sha256/expect.no-assertion-error new file mode 100644 index 0000000000..36ed12aa9c --- /dev/null +++ b/t/t4211/sha256/expect.no-assertion-error @@ -0,0 +1,90 @@ +commit eb871b8aa9aff323e484723039c9a92ab0266e060bc0ef2afb08fadda25c5ace +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:50:24 2013 +0100 + + move within the file + +diff --git a/b.c b/b.c +--- a/b.c ++++ b/b.c +@@ -25,0 +18,9 @@ ++long f(long x) ++{ ++ int s = 0; ++ while (x) { ++ x /= 2; ++ s++; ++ } ++ return s; ++} + +commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:43 2013 +0100 + + change back to complete line + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,7 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} +\ No newline at end of file ++} ++ ++/* incomplete lines are bad! */ + +commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:10 2013 +0100 + + change to an incomplete line at end + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,5 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} ++} +\ No newline at end of file + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -17,5 +17,5 @@ + int main () + { +- printf("%d\n", f(15)); ++ printf("%ld\n", f(15)); + return 0; + } + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +16,5 @@ ++int main () ++{ ++ printf("%d\n", f(15)); ++ return 0; ++} diff --git a/t/t4211/sha256/expect.two-ranges b/t/t4211/sha256/expect.two-ranges index af57c8b997..6a94d3b9cb 100644 --- a/t/t4211/sha256/expect.two-ranges +++ b/t/t4211/sha256/expect.two-ranges @@ -100,3 +100,9 @@ diff --git a/a.c b/a.c + s++; + } +} +@@ -0,0 +16,5 @@ ++int main () ++{ ++ printf("%d\n", f(15)); ++ return 0; ++} 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/t5564-http-proxy.sh b/t/t5564-http-proxy.sh index b27e481f95..c3903faf2d 100755 --- a/t/t5564-http-proxy.sh +++ b/t/t5564-http-proxy.sh @@ -72,7 +72,9 @@ test_expect_success SOCKS_PROXY 'clone via Unix socket' ' test_when_finished "rm -rf clone" && test_config_global http.proxy "socks4://localhost$PWD/%2530.sock" && { { - GIT_TRACE_CURL=$PWD/trace git clone "$HTTPD_URL/smart/repo.git" clone 2>err && + GIT_TRACE_CURL=$PWD/trace \ + GIT_TRACE_CURL_COMPONENTS=socks \ + git clone "$HTTPD_URL/smart/repo.git" clone 2>err && grep -i "SOCKS4 request granted" trace } || old_libcurl_error err diff --git a/t/t5710-promisor-remote-capability.sh b/t/t5710-promisor-remote-capability.sh index cb061b1f35..023735d6a8 100755 --- a/t/t5710-promisor-remote-capability.sh +++ b/t/t5710-promisor-remote-capability.sh @@ -295,6 +295,71 @@ test_expect_success "clone with 'KnownUrl' and empty url, so not advertised" ' check_missing_objects server 1 "$oid" ' +test_expect_success "clone with promisor.sendFields" ' + git -C server config promisor.advertise true && + test_when_finished "rm -rf client" && + + git -C server remote add otherLop "https://invalid.invalid" && + git -C server config remote.otherLop.token "fooBar" && + git -C server config remote.otherLop.stuff "baz" && + git -C server config remote.otherLop.partialCloneFilter "blob:limit=10k" && + test_when_finished "git -C server remote remove otherLop" && + test_config -C server promisor.sendFields "partialCloneFilter, token" && + test_when_finished "rm trace" && + + # Clone from server to create a client + GIT_TRACE_PACKET="$(pwd)/trace" GIT_NO_LAZY_FETCH=0 git clone \ + -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=All \ + --no-local --filter="blob:limit=5k" server client && + + # Check that fields are properly transmitted + ENCODED_URL=$(echo "file://$(pwd)/lop" | sed -e "s/ /%20/g") && + PR1="name=lop,url=$ENCODED_URL,partialCloneFilter=blob:none" && + PR2="name=otherLop,url=https://invalid.invalid,partialCloneFilter=blob:limit=10k,token=fooBar" && + test_grep "clone< promisor-remote=$PR1;$PR2" trace && + test_grep "clone> promisor-remote=lop;otherLop" trace && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "clone with promisor.checkFields" ' + git -C server config promisor.advertise true && + test_when_finished "rm -rf client" && + + git -C server remote add otherLop "https://invalid.invalid" && + git -C server config remote.otherLop.token "fooBar" && + git -C server config remote.otherLop.stuff "baz" && + git -C server config remote.otherLop.partialCloneFilter "blob:limit=10k" && + test_when_finished "git -C server remote remove otherLop" && + test_config -C server promisor.sendFields "partialCloneFilter, token" && + test_when_finished "rm trace" && + + # Clone from server to create a client + GIT_TRACE_PACKET="$(pwd)/trace" GIT_NO_LAZY_FETCH=0 git clone \ + -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c remote.lop.partialCloneFilter="blob:none" \ + -c promisor.acceptfromserver=All \ + -c promisor.checkFields=partialcloneFilter \ + --no-local --filter="blob:limit=5k" server client && + + # Check that fields are properly transmitted + ENCODED_URL=$(echo "file://$(pwd)/lop" | sed -e "s/ /%20/g") && + PR1="name=lop,url=$ENCODED_URL,partialCloneFilter=blob:none" && + PR2="name=otherLop,url=https://invalid.invalid,partialCloneFilter=blob:limit=10k,token=fooBar" && + test_grep "clone< promisor-remote=$PR1;$PR2" trace && + test_grep "clone> promisor-remote=lop" trace && + test_grep ! "clone> promisor-remote=lop;otherLop" trace && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + test_expect_success "clone with promisor.advertise set to 'true' but don't delete the client" ' git -C server config promisor.advertise true && diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh index b37e2018a7..05f6da4ad9 100755 --- a/t/t7502-commit-porcelain.sh +++ b/t/t7502-commit-porcelain.sh @@ -956,13 +956,39 @@ test_expect_success 'commit --status with custom comment character' ' test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG ' -test_expect_success 'switch core.commentchar' ' +test_expect_success !WITH_BREAKING_CHANGES 'switch core.commentchar' ' test_commit "#foo" foo && - GIT_EDITOR=.git/FAKE_EDITOR git -c core.commentChar=auto commit --amend && + cat >config-include <<-\EOF && + [core] + commentString=: + commentString=% + commentChar=auto + EOF + test_when_finished "rm config-include" && + test_config include.path "$(pwd)/config-include" && + test_config core.commentChar ! && + GIT_EDITOR=.git/FAKE_EDITOR git commit --amend 2>err && + sed -n "s/^hint: *\$//p; s/^hint: //p; s/^warning: //p" err >actual && + cat >expect <<-EOF && + Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0 + + To use the default comment string (#) please run + + git config unset core.commentChar + git config unset --file ~/config-include --all core.commentString + git config unset --file ~/config-include core.commentChar + + To set a custom comment string please run + + git config set --file ~/config-include core.commentChar <comment string> + + where ${SQ}<comment string>${SQ} is the string you wish to use. + EOF + test_cmp expect actual && test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG ' -test_expect_success 'switch core.commentchar but out of options' ' +test_expect_success !WITH_BREAKING_CHANGES 'switch core.commentchar but out of options' ' cat >text <<\EOF && # 1 ; 2 @@ -982,4 +1008,24 @@ EOF ) ' +test_expect_success WITH_BREAKING_CHANGES 'core.commentChar=auto is rejected' ' + test_config core.commentChar auto && + test_must_fail git rev-parse --git-dir 2>err && + sed -n "s/^hint: *\$//p; s/^hint: //p; s/^fatal: //p" err >actual && + cat >expect <<-EOF && + Support for ${SQ}core.commentChar=auto${SQ} has been removed in Git 3.0 + + To use the default comment string (#) please run + + git config unset core.commentChar + + To set a custom comment string please run + + git config set core.commentChar <comment string> + + where ${SQ}<comment string>${SQ} is the string you wish to use. + EOF + test_cmp expect actual +' + test_done 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.sh b/t/test-lib.sh index 621cd31ae1..562f950fb0 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" 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/transport.c b/transport.c index 6ac8aa402b..c7f06a7382 100644 --- a/transport.c +++ b/transport.c @@ -30,7 +30,7 @@ #include "color.h" #include "bundle-uri.h" -static int transport_use_color = -1; +static enum git_colorbool transport_use_color = GIT_COLOR_UNKNOWN; static char transport_colors[][COLOR_MAXLEN] = { GIT_COLOR_RESET, GIT_COLOR_RED /* REJECTED */ diff --git a/upload-pack.c b/upload-pack.c index f78fabc1e1..1e87ae9559 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -913,13 +913,12 @@ static void deepen(struct upload_pack_data *data, int depth) } static void deepen_by_rev_list(struct upload_pack_data *data, - int ac, - const char **av) + struct strvec *argv) { struct commit_list *result; disable_commit_graph(the_repository); - result = get_shallow_commits_by_rev_list(ac, av, SHALLOW, NOT_SHALLOW); + result = get_shallow_commits_by_rev_list(argv, SHALLOW, NOT_SHALLOW); send_shallow(data, result); free_commit_list(result); send_unshallow(data); @@ -955,7 +954,7 @@ static int send_shallow_list(struct upload_pack_data *data) struct object *o = data->want_obj.objects[i].item; strvec_push(&av, oid_to_hex(&o->oid)); } - deepen_by_rev_list(data, av.nr, av.v); + deepen_by_rev_list(data, &av); strvec_clear(&av); ret = 1; } else { diff --git a/wt-status.c b/wt-status.c index 21dabab77d..8ffe6d3988 100644 --- a/wt-status.c +++ b/wt-status.c @@ -148,7 +148,7 @@ void wt_status_prepare(struct repository *r, struct wt_status *s) memcpy(s->color_palette, default_wt_status_colors, sizeof(default_wt_status_colors)); s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; - s->use_color = -1; + s->use_color = GIT_COLOR_UNKNOWN; s->relative_paths = 1; s->branch = refs_resolve_refdup(get_main_ref_store(the_repository), "HEAD", 0, NULL, NULL); @@ -1165,7 +1165,7 @@ static void wt_longstatus_print_verbose(struct wt_status *s) * before. */ if (s->fp != stdout) { - rev.diffopt.use_color = 0; + rev.diffopt.use_color = GIT_COLOR_NEVER; wt_status_add_cut_line(s); } if (s->verbose > 1 && s->committable) { @@ -2155,7 +2155,7 @@ static void wt_shortstatus_print(struct wt_status *s) static void wt_porcelain_print(struct wt_status *s) { - s->use_color = 0; + s->use_color = GIT_COLOR_NEVER; s->relative_paths = 0; s->prefix = NULL; s->no_gettext = 1; diff --git a/wt-status.h b/wt-status.h index 4e377ce62b..e40a27214a 100644 --- a/wt-status.h +++ b/wt-status.h @@ -111,7 +111,7 @@ struct wt_status { int amend; enum commit_whence whence; int nowarn; - int use_color; + enum git_colorbool use_color; int no_gettext; int display_comment_prefix; int relative_paths; |
