aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/.gitattributes1
-rw-r--r--t/Makefile10
-rw-r--r--t/README16
-rwxr-xr-xt/aggregate-results.sh2
-rw-r--r--t/annotate-tests.sh30
-rwxr-xr-xt/chainlint.pl188
-rw-r--r--t/chainlint/block-comment.expect2
-rw-r--r--t/chainlint/case-comment.expect3
-rw-r--r--t/chainlint/close-subshell.expect3
-rw-r--r--t/chainlint/comment.expect4
-rw-r--r--t/chainlint/double-here-doc.expect14
-rw-r--r--t/chainlint/empty-here-doc.expect3
-rw-r--r--t/chainlint/for-loop.expect4
-rw-r--r--t/chainlint/here-doc-close-subshell.expect4
-rw-r--r--t/chainlint/here-doc-indent-operator.expect10
-rw-r--r--t/chainlint/here-doc-multi-line-command-subst.expect5
-rw-r--r--t/chainlint/here-doc-multi-line-string.expect4
-rw-r--r--t/chainlint/here-doc.expect24
-rw-r--r--t/chainlint/if-then-else.expect4
-rw-r--r--t/chainlint/incomplete-line.expect10
-rw-r--r--t/chainlint/inline-comment.expect4
-rw-r--r--t/chainlint/loop-detect-status.expect2
-rw-r--r--t/chainlint/nested-here-doc.expect27
-rw-r--r--t/chainlint/nested-subshell-comment.expect2
-rw-r--r--t/chainlint/subshell-here-doc.expect28
-rw-r--r--t/chainlint/t7900-subtree.expect4
-rw-r--r--t/chainlint/unclosed-here-doc-indent.expect4
-rw-r--r--t/chainlint/unclosed-here-doc-indent.test4
-rw-r--r--t/chainlint/unclosed-here-doc.expect7
-rw-r--r--t/chainlint/unclosed-here-doc.test7
-rw-r--r--t/chainlint/while-loop.expect4
-rwxr-xr-xt/check-non-portable-shell.pl1
-rw-r--r--t/helper/test-advise.c2
-rw-r--r--t/helper/test-bitmap.c3
-rw-r--r--t/helper/test-bloom.c6
-rw-r--r--t/helper/test-bundle-uri.c137
-rw-r--r--t/helper/test-cache-tree.c69
-rw-r--r--t/helper/test-chmtime.c2
-rw-r--r--t/helper/test-config.c67
-rw-r--r--t/helper/test-crontab.c1
-rw-r--r--t/helper/test-ctype.c35
-rw-r--r--t/helper/test-date.c8
-rw-r--r--t/helper/test-delta.c1
-rw-r--r--t/helper/test-dir-iterator.c6
-rw-r--r--t/helper/test-drop-caches.c2
-rw-r--r--t/helper/test-dump-cache-tree.c14
-rw-r--r--t/helper/test-dump-fsmonitor.c6
-rw-r--r--t/helper/test-dump-split-index.c10
-rw-r--r--t/helper/test-dump-untracked-cache.c11
-rw-r--r--t/helper/test-env-helper.c100
-rw-r--r--t/helper/test-example-decorate.c5
-rw-r--r--t/helper/test-fake-ssh.c8
-rw-r--r--t/helper/test-fast-rebase.c31
-rw-r--r--t/helper/test-fsmonitor-client.c6
-rw-r--r--t/helper/test-genzeros.c11
-rw-r--r--t/helper/test-hash-speed.c2
-rw-r--r--t/helper/test-hash.c2
-rw-r--r--t/helper/test-hashmap.c22
-rw-r--r--t/helper/test-hexdump.c2
-rw-r--r--t/helper/test-index-version.c15
-rw-r--r--t/helper/test-json-writer.c77
-rw-r--r--t/helper/test-lazy-init-name-hash.c28
-rw-r--r--t/helper/test-match-trees.c12
-rw-r--r--t/helper/test-mergesort.c3
-rw-r--r--t/helper/test-oid-array.c8
-rw-r--r--t/helper/test-oidmap.c33
-rw-r--r--t/helper/test-oidtree.c8
-rw-r--r--t/helper/test-online-cpus.c2
-rw-r--r--t/helper/test-pack-mtimes.c5
-rw-r--r--t/helper/test-parse-options.c8
-rw-r--r--t/helper/test-parse-pathspec-file.c4
-rw-r--r--t/helper/test-partial-clone.c5
-rw-r--r--t/helper/test-path-utils.c10
-rw-r--r--t/helper/test-pcre2-config.c1
-rw-r--r--t/helper/test-pkt-line.c3
-rw-r--r--t/helper/test-prio-queue.c5
-rw-r--r--t/helper/test-proc-receive.c7
-rw-r--r--t/helper/test-progress.c1
-rw-r--r--t/helper/test-reach.c19
-rw-r--r--t/helper/test-read-cache.c9
-rw-r--r--t/helper/test-read-graph.c6
-rw-r--r--t/helper/test-read-midx.c6
-rw-r--r--t/helper/test-ref-store.c39
-rw-r--r--t/helper/test-reftable.c1
-rw-r--r--t/helper/test-repository.c6
-rw-r--r--t/helper/test-revision-walking.c6
-rw-r--r--t/helper/test-run-command.c94
-rw-r--r--t/helper/test-scrap-cache-tree.c15
-rw-r--r--t/helper/test-serve-v2.c3
-rw-r--r--t/helper/test-sha1.c10
-rw-r--r--t/helper/test-sha256.c2
-rw-r--r--t/helper/test-sigchain.c3
-rw-r--r--t/helper/test-simple-ipc.c3
-rw-r--r--t/helper/test-strcmp-offset.c4
-rw-r--r--t/helper/test-string-list.c6
-rw-r--r--t/helper/test-submodule-config.c9
-rw-r--r--t/helper/test-submodule-nested-repo-config.c2
-rw-r--r--t/helper/test-submodule.c87
-rw-r--r--t/helper/test-subprocess.c2
-rw-r--r--t/helper/test-tool.c5
-rw-r--r--t/helper/test-tool.h6
-rw-r--r--t/helper/test-trace2.c206
-rw-r--r--t/helper/test-userdiff.c6
-rw-r--r--t/helper/test-wildmatch.c2
-rw-r--r--t/helper/test-write-cache.c10
-rw-r--r--t/helper/test-xml-encode.c2
-rw-r--r--t/interop/interop-lib.sh2
-rw-r--r--t/lib-bundle-uri-protocol.sh216
-rwxr-xr-xt/lib-commit-graph.sh34
-rw-r--r--t/lib-credential.sh239
-rw-r--r--t/lib-diff-alternative.sh59
-rw-r--r--t/lib-gpg.sh25
-rw-r--r--t/lib-httpd.sh55
-rw-r--r--t/lib-httpd/apache.conf74
-rw-r--r--t/lib-httpd/apply-one-time-perl.sh2
-rw-r--r--t/lib-httpd/nph-custom-auth.sh39
-rw-r--r--t/lib-httpd/proxy-passwd1
-rw-r--r--t/lib-httpd/ssl.cnf2
-rw-r--r--t/lib-patch-mode.sh11
-rw-r--r--t/lib-rebase.sh35
-rw-r--r--t/lib-submodule-update.sh28
-rwxr-xr-xt/perf/p0006-read-tree-checkout.sh8
-rwxr-xr-xt/perf/p0090-cache-tree.sh36
-rwxr-xr-xt/perf/p1500-graph-walks.sh50
-rwxr-xr-xt/perf/p2000-sparse-operations.sh11
-rwxr-xr-xt/perf/p5312-pack-bitmaps-revs.sh3
-rwxr-xr-xt/perf/p7102-reset.sh21
-rwxr-xr-xt/perf/p7822-grep-perl-character.sh42
-rwxr-xr-xt/perf/run4
-rwxr-xr-xt/t0000-basic.sh9
-rwxr-xr-xt/t0001-init.sh9
-rwxr-xr-xt/t0002-gitfile.sh4
-rwxr-xr-xt/t0003-attributes.sh61
-rwxr-xr-xt/t0006-date.sh8
-rwxr-xr-xt/t0007-git-var.sh209
-rwxr-xr-xt/t0013-sha1dc.sh6
-rwxr-xr-xt/t0017-env-helper.sh62
-rwxr-xr-xt/t0020-crlf.sh38
-rwxr-xr-xt/t0021-conversion.sh4
-rwxr-xr-xt/t0023-crlf-am.sh1
-rwxr-xr-xt/t0027-auto-crlf.sh66
-rwxr-xr-xt/t0030-stripspace.sh560
-rwxr-xr-xt/t0033-safe-directory.sh9
-rwxr-xr-xt/t0035-safe-bare-repository.sh41
-rwxr-xr-xt/t0040-parse-options.sh57
-rwxr-xr-xt/t0041-usage.sh1
-rwxr-xr-xt/t0055-beyond-symlinks.sh14
-rwxr-xr-xt/t0060-path-utils.sh108
-rwxr-xr-xt/t0061-run-command.sh15
-rwxr-xr-xt/t0063-string-list.sh51
-rwxr-xr-xt/t0066-dir-iterator.sh44
-rwxr-xr-xt/t0068-for-each-repo.sh26
-rwxr-xr-xt/t0070-fundamental.sh1
-rwxr-xr-xt/t0091-bugreport.sh67
-rwxr-xr-xt/t0100-previous.sh8
-rwxr-xr-xt/t0211-trace2-perf.sh95
-rw-r--r--t/t0211/scrub_perf.perl6
-rwxr-xr-xt/t0300-credentials.sh114
-rwxr-xr-xt/t0301-credential-cache.sh2
-rwxr-xr-xt/t0303-credential-external.sh2
-rwxr-xr-xt/t0410-partial-clone.sh14
-rwxr-xr-xt/t0450-txt-doc-vs-help.sh172
-rw-r--r--t/t0450/txt-help-mismatches58
-rwxr-xr-xt/t1001-read-tree-m-2way.sh4
-rwxr-xr-xt/t1002-read-tree-m-u-2way.sh589
-rwxr-xr-xt/t1005-read-tree-reset.sh15
-rwxr-xr-xt/t1006-cat-file.sh254
-rwxr-xr-xt/t1007-hash-object.sh29
-rwxr-xr-xt/t1010-mktree.sh4
-rwxr-xr-xt/t1011-read-tree-sparse-checkout.sh1
-rwxr-xr-xt/t1022-read-tree-partial-clone.sh4
-rwxr-xr-xt/t1050-large.sh6
-rwxr-xr-xt/t1091-sparse-checkout-builtin.sh178
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh352
-rwxr-xr-xt/t1300-config.sh76
-rwxr-xr-xt/t1301-shared-repo.sh41
-rwxr-xr-xt/t1302-repo-version.sh5
-rwxr-xr-xt/t1304-default-acl.sh5
-rwxr-xr-xt/t1308-config-set.sh117
-rwxr-xr-xt/t1400-update-ref.sh3
-rwxr-xr-xt/t1401-symbolic-ref.sh51
-rwxr-xr-xt/t1404-update-ref-errors.sh3
-rwxr-xr-xt/t1408-packed-refs.sh1
-rwxr-xr-xt/t1409-avoid-packing-refs.sh1
-rwxr-xr-xt/t1410-reflog.sh1
-rwxr-xr-xt/t1413-reflog-detach.sh1
-rwxr-xr-xt/t1416-ref-transaction-hooks.sh1
-rwxr-xr-xt/t1419-exclude-refs.sh122
-rwxr-xr-xt/t1450-fsck.sh73
-rwxr-xr-xt/t1451-fsck-buffer.sh142
-rwxr-xr-xt/t1500-rev-parse.sh2
-rwxr-xr-xt/t1501-work-tree.sh2
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh137
-rw-r--r--t/t1502/.gitattributes1
-rw-r--r--t/t1502/optionspec-neg8
-rw-r--r--t/t1502/optionspec-neg.help12
-rwxr-xr-xt/t1502/optionspec.help36
-rwxr-xr-xt/t1504-ceiling-dirs.sh8
-rwxr-xr-xt/t1507-rev-parse-upstream.sh15
-rwxr-xr-xt/t1508-at-combinations.sh1
-rwxr-xr-xt/t1509-root-work-tree.sh10
-rwxr-xr-xt/t1514-rev-parse-push.sh1
-rwxr-xr-xt/t1600-index.sh33
-rwxr-xr-xt/t1700-split-index.sh2
-rwxr-xr-xt/t1800-hook.sh38
-rwxr-xr-xt/t2004-checkout-cache-temp.sh20
-rwxr-xr-xt/t2005-checkout-index-symlinks.sh8
-rwxr-xr-xt/t2012-checkout-last.sh1
-rwxr-xr-xt/t2015-checkout-unborn.sh11
-rwxr-xr-xt/t2016-checkout-patch.sh6
-rwxr-xr-xt/t2018-checkout-branch.sh1
-rwxr-xr-xt/t2019-checkout-ambiguous-ref.sh4
-rwxr-xr-xt/t2021-checkout-overwrite.sh16
-rwxr-xr-xt/t2024-checkout-dwim.sh7
-rwxr-xr-xt/t2025-checkout-no-overlay.sh1
-rwxr-xr-xt/t2027-checkout-track.sh1
-rwxr-xr-xt/t2060-switch.sh29
-rwxr-xr-xt/t2070-restore.sh16
-rwxr-xr-xt/t2104-update-index-skip-worktree.sh6
-rwxr-xr-xt/t2107-update-index-basic.sh33
-rwxr-xr-xt/t2200-add-update.sh11
-rwxr-xr-xt/t2400-worktree-add.sh510
-rwxr-xr-xt/t2401-worktree-prune.sh1
-rwxr-xr-xt/t2402-worktree-list.sh1
-rwxr-xr-xt/t2406-worktree-repair.sh1
-rwxr-xr-xt/t2407-worktree-heads.sh10
-rwxr-xr-xt/t3007-ls-files-recurse-submodules.sh33
-rwxr-xr-xt/t3009-ls-files-others-nonsubmodule.sh1
-rwxr-xr-xt/t3010-ls-files-killed-modified.sh2
-rwxr-xr-xt/t3013-ls-files-format.sh51
-rwxr-xr-xt/t3050-subprojects-fetch.sh1
-rwxr-xr-xt/t3060-ls-files-with-tree.sh6
-rwxr-xr-xt/t3070-wildmatch.sh11
-rwxr-xr-xt/t3101-ls-tree-dirname.sh8
-rwxr-xr-xt/t3104-ls-tree-format.sh7
-rwxr-xr-xt/t3200-branch.sh105
-rwxr-xr-xt/t3202-show-branch.sh43
-rwxr-xr-xt/t3203-branch-output.sh54
-rwxr-xr-xt/t3204-branch-name-interpretation.sh35
-rwxr-xr-xt/t3206-range-diff.sh32
-rwxr-xr-xt/t3210-pack-refs.sh192
-rwxr-xr-xt/t3301-notes.sh169
-rwxr-xr-xt/t3305-notes-fanout.sh2
-rwxr-xr-xt/t3309-notes-merge-auto-resolve.sh7
-rwxr-xr-xt/t3321-notes-stripspace.sh578
-rwxr-xr-xt/t3400-rebase.sh16
-rwxr-xr-xt/t3402-rebase-merge.sh22
-rwxr-xr-xt/t3404-rebase-interactive.sh122
-rwxr-xr-xt/t3405-rebase-malformed.sh1
-rwxr-xr-xt/t3406-rebase-message.sh185
-rwxr-xr-xt/t3409-rebase-environ.sh1
-rwxr-xr-xt/t3412-rebase-root.sh1
-rwxr-xr-xt/t3413-rebase-hook.sh1
-rwxr-xr-xt/t3416-rebase-onto-threedots.sh63
-rwxr-xr-xt/t3418-rebase-continue.sh138
-rwxr-xr-xt/t3419-rebase-patch-id.sh64
-rwxr-xr-xt/t3422-rebase-incompatible-options.sh88
-rwxr-xr-xt/t3423-rebase-reword.sh1
-rwxr-xr-xt/t3425-rebase-topology-merges.sh2
-rwxr-xr-xt/t3427-rebase-subtree.sh12
-rwxr-xr-xt/t3428-rebase-signoff.sh1
-rwxr-xr-xt/t3429-rebase-edit-todo.sh1
-rwxr-xr-xt/t3430-rebase-merges.sh110
-rwxr-xr-xt/t3431-rebase-fork-point.sh3
-rwxr-xr-xt/t3432-rebase-fast-forward.sh1
-rwxr-xr-xt/t3433-rebase-across-mode-change.sh1
-rwxr-xr-xt/t3437-rebase-fixup-options.sh42
-rwxr-xr-xt/t3438-rebase-broken-files.sh2
-rwxr-xr-xt/t3500-cherry.sh69
-rwxr-xr-xt/t3501-revert-cherry-pick.sh42
-rwxr-xr-xt/t3502-cherry-pick-merge.sh1
-rwxr-xr-xt/t3503-cherry-pick-root.sh1
-rwxr-xr-xt/t3506-cherry-pick-ff.sh1
-rwxr-xr-xt/t3511-cherry-pick-x.sh1
-rwxr-xr-xt/t3700-add.sh54
-rwxr-xr-xt/t3701-add-interactive.sh100
-rwxr-xr-xt/t3702-add-edit.sh2
-rwxr-xr-xt/t3800-mktag.sh1
-rwxr-xr-xt/t3903-stash.sh26
-rwxr-xr-xt/t3920-crlf-messages.sh2
-rwxr-xr-xt/t4000-diff-format.sh34
-rwxr-xr-xt/t4002-diff-basic.sh243
-rwxr-xr-xt/t4003-diff-rename-1.sh62
-rwxr-xr-xt/t4004-diff-rename-symlink.sh42
-rwxr-xr-xt/t4012-diff-binary.sh14
-rwxr-xr-xt/t4013-diff-various.sh42
-rwxr-xr-xt/t4014-format-patch.sh155
-rwxr-xr-xt/t4015-diff-whitespace.sh43
-rwxr-xr-xt/t4017-diff-retval.sh5
-rwxr-xr-xt/t4018-diff-funcname.sh19
-rw-r--r--t/t4018/java-class-brace-on-separate-line6
-rw-r--r--t/t4018/java-class-space-before-type-parameters6
-rw-r--r--t/t4018/java-class-type-parameters6
-rw-r--r--t/t4018/java-class-type-parameters-implements6
-rw-r--r--t/t4018/java-interface-type-parameters6
-rw-r--r--t/t4018/java-interface-type-parameters-extends6
-rw-r--r--t/t4018/java-non-sealed8
-rw-r--r--t/t4018/java-record6
-rw-r--r--t/t4018/java-record-space-before-components6
-rw-r--r--t/t4018/java-record-type-parameters6
-rw-r--r--t/t4018/java-sealed7
-rw-r--r--t/t4018/java-sealed-permits6
-rw-r--r--t/t4018/java-sealed-type-parameters6
-rw-r--r--t/t4018/java-sealed-type-parameters-implements-permits6
-rw-r--r--t/t4018/java-sealed-type-parameters-permits6
-rwxr-xr-xt/t4022-diff-rewrite.sh2
-rwxr-xr-xt/t4023-diff-rename-typechange.sh12
-rwxr-xr-xt/t4034-diff-words.sh4
-rwxr-xr-xt/t4038-diff-combined.sh10
-rwxr-xr-xt/t4040-whitespace-status.sh3
-rwxr-xr-xt/t4044-diff-index-unique-abbrev.sh4
-rwxr-xr-xt/t4045-diff-relative.sh31
-rwxr-xr-xt/t4046-diff-unmerged.sh10
-rwxr-xr-xt/t4047-diff-dirstat.sh2
-rwxr-xr-xt/t4052-stat-output.sh1
-rwxr-xr-xt/t4053-diff-no-index.sh80
-rwxr-xr-xt/t4054-diff-bogus-tree.sh2
-rwxr-xr-xt/t4058-diff-duplicates.sh2
-rwxr-xr-xt/t4062-diff-pickaxe.sh2
-rwxr-xr-xt/t4067-diff-partial-clone.sh5
-rwxr-xr-xt/t4111-apply-subdir.sh1
-rwxr-xr-xt/t4115-apply-symlink.sh2
-rwxr-xr-xt/t4135-apply-weird-filenames.sh1
-rwxr-xr-xt/t4141-apply-too-large.sh23
-rwxr-xr-xt/t4150-am.sh42
-rwxr-xr-xt/t4152-am-subjects.sh2
-rwxr-xr-xt/t4201-shortlog.sh39
-rwxr-xr-xt/t4202-log.sh47
-rwxr-xr-xt/t4203-mailmap.sh69
-rwxr-xr-xt/t4204-patch-id.sh95
-rwxr-xr-xt/t4205-log-pretty-formats.sh78
-rwxr-xr-xt/t4206-log-follow-harder-copies.sh36
-rwxr-xr-xt/t4207-log-decoration-colors.sh44
-rwxr-xr-xt/t4211-line-log.sh22
-rwxr-xr-xt/t4212-log-corrupt.sh55
-rwxr-xr-xt/t4213-log-tabexpand.sh1
-rwxr-xr-xt/t4254-am-corrupt.sh2
-rwxr-xr-xt/t4256-am-format-flowed.sh1
-rwxr-xr-xt/t4257-am-interactive.sh2
-rw-r--r--t/t4258/mbox2
-rwxr-xr-xt/t4300-merge-tree.sh18
-rwxr-xr-xt/t4301-merge-tree-write-tree.sh107
-rwxr-xr-xt/t5000-tar-tree.sh58
-rwxr-xr-xt/t5001-archive-attr.sh17
-rwxr-xr-xt/t5004-archive-corner-cases.sh2
-rw-r--r--t/t5100/msg00022
-rw-r--r--t/t5100/msg00032
-rw-r--r--t/t5100/msg0012--message-id2
-rw-r--r--t/t5100/quoted-cr.mbox4
-rw-r--r--t/t5100/sample.mbox6
-rwxr-xr-xt/t5300-pack-object.sh319
-rwxr-xr-xt/t5301-sliding-window.sh100
-rwxr-xr-xt/t5302-pack-index.sh4
-rwxr-xr-xt/t5303-pack-corruption-resilience.sh584
-rwxr-xr-xt/t5304-prune.sh78
-rwxr-xr-xt/t5306-pack-nobase.sh96
-rwxr-xr-xt/t5310-pack-bitmaps.sh63
-rwxr-xr-xt/t5312-prune-corruption.sh1
-rwxr-xr-xt/t5313-pack-bounds-checks.sh2
-rwxr-xr-xt/t5314-pack-cycle-detection.sh17
-rwxr-xr-xt/t5317-pack-objects-filter-objects.sh91
-rwxr-xr-xt/t5318-commit-graph.sh406
-rwxr-xr-xt/t5319-multi-pack-index.sh40
-rwxr-xr-xt/t5320-delta-islands.sh2
-rwxr-xr-xt/t5324-split-commit-graph.sh3
-rwxr-xr-xt/t5325-reverse-index.sh90
-rwxr-xr-xt/t5326-multi-pack-bitmaps.sh103
-rwxr-xr-xt/t5328-commit-graph-64bit-time.sh53
-rwxr-xr-xt/t5329-pack-objects-cruft.sh225
-rwxr-xr-xt/t5330-no-lazy-fetch-with-commit-graph.sh1
-rwxr-xr-xt/t5331-pack-objects-stdin.sh240
-rwxr-xr-xt/t5351-unpack-large-objects.sh6
-rwxr-xr-xt/t5403-post-checkout-hook.sh1
-rwxr-xr-xt/t5404-tracking-branches.sh1
-rwxr-xr-xt/t5405-send-pack-rewind.sh1
-rwxr-xr-xt/t5406-remote-rejects.sh1
-rwxr-xr-xt/t5407-post-rewrite-hook.sh48
-rwxr-xr-xt/t5502-quickfetch.sh1
-rwxr-xr-xt/t5504-fetch-receive-strict.sh3
-rwxr-xr-xt/t5506-remote-groups.sh9
-rwxr-xr-xt/t5507-remote-environment.sh2
-rwxr-xr-xt/t5510-fetch.sh110
-rwxr-xr-xt/t5512-ls-remote.sh156
-rwxr-xr-xt/t5514-fetch-multiple.sh12
-rwxr-xr-xt/t5516-fetch-push.sh60
-rwxr-xr-xt/t5517-push-mirror.sh1
-rwxr-xr-xt/t5522-pull-symlink.sh5
-rwxr-xr-xt/t5523-push-upstream.sh13
-rwxr-xr-xt/t5525-fetch-tagopt.sh1
-rwxr-xr-xt/t5526-fetch-submodules.sh42
-rwxr-xr-xt/t5527-fetch-odd-refs.sh1
-rwxr-xr-xt/t5529-push-errors.sh2
-rwxr-xr-xt/t5531-deep-submodule-push.sh50
-rwxr-xr-xt/t5541-http-push-smart.sh57
-rwxr-xr-xt/t5543-atomic-push.sh5
-rwxr-xr-xt/t5544-pack-objects-hook.sh2
-rwxr-xr-xt/t5546-receive-limits.sh37
-rwxr-xr-xt/t5547-push-quarantine.sh2
-rwxr-xr-xt/t5550-http-fetch-dumb.sh2
-rwxr-xr-xt/t5551-http-fetch-smart.sh285
-rwxr-xr-xt/t5552-skipping-fetch-negotiator.sh16
-rwxr-xr-xt/t5554-noop-fetch-negotiator.sh2
-rwxr-xr-xt/t5558-clone-bundle-uri.sh977
-rwxr-xr-xt/t5559-http-fetch-smart-http2.sh5
-rwxr-xr-xt/t5560-http-backend-noserver.sh1
-rwxr-xr-xt/t5561-http-backend.sh1
-rwxr-xr-xt/t5562-http-backend-content-length.sh2
-rwxr-xr-xt/t5563-simple-http-auth.sh329
-rwxr-xr-xt/t5564-http-proxy.sh41
-rwxr-xr-xt/t5571-pre-push-hook.sh1
-rwxr-xr-xt/t5572-pull-submodule.sh4
-rwxr-xr-xt/t5573-pull-verify-signatures.sh2
-rwxr-xr-xt/t5574-fetch-output.sh293
-rwxr-xr-xt/t5583-push-branches.sh116
-rwxr-xr-xt/t5601-clone.sh128
-rwxr-xr-xt/t5604-clone-reference.sh3
-rwxr-xr-xt/t5605-clone-local.sh12
-rwxr-xr-xt/t5606-clone-options.sh11
-rwxr-xr-xt/t5610-clone-detached.sh1
-rwxr-xr-xt/t5611-clone-config.sh1
-rwxr-xr-xt/t5613-info-alternate.sh2
-rwxr-xr-xt/t5614-clone-submodules-shallow.sh1
-rwxr-xr-xt/t5616-partial-clone.sh53
-rwxr-xr-xt/t5617-clone-submodules-remote.sh1
-rwxr-xr-xt/t5618-alternate-refs.sh2
-rwxr-xr-xt/t5700-protocol-v1.sh31
-rwxr-xr-xt/t5701-git-serve.sh40
-rwxr-xr-xt/t5702-protocol-v2.sh42
-rwxr-xr-xt/t5705-session-id-in-capabilities.sh1
-rwxr-xr-xt/t5730-protocol-v2-bundle-uri-file.sh17
-rwxr-xr-xt/t5731-protocol-v2-bundle-uri-git.sh17
-rwxr-xr-xt/t5732-protocol-v2-bundle-uri-http.sh17
-rwxr-xr-xt/t5750-bundle-uri-parse.sh290
-rwxr-xr-xt/t5810-proto-disable-local.sh2
-rwxr-xr-xt/t5813-proto-disable-ssh.sh2
-rwxr-xr-xt/t6003-rev-list-topo-order.sh23
-rwxr-xr-xt/t6006-rev-list-format.sh2
-rwxr-xr-xt/t6011-rev-list-with-bad-commit.sh1
-rwxr-xr-xt/t6014-rev-list-all.sh1
-rwxr-xr-xt/t6017-rev-list-stdin.sh51
-rwxr-xr-xt/t6018-rev-list-glob.sh40
-rwxr-xr-xt/t6020-bundle-misc.sh92
-rwxr-xr-xt/t6021-rev-list-exclude-hidden.sh164
-rwxr-xr-xt/t6030-bisect-porcelain.sh202
-rwxr-xr-xt/t6040-tracking-info.sh1
-rwxr-xr-xt/t6050-replace.sh296
-rwxr-xr-xt/t6060-merge-index.sh2
-rwxr-xr-xt/t6102-rev-list-unexpected-objects.sh4
-rwxr-xr-xt/t6120-describe.sh14
-rwxr-xr-xt/t6132-pathspec-exclude.sh6
-rwxr-xr-xt/t6135-pathspec-with-attrs.sh46
-rwxr-xr-xt/t6300-for-each-ref.sh495
-rwxr-xr-xt/t6301-for-each-ref-errors.sh15
-rwxr-xr-xt/t6302-for-each-ref-filter.sh2
-rwxr-xr-xt/t6401-merge-criss-cross.sh2
-rwxr-xr-xt/t6406-merge-attr.sh25
-rwxr-xr-xt/t6407-merge-binary.sh1
-rwxr-xr-xt/t6415-merge-dir-to-symlink.sh1
-rwxr-xr-xt/t6421-merge-partial-clone.sh4
-rwxr-xr-xt/t6422-merge-rename-corner-cases.sh2
-rwxr-xr-xt/t6423-merge-rename-directories.sh56
-rwxr-xr-xt/t6426-merge-skip-unneeded-updates.sh58
-rwxr-xr-xt/t6435-merge-sparse.sh1
-rwxr-xr-xt/t6439-merge-co-error-msgs.sh1
-rwxr-xr-xt/t6500-gc.sh101
-rwxr-xr-xt/t6501-freshen-objects.sh13
-rwxr-xr-xt/t6600-test-reach.sh169
-rwxr-xr-xt/t6700-tree-depth.sh93
-rwxr-xr-xt/t7001-mv.sh106
-rwxr-xr-xt/t7003-filter-branch.sh4
-rwxr-xr-xt/t7004-tag.sh80
-rwxr-xr-xt/t7030-verify-tag.sh2
-rwxr-xr-xt/t7031-verify-tag-signed-ssh.sh12
-rwxr-xr-xt/t7101-reset-empty-subdirs.sh48
-rwxr-xr-xt/t7102-reset.sh10
-rwxr-xr-xt/t7103-reset-bare.sh2
-rwxr-xr-xt/t7105-reset-patch.sh2
-rwxr-xr-xt/t7106-reset-unborn-branch.sh2
-rwxr-xr-xt/t7107-reset-pathspec-file.sh1
-rwxr-xr-xt/t7110-reset-merge.sh314
-rwxr-xr-xt/t7111-reset-table.sh20
-rwxr-xr-xt/t7201-co.sh92
-rwxr-xr-xt/t7300-clean.sh4
-rwxr-xr-xt/t7301-clean-interactive.sh1
-rwxr-xr-xt/t7400-submodule-basic.sh26
-rwxr-xr-xt/t7402-submodule-rebase.sh24
-rwxr-xr-xt/t7403-submodule-sync.sh1
-rwxr-xr-xt/t7406-submodule-update.sh23
-rwxr-xr-xt/t7407-submodule-foreach.sh5
-rwxr-xr-xt/t7409-submodule-detached-work-tree.sh1
-rwxr-xr-xt/t7411-submodule-config.sh36
-rwxr-xr-xt/t7412-submodule-absorbgitdirs.sh64
-rwxr-xr-xt/t7413-submodule-is-active.sh16
-rwxr-xr-xt/t7416-submodule-dash-url.sh2
-rwxr-xr-xt/t7418-submodule-sparse-gitmodules.sh4
-rwxr-xr-xt/t7422-submodule-output.sh170
-rwxr-xr-xt/t7450-bad-git-dotfiles.sh2
-rwxr-xr-xt/t7502-commit-porcelain.sh19
-rwxr-xr-xt/t7504-commit-msg-hook.sh5
-rwxr-xr-xt/t7508-status.sh123
-rwxr-xr-xt/t7509-commit-authorship.sh2
-rwxr-xr-xt/t7510-signed-commit.sh74
-rwxr-xr-xt/t7512-status-help.sh22
-rwxr-xr-xt/t7516-commit-races.sh5
-rwxr-xr-xt/t7517-per-repo-email.sh1
-rwxr-xr-xt/t7518-ident-corner-cases.sh11
-rwxr-xr-xt/t7520-ignored-hook-warning.sh1
-rwxr-xr-xt/t7527-builtin-fsmonitor.sh104
-rwxr-xr-xt/t7528-signed-commit-ssh.sh2
-rwxr-xr-xt/t7600-merge.sh42
-rwxr-xr-xt/t7605-merge-resolve.sh1
-rwxr-xr-xt/t7610-mergetool.sh42
-rwxr-xr-xt/t7612-merge-verify-signatures.sh1
-rwxr-xr-xt/t7614-merge-signoff.sh1
-rwxr-xr-xt/t7700-repack.sh272
-rwxr-xr-xt/t7701-repack-unpack-unreachable.sh47
-rwxr-xr-xt/t7703-repack-geometric.sh170
-rwxr-xr-xt/t7800-difftool.sh52
-rwxr-xr-xt/t7810-grep.sh19
-rwxr-xr-xt/t7814-grep-recurse-submodules.sh40
-rwxr-xr-xt/t7900-maintenance.sh96
-rwxr-xr-xt/t8003-blame-corner-cases.sh2
-rwxr-xr-xt/t9001-send-email.sh206
-rwxr-xr-xt/t9003-help-autocorrect.sh8
-rwxr-xr-xt/t9100-git-svn-basic.sh31
-rwxr-xr-xt/t9104-git-svn-follow-parent.sh62
-rwxr-xr-xt/t9106-git-svn-commit-diff-clobber.sh1
-rwxr-xr-xt/t9115-git-svn-dcommit-funky-renames.sh1
-rwxr-xr-xt/t9119-git-svn-info.sh2
-rwxr-xr-xt/t9133-git-svn-nested-git-repo.sh6
-rwxr-xr-xt/t9134-git-svn-ignore-paths.sh8
-rwxr-xr-xt/t9140-git-svn-reset.sh4
-rwxr-xr-xt/t9146-git-svn-empty-dirs.sh1
-rwxr-xr-xt/t9147-git-svn-include-paths.sh8
-rwxr-xr-xt/t9148-git-svn-propset.sh1
-rwxr-xr-xt/t9160-git-svn-preserve-empty-dirs.sh1
-rwxr-xr-xt/t9164-git-svn-dcommit-concurrent.sh1
-rwxr-xr-xt/t9200-git-cvsexportcommit.sh351
-rwxr-xr-xt/t9210-scalar.sh26
-rwxr-xr-xt/t9211-scalar-clone.sh44
-rwxr-xr-xt/t9300-fast-import.sh13
-rwxr-xr-xt/t9304-fast-import-marks.sh29
-rwxr-xr-xt/t9350-fast-export.sh2
-rwxr-xr-xt/t9351-fast-export-anonymize.sh2
-rwxr-xr-xt/t9400-git-cvsserver-server.sh530
-rwxr-xr-xt/t9700-perl-git.sh65
-rwxr-xr-xt/t9700/test.pl12
-rwxr-xr-xt/t9800-git-p4-basic.sh2
-rwxr-xr-xt/t9814-git-p4-rename.sh2
-rwxr-xr-xt/t9815-git-p4-submit-fail.sh4
-rwxr-xr-xt/t9902-completion.sh72
-rwxr-xr-xt/t9903-bash-prompt.sh8
-rw-r--r--t/test-lib-functions.sh200
-rw-r--r--t/test-lib.sh56
554 files changed, 19012 insertions, 4902 deletions
diff --git a/t/.gitattributes b/t/.gitattributes
index 9930e28351..b9cea1795d 100644
--- a/t/.gitattributes
+++ b/t/.gitattributes
@@ -22,3 +22,4 @@ t[0-9][0-9][0-9][0-9]/* -whitespace
/t7500/* eol=lf
/t8005/*.txt eol=lf
/t9*/*.dump eol=lf
+/t0040*.sh whitespace=-indent-with-non-tab
diff --git a/t/Makefile b/t/Makefile
index 882782a519..3e00cdd801 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -44,8 +44,8 @@ CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl
# `test-chainlint` (which is a dependency of `test-lint`, `test` and `prove`)
# checks all tests in all scripts via a single invocation, so tell individual
-# scripts not to "chainlint" themselves
-CHAINLINTSUPPRESS = GIT_TEST_CHAIN_LINT=0 && export GIT_TEST_CHAIN_LINT &&
+# scripts not to run the external "chainlint.pl" script themselves
+CHAINLINTSUPPRESS = GIT_TEST_EXT_CHAIN_LINT=0 && export GIT_TEST_EXT_CHAIN_LINT &&
all: $(DEFAULT_TEST_TARGET)
@@ -94,7 +94,7 @@ check-chainlint:
done \
} >'$(CHAINLINTTMP_SQ)'/expect && \
$(CHAINLINT) --emit-all '$(CHAINLINTTMP_SQ)'/tests | \
- grep -v '^[ ]*$$' >'$(CHAINLINTTMP_SQ)'/actual && \
+ sed -e 's/^[1-9][0-9]* //;/^[ ]*$$/d' >'$(CHAINLINTTMP_SQ)'/actual && \
if test -f ../GIT-BUILD-OPTIONS; then \
. ../GIT-BUILD-OPTIONS; \
fi && \
@@ -140,9 +140,7 @@ aggregate-results-and-cleanup: $(T)
$(MAKE) clean
aggregate-results:
- for f in '$(TEST_RESULTS_DIRECTORY_SQ)'/t*-*.counts; do \
- echo "$$f"; \
- done | '$(SHELL_PATH_SQ)' ./aggregate-results.sh
+ @'$(SHELL_PATH_SQ)' ./aggregate-results.sh '$(TEST_RESULTS_DIRECTORY_SQ)'
valgrind:
$(MAKE) GIT_TEST_OPTS="$(GIT_TEST_OPTS) --valgrind"
diff --git a/t/README b/t/README
index 979b2d4833..6108085989 100644
--- a/t/README
+++ b/t/README
@@ -442,6 +442,10 @@ GIT_TEST_INDEX_VERSION=<n> exercises the index read/write code path
for the index version specified. Can be set to any valid version
(currently 2, 3, or 4).
+GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL=<boolean> if enabled will
+use the boundary-based bitmap traversal algorithm. See the documentation
+of `pack.useBitmapBoundaryTraversal` for more details.
+
GIT_TEST_PACK_SPARSE=<boolean> if disabled will default the pack-objects
builtin to use the non-sparse object walk. This can still be overridden by
the --sparse command-line argument.
@@ -449,10 +453,6 @@ the --sparse command-line argument.
GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path
by overriding the minimum number of cache entries required per thread.
-GIT_TEST_ADD_I_USE_BUILTIN=<boolean>, when false, disables the
-built-in version of git add -i. See 'add.interactive.useBuiltin' in
-git-config(1).
-
GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading
of the index for the whole test suite by bypassing the default number of
cache entries and thread minimums. Setting this to 1 will make the
@@ -479,7 +479,7 @@ GIT_TEST_DEFAULT_HASH=<hash-algo> specifies which hash algorithm to
use in the test scripts. Recognized values for <hash-algo> are "sha1"
and "sha256".
-GIT_TEST_WRITE_REV_INDEX=<boolean>, when true enables the
+GIT_TEST_NO_WRITE_REV_INDEX=<boolean>, when true disables the
'pack.writeReverseIndex' setting.
GIT_TEST_SPARSE_INDEX=<boolean>, when true enables index writes to use the
@@ -1102,6 +1102,12 @@ see test-lib-functions.sh for the full list and their options.
the symbolic link in the file system and a part that does; then only
the latter part need be protected by a SYMLINKS prerequisite (see below).
+ - test_path_is_executable
+
+ This tests whether a file is executable and prints an error message
+ if not. This must be used only under the POSIXPERM prerequisite
+ (see below).
+
- test_oid_init
This function loads facts and useful object IDs related to the hash
diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh
index 7f2b83bdc8..6e3bcc4aec 100755
--- a/t/aggregate-results.sh
+++ b/t/aggregate-results.sh
@@ -8,7 +8,7 @@ broken=0
total=0
missing_prereq=
-while read file
+for file in "$1"/t*-*.counts
do
while read type value
do
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index f1b9a6ce4d..5e21e84f38 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -72,6 +72,32 @@ test_expect_success 'blame 1 author' '
check_count A 2
'
+test_expect_success 'blame working copy' '
+ test_when_finished "git restore file" &&
+ echo "1A quick brown fox jumps over the" >file &&
+ echo "another lazy dog" >>file &&
+ check_count A 1 "Not Committed Yet" 1
+'
+
+test_expect_success 'blame with --contents' '
+ check_count --contents=file A 2
+'
+
+test_expect_success 'blame with --contents in a bare repo' '
+ git clone --bare . bare-contents.git &&
+ (
+ cd bare-contents.git &&
+ echo "1A quick brown fox jumps over the" >contents &&
+ check_count --contents=contents A 1
+ )
+'
+
+test_expect_success 'blame with --contents changed' '
+ echo "1A quick brown fox jumps over the" >contents &&
+ echo "another lazy dog" >>contents &&
+ check_count --contents=contents A 1 "External file (--contents)" 1
+'
+
test_expect_success 'blame in a bare repo without starting commit' '
git clone --bare . bare.git &&
(
@@ -98,6 +124,10 @@ test_expect_success 'blame 2 authors' '
check_count A 2 B 2
'
+test_expect_success 'blame with --contents and revision' '
+ check_count -h testTag --contents=file A 2 "External file (--contents)" 2
+'
+
test_expect_success 'setup B1 lines (branch1)' '
git checkout -b branch1 main &&
echo "3A slow green fox jumps into the" >>file &&
diff --git a/t/chainlint.pl b/t/chainlint.pl
index 976db4b8a0..556ee91a15 100755
--- a/t/chainlint.pl
+++ b/t/chainlint.pl
@@ -67,6 +67,7 @@ sub new {
bless {
parser => $parser,
buff => $s,
+ lineno => 1,
heretags => []
} => $class;
}
@@ -75,9 +76,12 @@ sub scan_heredoc_tag {
my $self = shift @_;
${$self->{buff}} =~ /\G(-?)/gc;
my $indented = $1;
- my $tag = $self->scan_token();
+ my $token = $self->scan_token();
+ return "<<$indented" unless $token;
+ my $tag = $token->[0];
$tag =~ s/['"\\]//g;
- push(@{$self->{heretags}}, $indented ? "\t$tag" : "$tag");
+ $$token[0] = $indented ? "\t$tag" : "$tag";
+ push(@{$self->{heretags}}, $token);
return "<<$indented$tag";
}
@@ -95,7 +99,9 @@ sub scan_op {
sub scan_sqstring {
my $self = shift @_;
${$self->{buff}} =~ /\G([^']*'|.*\z)/sgc;
- return "'" . $1;
+ my $s = $1;
+ $self->{lineno} += () = $s =~ /\n/sg;
+ return "'" . $s;
}
sub scan_dqstring {
@@ -113,7 +119,7 @@ sub scan_dqstring {
if ($c eq '\\') {
$s .= '\\', last unless $$b =~ /\G(.)/sgc;
$c = $1;
- next if $c eq "\n"; # line splice
+ $self->{lineno}++, next if $c eq "\n"; # line splice
# backslash escapes only $, `, ", \ in dq-string
$s .= '\\' unless $c =~ /^[\$`"\\]$/;
$s .= $c;
@@ -121,6 +127,7 @@ sub scan_dqstring {
}
die("internal error scanning dq-string '$c'\n");
}
+ $self->{lineno} += () = $s =~ /\n/sg;
return $s;
}
@@ -135,6 +142,7 @@ sub scan_balanced {
$depth--;
last if $depth == 0;
}
+ $self->{lineno} += () = $s =~ /\n/sg;
return $s;
}
@@ -149,7 +157,7 @@ sub scan_dollar {
my $self = shift @_;
my $b = $self->{buff};
return $self->scan_balanced('(', ')') if $$b =~ /\G\((?=\()/gc; # $((...))
- return '(' . join(' ', $self->scan_subst()) . ')' if $$b =~ /\G\(/gc; # $(...)
+ return '(' . join(' ', map {$_->[0]} $self->scan_subst()) . ')' if $$b =~ /\G\(/gc; # $(...)
return $self->scan_balanced('{', '}') if $$b =~ /\G\{/gc; # ${...}
return $1 if $$b =~ /\G(\w+)/gc; # $var
return $1 if $$b =~ /\G([@*#?$!0-9-])/gc; # $*, $1, $$, etc.
@@ -161,8 +169,19 @@ sub swallow_heredocs {
my $b = $self->{buff};
my $tags = $self->{heretags};
while (my $tag = shift @$tags) {
- my $indent = $tag =~ s/^\t// ? '\\s*' : '';
- $$b =~ /(?:\G|\n)$indent\Q$tag\E(?:\n|\z)/gc;
+ my $start = pos($$b);
+ my $indent = $$tag[0] =~ s/^\t// ? '\\s*' : '';
+ $$b =~ /(?:\G|\n)$indent\Q$$tag[0]\E(?:\n|\z)/gc;
+ if (pos($$b) > $start) {
+ my $body = substr($$b, $start, pos($$b) - $start);
+ $self->{lineno} += () = $body =~ /\n/sg;
+ next;
+ }
+ push(@{$self->{parser}->{problems}}, ['UNCLOSED-HEREDOC', $tag]);
+ $$b =~ /(?:\G|\n).*\z/gc; # consume rest of input
+ my $body = substr($$b, $start, pos($$b) - $start);
+ $self->{lineno} += () = $body =~ /\n/sg;
+ last;
}
}
@@ -170,34 +189,37 @@ sub scan_token {
my $self = shift @_;
my $b = $self->{buff};
my $token = '';
+ my ($start, $startln);
RESTART:
+ $startln = $self->{lineno};
$$b =~ /\G[ \t]+/gc; # skip whitespace (but not newline)
- return "\n" if $$b =~ /\G#[^\n]*(?:\n|\z)/gc; # comment
+ $start = pos($$b) || 0;
+ $self->{lineno}++, return ["\n", $start, pos($$b), $startln, $startln] if $$b =~ /\G#[^\n]*(?:\n|\z)/gc; # comment
while (1) {
# slurp up non-special characters
$token .= $1 if $$b =~ /\G([^\\;&|<>(){}'"\$\s]+)/gc;
# handle special characters
last unless $$b =~ /\G(.)/sgc;
my $c = $1;
- last if $c =~ /^[ \t]$/; # whitespace ends token
+ pos($$b)--, last if $c =~ /^[ \t]$/; # whitespace ends token
pos($$b)--, last if length($token) && $c =~ /^[;&|<>(){}\n]$/;
$token .= $self->scan_sqstring(), next if $c eq "'";
$token .= $self->scan_dqstring(), next if $c eq '"';
$token .= $c . $self->scan_dollar(), next if $c eq '$';
- $self->swallow_heredocs(), $token = $c, last if $c eq "\n";
+ $self->{lineno}++, $self->swallow_heredocs(), $token = $c, last if $c eq "\n";
$token = $self->scan_op($c), last if $c =~ /^[;&|<>]$/;
$token = $c, last if $c =~ /^[(){}]$/;
if ($c eq '\\') {
$token .= '\\', last unless $$b =~ /\G(.)/sgc;
$c = $1;
- next if $c eq "\n" && length($token); # line splice
- goto RESTART if $c eq "\n"; # line splice
+ $self->{lineno}++, next if $c eq "\n" && length($token); # line splice
+ $self->{lineno}++, goto RESTART if $c eq "\n"; # line splice
$token .= '\\' . $c;
next;
}
die("internal error scanning character '$c'\n");
}
- return length($token) ? $token : undef;
+ return length($token) ? [$token, $start, pos($$b), $startln, $self->{lineno}] : undef;
}
# ShellParser parses POSIX shell scripts (with minor extensions for Bash). It
@@ -239,14 +261,14 @@ sub stop_at {
my ($self, $token) = @_;
return 1 unless defined($token);
my $stop = ${$self->{stop}}[-1] if @{$self->{stop}};
- return defined($stop) && $token =~ $stop;
+ return defined($stop) && $token->[0] =~ $stop;
}
sub expect {
my ($self, $expect) = @_;
my $token = $self->next_token();
- return $token if defined($token) && $token eq $expect;
- push(@{$self->{output}}, "?!ERR?! expected '$expect' but found '" . (defined($token) ? $token : "<end-of-input>") . "'\n");
+ return $token if defined($token) && $token->[0] eq $expect;
+ push(@{$self->{output}}, "?!ERR?! expected '$expect' but found '" . (defined($token) ? $token->[0] : "<end-of-input>") . "'\n");
$self->untoken($token) if defined($token);
return ();
}
@@ -255,7 +277,7 @@ sub optional_newlines {
my $self = shift @_;
my @tokens;
while (my $token = $self->peek()) {
- last unless $token eq "\n";
+ last unless $token->[0] eq "\n";
push(@tokens, $self->next_token());
}
return @tokens;
@@ -278,7 +300,7 @@ sub parse_case_pattern {
my @tokens;
while (defined(my $token = $self->next_token())) {
push(@tokens, $token);
- last if $token eq ')';
+ last if $token->[0] eq ')';
}
return @tokens;
}
@@ -293,13 +315,13 @@ sub parse_case {
$self->optional_newlines());
while (1) {
my $token = $self->peek();
- last unless defined($token) && $token ne 'esac';
+ last unless defined($token) && $token->[0] ne 'esac';
push(@tokens,
$self->parse_case_pattern(),
$self->optional_newlines(),
$self->parse(qr/^(?:;;|esac)$/)); # item body
$token = $self->peek();
- last unless defined($token) && $token ne 'esac';
+ last unless defined($token) && $token->[0] ne 'esac';
push(@tokens,
$self->expect(';;'),
$self->optional_newlines());
@@ -315,7 +337,7 @@ sub parse_for {
$self->next_token(), # variable
$self->optional_newlines());
my $token = $self->peek();
- if (defined($token) && $token eq 'in') {
+ if (defined($token) && $token->[0] eq 'in') {
push(@tokens,
$self->expect('in'),
$self->optional_newlines());
@@ -339,11 +361,11 @@ sub parse_if {
$self->optional_newlines(),
$self->parse(qr/^(?:elif|else|fi)$/)); # if/elif body
my $token = $self->peek();
- last unless defined($token) && $token eq 'elif';
+ last unless defined($token) && $token->[0] eq 'elif';
push(@tokens, $self->expect('elif'));
}
my $token = $self->peek();
- if (defined($token) && $token eq 'else') {
+ if (defined($token) && $token->[0] eq 'else') {
push(@tokens,
$self->expect('else'),
$self->optional_newlines(),
@@ -380,7 +402,7 @@ sub parse_bash_array_assignment {
my @tokens = $self->expect('(');
while (defined(my $token = $self->next_token())) {
push(@tokens, $token);
- last if $token eq ')';
+ last if $token->[0] eq ')';
}
return @tokens;
}
@@ -398,29 +420,31 @@ sub parse_cmd {
my $self = shift @_;
my $cmd = $self->next_token();
return () unless defined($cmd);
- return $cmd if $cmd eq "\n";
+ return $cmd if $cmd->[0] eq "\n";
my $token;
my @tokens = $cmd;
- if ($cmd eq '!') {
+ if ($cmd->[0] eq '!') {
push(@tokens, $self->parse_cmd());
return @tokens;
- } elsif (my $f = $compound{$cmd}) {
+ } elsif (my $f = $compound{$cmd->[0]}) {
push(@tokens, $self->$f());
- } elsif (defined($token = $self->peek()) && $token eq '(') {
- if ($cmd !~ /\w=$/) {
+ } elsif (defined($token = $self->peek()) && $token->[0] eq '(') {
+ if ($cmd->[0] !~ /\w=$/) {
push(@tokens, $self->parse_func());
return @tokens;
}
- $tokens[-1] .= join(' ', $self->parse_bash_array_assignment());
+ my @array = $self->parse_bash_array_assignment();
+ $tokens[-1]->[0] .= join(' ', map {$_->[0]} @array);
+ $tokens[-1]->[2] = $array[$#array][2] if @array;
}
while (defined(my $token = $self->next_token())) {
$self->untoken($token), last if $self->stop_at($token);
push(@tokens, $token);
- last if $token =~ /^(?:[;&\n|]|&&|\|\|)$/;
+ last if $token->[0] =~ /^(?:[;&\n|]|&&|\|\|)$/;
}
- push(@tokens, $self->next_token()) if $tokens[-1] ne "\n" && defined($token = $self->peek()) && $token eq "\n";
+ push(@tokens, $self->next_token()) if $tokens[-1]->[0] ne "\n" && defined($token = $self->peek()) && $token->[0] eq "\n";
return @tokens;
}
@@ -453,11 +477,18 @@ package TestParser;
use base 'ShellParser';
+sub new {
+ my $class = shift @_;
+ my $self = $class->SUPER::new(@_);
+ $self->{problems} = [];
+ return $self;
+}
+
sub find_non_nl {
my $tokens = shift @_;
my $n = shift @_;
$n = $#$tokens if !defined($n);
- $n-- while $n >= 0 && $$tokens[$n] eq "\n";
+ $n-- while $n >= 0 && $$tokens[$n]->[0] eq "\n";
return $n;
}
@@ -467,7 +498,7 @@ sub ends_with {
for my $needle (reverse(@$needles)) {
return undef if $n < 0;
$n = find_non_nl($tokens, $n), next if $needle eq "\n";
- return undef if $$tokens[$n] !~ $needle;
+ return undef if $$tokens[$n]->[0] !~ $needle;
$n--;
}
return 1;
@@ -486,13 +517,13 @@ sub parse_loop_body {
my $self = shift @_;
my @tokens = $self->SUPER::parse_loop_body(@_);
# did loop signal failure via "|| return" or "|| exit"?
- return @tokens if !@tokens || grep(/^(?:return|exit|\$\?)$/, @tokens);
+ return @tokens if !@tokens || grep {$_->[0] =~ /^(?:return|exit|\$\?)$/} @tokens;
# did loop upstream of a pipe signal failure via "|| echo 'impossible
# text'" as the final command in the loop body?
return @tokens if ends_with(\@tokens, [qr/^\|\|$/, "\n", qr/^echo$/, qr/^.+$/]);
# flag missing "return/exit" handling explicit failure in loop body
my $n = find_non_nl(\@tokens);
- splice(@tokens, $n + 1, 0, '?!LOOP?!');
+ push(@{$self->{problems}}, ['LOOP', $tokens[$n]]);
return @tokens;
}
@@ -505,8 +536,13 @@ my @safe_endings = (
sub accumulate {
my ($self, $tokens, $cmd) = @_;
+ my $problems = $self->{problems};
+
+ # no previous command to check for missing "&&"
goto DONE unless @$tokens;
- goto DONE if @$cmd == 1 && $$cmd[0] eq "\n";
+
+ # new command is empty line; can't yet check if previous is missing "&&"
+ goto DONE if @$cmd == 1 && $$cmd[0]->[0] eq "\n";
# did previous command end with "&&", "|", "|| return" or similar?
goto DONE if match_ending($tokens, \@safe_endings);
@@ -514,20 +550,20 @@ sub accumulate {
# if this command handles "$?" specially, then okay for previous
# command to be missing "&&"
for my $token (@$cmd) {
- goto DONE if $token =~ /\$\?/;
+ goto DONE if $token->[0] =~ /\$\?/;
}
# if this command is "false", "return 1", or "exit 1" (which signal
# failure explicitly), then okay for all preceding commands to be
# missing "&&"
- if ($$cmd[0] =~ /^(?:false|return|exit)$/) {
- @$tokens = grep(!/^\?!AMP\?!$/, @$tokens);
+ if ($$cmd[0]->[0] =~ /^(?:false|return|exit)$/) {
+ @$problems = grep {$_->[0] ne 'AMP'} @$problems;
goto DONE;
}
# flag missing "&&" at end of previous command
my $n = find_non_nl($tokens);
- splice(@$tokens, $n + 1, 0, '?!AMP?!') unless $n < 0;
+ push(@$problems, ['AMP', $tokens->[$n]]) unless $n < 0;
DONE:
$self->SUPER::accumulate($tokens, $cmd);
@@ -553,7 +589,7 @@ sub new {
# composition of multiple strings and non-string character runs; for instance,
# `"test body"` unwraps to `test body`; `word"a b"42'c d'` to `worda b42c d`
sub unwrap {
- my $token = @_ ? shift @_ : $_;
+ my $token = (@_ ? shift @_ : $_)->[0];
# simple case: 'sqstring' or "dqstring"
return $token if $token =~ s/^'([^']*)'$/$1/;
return $token if $token =~ s/^"([^"]*)"$/$1/;
@@ -584,13 +620,25 @@ sub check_test {
$self->{ntests}++;
my $parser = TestParser->new(\$body);
my @tokens = $parser->parse();
- return unless $emit_all || grep(/\?![^?]+\?!/, @tokens);
+ my $problems = $parser->{problems};
+ return unless $emit_all || @$problems;
my $c = main::fd_colors(1);
- my $checked = join(' ', @tokens);
- $checked =~ s/^\n//;
- $checked =~ s/^ //mg;
- $checked =~ s/ $//mg;
+ my $lineno = $_[1]->[3];
+ my $start = 0;
+ my $checked = '';
+ for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) {
+ my ($label, $token) = @$_;
+ my $pos = $token->[2];
+ $checked .= substr($body, $start, $pos - $start) . " ?!$label?! ";
+ $start = $pos;
+ }
+ $checked .= substr($body, $start);
+ $checked =~ s/^/$lineno++ . ' '/mge;
+ $checked =~ s/^\d+ \n//;
+ $checked =~ s/(\s) \?!/$1?!/mg;
+ $checked =~ s/\?! (\s)/?!$1/mg;
$checked =~ s/(\?![^?]+\?!)/$c->{rev}$c->{red}$1$c->{reset}/mg;
+ $checked =~ s/^\d+/$c->{dim}$&$c->{reset}/mg;
$checked .= "\n" unless $checked =~ /\n$/;
push(@{$self->{output}}, "$c->{blue}# chainlint: $title$c->{reset}\n$checked");
}
@@ -598,9 +646,9 @@ sub check_test {
sub parse_cmd {
my $self = shift @_;
my @tokens = $self->SUPER::parse_cmd();
- return @tokens unless @tokens && $tokens[0] =~ /^test_expect_(?:success|failure)$/;
+ return @tokens unless @tokens && $tokens[0]->[0] =~ /^test_expect_(?:success|failure)$/;
my $n = $#tokens;
- $n-- while $n >= 0 && $tokens[$n] =~ /^(?:[;&\n|]|&&|\|\|)$/;
+ $n-- while $n >= 0 && $tokens[$n]->[0] =~ /^(?:[;&\n|]|&&|\|\|)$/;
$self->check_test($tokens[1], $tokens[2]) if $n == 2; # title body
$self->check_test($tokens[2], $tokens[3]) if $n > 2; # prereq title body
return @tokens;
@@ -622,25 +670,39 @@ if (eval {require Time::HiRes; Time::HiRes->import(); 1;}) {
# thread and ignore %ENV changes in subthreads.
$ENV{TERM} = $ENV{USER_TERM} if $ENV{USER_TERM};
-my @NOCOLORS = (bold => '', rev => '', reset => '', blue => '', green => '', red => '');
+my @NOCOLORS = (bold => '', rev => '', dim => '', reset => '', blue => '', green => '', red => '');
my %COLORS = ();
sub get_colors {
return \%COLORS if %COLORS;
- if (exists($ENV{NO_COLOR}) ||
- system("tput sgr0 >/dev/null 2>&1") != 0 ||
- system("tput bold >/dev/null 2>&1") != 0 ||
- system("tput rev >/dev/null 2>&1") != 0 ||
- system("tput setaf 1 >/dev/null 2>&1") != 0) {
+ if (exists($ENV{NO_COLOR})) {
%COLORS = @NOCOLORS;
return \%COLORS;
}
- %COLORS = (bold => `tput bold`,
- rev => `tput rev`,
- reset => `tput sgr0`,
- blue => `tput setaf 4`,
- green => `tput setaf 2`,
- red => `tput setaf 1`);
- chomp(%COLORS);
+ if ($ENV{TERM} =~ /xterm|xterm-\d+color|xterm-new|xterm-direct|nsterm|nsterm-\d+color|nsterm-direct/) {
+ %COLORS = (bold => "\e[1m",
+ rev => "\e[7m",
+ dim => "\e[2m",
+ reset => "\e[0m",
+ blue => "\e[34m",
+ green => "\e[32m",
+ red => "\e[31m");
+ return \%COLORS;
+ }
+ if (system("tput sgr0 >/dev/null 2>&1") == 0 &&
+ system("tput bold >/dev/null 2>&1") == 0 &&
+ system("tput rev >/dev/null 2>&1") == 0 &&
+ system("tput dim >/dev/null 2>&1") == 0 &&
+ system("tput setaf 1 >/dev/null 2>&1") == 0) {
+ %COLORS = (bold => `tput bold`,
+ rev => `tput rev`,
+ dim => `tput dim`,
+ reset => `tput sgr0`,
+ blue => `tput setaf 4`,
+ green => `tput setaf 2`,
+ red => `tput setaf 1`);
+ return \%COLORS;
+ }
+ %COLORS = @NOCOLORS;
return \%COLORS;
}
@@ -656,7 +718,7 @@ sub ncores {
# Windows
return $ENV{NUMBER_OF_PROCESSORS} if exists($ENV{NUMBER_OF_PROCESSORS});
# Linux / MSYS2 / Cygwin / WSL
- do { local @ARGV='/proc/cpuinfo'; return scalar(grep(/^processor\s*:/, <>)); } if -r '/proc/cpuinfo';
+ do { local @ARGV='/proc/cpuinfo'; return scalar(grep(/^processor[\s\d]*:/, <>)); } if -r '/proc/cpuinfo';
# macOS & BSD
return qx/sysctl -n hw.ncpu/ if $^O =~ /(?:^darwin$|bsd)/;
return 1;
diff --git a/t/chainlint/block-comment.expect b/t/chainlint/block-comment.expect
index d10b2eeaf2..df2beea888 100644
--- a/t/chainlint/block-comment.expect
+++ b/t/chainlint/block-comment.expect
@@ -1,6 +1,8 @@
(
{
+ # show a
echo a &&
+ # show b
echo b
}
)
diff --git a/t/chainlint/case-comment.expect b/t/chainlint/case-comment.expect
index 1e4b054bda..641c157b98 100644
--- a/t/chainlint/case-comment.expect
+++ b/t/chainlint/case-comment.expect
@@ -1,7 +1,10 @@
(
case "$x" in
+ # found foo
x) foo ;;
+ # found other
*)
+ # treat it as bar
bar
;;
esac
diff --git a/t/chainlint/close-subshell.expect b/t/chainlint/close-subshell.expect
index 0f87db9ae6..2192a2870a 100644
--- a/t/chainlint/close-subshell.expect
+++ b/t/chainlint/close-subshell.expect
@@ -15,7 +15,8 @@
) | wuzzle &&
(
bop
-) | fazz fozz &&
+) | fazz \
+ fozz &&
(
bup
) |
diff --git a/t/chainlint/comment.expect b/t/chainlint/comment.expect
index f76fde1ffb..a68f1f9d7c 100644
--- a/t/chainlint/comment.expect
+++ b/t/chainlint/comment.expect
@@ -1,4 +1,8 @@
(
+ # comment 1
nothing &&
+ # comment 2
something
+ # comment 3
+ # comment 4
)
diff --git a/t/chainlint/double-here-doc.expect b/t/chainlint/double-here-doc.expect
index 75477bb1ad..cd584a4357 100644
--- a/t/chainlint/double-here-doc.expect
+++ b/t/chainlint/double-here-doc.expect
@@ -1,2 +1,12 @@
-run_sub_test_lib_test_err run-inv-range-start "--run invalid range start" --run="a-5" <<-EOF &&
-check_sub_test_lib_test_err run-inv-range-start <<-EOF_OUT 3 <<-EOF_ERR
+run_sub_test_lib_test_err run-inv-range-start \
+ "--run invalid range start" \
+ --run="a-5" <<-\EOF &&
+test_expect_success "passing test #1" "true"
+test_done
+EOF
+check_sub_test_lib_test_err run-inv-range-start \
+ <<-\EOF_OUT 3<<-EOF_ERR
+> FATAL: Unexpected exit with code 1
+EOF_OUT
+> error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ}
+EOF_ERR
diff --git a/t/chainlint/empty-here-doc.expect b/t/chainlint/empty-here-doc.expect
index f42f2d41ba..e8733c97c6 100644
--- a/t/chainlint/empty-here-doc.expect
+++ b/t/chainlint/empty-here-doc.expect
@@ -1,3 +1,4 @@
git ls-tree $tree path > current &&
-cat > expected <<EOF &&
+cat > expected <<\EOF &&
+EOF
test_output
diff --git a/t/chainlint/for-loop.expect b/t/chainlint/for-loop.expect
index a5810c9bdd..d65c82129a 100644
--- a/t/chainlint/for-loop.expect
+++ b/t/chainlint/for-loop.expect
@@ -2,7 +2,9 @@
for i in a b c
do
echo $i ?!AMP?!
- cat <<-EOF ?!LOOP?!
+ cat <<-\EOF ?!LOOP?!
+ bar
+ EOF
done ?!AMP?!
for i in a b c; do
echo $i &&
diff --git a/t/chainlint/here-doc-close-subshell.expect b/t/chainlint/here-doc-close-subshell.expect
index 2af9ced71c..7d9c2b5607 100644
--- a/t/chainlint/here-doc-close-subshell.expect
+++ b/t/chainlint/here-doc-close-subshell.expect
@@ -1,2 +1,4 @@
(
- cat <<-INPUT)
+ cat <<-\INPUT)
+ fizz
+ INPUT
diff --git a/t/chainlint/here-doc-indent-operator.expect b/t/chainlint/here-doc-indent-operator.expect
index fb6cf7285d..f92a7ce999 100644
--- a/t/chainlint/here-doc-indent-operator.expect
+++ b/t/chainlint/here-doc-indent-operator.expect
@@ -1,5 +1,11 @@
-cat > expect <<-EOF &&
+cat >expect <<- EOF &&
+header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
+num_commits: $1
+chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data
+EOF
-cat > expect <<-EOF ?!AMP?!
+cat >expect << -EOF ?!AMP?!
+this is not indented
+-EOF
cleanup
diff --git a/t/chainlint/here-doc-multi-line-command-subst.expect b/t/chainlint/here-doc-multi-line-command-subst.expect
index f8b3aa73c4..b7364c82c8 100644
--- a/t/chainlint/here-doc-multi-line-command-subst.expect
+++ b/t/chainlint/here-doc-multi-line-command-subst.expect
@@ -1,5 +1,8 @@
(
- x=$(bobble <<-END &&
+ x=$(bobble <<-\END &&
+ fossil
+ vegetable
+ END
wiffle) ?!AMP?!
echo $x
)
diff --git a/t/chainlint/here-doc-multi-line-string.expect b/t/chainlint/here-doc-multi-line-string.expect
index be64b26869..6c13bdcbfb 100644
--- a/t/chainlint/here-doc-multi-line-string.expect
+++ b/t/chainlint/here-doc-multi-line-string.expect
@@ -1,5 +1,7 @@
(
- cat <<-TXT && echo "multi-line
+ cat <<-\TXT && echo "multi-line
string" ?!AMP?!
+ fizzle
+ TXT
bap
)
diff --git a/t/chainlint/here-doc.expect b/t/chainlint/here-doc.expect
index 110059ba58..1df3f78282 100644
--- a/t/chainlint/here-doc.expect
+++ b/t/chainlint/here-doc.expect
@@ -1,7 +1,25 @@
-boodle wobba gorgo snoot wafta snurb <<EOF &&
+boodle wobba \
+ gorgo snoot \
+ wafta snurb <<EOF &&
+quoth the raven,
+nevermore...
+EOF
cat <<-Arbitrary_Tag_42 >foo &&
+snoz
+boz
+woz
+Arbitrary_Tag_42
-cat <<zump >boo &&
+cat <<"zump" >boo &&
+snoz
+boz
+woz
+zump
-horticulture <<EOF
+horticulture <<\EOF
+gomez
+morticia
+wednesday
+pugsly
+EOF
diff --git a/t/chainlint/if-then-else.expect b/t/chainlint/if-then-else.expect
index 44d86c3597..cbaaf857d4 100644
--- a/t/chainlint/if-then-else.expect
+++ b/t/chainlint/if-then-else.expect
@@ -8,7 +8,9 @@
echo foo
else
echo foo &&
- cat <<-EOF
+ cat <<-\EOF
+ bar
+ EOF
fi ?!AMP?!
echo poodle
) &&
diff --git a/t/chainlint/incomplete-line.expect b/t/chainlint/incomplete-line.expect
index ffac8f9018..134d3a14f5 100644
--- a/t/chainlint/incomplete-line.expect
+++ b/t/chainlint/incomplete-line.expect
@@ -1,4 +1,10 @@
-line 1 line 2 line 3 line 4 &&
+line 1 \
+line 2 \
+line 3 \
+line 4 &&
(
- line 5 line 6 line 7 line 8
+ line 5 \
+ line 6 \
+ line 7 \
+ line 8
)
diff --git a/t/chainlint/inline-comment.expect b/t/chainlint/inline-comment.expect
index dd0dace077..6bad218530 100644
--- a/t/chainlint/inline-comment.expect
+++ b/t/chainlint/inline-comment.expect
@@ -1,6 +1,6 @@
(
- foobar &&
- barfoo ?!AMP?!
+ foobar && # comment 1
+ barfoo ?!AMP?! # wrong position for &&
flibble "not a # comment"
) &&
diff --git a/t/chainlint/loop-detect-status.expect b/t/chainlint/loop-detect-status.expect
index 0ad23bb35e..24da9e86d5 100644
--- a/t/chainlint/loop-detect-status.expect
+++ b/t/chainlint/loop-detect-status.expect
@@ -2,7 +2,7 @@
do
printf "Generating blob $i/$blobcount\r" >& 2 &&
printf "blob\nmark :$i\ndata $blobsize\n" &&
-
+ #test-tool genrandom $i $blobsize &&
printf "%-${blobsize}s" $i &&
echo "M 100644 :$i $i" >> commit &&
i=$(($i+1)) ||
diff --git a/t/chainlint/nested-here-doc.expect b/t/chainlint/nested-here-doc.expect
index e3bef63f75..29b3832a98 100644
--- a/t/chainlint/nested-here-doc.expect
+++ b/t/chainlint/nested-here-doc.expect
@@ -1,7 +1,30 @@
cat <<ARBITRARY >foop &&
+naddle
+fub <<EOF
+ nozzle
+ noodle
+EOF
+formp
+ARBITRARY
(
- cat <<-INPUT_END &&
- cat <<-EOT ?!AMP?!
+ cat <<-\INPUT_END &&
+ fish are mice
+ but geese go slow
+ data <<EOF
+ perl is lerp
+ and nothing else
+ EOF
+ toink
+ INPUT_END
+
+ cat <<-\EOT ?!AMP?!
+ text goes here
+ data <<EOF
+ data goes here
+ EOF
+ more test here
+ EOT
+
foobar
)
diff --git a/t/chainlint/nested-subshell-comment.expect b/t/chainlint/nested-subshell-comment.expect
index be4b27a305..9138cf386d 100644
--- a/t/chainlint/nested-subshell-comment.expect
+++ b/t/chainlint/nested-subshell-comment.expect
@@ -2,6 +2,8 @@
foo &&
(
bar &&
+ # bottles wobble while fiddles gobble
+ # minor numbers of cows (or do they?)
baz &&
snaff
) ?!AMP?!
diff --git a/t/chainlint/subshell-here-doc.expect b/t/chainlint/subshell-here-doc.expect
index 029d129299..52789278d1 100644
--- a/t/chainlint/subshell-here-doc.expect
+++ b/t/chainlint/subshell-here-doc.expect
@@ -1,10 +1,30 @@
(
- echo wobba gorgo snoot wafta snurb <<-EOF &&
+ echo wobba \
+ gorgo snoot \
+ wafta snurb <<-EOF &&
+ quoth the raven,
+ nevermore...
+ EOF
+
cat <<EOF >bip ?!AMP?!
- echo <<-EOF >bop
+ fish fly high
+EOF
+
+ echo <<-\EOF >bop
+ gomez
+ morticia
+ wednesday
+ pugsly
+ EOF
) &&
(
- cat <<-ARBITRARY >bup &&
- cat <<-ARBITRARY3 >bup3 &&
+ cat <<-\ARBITRARY >bup &&
+ glink
+ FIZZ
+ ARBITRARY
+ cat <<-"ARBITRARY3" >bup3 &&
+ glink
+ FIZZ
+ ARBITRARY3
meep
)
diff --git a/t/chainlint/t7900-subtree.expect b/t/chainlint/t7900-subtree.expect
index 69167da2f2..71b3b3bc20 100644
--- a/t/chainlint/t7900-subtree.expect
+++ b/t/chainlint/t7900-subtree.expect
@@ -4,12 +4,16 @@ sub2
sub3
sub4" &&
chks_sub=$(cat <<TXT | sed "s,^,sub dir/,"
+$chks
+TXT
) &&
chkms="main-sub1
main-sub2
main-sub3
main-sub4" &&
chkms_sub=$(cat <<TXT | sed "s,^,sub dir/,"
+$chkms
+TXT
) &&
subfiles=$(git ls-files) &&
check_equal "$subfiles" "$chkms
diff --git a/t/chainlint/unclosed-here-doc-indent.expect b/t/chainlint/unclosed-here-doc-indent.expect
new file mode 100644
index 0000000000..7c30a1a024
--- /dev/null
+++ b/t/chainlint/unclosed-here-doc-indent.expect
@@ -0,0 +1,4 @@
+command_which_is_run &&
+cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! &&
+we forget to end the here-doc
+command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc-indent.test b/t/chainlint/unclosed-here-doc-indent.test
new file mode 100644
index 0000000000..5c841a9dfd
--- /dev/null
+++ b/t/chainlint/unclosed-here-doc-indent.test
@@ -0,0 +1,4 @@
+command_which_is_run &&
+cat >expect <<-\EOF &&
+we forget to end the here-doc
+command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc.expect b/t/chainlint/unclosed-here-doc.expect
new file mode 100644
index 0000000000..d65e50f78d
--- /dev/null
+++ b/t/chainlint/unclosed-here-doc.expect
@@ -0,0 +1,7 @@
+command_which_is_run &&
+cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! &&
+ we try to end the here-doc below,
+ but the indentation throws us off
+ since the operator is not "<<-".
+ EOF
+command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc.test b/t/chainlint/unclosed-here-doc.test
new file mode 100644
index 0000000000..69d3786c34
--- /dev/null
+++ b/t/chainlint/unclosed-here-doc.test
@@ -0,0 +1,7 @@
+command_which_is_run &&
+cat >expect <<\EOF &&
+ we try to end the here-doc below,
+ but the indentation throws us off
+ since the operator is not "<<-".
+ EOF
+command_which_is_gobbled
diff --git a/t/chainlint/while-loop.expect b/t/chainlint/while-loop.expect
index f272aa21fe..1f5eaea0fd 100644
--- a/t/chainlint/while-loop.expect
+++ b/t/chainlint/while-loop.expect
@@ -2,7 +2,9 @@
while true
do
echo foo ?!AMP?!
- cat <<-EOF ?!LOOP?!
+ cat <<-\EOF ?!LOOP?!
+ bar
+ EOF
done ?!AMP?!
while true; do
echo foo &&
diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl
index fd3303552b..dd8107cd7d 100755
--- a/t/check-non-portable-shell.pl
+++ b/t/check-non-portable-shell.pl
@@ -45,6 +45,7 @@ while (<>) {
/\bhead\s+-c\b/ and err 'head -c is not portable (use test_copy_bytes BYTES <file >out)';
/(?:\$\(seq|^\s*seq\b)/ and err 'seq is not portable (use test_seq)';
/\bgrep\b.*--file\b/ and err 'grep --file FILE is not portable (use grep -f FILE)';
+ /\b[ef]grep\b/ and err 'egrep/fgrep obsolescent (use grep -E/-F)';
/\bexport\s+[A-Za-z0-9_]*=/ and err '"export FOO=bar" is not portable (use FOO=bar && export FOO)';
/^\s*([A-Z0-9_]+=(\w*|(["']).*?\3)\s+)+(\w+)/ and exists($func{$4}) and
err '"FOO=bar shell_func" assignment extends beyond "shell_func"';
diff --git a/t/helper/test-advise.c b/t/helper/test-advise.c
index cb881139f7..8a3fd0009a 100644
--- a/t/helper/test-advise.c
+++ b/t/helper/test-advise.c
@@ -1,7 +1,7 @@
#include "test-tool.h"
-#include "cache.h"
#include "advice.h"
#include "config.h"
+#include "setup.h"
int cmd__advise_if_enabled(int argc, const char **argv)
{
diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c
index ff35f5999b..af43ee1cb5 100644
--- a/t/helper/test-bitmap.c
+++ b/t/helper/test-bitmap.c
@@ -1,6 +1,7 @@
#include "test-tool.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "pack-bitmap.h"
+#include "setup.h"
static int bitmap_list_commits(void)
{
diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c
index 6c900ca668..aabe31d724 100644
--- a/t/helper/test-bloom.c
+++ b/t/helper/test-bloom.c
@@ -1,7 +1,9 @@
-#include "git-compat-util.h"
-#include "bloom.h"
#include "test-tool.h"
+#include "bloom.h"
+#include "hex.h"
#include "commit.h"
+#include "repository.h"
+#include "setup.h"
static struct bloom_filter_settings settings = DEFAULT_BLOOM_FILTER_SETTINGS;
diff --git a/t/helper/test-bundle-uri.c b/t/helper/test-bundle-uri.c
new file mode 100644
index 0000000000..475058592d
--- /dev/null
+++ b/t/helper/test-bundle-uri.c
@@ -0,0 +1,137 @@
+#include "test-tool.h"
+#include "parse-options.h"
+#include "bundle-uri.h"
+#include "gettext.h"
+#include "strbuf.h"
+#include "string-list.h"
+#include "transport.h"
+#include "ref-filter.h"
+#include "remote.h"
+#include "refs.h"
+
+enum input_mode {
+ KEY_VALUE_PAIRS,
+ CONFIG_FILE,
+};
+
+static int cmd__bundle_uri_parse(int argc, const char **argv, enum input_mode mode)
+{
+ const char *key_value_usage[] = {
+ "test-tool bundle-uri parse-key-values <input>",
+ NULL
+ };
+ const char *config_usage[] = {
+ "test-tool bundle-uri parse-config <input>",
+ NULL
+ };
+ const char **usage = key_value_usage;
+ struct option options[] = {
+ OPT_END(),
+ };
+ struct strbuf sb = STRBUF_INIT;
+ struct bundle_list list;
+ int err = 0;
+ FILE *fp;
+
+ if (mode == CONFIG_FILE)
+ usage = config_usage;
+
+ argc = parse_options(argc, argv, NULL, options, usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+
+ init_bundle_list(&list);
+
+ list.baseURI = xstrdup("<uri>");
+
+ switch (mode) {
+ case KEY_VALUE_PAIRS:
+ if (argc != 1)
+ goto usage;
+ fp = fopen(argv[0], "r");
+ if (!fp)
+ die("failed to open '%s'", argv[0]);
+ while (strbuf_getline(&sb, fp) != EOF) {
+ if (bundle_uri_parse_line(&list, sb.buf))
+ err = error("bad line: '%s'", sb.buf);
+ }
+ fclose(fp);
+ break;
+
+ case CONFIG_FILE:
+ if (argc != 1)
+ goto usage;
+ err = bundle_uri_parse_config_format("<uri>", argv[0], &list);
+ break;
+ }
+ strbuf_release(&sb);
+
+ print_bundle_list(stdout, &list);
+
+ clear_bundle_list(&list);
+
+ return !!err;
+
+usage:
+ usage_with_options(usage, options);
+}
+
+static int cmd_ls_remote(int argc, const char **argv)
+{
+ const char *dest;
+ struct remote *remote;
+ struct transport *transport;
+ int status = 0;
+
+ dest = argc > 1 ? argv[1] : NULL;
+
+ remote = remote_get(dest);
+ if (!remote) {
+ if (dest)
+ die(_("bad repository '%s'"), dest);
+ die(_("no remote configured to get bundle URIs from"));
+ }
+ if (!remote->url_nr)
+ die(_("remote '%s' has no configured URL"), dest);
+
+ transport = transport_get(remote, NULL);
+ if (transport_get_remote_bundle_uri(transport) < 0) {
+ error(_("could not get the bundle-uri list"));
+ status = 1;
+ goto cleanup;
+ }
+
+ print_bundle_list(stdout, transport->bundles);
+
+cleanup:
+ if (transport_disconnect(transport))
+ return 1;
+ return status;
+}
+
+int cmd__bundle_uri(int argc, const char **argv)
+{
+ const char *usage[] = {
+ "test-tool bundle-uri <subcommand> [<options>]",
+ NULL
+ };
+ struct option options[] = {
+ OPT_END(),
+ };
+
+ argc = parse_options(argc, argv, NULL, options, usage,
+ PARSE_OPT_STOP_AT_NON_OPTION |
+ PARSE_OPT_KEEP_ARGV0);
+ if (argc == 1)
+ goto usage;
+
+ if (!strcmp(argv[1], "parse-key-values"))
+ return cmd__bundle_uri_parse(argc - 1, argv + 1, KEY_VALUE_PAIRS);
+ if (!strcmp(argv[1], "parse-config"))
+ return cmd__bundle_uri_parse(argc - 1, argv + 1, CONFIG_FILE);
+ if (!strcmp(argv[1], "ls-remote"))
+ return cmd_ls_remote(argc - 1, argv + 1);
+ error("there is no test-tool bundle-uri tool '%s'", argv[1]);
+
+usage:
+ usage_with_options(usage, options);
+}
diff --git a/t/helper/test-cache-tree.c b/t/helper/test-cache-tree.c
new file mode 100644
index 0000000000..e7236392c8
--- /dev/null
+++ b/t/helper/test-cache-tree.c
@@ -0,0 +1,69 @@
+#define USE_THE_INDEX_VARIABLE
+#include "test-tool.h"
+#include "gettext.h"
+#include "hex.h"
+#include "tree.h"
+#include "cache-tree.h"
+#include "parse-options.h"
+#include "read-cache-ll.h"
+#include "repository.h"
+#include "setup.h"
+
+static char const * const test_cache_tree_usage[] = {
+ N_("test-tool cache-tree <options> (control|prime|update)"),
+ NULL
+};
+
+int cmd__cache_tree(int argc, const char **argv)
+{
+ struct object_id oid;
+ struct tree *tree;
+ int empty = 0;
+ int invalidate_qty = 0;
+ int i;
+
+ struct option options[] = {
+ OPT_BOOL(0, "empty", &empty,
+ N_("clear the cache tree before each iteration")),
+ OPT_INTEGER_F(0, "invalidate", &invalidate_qty,
+ N_("number of entries in the cache tree to invalidate (default 0)"),
+ PARSE_OPT_NONEG),
+ OPT_END()
+ };
+
+ setup_git_directory();
+
+ argc = parse_options(argc, argv, NULL, options, test_cache_tree_usage, 0);
+
+ if (repo_read_index(the_repository) < 0)
+ die(_("unable to read index file"));
+
+ oidcpy(&oid, &the_index.cache_tree->oid);
+ tree = parse_tree_indirect(&oid);
+ if (!tree)
+ die(_("not a tree object: %s"), oid_to_hex(&oid));
+
+ if (empty) {
+ /* clear the cache tree & allocate a new one */
+ cache_tree_free(&the_index.cache_tree);
+ the_index.cache_tree = cache_tree();
+ } else if (invalidate_qty) {
+ /* invalidate the specified number of unique paths */
+ float f_interval = (float)the_index.cache_nr / invalidate_qty;
+ int interval = f_interval < 1.0 ? 1 : (int)f_interval;
+ for (i = 0; i < invalidate_qty && i * interval < the_index.cache_nr; i++)
+ cache_tree_invalidate_path(&the_index, the_index.cache[i * interval]->name);
+ }
+
+ if (argc != 1)
+ usage_with_options(test_cache_tree_usage, options);
+ else if (!strcmp(argv[0], "prime"))
+ prime_cache_tree(the_repository, &the_index, tree);
+ else if (!strcmp(argv[0], "update"))
+ cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
+ /* use "control" subcommand to specify no-op */
+ else if (!!strcmp(argv[0], "control"))
+ die(_("Unhandled subcommand '%s'"), argv[0]);
+
+ return 0;
+}
diff --git a/t/helper/test-chmtime.c b/t/helper/test-chmtime.c
index dc28890a18..0e5538833a 100644
--- a/t/helper/test-chmtime.c
+++ b/t/helper/test-chmtime.c
@@ -94,7 +94,7 @@ int cmd__chmtime(int argc, const char **argv)
if (timespec_arg(argv[i], &set_time, &set_eq)) {
++i;
} else {
- if (get == 0) {
+ if (get == 0 && verbose == 0) {
fprintf(stderr, "Not a base-10 integer: %s\n", argv[i] + 1);
goto usage;
}
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 4ba9eb6560..ed444ca4c2 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -1,6 +1,6 @@
#include "test-tool.h"
-#include "cache.h"
#include "config.h"
+#include "setup.h"
#include "string-list.h"
/*
@@ -14,6 +14,8 @@
* get_value_multi -> prints all values for the entered key in increasing order
* of priority
*
+ * get -> print return value for the entered key
+ *
* get_int -> print integer value for the entered key or die
*
* get_bool -> print bool value for the entered key or die
@@ -30,6 +32,9 @@
* iterate -> iterate over all values using git_config(), and print some
* data for each
*
+ * git_config_int -> iterate over all values using git_config() and print the
+ * integer value for the entered key or die
+ *
* Examples:
*
* To print the value with highest priority for key "foo.bAr Baz.rock":
@@ -37,8 +42,11 @@
*
*/
-static int iterate_cb(const char *var, const char *value, void *data UNUSED)
+static int iterate_cb(const char *var, const char *value,
+ const struct config_context *ctx,
+ void *data UNUSED)
{
+ const struct key_value_info *kvi = ctx->kvi;
static int nr;
if (nr++)
@@ -46,15 +54,29 @@ static int iterate_cb(const char *var, const char *value, void *data UNUSED)
printf("key=%s\n", var);
printf("value=%s\n", value ? value : "(null)");
- printf("origin=%s\n", current_config_origin_type());
- printf("name=%s\n", current_config_name());
- printf("lno=%d\n", current_config_line());
- printf("scope=%s\n", config_scope_name(current_config_scope()));
+ printf("origin=%s\n", config_origin_type_name(kvi->origin_type));
+ printf("name=%s\n", kvi->filename ? kvi->filename : "");
+ printf("lno=%d\n", kvi->linenr);
+ printf("scope=%s\n", config_scope_name(kvi->scope));
return 0;
}
-static int early_config_cb(const char *var, const char *value, void *vdata)
+static int parse_int_cb(const char *var, const char *value,
+ const struct config_context *ctx, void *data)
+{
+ const char *key_to_match = data;
+
+ if (!strcmp(key_to_match, var)) {
+ int parsed = git_config_int(value, value, ctx->kvi);
+ printf("%d\n", parsed);
+ }
+ return 0;
+}
+
+static int early_config_cb(const char *var, const char *value,
+ const struct config_context *ctx UNUSED,
+ void *vdata)
{
const char *key = vdata;
@@ -95,8 +117,7 @@ int cmd__config(int argc, const char **argv)
goto exit1;
}
} else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
- strptr = git_config_get_value_multi(argv[2]);
- if (strptr) {
+ if (!git_config_get_value_multi(argv[2], &strptr)) {
for (i = 0; i < strptr->nr; i++) {
v = strptr->items[i].string;
if (!v)
@@ -109,6 +130,26 @@ int cmd__config(int argc, const char **argv)
printf("Value not found for \"%s\"\n", argv[2]);
goto exit1;
}
+ } else if (argc == 3 && !strcmp(argv[1], "get")) {
+ int ret;
+
+ if (!(ret = git_config_get(argv[2])))
+ goto exit0;
+ else if (ret == 1)
+ printf("Value not found for \"%s\"\n", argv[2]);
+ else if (ret == -CONFIG_INVALID_KEY)
+ printf("Key \"%s\" is invalid\n", argv[2]);
+ else if (ret == -CONFIG_NO_SECTION_OR_NAME)
+ printf("Key \"%s\" has no section\n", argv[2]);
+ else
+ /*
+ * A normal caller should just check "ret <
+ * 0", but for our own tests let's BUG() if
+ * our whitelist of git_config_parse_key()
+ * return values isn't exhaustive.
+ */
+ BUG("Key \"%s\" has unknown return %d", argv[2], ret);
+ goto exit1;
} else if (argc == 3 && !strcmp(argv[1], "get_int")) {
if (!git_config_get_int(argv[2], &val)) {
printf("%d\n", val);
@@ -141,7 +182,7 @@ int cmd__config(int argc, const char **argv)
goto exit2;
}
}
- if (!git_configset_get_value(&cs, argv[2], &v)) {
+ if (!git_configset_get_value(&cs, argv[2], &v, NULL)) {
if (!v)
printf("(NULL)\n");
else
@@ -159,8 +200,7 @@ int cmd__config(int argc, const char **argv)
goto exit2;
}
}
- strptr = git_configset_get_value_multi(&cs, argv[2]);
- if (strptr) {
+ if (!git_configset_get_value_multi(&cs, argv[2], &strptr)) {
for (i = 0; i < strptr->nr; i++) {
v = strptr->items[i].string;
if (!v)
@@ -176,6 +216,9 @@ int cmd__config(int argc, const char **argv)
} else if (!strcmp(argv[1], "iterate")) {
git_config(iterate_cb, NULL);
goto exit0;
+ } else if (argc == 3 && !strcmp(argv[1], "git_config_int")) {
+ git_config(parse_int_cb, (void *) argv[2]);
+ goto exit0;
}
die("%s: Please check the syntax and the function name", argv[0]);
diff --git a/t/helper/test-crontab.c b/t/helper/test-crontab.c
index e6c1b1e22b..597027a96e 100644
--- a/t/helper/test-crontab.c
+++ b/t/helper/test-crontab.c
@@ -1,5 +1,4 @@
#include "test-tool.h"
-#include "cache.h"
/*
* Usage: test-tool crontab <file> -l|<input>
diff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c
index 92c4c2313e..e5659df40b 100644
--- a/t/helper/test-ctype.c
+++ b/t/helper/test-ctype.c
@@ -1,5 +1,4 @@
#include "test-tool.h"
-#include "cache.h"
static int rc;
@@ -11,9 +10,14 @@ static void report_error(const char *class, int ch)
static int is_in(const char *s, int ch)
{
- /* We can't find NUL using strchr. It's classless anyway. */
+ /*
+ * We can't find NUL using strchr. Accept it as the first
+ * character in the spec -- there are no empty classes.
+ */
if (ch == '\0')
- return 0;
+ return ch == *s;
+ if (*s == '\0')
+ s++;
return !!strchr(s, ch);
}
@@ -23,13 +27,29 @@ static int is_in(const char *s, int ch)
if (is_in(s, i) != t(i)) \
report_error(#t, i); \
} \
+ if (t(EOF)) \
+ report_error(#t, EOF); \
}
#define DIGIT "0123456789"
#define LOWER "abcdefghijklmnopqrstuvwxyz"
#define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define PUNCT "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
+#define ASCII \
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" \
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
+ "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" \
+ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" \
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" \
+ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" \
+ "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" \
+ "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+#define CNTRL \
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" \
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
+ "\x7f"
-int cmd__ctype(int argc, const char **argv)
+int cmd__ctype(int argc UNUSED, const char **argv UNUSED)
{
TEST_CLASS(isdigit, DIGIT);
TEST_CLASS(isspace, " \n\r\t");
@@ -38,6 +58,13 @@ int cmd__ctype(int argc, const char **argv)
TEST_CLASS(is_glob_special, "*?[\\");
TEST_CLASS(is_regex_special, "$()*+.?[\\^{|");
TEST_CLASS(is_pathspec_magic, "!\"#%&',-/:;<=>@_`~");
+ TEST_CLASS(isascii, ASCII);
+ TEST_CLASS(islower, LOWER);
+ TEST_CLASS(isupper, UPPER);
+ TEST_CLASS(iscntrl, CNTRL);
+ TEST_CLASS(ispunct, PUNCT);
+ TEST_CLASS(isxdigit, DIGIT "abcdefABCDEF");
+ TEST_CLASS(isprint, LOWER UPPER DIGIT PUNCT " ");
return rc;
}
diff --git a/t/helper/test-date.c b/t/helper/test-date.c
index 45951b1df8..0683d46574 100644
--- a/t/helper/test-date.c
+++ b/t/helper/test-date.c
@@ -1,6 +1,6 @@
#include "test-tool.h"
-#include "cache.h"
#include "date.h"
+#include "trace.h"
static const char *usage_msg = "\n"
" test-tool date relative [time_t]...\n"
@@ -81,7 +81,7 @@ static void parse_approxidate(const char **argv)
{
for (; *argv; argv++) {
timestamp_t t;
- t = approxidate_relative(*argv);
+ t = approxidate(*argv);
printf("%s -> %s\n", *argv, show_date(t, 0, DATE_MODE(ISO8601)));
}
}
@@ -90,7 +90,7 @@ static void parse_approx_timestamp(const char **argv)
{
for (; *argv; argv++) {
timestamp_t t;
- t = approxidate_relative(*argv);
+ t = approxidate(*argv);
printf("%s -> %"PRItime"\n", *argv, t);
}
}
@@ -104,7 +104,7 @@ static void getnanos(const char **argv)
printf("%lf\n", seconds);
}
-int cmd__date(int argc, const char **argv)
+int cmd__date(int argc UNUSED, const char **argv)
{
const char *x;
diff --git a/t/helper/test-delta.c b/t/helper/test-delta.c
index b15481ea59..6bc787a474 100644
--- a/t/helper/test-delta.c
+++ b/t/helper/test-delta.c
@@ -11,7 +11,6 @@
#include "test-tool.h"
#include "git-compat-util.h"
#include "delta.h"
-#include "cache.h"
static const char usage_str[] =
"test-tool delta (-d|-p) <from_file> <data_file> <out_file>";
diff --git a/t/helper/test-dir-iterator.c b/t/helper/test-dir-iterator.c
index 659b6bfa81..6b297bd753 100644
--- a/t/helper/test-dir-iterator.c
+++ b/t/helper/test-dir-iterator.c
@@ -15,7 +15,7 @@ static const char *error_name(int error_number)
/*
* usage:
- * tool-test dir-iterator [--follow-symlinks] [--pedantic] directory_path
+ * tool-test dir-iterator [--pedantic] directory_path
*/
int cmd__dir_iterator(int argc, const char **argv)
{
@@ -24,9 +24,7 @@ int cmd__dir_iterator(int argc, const char **argv)
int iter_status;
for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) {
- if (strcmp(*argv, "--follow-symlinks") == 0)
- flags |= DIR_ITERATOR_FOLLOW_SYMLINKS;
- else if (strcmp(*argv, "--pedantic") == 0)
+ if (strcmp(*argv, "--pedantic") == 0)
flags |= DIR_ITERATOR_PEDANTIC;
else
die("invalid option '%s'", *argv);
diff --git a/t/helper/test-drop-caches.c b/t/helper/test-drop-caches.c
index e37396dd9c..73e551cfc2 100644
--- a/t/helper/test-drop-caches.c
+++ b/t/helper/test-drop-caches.c
@@ -155,7 +155,7 @@ static int cmd_dropcaches(void)
#endif
-int cmd__drop_caches(int argc, const char **argv)
+int cmd__drop_caches(int argc UNUSED, const char **argv UNUSED)
{
cmd_sync();
return cmd_dropcaches();
diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c
index 0d6d7f1ecb..c38f546e4f 100644
--- a/t/helper/test-dump-cache-tree.c
+++ b/t/helper/test-dump-cache-tree.c
@@ -1,8 +1,12 @@
+#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
-#include "cache.h"
+#include "hash.h"
+#include "hex.h"
#include "tree.h"
#include "cache-tree.h"
-
+#include "read-cache-ll.h"
+#include "repository.h"
+#include "setup.h"
static void dump_one(struct cache_tree *it, const char *pfx, const char *x)
{
@@ -55,19 +59,19 @@ static int dump_cache_tree(struct cache_tree *it,
return errs;
}
-int cmd__dump_cache_tree(int ac, const char **av)
+int cmd__dump_cache_tree(int ac UNUSED, const char **av UNUSED)
{
struct index_state istate;
struct cache_tree *another = cache_tree();
int ret;
setup_git_directory();
- if (read_cache() < 0)
+ if (repo_read_index(the_repository) < 0)
die("unable to read index file");
istate = the_index;
istate.cache_tree = another;
cache_tree_update(&istate, WRITE_TREE_DRY_RUN);
- ret = dump_cache_tree(active_cache_tree, another, "");
+ ret = dump_cache_tree(the_index.cache_tree, another, "");
cache_tree_free(&another);
return ret;
diff --git a/t/helper/test-dump-fsmonitor.c b/t/helper/test-dump-fsmonitor.c
index 975f0ac890..4f215fea02 100644
--- a/t/helper/test-dump-fsmonitor.c
+++ b/t/helper/test-dump-fsmonitor.c
@@ -1,7 +1,9 @@
#include "test-tool.h"
-#include "cache.h"
+#include "read-cache-ll.h"
+#include "repository.h"
+#include "setup.h"
-int cmd__dump_fsmonitor(int ac, const char **av)
+int cmd__dump_fsmonitor(int ac UNUSED, const char **av UNUSED)
{
struct index_state *istate = the_repository->index;
int i;
diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c
index a209880eb3..f29d18ef94 100644
--- a/t/helper/test-dump-split-index.c
+++ b/t/helper/test-dump-split-index.c
@@ -1,14 +1,18 @@
+#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
+#include "read-cache-ll.h"
+#include "repository.h"
+#include "setup.h"
#include "split-index.h"
#include "ewah/ewok.h"
-static void show_bit(size_t pos, void *data)
+static void show_bit(size_t pos, void *data UNUSED)
{
printf(" %d", (int)pos);
}
-int cmd__dump_split_index(int ac, const char **av)
+int cmd__dump_split_index(int ac UNUSED, const char **av)
{
struct split_index *si;
int i;
diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index 99010614f6..b4af9712fe 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -1,7 +1,10 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
-#include "cache.h"
#include "dir.h"
+#include "hex.h"
+#include "read-cache-ll.h"
+#include "repository.h"
+#include "setup.h"
static int compare_untracked(const void *a_, const void *b_)
{
@@ -40,7 +43,7 @@ static void dump(struct untracked_cache_dir *ucd, struct strbuf *base)
strbuf_setlen(base, len);
}
-int cmd__dump_untracked_cache(int ac, const char **av)
+int cmd__dump_untracked_cache(int ac UNUSED, const char **av UNUSED)
{
struct untracked_cache *uc;
struct strbuf base = STRBUF_INIT;
@@ -51,7 +54,7 @@ int cmd__dump_untracked_cache(int ac, const char **av)
xsetenv("GIT_CONFIG_VALUE_0", "keep", 1);
setup_git_directory();
- if (read_cache() < 0)
+ if (repo_read_index(the_repository) < 0)
die("unable to read index file");
uc = the_index.untracked;
if (!uc) {
diff --git a/t/helper/test-env-helper.c b/t/helper/test-env-helper.c
new file mode 100644
index 0000000000..66c88b8ff3
--- /dev/null
+++ b/t/helper/test-env-helper.c
@@ -0,0 +1,100 @@
+#include "test-tool.h"
+#include "config.h"
+#include "parse-options.h"
+
+static char const * const env__helper_usage[] = {
+ "test-tool env-helper --type=[bool|ulong] <options> <env-var>",
+ NULL
+};
+
+enum cmdmode {
+ ENV_HELPER_TYPE_BOOL = 1,
+ ENV_HELPER_TYPE_ULONG
+};
+
+static int option_parse_type(const struct option *opt, const char *arg,
+ int unset)
+{
+ enum cmdmode *cmdmode = opt->value;
+
+ BUG_ON_OPT_NEG(unset);
+
+ if (!strcmp(arg, "bool"))
+ *cmdmode = ENV_HELPER_TYPE_BOOL;
+ else if (!strcmp(arg, "ulong"))
+ *cmdmode = ENV_HELPER_TYPE_ULONG;
+ else
+ die("unrecognized --type argument, %s", arg);
+
+ return 0;
+}
+
+int cmd__env_helper(int argc, const char **argv)
+{
+ int exit_code = 0;
+ const char *env_variable = NULL;
+ const char *env_default = NULL;
+ int ret;
+ int ret_int, default_int;
+ unsigned long ret_ulong, default_ulong;
+ enum cmdmode cmdmode = 0;
+ struct option opts[] = {
+ OPT_CALLBACK_F(0, "type", &cmdmode, "type",
+ "value is given this type", PARSE_OPT_NONEG,
+ option_parse_type),
+ OPT_STRING(0, "default", &env_default, "value",
+ "default for git_env_*(...) to fall back on"),
+ OPT_BOOL(0, "exit-code", &exit_code,
+ "be quiet only use git_env_*() value as exit code"),
+ OPT_END(),
+ };
+
+ argc = parse_options(argc, argv, NULL, opts, env__helper_usage,
+ PARSE_OPT_KEEP_UNKNOWN_OPT);
+ if (env_default && !*env_default)
+ usage_with_options(env__helper_usage, opts);
+ if (!cmdmode)
+ usage_with_options(env__helper_usage, opts);
+ if (argc != 1)
+ usage_with_options(env__helper_usage, opts);
+ env_variable = argv[0];
+
+ switch (cmdmode) {
+ case ENV_HELPER_TYPE_BOOL:
+ if (env_default) {
+ default_int = git_parse_maybe_bool(env_default);
+ if (default_int == -1) {
+ error("option `--default' expects a boolean value with `--type=bool`, not `%s`",
+ env_default);
+ usage_with_options(env__helper_usage, opts);
+ }
+ } else {
+ default_int = 0;
+ }
+ ret_int = git_env_bool(env_variable, default_int);
+ if (!exit_code)
+ puts(ret_int ? "true" : "false");
+ ret = ret_int;
+ break;
+ case ENV_HELPER_TYPE_ULONG:
+ if (env_default) {
+ if (!git_parse_ulong(env_default, &default_ulong)) {
+ error("option `--default' expects an unsigned long value with `--type=ulong`, not `%s`",
+ env_default);
+ usage_with_options(env__helper_usage, opts);
+ }
+ } else {
+ default_ulong = 0;
+ }
+ ret_ulong = git_env_ulong(env_variable, default_ulong);
+ if (!exit_code)
+ printf("%lu\n", ret_ulong);
+ ret = ret_ulong;
+ break;
+ default:
+ BUG("unknown <type> value");
+ break;
+ }
+
+ return !ret;
+}
diff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c
index b9d1200eb9..2ed910adaa 100644
--- a/t/helper/test-example-decorate.c
+++ b/t/helper/test-example-decorate.c
@@ -1,9 +1,10 @@
#include "test-tool.h"
-#include "cache.h"
+#include "git-compat-util.h"
#include "object.h"
#include "decorate.h"
+#include "repository.h"
-int cmd__example_decorate(int argc, const char **argv)
+int cmd__example_decorate(int argc UNUSED, const char **argv UNUSED)
{
struct decoration n;
struct object_id one_oid = { {1} };
diff --git a/t/helper/test-fake-ssh.c b/t/helper/test-fake-ssh.c
index 12beee99ad..27323cb367 100644
--- a/t/helper/test-fake-ssh.c
+++ b/t/helper/test-fake-ssh.c
@@ -8,7 +8,7 @@ int cmd_main(int argc, const char **argv)
struct strbuf buf = STRBUF_INIT;
FILE *f;
int i;
- const char *child_argv[] = { NULL, NULL };
+ struct child_process cmd = CHILD_PROCESS_INIT;
/* First, print all parameters into $TRASH_DIRECTORY/ssh-output */
if (!trash_directory)
@@ -17,6 +17,7 @@ int cmd_main(int argc, const char **argv)
f = fopen(buf.buf, "w");
if (!f)
die("Could not write to %s", buf.buf);
+ strbuf_release(&buf);
for (i = 0; i < argc; i++)
fprintf(f, "%s%s", i > 0 ? " " : "", i > 0 ? argv[i] : "ssh:");
fprintf(f, "\n");
@@ -25,6 +26,7 @@ int cmd_main(int argc, const char **argv)
/* Now, evaluate the *last* parameter */
if (argc < 2)
return 0;
- child_argv[0] = argv[argc - 1];
- return run_command_v_opt(child_argv, RUN_USING_SHELL);
+ cmd.use_shell = 1;
+ strvec_push(&cmd.args, argv[argc - 1]);
+ return run_command(&cmd);
}
diff --git a/t/helper/test-fast-rebase.c b/t/helper/test-fast-rebase.c
index 45665ec19a..cac20a72b3 100644
--- a/t/helper/test-fast-rebase.c
+++ b/t/helper/test-fast-rebase.c
@@ -10,22 +10,29 @@
* refactoring is the better route).
*/
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
-
#include "cache-tree.h"
#include "commit.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hash.h"
+#include "hex.h"
#include "lockfile.h"
#include "merge-ort.h"
+#include "object-name.h"
+#include "read-cache-ll.h"
#include "refs.h"
#include "revision.h"
#include "sequencer.h"
+#include "setup.h"
#include "strvec.h"
#include "tree.h"
static const char *short_commit_name(struct commit *commit)
{
- return find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV);
+ return repo_find_unique_abbrev(the_repository, &commit->object.oid,
+ DEFAULT_ABBREV);
}
static struct commit *peel_committish(const char *name)
@@ -33,10 +40,11 @@ static struct commit *peel_committish(const char *name)
struct object *obj;
struct object_id oid;
- if (get_oid(name, &oid))
+ if (repo_get_oid(the_repository, name, &oid))
return NULL;
obj = parse_object(the_repository, &oid);
- return (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
+ return (struct commit *)repo_peel_to_type(the_repository, name, 0, obj,
+ OBJ_COMMIT);
}
static char *get_author(const char *message)
@@ -63,7 +71,8 @@ static struct commit *create_commit(struct tree *tree,
struct commit_extra_header *extra;
struct strbuf msg = STRBUF_INIT;
const char *out_enc = get_commit_output_encoding();
- const char *message = logmsg_reencode(based_on, NULL, out_enc);
+ const char *message = repo_logmsg_reencode(the_repository, based_on,
+ NULL, out_enc);
const char *orig_message = NULL;
const char *exclude_gpgsig[] = { "gpgsig", NULL };
@@ -119,11 +128,11 @@ int cmd__fast_rebase(int argc, const char **argv)
strbuf_addf(&branch_name, "refs/heads/%s", argv[4]);
/* Sanity check */
- if (get_oid("HEAD", &head))
+ if (repo_get_oid(the_repository, "HEAD", &head))
die(_("Cannot read HEAD"));
assert(oideq(&onto->object.oid, &head));
- hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
+ repo_hold_locked_index(the_repository, &lock, LOCK_DIE_ON_ERROR);
if (repo_read_index(the_repository) < 0)
BUG("Could not read index");
@@ -154,7 +163,7 @@ int cmd__fast_rebase(int argc, const char **argv)
memset(&result, 0, sizeof(result));
merge_opt.show_rename_progress = 1;
merge_opt.branch1 = "HEAD";
- head_tree = get_commit_tree(onto);
+ head_tree = repo_get_commit_tree(the_repository, onto);
result.tree = head_tree;
last_commit = onto;
while ((commit = get_revision(&revs))) {
@@ -165,8 +174,8 @@ int cmd__fast_rebase(int argc, const char **argv)
assert(commit->parents && !commit->parents->next);
base = commit->parents->item;
- next_tree = get_commit_tree(commit);
- base_tree = get_commit_tree(base);
+ next_tree = repo_get_commit_tree(the_repository, commit);
+ base_tree = repo_get_commit_tree(the_repository, base);
merge_opt.branch2 = short_commit_name(commit);
merge_opt.ancestor = xstrfmt("parent of %s", merge_opt.branch2);
diff --git a/t/helper/test-fsmonitor-client.c b/t/helper/test-fsmonitor-client.c
index 54a4856c48..8280984d08 100644
--- a/t/helper/test-fsmonitor-client.c
+++ b/t/helper/test-fsmonitor-client.c
@@ -4,14 +4,16 @@
*/
#include "test-tool.h"
-#include "cache.h"
#include "parse-options.h"
#include "fsmonitor-ipc.h"
+#include "read-cache-ll.h"
+#include "repository.h"
+#include "setup.h"
#include "thread-utils.h"
#include "trace2.h"
#ifndef HAVE_FSMONITOR_DAEMON_BACKEND
-int cmd__fsmonitor_client(int argc, const char **argv)
+int cmd__fsmonitor_client(int argc UNUSED, const char **argv UNUSED)
{
die("fsmonitor--daemon not available on this platform");
}
diff --git a/t/helper/test-genzeros.c b/t/helper/test-genzeros.c
index 8ca988d621..47af843b68 100644
--- a/t/helper/test-genzeros.c
+++ b/t/helper/test-genzeros.c
@@ -17,15 +17,16 @@ int cmd__genzeros(int argc, const char **argv)
/* Writing out individual NUL bytes is slow... */
while (count < 0)
- if (write(1, zeros, ARRAY_SIZE(zeros)) < 0)
- return -1;
+ if (xwrite(1, zeros, ARRAY_SIZE(zeros)) < 0)
+ die_errno("write error");
while (count > 0) {
- n = write(1, zeros, count < ARRAY_SIZE(zeros) ?
- count : ARRAY_SIZE(zeros));
+ n = xwrite(1, zeros,
+ count < ARRAY_SIZE(zeros)
+ ? count : ARRAY_SIZE(zeros));
if (n < 0)
- return -1;
+ die_errno("write error");
count -= n;
}
diff --git a/t/helper/test-hash-speed.c b/t/helper/test-hash-speed.c
index f40d9ad0c2..b235da594f 100644
--- a/t/helper/test-hash-speed.c
+++ b/t/helper/test-hash-speed.c
@@ -1,5 +1,5 @@
#include "test-tool.h"
-#include "cache.h"
+#include "hash-ll.h"
#define NUM_SECONDS 3
diff --git a/t/helper/test-hash.c b/t/helper/test-hash.c
index 5860dab0ff..45d829c908 100644
--- a/t/helper/test-hash.c
+++ b/t/helper/test-hash.c
@@ -1,5 +1,5 @@
#include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
int cmd_hash_impl(int ac, const char **av, int algo)
{
diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c
index 36ff07bd4b..0eb0b3d49c 100644
--- a/t/helper/test-hashmap.c
+++ b/t/helper/test-hashmap.c
@@ -2,6 +2,7 @@
#include "git-compat-util.h"
#include "hashmap.h"
#include "strbuf.h"
+#include "string-list.h"
struct test_entry
{
@@ -150,6 +151,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
*/
int cmd__hashmap(int argc, const char **argv)
{
+ struct string_list parts = STRING_LIST_INIT_NODUP;
struct strbuf line = STRBUF_INIT;
int icase;
struct hashmap map = HASHMAP_INIT(test_entry_cmp, &icase);
@@ -159,21 +161,26 @@ int cmd__hashmap(int argc, const char **argv)
/* process commands from stdin */
while (strbuf_getline(&line, stdin) != EOF) {
- char *cmd, *p1 = NULL, *p2 = NULL;
+ char *cmd, *p1, *p2;
unsigned int hash = 0;
struct test_entry *entry;
/* break line into command and up to two parameters */
- cmd = strtok(line.buf, DELIM);
+ string_list_setlen(&parts, 0);
+ string_list_split_in_place(&parts, line.buf, DELIM, 2);
+ string_list_remove_empty_items(&parts, 0);
+
/* ignore empty lines */
- if (!cmd || *cmd == '#')
+ if (!parts.nr)
+ continue;
+ if (!*parts.items[0].string || *parts.items[0].string == '#')
continue;
- p1 = strtok(NULL, DELIM);
- if (p1) {
+ cmd = parts.items[0].string;
+ p1 = parts.nr >= 1 ? parts.items[1].string : NULL;
+ p2 = parts.nr >= 2 ? parts.items[2].string : NULL;
+ if (p1)
hash = icase ? strihash(p1) : strhash(p1);
- p2 = strtok(NULL, DELIM);
- }
if (!strcmp("add", cmd) && p1 && p2) {
@@ -260,6 +267,7 @@ int cmd__hashmap(int argc, const char **argv)
}
}
+ string_list_clear(&parts, 0);
strbuf_release(&line);
hashmap_clear_and_free(&map, struct test_entry, ent);
return 0;
diff --git a/t/helper/test-hexdump.c b/t/helper/test-hexdump.c
index 811e89c1bc..05f55eca21 100644
--- a/t/helper/test-hexdump.c
+++ b/t/helper/test-hexdump.c
@@ -4,7 +4,7 @@
/*
* Read stdin and print a hexdump to stdout.
*/
-int cmd__hexdump(int argc, const char **argv)
+int cmd__hexdump(int argc UNUSED, const char **argv UNUSED)
{
char buf[1024];
ssize_t i, len;
diff --git a/t/helper/test-index-version.c b/t/helper/test-index-version.c
deleted file mode 100644
index fcd10968cc..0000000000
--- a/t/helper/test-index-version.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "test-tool.h"
-#include "cache.h"
-
-int cmd__index_version(int argc, const char **argv)
-{
- struct cache_header hdr;
- int version;
-
- memset(&hdr,0,sizeof(hdr));
- if (read(0, &hdr, sizeof(hdr)) != sizeof(hdr))
- return 0;
- version = ntohl(hdr.hdr_version);
- printf("%d\n", version);
- return 0;
-}
diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c
index 8c3edacc00..afe393f597 100644
--- a/t/helper/test-json-writer.c
+++ b/t/helper/test-json-writer.c
@@ -1,6 +1,6 @@
#include "test-tool.h"
-#include "cache.h"
#include "json-writer.h"
+#include "string-list.h"
static const char *expect_obj1 = "{\"a\":\"abc\",\"b\":42,\"c\":true}";
static const char *expect_obj2 = "{\"a\":-1,\"b\":2147483647,\"c\":0}";
@@ -395,35 +395,41 @@ static int unit_tests(void)
return 0;
}
-static void get_s(int line_nr, char **s_in)
+struct line {
+ struct string_list *parts;
+ size_t consumed_nr;
+ int nr;
+};
+
+static void get_s(struct line *line, char **s_in)
{
- *s_in = strtok(NULL, " ");
- if (!*s_in)
- die("line[%d]: expected: <s>", line_nr);
+ if (line->consumed_nr > line->parts->nr)
+ die("line[%d]: expected: <s>", line->nr);
+ *s_in = line->parts->items[line->consumed_nr++].string;
}
-static void get_i(int line_nr, intmax_t *s_in)
+static void get_i(struct line *line, intmax_t *s_in)
{
char *s;
char *endptr;
- get_s(line_nr, &s);
+ get_s(line, &s);
*s_in = strtol(s, &endptr, 10);
if (*endptr || errno == ERANGE)
- die("line[%d]: invalid integer value", line_nr);
+ die("line[%d]: invalid integer value", line->nr);
}
-static void get_d(int line_nr, double *s_in)
+static void get_d(struct line *line, double *s_in)
{
char *s;
char *endptr;
- get_s(line_nr, &s);
+ get_s(line, &s);
*s_in = strtod(s, &endptr);
if (*endptr || errno == ERANGE)
- die("line[%d]: invalid float value", line_nr);
+ die("line[%d]: invalid float value", line->nr);
}
static int pretty;
@@ -454,6 +460,7 @@ static char *get_trimmed_line(char *buf, int buf_size)
static int scripted(void)
{
+ struct string_list parts = STRING_LIST_INIT_NODUP;
struct json_writer jw = JSON_WRITER_INIT;
char buf[MAX_LINE_LENGTH];
char *line;
@@ -471,66 +478,77 @@ static int scripted(void)
die("expected first line to be 'object' or 'array'");
while ((line = get_trimmed_line(buf, MAX_LINE_LENGTH)) != NULL) {
+ struct line state = { 0 };
char *verb;
char *key;
char *s_value;
intmax_t i_value;
double d_value;
- line_nr++;
+ state.parts = &parts;
+ state.nr = ++line_nr;
+
+ /* break line into command and zero or more tokens */
+ string_list_setlen(&parts, 0);
+ string_list_split_in_place(&parts, line, " ", -1);
+ string_list_remove_empty_items(&parts, 0);
+
+ /* ignore empty lines */
+ if (!parts.nr || !*parts.items[0].string)
+ continue;
- verb = strtok(line, " ");
+ verb = parts.items[state.consumed_nr++].string;
if (!strcmp(verb, "end")) {
jw_end(&jw);
}
else if (!strcmp(verb, "object-string")) {
- get_s(line_nr, &key);
- get_s(line_nr, &s_value);
+ get_s(&state, &key);
+ get_s(&state, &s_value);
jw_object_string(&jw, key, s_value);
}
else if (!strcmp(verb, "object-int")) {
- get_s(line_nr, &key);
- get_i(line_nr, &i_value);
+ get_s(&state, &key);
+ get_i(&state, &i_value);
jw_object_intmax(&jw, key, i_value);
}
else if (!strcmp(verb, "object-double")) {
- get_s(line_nr, &key);
- get_i(line_nr, &i_value);
- get_d(line_nr, &d_value);
+ get_s(&state, &key);
+ get_i(&state, &i_value);
+ get_d(&state, &d_value);
jw_object_double(&jw, key, i_value, d_value);
}
else if (!strcmp(verb, "object-true")) {
- get_s(line_nr, &key);
+ get_s(&state, &key);
jw_object_true(&jw, key);
}
else if (!strcmp(verb, "object-false")) {
- get_s(line_nr, &key);
+ get_s(&state, &key);
jw_object_false(&jw, key);
}
else if (!strcmp(verb, "object-null")) {
- get_s(line_nr, &key);
+ get_s(&state, &key);
jw_object_null(&jw, key);
}
else if (!strcmp(verb, "object-object")) {
- get_s(line_nr, &key);
+ get_s(&state, &key);
jw_object_inline_begin_object(&jw, key);
}
else if (!strcmp(verb, "object-array")) {
- get_s(line_nr, &key);
+ get_s(&state, &key);
jw_object_inline_begin_array(&jw, key);
}
else if (!strcmp(verb, "array-string")) {
- get_s(line_nr, &s_value);
+ get_s(&state, &s_value);
jw_array_string(&jw, s_value);
}
else if (!strcmp(verb, "array-int")) {
- get_i(line_nr, &i_value);
+ get_i(&state, &i_value);
jw_array_intmax(&jw, i_value);
}
else if (!strcmp(verb, "array-double")) {
- get_i(line_nr, &i_value);
- get_d(line_nr, &d_value);
+ get_i(&state, &i_value);
+ get_d(&state, &d_value);
jw_array_double(&jw, i_value, d_value);
}
else if (!strcmp(verb, "array-true"))
@@ -553,6 +571,7 @@ static int scripted(void)
printf("%s\n", jw.json.buf);
jw_release(&jw);
+ string_list_clear(&parts, 0);
return 0;
}
diff --git a/t/helper/test-lazy-init-name-hash.c b/t/helper/test-lazy-init-name-hash.c
index cd1b4c9736..187a115d57 100644
--- a/t/helper/test-lazy-init-name-hash.c
+++ b/t/helper/test-lazy-init-name-hash.c
@@ -1,6 +1,12 @@
+#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
-#include "cache.h"
+#include "environment.h"
+#include "name-hash.h"
#include "parse-options.h"
+#include "read-cache-ll.h"
+#include "repository.h"
+#include "setup.h"
+#include "trace.h"
static int single;
static int multi;
@@ -32,7 +38,7 @@ static void dump_run(void)
struct dir_entry *dir;
struct cache_entry *ce;
- read_cache();
+ repo_read_index(the_repository);
if (single) {
test_lazy_init_name_hash(&the_index, 0);
} else {
@@ -49,7 +55,7 @@ static void dump_run(void)
ent /* member name */)
printf("name %08x %s\n", ce->ent.hash, ce->name);
- discard_cache();
+ discard_index(&the_index);
}
/*
@@ -66,7 +72,7 @@ static uint64_t time_runs(int try_threaded)
for (i = 0; i < count; i++) {
t0 = getnanotime();
- read_cache();
+ repo_read_index(the_repository);
t1 = getnanotime();
nr_threads_used = test_lazy_init_name_hash(&the_index, try_threaded);
t2 = getnanotime();
@@ -89,7 +95,7 @@ static uint64_t time_runs(int try_threaded)
the_index.cache_nr);
fflush(stdout);
- discard_cache();
+ discard_index(&the_index);
}
avg = sum / count;
@@ -113,9 +119,9 @@ static void analyze_run(void)
int i;
int nr;
- read_cache();
+ repo_read_index(the_repository);
cache_nr_limit = the_index.cache_nr;
- discard_cache();
+ discard_index(&the_index);
nr = analyze;
while (1) {
@@ -128,23 +134,23 @@ static void analyze_run(void)
nr = cache_nr_limit;
for (i = 0; i < count; i++) {
- read_cache();
+ repo_read_index(the_repository);
the_index.cache_nr = nr; /* cheap truncate of index */
t1s = getnanotime();
test_lazy_init_name_hash(&the_index, 0);
t2s = getnanotime();
sum_single += (t2s - t1s);
the_index.cache_nr = cache_nr_limit;
- discard_cache();
+ discard_index(&the_index);
- read_cache();
+ repo_read_index(the_repository);
the_index.cache_nr = nr; /* cheap truncate of index */
t1m = getnanotime();
nr_threads_used = test_lazy_init_name_hash(&the_index, 1);
t2m = getnanotime();
sum_multi += (t2m - t1m);
the_index.cache_nr = cache_nr_limit;
- discard_cache();
+ discard_index(&the_index);
if (!nr_threads_used)
printf(" [size %8d] [single %f] non-threaded code path used\n",
diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c
index 4079fdee06..d0db5ff26f 100644
--- a/t/helper/test-match-trees.c
+++ b/t/helper/test-match-trees.c
@@ -1,17 +1,21 @@
#include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
+#include "match-trees.h"
+#include "object-name.h"
+#include "repository.h"
+#include "setup.h"
#include "tree.h"
-int cmd__match_trees(int ac, const char **av)
+int cmd__match_trees(int ac UNUSED, const char **av)
{
struct object_id hash1, hash2, shifted;
struct tree *one, *two;
setup_git_directory();
- if (get_oid(av[1], &hash1))
+ if (repo_get_oid(the_repository, av[1], &hash1))
die("cannot parse %s as an object name", av[1]);
- if (get_oid(av[2], &hash2))
+ if (repo_get_oid(the_repository, av[2], &hash2))
die("cannot parse %s as an object name", av[2]);
one = parse_tree_indirect(&hash1);
if (!one)
diff --git a/t/helper/test-mergesort.c b/t/helper/test-mergesort.c
index 335e5bb3a9..42ccc87051 100644
--- a/t/helper/test-mergesort.c
+++ b/t/helper/test-mergesort.c
@@ -1,6 +1,7 @@
#include "test-tool.h"
-#include "cache.h"
+#include "mem-pool.h"
#include "mergesort.h"
+#include "strbuf.h"
static uint32_t minstd_rand(uint32_t *state)
{
diff --git a/t/helper/test-oid-array.c b/t/helper/test-oid-array.c
index d1324d086a..aafe398ef0 100644
--- a/t/helper/test-oid-array.c
+++ b/t/helper/test-oid-array.c
@@ -1,14 +1,16 @@
#include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
#include "oid-array.h"
+#include "setup.h"
+#include "strbuf.h"
-static int print_oid(const struct object_id *oid, void *data)
+static int print_oid(const struct object_id *oid, void *data UNUSED)
{
puts(oid_to_hex(oid));
return 0;
}
-int cmd__oid_array(int argc, const char **argv)
+int cmd__oid_array(int argc UNUSED, const char **argv UNUSED)
{
struct oid_array array = OID_ARRAY_INIT;
struct strbuf line = STRBUF_INIT;
diff --git a/t/helper/test-oidmap.c b/t/helper/test-oidmap.c
index 0acf99931e..bd30244a54 100644
--- a/t/helper/test-oidmap.c
+++ b/t/helper/test-oidmap.c
@@ -1,7 +1,11 @@
#include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
+#include "object-name.h"
#include "oidmap.h"
+#include "repository.h"
+#include "setup.h"
#include "strbuf.h"
+#include "string-list.h"
/* key is an oid and value is a name (could be a refname for example) */
struct test_entry {
@@ -21,8 +25,9 @@ struct test_entry {
* iterate -> oidkey1 namevalue1\noidkey2 namevalue2\n...
*
*/
-int cmd__oidmap(int argc, const char **argv)
+int cmd__oidmap(int argc UNUSED, const char **argv UNUSED)
{
+ struct string_list parts = STRING_LIST_INIT_NODUP;
struct strbuf line = STRBUF_INIT;
struct oidmap map = OIDMAP_INIT;
@@ -33,23 +38,28 @@ int cmd__oidmap(int argc, const char **argv)
/* process commands from stdin */
while (strbuf_getline(&line, stdin) != EOF) {
- char *cmd, *p1 = NULL, *p2 = NULL;
+ char *cmd, *p1, *p2;
struct test_entry *entry;
struct object_id oid;
/* break line into command and up to two parameters */
- cmd = strtok(line.buf, DELIM);
+ string_list_setlen(&parts, 0);
+ string_list_split_in_place(&parts, line.buf, DELIM, 2);
+ string_list_remove_empty_items(&parts, 0);
+
/* ignore empty lines */
- if (!cmd || *cmd == '#')
+ if (!parts.nr)
+ continue;
+ if (!*parts.items[0].string || *parts.items[0].string == '#')
continue;
- p1 = strtok(NULL, DELIM);
- if (p1)
- p2 = strtok(NULL, DELIM);
+ cmd = parts.items[0].string;
+ p1 = parts.nr >= 1 ? parts.items[1].string : NULL;
+ p2 = parts.nr >= 2 ? parts.items[2].string : NULL;
if (!strcmp("put", cmd) && p1 && p2) {
- if (get_oid(p1, &oid)) {
+ if (repo_get_oid(the_repository, p1, &oid)) {
printf("Unknown oid: %s\n", p1);
continue;
}
@@ -67,7 +77,7 @@ int cmd__oidmap(int argc, const char **argv)
} else if (!strcmp("get", cmd) && p1) {
- if (get_oid(p1, &oid)) {
+ if (repo_get_oid(the_repository, p1, &oid)) {
printf("Unknown oid: %s\n", p1);
continue;
}
@@ -80,7 +90,7 @@ int cmd__oidmap(int argc, const char **argv)
} else if (!strcmp("remove", cmd) && p1) {
- if (get_oid(p1, &oid)) {
+ if (repo_get_oid(the_repository, p1, &oid)) {
printf("Unknown oid: %s\n", p1);
continue;
}
@@ -106,6 +116,7 @@ int cmd__oidmap(int argc, const char **argv)
}
}
+ string_list_clear(&parts, 0);
strbuf_release(&line);
oidmap_free(&map, 1);
return 0;
diff --git a/t/helper/test-oidtree.c b/t/helper/test-oidtree.c
index d48a409f4e..c7a1d4c642 100644
--- a/t/helper/test-oidtree.c
+++ b/t/helper/test-oidtree.c
@@ -1,14 +1,16 @@
#include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
#include "oidtree.h"
+#include "setup.h"
+#include "strbuf.h"
-static enum cb_next print_oid(const struct object_id *oid, void *data)
+static enum cb_next print_oid(const struct object_id *oid, void *data UNUSED)
{
puts(oid_to_hex(oid));
return CB_CONTINUE;
}
-int cmd__oidtree(int argc, const char **argv)
+int cmd__oidtree(int argc UNUSED, const char **argv UNUSED)
{
struct oidtree ot;
struct strbuf line = STRBUF_INIT;
diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
index 8cb0d53840..47dc211711 100644
--- a/t/helper/test-online-cpus.c
+++ b/t/helper/test-online-cpus.c
@@ -2,7 +2,7 @@
#include "git-compat-util.h"
#include "thread-utils.h"
-int cmd__online_cpus(int argc, const char **argv)
+int cmd__online_cpus(int argc UNUSED, const char **argv UNUSED)
{
printf("%d\n", online_cpus());
return 0;
diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c
index f7b79daf4c..67a964ef90 100644
--- a/t/helper/test-pack-mtimes.c
+++ b/t/helper/test-pack-mtimes.c
@@ -1,9 +1,10 @@
-#include "git-compat-util.h"
#include "test-tool.h"
+#include "hex.h"
#include "strbuf.h"
-#include "object-store.h"
+#include "object-store-ll.h"
#include "packfile.h"
#include "pack-mtimes.h"
+#include "setup.h"
static void dump_mtimes(struct packed_git *p)
{
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index 506835521a..a4f6e24b0c 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -1,6 +1,6 @@
#include "test-tool.h"
-#include "cache.h"
#include "parse-options.h"
+#include "strbuf.h"
#include "string-list.h"
#include "trace2.h"
@@ -133,6 +133,8 @@ int cmd__parse_options(int argc, const char **argv)
OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"),
OPT_STRING('o', NULL, &string, "str", "get another string"),
OPT_NOOP_NOARG(0, "obsolete"),
+ OPT_SET_INT_F(0, "longhelp", &integer, "help text of this entry\n"
+ "spans multiple lines", 0, PARSE_OPT_NONEG),
OPT_STRING_LIST(0, "list", &list, "str", "add str to list"),
OPT_GROUP("Magic arguments"),
OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
@@ -263,14 +265,14 @@ int cmd__parse_options_flags(int argc, const char **argv)
return parse_options_flags__cmd(argc, argv, test_flags);
}
-static int subcmd_one(int argc, const char **argv, const char *prefix)
+static int subcmd_one(int argc, const char **argv, const char *prefix UNUSED)
{
printf("fn: subcmd_one\n");
print_args(argc, argv);
return 0;
}
-static int subcmd_two(int argc, const char **argv, const char *prefix)
+static int subcmd_two(int argc, const char **argv, const char *prefix UNUSED)
{
printf("fn: subcmd_two\n");
print_args(argc, argv);
diff --git a/t/helper/test-parse-pathspec-file.c b/t/helper/test-parse-pathspec-file.c
index b3e08cef4b..89ecefd1cd 100644
--- a/t/helper/test-parse-pathspec-file.c
+++ b/t/helper/test-parse-pathspec-file.c
@@ -1,12 +1,11 @@
#include "test-tool.h"
#include "parse-options.h"
#include "pathspec.h"
-#include "gettext.h"
int cmd__parse_pathspec_file(int argc, const char **argv)
{
struct pathspec pathspec;
- const char *pathspec_from_file = NULL;
+ char *pathspec_from_file = NULL;
int pathspec_file_nul = 0, i;
static const char *const usage[] = {
@@ -29,5 +28,6 @@ int cmd__parse_pathspec_file(int argc, const char **argv)
printf("%s\n", pathspec.items[i].original);
clear_pathspec(&pathspec);
+ free(pathspec_from_file);
return 0;
}
diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c
index 3f102cfddd..910a128614 100644
--- a/t/helper/test-partial-clone.c
+++ b/t/helper/test-partial-clone.c
@@ -1,7 +1,8 @@
-#include "cache.h"
#include "test-tool.h"
+#include "hex.h"
#include "repository.h"
-#include "object-store.h"
+#include "object-store-ll.h"
+#include "setup.h"
/*
* Prints the size of the object corresponding to the given hash in a specific
diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c
index d20e1b7a18..70396fa384 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -1,6 +1,11 @@
#include "test-tool.h"
-#include "cache.h"
+#include "abspath.h"
+#include "environment.h"
+#include "path.h"
+#include "read-cache-ll.h"
+#include "setup.h"
#include "string-list.h"
+#include "trace.h"
#include "utf8.h"
/*
@@ -8,7 +13,8 @@
* GIT_CEILING_DIRECTORIES. If the path is unusable for some reason,
* die with an explanation.
*/
-static int normalize_ceiling_entry(struct string_list_item *item, void *unused)
+static int normalize_ceiling_entry(struct string_list_item *item,
+ void *data UNUSED)
{
char *ceil = item->string;
diff --git a/t/helper/test-pcre2-config.c b/t/helper/test-pcre2-config.c
index 5258fdddba..5d0b2a2e10 100644
--- a/t/helper/test-pcre2-config.c
+++ b/t/helper/test-pcre2-config.c
@@ -1,5 +1,4 @@
#include "test-tool.h"
-#include "cache.h"
#include "grep.h"
int cmd__pcre2_config(int argc, const char **argv)
diff --git a/t/helper/test-pkt-line.c b/t/helper/test-pkt-line.c
index c5e052e537..f4d134a145 100644
--- a/t/helper/test-pkt-line.c
+++ b/t/helper/test-pkt-line.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "test-tool.h"
#include "pkt-line.h"
+#include "write-or-die.h"
static void pack_line(const char *line)
{
diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c
index 133b5e6f4a..f0bf255f5f 100644
--- a/t/helper/test-prio-queue.c
+++ b/t/helper/test-prio-queue.c
@@ -1,8 +1,7 @@
#include "test-tool.h"
-#include "cache.h"
#include "prio-queue.h"
-static int intcmp(const void *va, const void *vb, void *data)
+static int intcmp(const void *va, const void *vb, void *data UNUSED)
{
const int *a = va, *b = vb;
return *a - *b;
@@ -17,7 +16,7 @@ static void show(int *v)
free(v);
}
-int cmd__prio_queue(int argc, const char **argv)
+int cmd__prio_queue(int argc UNUSED, const char **argv)
{
struct prio_queue pq = { intcmp };
diff --git a/t/helper/test-proc-receive.c b/t/helper/test-proc-receive.c
index cc08506cf0..f30022d222 100644
--- a/t/helper/test-proc-receive.c
+++ b/t/helper/test-proc-receive.c
@@ -1,12 +1,13 @@
-#include "cache.h"
+#include "test-tool.h"
#include "connect.h"
+#include "hex.h"
#include "parse-options.h"
#include "pkt-line.h"
+#include "setup.h"
#include "sigchain.h"
-#include "test-tool.h"
static const char *proc_receive_usage[] = {
- "test-tool proc-receive [<options>...]",
+ "test-tool proc-receive [<options>]",
NULL
};
diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c
index 6cc9735b60..66acb6a06c 100644
--- a/t/helper/test-progress.c
+++ b/t/helper/test-progress.c
@@ -19,7 +19,6 @@
*/
#define GIT_TEST_PROGRESS_ONLY
#include "test-tool.h"
-#include "gettext.h"
#include "parse-options.h"
#include "progress.h"
#include "strbuf.h"
diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index 2f65c7f6a5..3e173399a0 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -1,10 +1,13 @@
#include "test-tool.h"
-#include "cache.h"
#include "commit.h"
#include "commit-reach.h"
#include "config.h"
+#include "gettext.h"
+#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "ref-filter.h"
+#include "setup.h"
#include "string-list.h"
#include "tag.h"
@@ -57,7 +60,7 @@ int cmd__reach(int ac, const char **av)
if (buf.len < 3)
continue;
- if (get_oid_committish(buf.buf + 2, &oid))
+ if (repo_get_oid_committish(the_repository, buf.buf + 2, &oid))
die("failed to resolve %s", buf.buf + 2);
orig = parse_object(r, &oid);
@@ -106,13 +109,17 @@ int cmd__reach(int ac, const char **av)
if (!strcmp(av[1], "ref_newer"))
printf("%s(A,B):%d\n", av[1], ref_newer(&oid_A, &oid_B));
else if (!strcmp(av[1], "in_merge_bases"))
- printf("%s(A,B):%d\n", av[1], in_merge_bases(A, B));
+ printf("%s(A,B):%d\n", av[1],
+ repo_in_merge_bases(the_repository, A, B));
else if (!strcmp(av[1], "in_merge_bases_many"))
- printf("%s(A,X):%d\n", av[1], in_merge_bases_many(A, X_nr, X_array));
+ printf("%s(A,X):%d\n", av[1],
+ repo_in_merge_bases_many(the_repository, A, X_nr, X_array));
else if (!strcmp(av[1], "is_descendant_of"))
printf("%s(A,X):%d\n", av[1], repo_is_descendant_of(r, A, X));
else if (!strcmp(av[1], "get_merge_bases_many")) {
- struct commit_list *list = get_merge_bases_many(A, X_nr, X_array);
+ struct commit_list *list = repo_get_merge_bases_many(the_repository,
+ A, X_nr,
+ X_array);
printf("%s(A,X):\n", av[1]);
print_sorted_commit_ids(list);
} else if (!strcmp(av[1], "reduce_heads")) {
@@ -131,7 +138,7 @@ int cmd__reach(int ac, const char **av)
printf("%s(X,_,_,0,0):%d\n", av[1], can_all_from_reach_with_flag(&X_obj, 2, 4, 0, 0));
} else if (!strcmp(av[1], "commit_contains")) {
- struct ref_filter filter;
+ struct ref_filter filter = REF_FILTER_INIT;
struct contains_cache cache;
init_contains_cache(&cache);
diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index b736ef1642..1acd362346 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -1,6 +1,9 @@
+#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
-#include "cache.h"
#include "config.h"
+#include "read-cache-ll.h"
+#include "repository.h"
+#include "setup.h"
int cmd__read_cache(int argc, const char **argv)
{
@@ -20,7 +23,7 @@ int cmd__read_cache(int argc, const char **argv)
git_config(git_default_config, NULL);
for (i = 0; i < cnt; i++) {
- read_cache();
+ repo_read_index(the_repository);
if (name) {
int pos;
@@ -33,7 +36,7 @@ int cmd__read_cache(int argc, const char **argv)
ce_uptodate(the_index.cache[pos]) ? "" : " not");
write_file(name, "%d\n", i);
}
- discard_cache();
+ discard_index(&the_index);
}
return 0;
}
diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c
index 98b73bb8f2..8c7a83f578 100644
--- a/t/helper/test-read-graph.c
+++ b/t/helper/test-read-graph.c
@@ -1,11 +1,11 @@
#include "test-tool.h"
-#include "cache.h"
#include "commit-graph.h"
#include "repository.h"
-#include "object-store.h"
+#include "object-store-ll.h"
#include "bloom.h"
+#include "setup.h"
-int cmd__read_graph(int argc, const char **argv)
+int cmd__read_graph(int argc UNUSED, const char **argv UNUSED)
{
struct commit_graph *graph = NULL;
struct object_directory *odb;
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
index 27072ba94d..e9a444ddba 100644
--- a/t/helper/test-read-midx.c
+++ b/t/helper/test-read-midx.c
@@ -1,9 +1,11 @@
#include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
#include "midx.h"
#include "repository.h"
-#include "object-store.h"
+#include "object-store-ll.h"
#include "pack-bitmap.h"
+#include "packfile.h"
+#include "setup.h"
static int read_midx_file(const char *object_dir, int show_objects)
{
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index ae8a5648da..48552e6a9e 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -1,9 +1,13 @@
#include "test-tool.h"
-#include "cache.h"
+#include "hex.h"
#include "refs.h"
+#include "setup.h"
#include "worktree.h"
-#include "object-store.h"
+#include "object-store-ll.h"
+#include "path.h"
#include "repository.h"
+#include "strbuf.h"
+#include "revision.h"
struct flag_definition {
const char *name;
@@ -115,8 +119,16 @@ static struct flag_definition pack_flags[] = { FLAG_DEF(PACK_REFS_PRUNE),
static int cmd_pack_refs(struct ref_store *refs, const char **argv)
{
unsigned int flags = arg_flags(*argv++, "flags", pack_flags);
+ static struct ref_exclusions exclusions = REF_EXCLUSIONS_INIT;
+ static struct string_list included_refs = STRING_LIST_INIT_NODUP;
+ struct pack_refs_opts pack_opts = { .flags = flags,
+ .exclusions = &exclusions,
+ .includes = &included_refs };
- return refs_pack_refs(refs, flags);
+ if (pack_opts.flags & PACK_REFS_ALL)
+ string_list_append(pack_opts.includes, "*");
+
+ return refs_pack_refs(refs, &pack_opts);
}
static int cmd_create_symref(struct ref_store *refs, const char **argv)
@@ -174,6 +186,15 @@ static int cmd_for_each_ref(struct ref_store *refs, const char **argv)
return refs_for_each_ref_in(refs, prefix, each_ref, NULL);
}
+static int cmd_for_each_ref__exclude(struct ref_store *refs, const char **argv)
+{
+ const char *prefix = notnull(*argv++, "prefix");
+ const char **exclude_patterns = argv;
+
+ return refs_for_each_fullref_in(refs, prefix, exclude_patterns, each_ref,
+ NULL);
+}
+
static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
{
struct object_id oid = *null_oid();
@@ -200,7 +221,8 @@ static int cmd_verify_ref(struct ref_store *refs, const char **argv)
return ret;
}
-static int cmd_for_each_reflog(struct ref_store *refs, const char **argv)
+static int cmd_for_each_reflog(struct ref_store *refs,
+ const char **argv UNUSED)
{
return refs_for_each_reflog(refs, each_ref, NULL);
}
@@ -255,11 +277,6 @@ static int cmd_delete_reflog(struct ref_store *refs, const char **argv)
return refs_delete_reflog(refs, refname);
}
-static int cmd_reflog_expire(struct ref_store *refs, const char **argv)
-{
- die("not supported yet");
-}
-
static int cmd_delete_ref(struct ref_store *refs, const char **argv)
{
const char *msg = notnull(*argv++, "msg");
@@ -305,6 +322,7 @@ static struct command commands[] = {
{ "delete-refs", cmd_delete_refs },
{ "rename-ref", cmd_rename_ref },
{ "for-each-ref", cmd_for_each_ref },
+ { "for-each-ref--exclude", cmd_for_each_ref__exclude },
{ "resolve-ref", cmd_resolve_ref },
{ "verify-ref", cmd_verify_ref },
{ "for-each-reflog", cmd_for_each_reflog },
@@ -313,7 +331,6 @@ static struct command commands[] = {
{ "reflog-exists", cmd_reflog_exists },
{ "create-reflog", cmd_create_reflog },
{ "delete-reflog", cmd_delete_reflog },
- { "reflog-expire", cmd_reflog_expire },
/*
* backend transaction functions can't be tested separately
*/
@@ -322,7 +339,7 @@ static struct command commands[] = {
{ NULL, NULL }
};
-int cmd__ref_store(int argc, const char **argv)
+int cmd__ref_store(int argc UNUSED, const char **argv)
{
struct ref_store *refs;
const char *func;
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index 1f0a28cbb6..00237ef0d9 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -1,3 +1,4 @@
+#include "reftable/system.h"
#include "reftable/reftable-tests.h"
#include "test-tool.h"
diff --git a/t/helper/test-repository.c b/t/helper/test-repository.c
index 56f0e3c1be..4cd8a952e5 100644
--- a/t/helper/test-repository.c
+++ b/t/helper/test-repository.c
@@ -1,11 +1,13 @@
#include "test-tool.h"
-#include "cache.h"
#include "commit-graph.h"
#include "commit.h"
#include "config.h"
-#include "object-store.h"
+#include "environment.h"
+#include "hex.h"
+#include "object-store-ll.h"
#include "object.h"
#include "repository.h"
+#include "setup.h"
#include "tree.h"
static void test_parse_commit_in_graph(const char *gitdir, const char *worktree,
diff --git a/t/helper/test-revision-walking.c b/t/helper/test-revision-walking.c
index 4a45d5bac2..f346951bc2 100644
--- a/t/helper/test-revision-walking.c
+++ b/t/helper/test-revision-walking.c
@@ -9,17 +9,19 @@
*/
#include "test-tool.h"
-#include "cache.h"
#include "commit.h"
#include "diff.h"
+#include "repository.h"
#include "revision.h"
+#include "setup.h"
static void print_commit(struct commit *commit)
{
struct strbuf sb = STRBUF_INIT;
struct pretty_print_context ctx = {0};
ctx.date_mode.type = DATE_NORMAL;
- format_commit_message(commit, " %m %s", &sb, &ctx);
+ repo_format_commit_message(the_repository, commit, " %m %s", &sb,
+ &ctx);
printf("%s\n", sb.buf);
strbuf_release(&sb);
}
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index c9283b47af..c0ed8722c8 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -9,8 +9,6 @@
*/
#include "test-tool.h"
-#include "git-compat-util.h"
-#include "cache.h"
#include "run-command.h"
#include "strvec.h"
#include "strbuf.h"
@@ -18,13 +16,12 @@
#include "string-list.h"
#include "thread-utils.h"
#include "wildmatch.h"
-#include "gettext.h"
static int number_callbacks;
static int parallel_next(struct child_process *cp,
struct strbuf *err,
void *cb,
- void **task_cb)
+ void **task_cb UNUSED)
{
struct child_process *d = cb;
if (number_callbacks >= 4)
@@ -40,10 +37,10 @@ static int parallel_next(struct child_process *cp,
return 1;
}
-static int no_job(struct child_process *cp,
+static int no_job(struct child_process *cp UNUSED,
struct strbuf *err,
- void *cb,
- void **task_cb)
+ void *cb UNUSED,
+ void **task_cb UNUSED)
{
if (err)
strbuf_addstr(err, "no further jobs available\n");
@@ -52,10 +49,10 @@ static int no_job(struct child_process *cp,
return 0;
}
-static int task_finished(int result,
+static int task_finished(int result UNUSED,
struct strbuf *err,
- void *pp_cb,
- void *pp_task_cb)
+ void *pp_cb UNUSED,
+ void *pp_task_cb UNUSED)
{
if (err)
strbuf_addstr(err, "asking for a quick stop\n");
@@ -136,7 +133,7 @@ static const char * const testsuite_usage[] = {
static int testsuite(int argc, const char **argv)
{
struct testsuite suite = TESTSUITE_INIT;
- int max_jobs = 1, i, ret;
+ int max_jobs = 1, i, ret = 0;
DIR *dir;
struct dirent *d;
struct option options[] = {
@@ -152,6 +149,12 @@ static int testsuite(int argc, const char **argv)
"write JUnit-style XML files"),
OPT_END()
};
+ struct run_process_parallel_opts opts = {
+ .get_next_task = next_test,
+ .start_failure = test_failed,
+ .task_finished = test_finished,
+ .data = &suite,
+ };
argc = parse_options(argc, argv, NULL, options,
testsuite_usage, PARSE_OPT_STOP_AT_NON_OPTION);
@@ -192,8 +195,8 @@ static int testsuite(int argc, const char **argv)
fprintf(stderr, "Running %"PRIuMAX" tests (%d at a time)\n",
(uintmax_t)suite.tests.nr, max_jobs);
- ret = run_processes_parallel(max_jobs, next_test, test_failed,
- test_finished, &suite);
+ opts.processes = max_jobs;
+ run_processes_parallel(&opts);
if (suite.failed.nr > 0) {
ret = 1;
@@ -206,7 +209,7 @@ static int testsuite(int argc, const char **argv)
string_list_clear(&suite.tests, 0);
string_list_clear(&suite.failed, 0);
- return !!ret;
+ return ret;
}
static uint64_t my_random_next = 1234;
@@ -381,13 +384,17 @@ int cmd__run_command(int argc, const char **argv)
{
struct child_process proc = CHILD_PROCESS_INIT;
int jobs;
+ int ret;
+ struct run_process_parallel_opts opts = {
+ .data = &proc,
+ };
if (argc > 1 && !strcmp(argv[1], "testsuite"))
- exit(testsuite(argc - 1, argv + 1));
+ return testsuite(argc - 1, argv + 1);
if (!strcmp(argv[1], "inherited-handle"))
- exit(inherit_handle(argv[0]));
+ return inherit_handle(argv[0]);
if (!strcmp(argv[1], "inherited-handle-child"))
- exit(inherit_handle_child());
+ return inherit_handle_child();
if (argc >= 2 && !strcmp(argv[1], "quote-stress-test"))
return !!quote_stress_test(argc - 1, argv + 1);
@@ -404,41 +411,52 @@ int cmd__run_command(int argc, const char **argv)
argv += 2;
argc -= 2;
}
- if (argc < 3)
- return 1;
+ if (argc < 3) {
+ ret = 1;
+ goto cleanup;
+ }
strvec_pushv(&proc.args, (const char **)argv + 2);
if (!strcmp(argv[1], "start-command-ENOENT")) {
- if (start_command(&proc) < 0 && errno == ENOENT)
- return 0;
+ if (start_command(&proc) < 0 && errno == ENOENT) {
+ ret = 0;
+ goto cleanup;
+ }
fprintf(stderr, "FAIL %s\n", argv[1]);
return 1;
}
- if (!strcmp(argv[1], "run-command"))
- exit(run_command(&proc));
+ if (!strcmp(argv[1], "run-command")) {
+ ret = run_command(&proc);
+ goto cleanup;
+ }
if (!strcmp(argv[1], "--ungroup")) {
argv += 1;
argc -= 1;
- run_processes_parallel_ungroup = 1;
+ opts.ungroup = 1;
}
jobs = atoi(argv[2]);
strvec_clear(&proc.args);
strvec_pushv(&proc.args, (const char **)argv + 3);
- if (!strcmp(argv[1], "run-command-parallel"))
- exit(run_processes_parallel(jobs, parallel_next,
- NULL, NULL, &proc));
-
- if (!strcmp(argv[1], "run-command-abort"))
- exit(run_processes_parallel(jobs, parallel_next,
- NULL, task_finished, &proc));
-
- if (!strcmp(argv[1], "run-command-no-jobs"))
- exit(run_processes_parallel(jobs, no_job,
- NULL, task_finished, &proc));
-
- fprintf(stderr, "check usage\n");
- return 1;
+ if (!strcmp(argv[1], "run-command-parallel")) {
+ opts.get_next_task = parallel_next;
+ } else if (!strcmp(argv[1], "run-command-abort")) {
+ opts.get_next_task = parallel_next;
+ opts.task_finished = task_finished;
+ } else if (!strcmp(argv[1], "run-command-no-jobs")) {
+ opts.get_next_task = no_job;
+ opts.task_finished = task_finished;
+ } else {
+ ret = 1;
+ fprintf(stderr, "check usage\n");
+ goto cleanup;
+ }
+ opts.processes = jobs;
+ run_processes_parallel(&opts);
+ ret = 0;
+cleanup:
+ child_process_clear(&proc);
+ return ret;
}
diff --git a/t/helper/test-scrap-cache-tree.c b/t/helper/test-scrap-cache-tree.c
index 026c802479..0a816a96e2 100644
--- a/t/helper/test-scrap-cache-tree.c
+++ b/t/helper/test-scrap-cache-tree.c
@@ -1,19 +1,22 @@
+#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
-#include "cache.h"
#include "lockfile.h"
+#include "read-cache-ll.h"
+#include "repository.h"
+#include "setup.h"
#include "tree.h"
#include "cache-tree.h"
-int cmd__scrap_cache_tree(int ac, const char **av)
+int cmd__scrap_cache_tree(int ac UNUSED, const char **av UNUSED)
{
struct lock_file index_lock = LOCK_INIT;
setup_git_directory();
- hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
- if (read_cache() < 0)
+ repo_hold_locked_index(the_repository, &index_lock, LOCK_DIE_ON_ERROR);
+ if (repo_read_index(the_repository) < 0)
die("unable to read index file");
- cache_tree_free(&active_cache_tree);
- active_cache_tree = NULL;
+ cache_tree_free(&the_index.cache_tree);
+ the_index.cache_tree = NULL;
if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
die("unable to write index file");
return 0;
diff --git a/t/helper/test-serve-v2.c b/t/helper/test-serve-v2.c
index 824e5c0a95..054cbcf5d8 100644
--- a/t/helper/test-serve-v2.c
+++ b/t/helper/test-serve-v2.c
@@ -1,7 +1,8 @@
#include "test-tool.h"
-#include "cache.h"
+#include "gettext.h"
#include "parse-options.h"
#include "serve.h"
+#include "setup.h"
static char const * const serve_usage[] = {
N_("test-tool serve-v2 [<options>]"),
diff --git a/t/helper/test-sha1.c b/t/helper/test-sha1.c
index d860c387c3..dcb7f6c003 100644
--- a/t/helper/test-sha1.c
+++ b/t/helper/test-sha1.c
@@ -1,7 +1,15 @@
#include "test-tool.h"
-#include "cache.h"
+#include "hash-ll.h"
int cmd__sha1(int ac, const char **av)
{
return cmd_hash_impl(ac, av, GIT_HASH_SHA1);
}
+
+int cmd__sha1_is_sha1dc(int argc UNUSED, const char **argv UNUSED)
+{
+#ifdef platform_SHA_IS_SHA1DC
+ return 0;
+#endif
+ return 1;
+}
diff --git a/t/helper/test-sha256.c b/t/helper/test-sha256.c
index 0ac6a99d5f..08cf149001 100644
--- a/t/helper/test-sha256.c
+++ b/t/helper/test-sha256.c
@@ -1,5 +1,5 @@
#include "test-tool.h"
-#include "cache.h"
+#include "hash-ll.h"
int cmd__sha256(int ac, const char **av)
{
diff --git a/t/helper/test-sigchain.c b/t/helper/test-sigchain.c
index d013bccdda..2d5ecf7383 100644
--- a/t/helper/test-sigchain.c
+++ b/t/helper/test-sigchain.c
@@ -1,5 +1,4 @@
#include "test-tool.h"
-#include "cache.h"
#include "sigchain.h"
#define X(f) \
@@ -14,7 +13,7 @@ X(two)
X(three)
#undef X
-int cmd__sigchain(int argc, const char **argv)
+int cmd__sigchain(int argc UNUSED, const char **argv UNUSED)
{
sigchain_push(SIGTERM, one);
sigchain_push(SIGTERM, two);
diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
index 28365ff85b..3d1436da59 100644
--- a/t/helper/test-simple-ipc.c
+++ b/t/helper/test-simple-ipc.c
@@ -3,13 +3,14 @@
*/
#include "test-tool.h"
-#include "cache.h"
+#include "gettext.h"
#include "strbuf.h"
#include "simple-ipc.h"
#include "parse-options.h"
#include "thread-utils.h"
#include "strvec.h"
#include "run-command.h"
+#include "trace2.h"
#ifndef SUPPORTS_SIMPLE_IPC
int cmd__simple_ipc(int argc, const char **argv)
diff --git a/t/helper/test-strcmp-offset.c b/t/helper/test-strcmp-offset.c
index 44e4a6d143..d8473cf2fc 100644
--- a/t/helper/test-strcmp-offset.c
+++ b/t/helper/test-strcmp-offset.c
@@ -1,7 +1,7 @@
#include "test-tool.h"
-#include "cache.h"
+#include "read-cache-ll.h"
-int cmd__strcmp_offset(int argc, const char **argv)
+int cmd__strcmp_offset(int argc UNUSED, const char **argv)
{
int result;
size_t offset;
diff --git a/t/helper/test-string-list.c b/t/helper/test-string-list.c
index 2123dda85b..e2aad611d1 100644
--- a/t/helper/test-string-list.c
+++ b/t/helper/test-string-list.c
@@ -1,5 +1,5 @@
#include "test-tool.h"
-#include "cache.h"
+#include "strbuf.h"
#include "string-list.h"
/*
@@ -62,7 +62,7 @@ int cmd__string_list(int argc, const char **argv)
struct string_list list = STRING_LIST_INIT_NODUP;
int i;
char *s = xstrdup(argv[2]);
- int delim = *argv[3];
+ const char *delim = argv[3];
int maxsplit = atoi(argv[4]);
i = string_list_split_in_place(&list, s, delim, maxsplit);
@@ -111,7 +111,7 @@ int cmd__string_list(int argc, const char **argv)
*/
if (sb.len && sb.buf[sb.len - 1] == '\n')
strbuf_setlen(&sb, sb.len - 1);
- string_list_split_in_place(&list, sb.buf, '\n', -1);
+ string_list_split_in_place(&list, sb.buf, "\n", -1);
string_list_sort(&list);
diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index 22a41c4092..9df2f03ac8 100644
--- a/t/helper/test-submodule-config.c
+++ b/t/helper/test-submodule-config.c
@@ -1,10 +1,13 @@
#include "test-tool.h"
-#include "cache.h"
#include "config.h"
+#include "hash.h"
+#include "object-name.h"
+#include "repository.h"
+#include "setup.h"
#include "submodule-config.h"
#include "submodule.h"
-static void die_usage(int argc, const char **argv, const char *msg)
+static void die_usage(int argc UNUSED, const char **argv, const char *msg)
{
fprintf(stderr, "%s\n", msg);
fprintf(stderr, "Usage: %s [<commit> <submodulepath>] ...\n", argv[0]);
@@ -42,7 +45,7 @@ int cmd__submodule_config(int argc, const char **argv)
if (commit[0] == '\0')
oidclr(&commit_oid);
- else if (get_oid(commit, &commit_oid) < 0)
+ else if (repo_get_oid(the_repository, commit, &commit_oid) < 0)
die_usage(argc, argv, "Commit not found.");
if (lookup_name) {
diff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c
index dc1c14bde3..ecd40ded99 100644
--- a/t/helper/test-submodule-nested-repo-config.c
+++ b/t/helper/test-submodule-nested-repo-config.c
@@ -1,4 +1,6 @@
#include "test-tool.h"
+#include "repository.h"
+#include "setup.h"
#include "submodule-config.h"
static void die_usage(const char **argv, const char *msg)
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index b7d117cd55..356e0a26c5 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -1,8 +1,9 @@
#include "test-tool.h"
#include "test-tool-utils.h"
-#include "cache.h"
#include "parse-options.h"
#include "remote.h"
+#include "repository.h"
+#include "setup.h"
#include "submodule-config.h"
#include "submodule.h"
@@ -111,10 +112,94 @@ static int cmd__submodule_resolve_relative_url(int argc, const char **argv)
return 0;
}
+static int cmd__submodule_config_list(int argc, const char **argv)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ const char *const usage[] = {
+ "test-tool submodule config-list <key>",
+ NULL
+ };
+ argc = parse_options(argc, argv, "test-tools", options, usage,
+ PARSE_OPT_KEEP_ARGV0);
+
+ setup_git_directory();
+
+ if (argc == 2)
+ return print_config_from_gitmodules(the_repository, argv[1]);
+ usage_with_options(usage, options);
+}
+
+static int cmd__submodule_config_set(int argc, const char **argv)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ const char *const usage[] = {
+ "test-tool submodule config-set <key> <value>",
+ NULL
+ };
+ argc = parse_options(argc, argv, "test-tools", options, usage,
+ PARSE_OPT_KEEP_ARGV0);
+
+ setup_git_directory();
+
+ /* Equivalent to ACTION_SET in builtin/config.c */
+ if (argc == 3) {
+ if (!is_writing_gitmodules_ok())
+ die("please make sure that the .gitmodules file is in the working tree");
+
+ return config_set_in_gitmodules_file_gently(argv[1], argv[2]);
+ }
+ usage_with_options(usage, options);
+}
+
+static int cmd__submodule_config_unset(int argc, const char **argv)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ const char *const usage[] = {
+ "test-tool submodule config-unset <key>",
+ NULL
+ };
+
+ setup_git_directory();
+
+ if (argc == 2) {
+ if (!is_writing_gitmodules_ok())
+ die("please make sure that the .gitmodules file is in the working tree");
+ return config_set_in_gitmodules_file_gently(argv[1], NULL);
+ }
+ usage_with_options(usage, options);
+}
+
+static int cmd__submodule_config_writeable(int argc, const char **argv UNUSED)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ const char *const usage[] = {
+ "test-tool submodule config-writeable",
+ NULL
+ };
+ setup_git_directory();
+
+ if (argc == 1)
+ return is_writing_gitmodules_ok() ? 0 : -1;
+
+ usage_with_options(usage, options);
+}
+
static struct test_cmd cmds[] = {
{ "check-name", cmd__submodule_check_name },
{ "is-active", cmd__submodule_is_active },
{ "resolve-relative-url", cmd__submodule_resolve_relative_url},
+ { "config-list", cmd__submodule_config_list },
+ { "config-set", cmd__submodule_config_set },
+ { "config-unset", cmd__submodule_config_unset },
+ { "config-writeable", cmd__submodule_config_writeable },
};
int cmd__submodule(int argc, const char **argv)
diff --git a/t/helper/test-subprocess.c b/t/helper/test-subprocess.c
index ff22f2fa2c..c344f1694d 100644
--- a/t/helper/test-subprocess.c
+++ b/t/helper/test-subprocess.c
@@ -1,6 +1,6 @@
#include "test-tool.h"
-#include "cache.h"
#include "run-command.h"
+#include "setup.h"
int cmd__subprocess(int argc, const char **argv)
{
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index d1d013bcd9..621ac3dd10 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -13,6 +13,8 @@ static struct test_cmd cmds[] = {
{ "advise", cmd__advise_if_enabled },
{ "bitmap", cmd__bitmap },
{ "bloom", cmd__bloom },
+ { "bundle-uri", cmd__bundle_uri },
+ { "cache-tree", cmd__cache_tree },
{ "chmtime", cmd__chmtime },
{ "config", cmd__config },
{ "crontab", cmd__crontab },
@@ -26,6 +28,7 @@ static struct test_cmd cmds[] = {
{ "dump-fsmonitor", cmd__dump_fsmonitor },
{ "dump-split-index", cmd__dump_split_index },
{ "dump-untracked-cache", cmd__dump_untracked_cache },
+ { "env-helper", cmd__env_helper },
{ "example-decorate", cmd__example_decorate },
{ "fast-rebase", cmd__fast_rebase },
{ "fsmonitor-client", cmd__fsmonitor_client },
@@ -35,7 +38,6 @@ static struct test_cmd cmds[] = {
{ "hashmap", cmd__hashmap },
{ "hash-speed", cmd__hash_speed },
{ "hexdump", cmd__hexdump },
- { "index-version", cmd__index_version },
{ "json-writer", cmd__json_writer },
{ "lazy-init-name-hash", cmd__lazy_init_name_hash },
{ "match-trees", cmd__match_trees },
@@ -72,6 +74,7 @@ static struct test_cmd cmds[] = {
{ "scrap-cache-tree", cmd__scrap_cache_tree },
{ "serve-v2", cmd__serve_v2 },
{ "sha1", cmd__sha1 },
+ { "sha1-is-sha1dc", cmd__sha1_is_sha1dc },
{ "sha256", cmd__sha256 },
{ "sigchain", cmd__sigchain },
{ "simple-ipc", cmd__simple_ipc },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index 6b46b6444b..a641c3a81d 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -1,12 +1,13 @@
#ifndef TEST_TOOL_H
#define TEST_TOOL_H
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
#include "git-compat-util.h"
int cmd__advise_if_enabled(int argc, const char **argv);
int cmd__bitmap(int argc, const char **argv);
int cmd__bloom(int argc, const char **argv);
+int cmd__bundle_uri(int argc, const char **argv);
+int cmd__cache_tree(int argc, const char **argv);
int cmd__chmtime(int argc, const char **argv);
int cmd__config(int argc, const char **argv);
int cmd__crontab(int argc, const char **argv);
@@ -21,6 +22,7 @@ int cmd__dump_fsmonitor(int argc, const char **argv);
int cmd__dump_split_index(int argc, const char **argv);
int cmd__dump_untracked_cache(int argc, const char **argv);
int cmd__dump_reftable(int argc, const char **argv);
+int cmd__env_helper(int argc, const char **argv);
int cmd__example_decorate(int argc, const char **argv);
int cmd__fast_rebase(int argc, const char **argv);
int cmd__fsmonitor_client(int argc, const char **argv);
@@ -30,7 +32,6 @@ int cmd__getcwd(int argc, const char **argv);
int cmd__hashmap(int argc, const char **argv);
int cmd__hash_speed(int argc, const char **argv);
int cmd__hexdump(int argc, const char **argv);
-int cmd__index_version(int argc, const char **argv);
int cmd__json_writer(int argc, const char **argv);
int cmd__lazy_init_name_hash(int argc, const char **argv);
int cmd__match_trees(int argc, const char **argv);
@@ -65,6 +66,7 @@ int cmd__run_command(int argc, const char **argv);
int cmd__scrap_cache_tree(int argc, const char **argv);
int cmd__serve_v2(int argc, const char **argv);
int cmd__sha1(int argc, const char **argv);
+int cmd__sha1_is_sha1dc(int argc, const char **argv);
int cmd__oid_array(int argc, const char **argv);
int cmd__sha256(int argc, const char **argv);
int cmd__sigchain(int argc, const char **argv);
diff --git a/t/helper/test-trace2.c b/t/helper/test-trace2.c
index a714130ece..d5ca0046c8 100644
--- a/t/helper/test-trace2.c
+++ b/t/helper/test-trace2.c
@@ -1,9 +1,10 @@
#include "test-tool.h"
-#include "cache.h"
#include "strvec.h"
#include "run-command.h"
#include "exec-cmd.h"
#include "config.h"
+#include "repository.h"
+#include "trace2.h"
typedef int(fn_unit_test)(int argc, const char **argv);
@@ -44,7 +45,7 @@ static int get_i(int *p_value, const char *data)
* [] "def_param" events for all of the "interesting" pre-defined
* config settings.
*/
-static int ut_001return(int argc, const char **argv)
+static int ut_001return(int argc UNUSED, const char **argv)
{
int rc;
@@ -64,7 +65,7 @@ static int ut_001return(int argc, const char **argv)
* [] "def_param" events for all of the "interesting" pre-defined
* config settings.
*/
-static int ut_002exit(int argc, const char **argv)
+static int ut_002exit(int argc UNUSED, const char **argv)
{
int rc;
@@ -132,6 +133,7 @@ static int ut_003error(int argc, const char **argv)
*/
static int ut_004child(int argc, const char **argv)
{
+ struct child_process cmd = CHILD_PROCESS_INIT;
int result;
/*
@@ -141,7 +143,8 @@ static int ut_004child(int argc, const char **argv)
if (!argc)
return 0;
- result = run_command_v_opt(argv, 0);
+ strvec_pushv(&cmd.args, argv);
+ result = run_command(&cmd);
exit(result);
}
@@ -198,7 +201,7 @@ static int ut_006data(int argc, const char **argv)
return 0;
}
-static int ut_007BUG(int argc, const char **argv)
+static int ut_007BUG(int argc UNUSED, const char **argv UNUSED)
{
/*
* Exercise BUG() to ensure that the message is printed to trace2.
@@ -206,7 +209,7 @@ static int ut_007BUG(int argc, const char **argv)
BUG("the bug message");
}
-static int ut_008bug(int argc, const char **argv)
+static int ut_008bug(int argc UNUSED, const char **argv UNUSED)
{
bug("a bug message");
bug("another bug message");
@@ -214,7 +217,7 @@ static int ut_008bug(int argc, const char **argv)
return 0;
}
-static int ut_009bug_BUG(int argc, const char **argv)
+static int ut_009bug_BUG(int argc UNUSED, const char **argv UNUSED)
{
bug("a bug message");
bug("another bug message");
@@ -222,13 +225,194 @@ static int ut_009bug_BUG(int argc, const char **argv)
return 0;
}
-static int ut_010bug_BUG(int argc, const char **argv)
+static int ut_010bug_BUG(int argc UNUSED, const char **argv UNUSED)
{
bug("a %s message", "bug");
BUG("a %s message", "BUG");
}
/*
+ * Single-threaded timer test. Create several intervals using the
+ * TEST1 timer. The test script can verify that an aggregate Trace2
+ * "timer" event is emitted indicating that we started+stopped the
+ * timer the requested number of times.
+ */
+static int ut_100timer(int argc, const char **argv)
+{
+ const char *usage_error =
+ "expect <count> <ms_delay>";
+
+ int count = 0;
+ int delay = 0;
+ int k;
+
+ if (argc != 2)
+ die("%s", usage_error);
+ if (get_i(&count, argv[0]))
+ die("%s", usage_error);
+ if (get_i(&delay, argv[1]))
+ die("%s", usage_error);
+
+ for (k = 0; k < count; k++) {
+ trace2_timer_start(TRACE2_TIMER_ID_TEST1);
+ sleep_millisec(delay);
+ trace2_timer_stop(TRACE2_TIMER_ID_TEST1);
+ }
+
+ return 0;
+}
+
+struct ut_101_data {
+ int count;
+ int delay;
+};
+
+static void *ut_101timer_thread_proc(void *_ut_101_data)
+{
+ struct ut_101_data *data = _ut_101_data;
+ int k;
+
+ trace2_thread_start("ut_101");
+
+ for (k = 0; k < data->count; k++) {
+ trace2_timer_start(TRACE2_TIMER_ID_TEST2);
+ sleep_millisec(data->delay);
+ trace2_timer_stop(TRACE2_TIMER_ID_TEST2);
+ }
+
+ trace2_thread_exit();
+ return NULL;
+}
+
+/*
+ * Multi-threaded timer test. Create several threads that each create
+ * several intervals using the TEST2 timer. The test script can verify
+ * that an individual Trace2 "th_timer" events for each thread and an
+ * aggregate "timer" event are generated.
+ */
+static int ut_101timer(int argc, const char **argv)
+{
+ const char *usage_error =
+ "expect <count> <ms_delay> <threads>";
+
+ struct ut_101_data data = { 0, 0 };
+ int nr_threads = 0;
+ int k;
+ pthread_t *pids = NULL;
+
+ if (argc != 3)
+ die("%s", usage_error);
+ if (get_i(&data.count, argv[0]))
+ die("%s", usage_error);
+ if (get_i(&data.delay, argv[1]))
+ die("%s", usage_error);
+ if (get_i(&nr_threads, argv[2]))
+ die("%s", usage_error);
+
+ CALLOC_ARRAY(pids, nr_threads);
+
+ for (k = 0; k < nr_threads; k++) {
+ if (pthread_create(&pids[k], NULL, ut_101timer_thread_proc, &data))
+ die("failed to create thread[%d]", k);
+ }
+
+ for (k = 0; k < nr_threads; k++) {
+ if (pthread_join(pids[k], NULL))
+ die("failed to join thread[%d]", k);
+ }
+
+ free(pids);
+
+ return 0;
+}
+
+/*
+ * Single-threaded counter test. Add several values to the TEST1 counter.
+ * The test script can verify that the final sum is reported in the "counter"
+ * event.
+ */
+static int ut_200counter(int argc, const char **argv)
+{
+ const char *usage_error =
+ "expect <v1> [<v2> [...]]";
+ int value;
+ int k;
+
+ if (argc < 1)
+ die("%s", usage_error);
+
+ for (k = 0; k < argc; k++) {
+ if (get_i(&value, argv[k]))
+ die("invalid value[%s] -- %s",
+ argv[k], usage_error);
+ trace2_counter_add(TRACE2_COUNTER_ID_TEST1, value);
+ }
+
+ return 0;
+}
+
+/*
+ * Multi-threaded counter test. Create seveal threads that each increment
+ * the TEST2 global counter. The test script can verify that an individual
+ * "th_counter" event is generated with a partial sum for each thread and
+ * that a final aggregate "counter" event is generated.
+ */
+
+struct ut_201_data {
+ int v1;
+ int v2;
+};
+
+static void *ut_201counter_thread_proc(void *_ut_201_data)
+{
+ struct ut_201_data *data = _ut_201_data;
+
+ trace2_thread_start("ut_201");
+
+ trace2_counter_add(TRACE2_COUNTER_ID_TEST2, data->v1);
+ trace2_counter_add(TRACE2_COUNTER_ID_TEST2, data->v2);
+
+ trace2_thread_exit();
+ return NULL;
+}
+
+static int ut_201counter(int argc, const char **argv)
+{
+ const char *usage_error =
+ "expect <v1> <v2> <threads>";
+
+ struct ut_201_data data = { 0, 0 };
+ int nr_threads = 0;
+ int k;
+ pthread_t *pids = NULL;
+
+ if (argc != 3)
+ die("%s", usage_error);
+ if (get_i(&data.v1, argv[0]))
+ die("%s", usage_error);
+ if (get_i(&data.v2, argv[1]))
+ die("%s", usage_error);
+ if (get_i(&nr_threads, argv[2]))
+ die("%s", usage_error);
+
+ CALLOC_ARRAY(pids, nr_threads);
+
+ for (k = 0; k < nr_threads; k++) {
+ if (pthread_create(&pids[k], NULL, ut_201counter_thread_proc, &data))
+ die("failed to create thread[%d]", k);
+ }
+
+ for (k = 0; k < nr_threads; k++) {
+ if (pthread_join(pids[k], NULL))
+ die("failed to join thread[%d]", k);
+ }
+
+ free(pids);
+
+ return 0;
+}
+
+/*
* Usage:
* test-tool trace2 <ut_name_1> <ut_usage_1>
* test-tool trace2 <ut_name_2> <ut_usage_2>
@@ -248,6 +432,12 @@ static struct unit_test ut_table[] = {
{ ut_008bug, "008bug", "" },
{ ut_009bug_BUG, "009bug_BUG","" },
{ ut_010bug_BUG, "010bug_BUG","" },
+
+ { ut_100timer, "100timer", "<count> <ms_delay>" },
+ { ut_101timer, "101timer", "<count> <ms_delay> <threads>" },
+
+ { ut_200counter, "200counter", "<v1> [<v2> [<v3> [...]]]" },
+ { ut_201counter, "201counter", "<v1> <v2> <threads>" },
};
/* clang-format on */
diff --git a/t/helper/test-userdiff.c b/t/helper/test-userdiff.c
index a2b56b9cae..0ce31ce59f 100644
--- a/t/helper/test-userdiff.c
+++ b/t/helper/test-userdiff.c
@@ -1,5 +1,5 @@
#include "test-tool.h"
-#include "cache.h"
+#include "setup.h"
#include "userdiff.h"
#include "config.h"
@@ -12,7 +12,9 @@ static int driver_cb(struct userdiff_driver *driver,
return 0;
}
-static int cmd__userdiff_config(const char *var, const char *value, void *cb UNUSED)
+static int cmd__userdiff_config(const char *var, const char *value,
+ const struct config_context *ctx UNUSED,
+ void *cb UNUSED)
{
if (userdiff_config(var, value) < 0)
return -1;
diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c
index 2c103d1824..b4ff5f986a 100644
--- a/t/helper/test-wildmatch.c
+++ b/t/helper/test-wildmatch.c
@@ -1,5 +1,5 @@
#include "test-tool.h"
-#include "cache.h"
+#include "wildmatch.h"
int cmd__wildmatch(int argc, const char **argv)
{
diff --git a/t/helper/test-write-cache.c b/t/helper/test-write-cache.c
index 8837717d36..f084034d38 100644
--- a/t/helper/test-write-cache.c
+++ b/t/helper/test-write-cache.c
@@ -1,6 +1,9 @@
+#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
-#include "cache.h"
#include "lockfile.h"
+#include "read-cache-ll.h"
+#include "repository.h"
+#include "setup.h"
int cmd__write_cache(int argc, const char **argv)
{
@@ -9,9 +12,10 @@ int cmd__write_cache(int argc, const char **argv)
if (argc == 2)
cnt = strtol(argv[1], NULL, 0);
setup_git_directory();
- read_cache();
+ repo_read_index(the_repository);
for (i = 0; i < cnt; i++) {
- hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
+ repo_hold_locked_index(the_repository, &index_lock,
+ LOCK_DIE_ON_ERROR);
if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
die("unable to write index file");
}
diff --git a/t/helper/test-xml-encode.c b/t/helper/test-xml-encode.c
index a648bbd961..b2f330d1a4 100644
--- a/t/helper/test-xml-encode.c
+++ b/t/helper/test-xml-encode.c
@@ -6,7 +6,7 @@ static const char *utf8_replace_character = "&#xfffd;";
* Encodes (possibly incorrect) UTF-8 on <stdin> to <stdout>, to be embedded
* in an XML file.
*/
-int cmd__xml_encode(int argc, const char **argv)
+int cmd__xml_encode(int argc UNUSED, const char **argv UNUSED)
{
unsigned char buf[1024], tmp[4], *tmp2 = NULL;
ssize_t cur = 0, len = 1, remaining = 0;
diff --git a/t/interop/interop-lib.sh b/t/interop/interop-lib.sh
index 3e0a2911d4..62f4481b6e 100644
--- a/t/interop/interop-lib.sh
+++ b/t/interop/interop-lib.sh
@@ -68,7 +68,7 @@ generate_wrappers () {
wrap_git .bin/git.a "$DIR_A" &&
wrap_git .bin/git.b "$DIR_B" &&
write_script .bin/git <<-\EOF &&
- echo >&2 fatal: test tried to run generic git
+ echo >&2 fatal: test tried to run generic git: $*
exit 1
EOF
PATH=$(pwd)/.bin:$PATH
diff --git a/t/lib-bundle-uri-protocol.sh b/t/lib-bundle-uri-protocol.sh
new file mode 100644
index 0000000000..a4a1af8d02
--- /dev/null
+++ b/t/lib-bundle-uri-protocol.sh
@@ -0,0 +1,216 @@
+# Set up and run tests of the 'bundle-uri' command in protocol v2
+#
+# The test that includes this script should set BUNDLE_URI_PROTOCOL
+# to one of "file", "git", or "http".
+
+BUNDLE_URI_TEST_PARENT=
+BUNDLE_URI_TEST_URI=
+BUNDLE_URI_TEST_BUNDLE_URI=
+case "$BUNDLE_URI_PROTOCOL" in
+file)
+ BUNDLE_URI_PARENT=file_parent
+ BUNDLE_URI_REPO_URI="file://$PWD/file_parent"
+ BUNDLE_URI_BUNDLE_URI="$BUNDLE_URI_REPO_URI/fake.bdl"
+ test_set_prereq BUNDLE_URI_FILE
+ ;;
+git)
+ . "$TEST_DIRECTORY"/lib-git-daemon.sh
+ start_git_daemon --export-all --enable=receive-pack
+ BUNDLE_URI_PARENT="$GIT_DAEMON_DOCUMENT_ROOT_PATH/parent"
+ BUNDLE_URI_REPO_URI="$GIT_DAEMON_URL/parent"
+ BUNDLE_URI_BUNDLE_URI="https://example.com/fake.bdl"
+ test_set_prereq BUNDLE_URI_GIT
+ ;;
+http)
+ . "$TEST_DIRECTORY"/lib-httpd.sh
+ start_httpd
+ BUNDLE_URI_PARENT="$HTTPD_DOCUMENT_ROOT_PATH/http_parent"
+ BUNDLE_URI_REPO_URI="$HTTPD_URL/smart/http_parent"
+ BUNDLE_URI_BUNDLE_URI="https://example.com/fake.bdl"
+ test_set_prereq BUNDLE_URI_HTTP
+ ;;
+*)
+ BUG "Need to pass valid BUNDLE_URI_PROTOCOL (was \"$BUNDLE_URI_PROTOCOL\")"
+ ;;
+esac
+
+test_expect_success "setup protocol v2 $BUNDLE_URI_PROTOCOL:// tests" '
+ git init "$BUNDLE_URI_PARENT" &&
+ test_commit -C "$BUNDLE_URI_PARENT" one &&
+ git -C "$BUNDLE_URI_PARENT" config uploadpack.advertiseBundleURIs true
+'
+
+case "$BUNDLE_URI_PROTOCOL" in
+http)
+ test_expect_success "setup config for $BUNDLE_URI_PROTOCOL:// tests" '
+ git -C "$BUNDLE_URI_PARENT" config http.receivepack true
+ '
+ ;;
+*)
+ ;;
+esac
+BUNDLE_URI_BUNDLE_URI_ESCAPED=$(echo "$BUNDLE_URI_BUNDLE_URI" | test_uri_escape)
+
+test_expect_success "connect with $BUNDLE_URI_PROTOCOL:// using protocol v2: no bundle-uri" '
+ test_when_finished "rm -f log" &&
+ test_when_finished "git -C \"$BUNDLE_URI_PARENT\" config uploadpack.advertiseBundleURIs true" &&
+ git -C "$BUNDLE_URI_PARENT" config uploadpack.advertiseBundleURIs false &&
+
+ GIT_TRACE_PACKET="$PWD/log" \
+ git \
+ -c protocol.version=2 \
+ ls-remote --symref "$BUNDLE_URI_REPO_URI" \
+ >actual 2>err &&
+
+ # Server responded using protocol v2
+ grep "< version 2" log &&
+
+ ! grep bundle-uri log
+'
+
+test_expect_success "connect with $BUNDLE_URI_PROTOCOL:// using protocol v2: have bundle-uri" '
+ test_when_finished "rm -f log" &&
+
+ GIT_TRACE_PACKET="$PWD/log" \
+ git \
+ -c protocol.version=2 \
+ ls-remote --symref "$BUNDLE_URI_REPO_URI" \
+ >actual 2>err &&
+
+ # Server responded using protocol v2
+ grep "< version 2" log &&
+
+ # Server advertised bundle-uri capability
+ grep "< bundle-uri" log
+'
+
+test_expect_success "clone with $BUNDLE_URI_PROTOCOL:// using protocol v2: request bundle-uris" '
+ test_when_finished "rm -rf log* cloned*" &&
+
+ GIT_TRACE_PACKET="$PWD/log" \
+ git \
+ -c transfer.bundleURI=false \
+ -c protocol.version=2 \
+ clone "$BUNDLE_URI_REPO_URI" cloned \
+ >actual 2>err &&
+
+ # Server responded using protocol v2
+ grep "< version 2" log &&
+
+ # Server advertised bundle-uri capability
+ grep "< bundle-uri" log &&
+
+ # Client did not issue bundle-uri command
+ ! grep "> command=bundle-uri" log &&
+
+ GIT_TRACE_PACKET="$PWD/log" \
+ git \
+ -c transfer.bundleURI=true \
+ -c protocol.version=2 \
+ clone "$BUNDLE_URI_REPO_URI" cloned2 \
+ >actual 2>err &&
+
+ # Server responded using protocol v2
+ grep "< version 2" log &&
+
+ # Server advertised bundle-uri capability
+ grep "< bundle-uri" log &&
+
+ # Client issued bundle-uri command
+ grep "> command=bundle-uri" log &&
+
+ GIT_TRACE_PACKET="$PWD/log3" \
+ git \
+ -c transfer.bundleURI=true \
+ -c protocol.version=2 \
+ clone --bundle-uri="$BUNDLE_URI_BUNDLE_URI" \
+ "$BUNDLE_URI_REPO_URI" cloned3 \
+ >actual 2>err &&
+
+ # Server responded using protocol v2
+ grep "< version 2" log3 &&
+
+ # Server advertised bundle-uri capability
+ grep "< bundle-uri" log3 &&
+
+ # Client did not issue bundle-uri command (--bundle-uri override)
+ ! grep "> command=bundle-uri" log3
+'
+
+# The remaining tests will all assume transfer.bundleURI=true
+#
+# This test can be removed when transfer.bundleURI is enabled by default.
+test_expect_success 'enable transfer.bundleURI for remaining tests' '
+ git config --global transfer.bundleURI true
+'
+
+test_expect_success "test bundle-uri with $BUNDLE_URI_PROTOCOL:// using protocol v2" '
+ test_config -C "$BUNDLE_URI_PARENT" \
+ bundle.only.uri "$BUNDLE_URI_BUNDLE_URI_ESCAPED" &&
+
+ # All data about bundle URIs
+ cat >expect <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "only"]
+ uri = $BUNDLE_URI_BUNDLE_URI_ESCAPED
+ EOF
+
+ test-tool bundle-uri \
+ ls-remote \
+ "$BUNDLE_URI_REPO_URI" \
+ >actual &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success "test bundle-uri with $BUNDLE_URI_PROTOCOL:// using protocol v2 and extra data" '
+ test_config -C "$BUNDLE_URI_PARENT" \
+ bundle.only.uri "$BUNDLE_URI_BUNDLE_URI_ESCAPED" &&
+
+ # Extra data should be ignored
+ test_config -C "$BUNDLE_URI_PARENT" bundle.only.extra bogus &&
+
+ # All data about bundle URIs
+ cat >expect <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "only"]
+ uri = $BUNDLE_URI_BUNDLE_URI_ESCAPED
+ EOF
+
+ test-tool bundle-uri \
+ ls-remote \
+ "$BUNDLE_URI_REPO_URI" \
+ >actual &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success "test bundle-uri with $BUNDLE_URI_PROTOCOL:// using protocol v2 with list" '
+ test_config -C "$BUNDLE_URI_PARENT" \
+ bundle.bundle1.uri "$BUNDLE_URI_BUNDLE_URI_ESCAPED-1.bdl" &&
+ test_config -C "$BUNDLE_URI_PARENT" \
+ bundle.bundle2.uri "$BUNDLE_URI_BUNDLE_URI_ESCAPED-2.bdl" &&
+ test_config -C "$BUNDLE_URI_PARENT" \
+ bundle.bundle3.uri "$BUNDLE_URI_BUNDLE_URI_ESCAPED-3.bdl" &&
+
+ # All data about bundle URIs
+ cat >expect <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "bundle1"]
+ uri = $BUNDLE_URI_BUNDLE_URI_ESCAPED-1.bdl
+ [bundle "bundle2"]
+ uri = $BUNDLE_URI_BUNDLE_URI_ESCAPED-2.bdl
+ [bundle "bundle3"]
+ uri = $BUNDLE_URI_BUNDLE_URI_ESCAPED-3.bdl
+ EOF
+
+ test-tool bundle-uri \
+ ls-remote \
+ "$BUNDLE_URI_REPO_URI" \
+ >actual &&
+ test_cmp_config_output expect actual
+'
diff --git a/t/lib-commit-graph.sh b/t/lib-commit-graph.sh
index 5d79e1a4e9..89b26676fb 100755
--- a/t/lib-commit-graph.sh
+++ b/t/lib-commit-graph.sh
@@ -14,24 +14,37 @@ graph_git_two_modes() {
test_cmp expect output
}
+# graph_git_behavior <name> <directory> <branch> <compare>
+#
+# Ensures that a handful of traversal operations produce the same
+# results with and without the commit-graph in use.
+#
+# NOTE: it is a bug to call this function with <directory> containing
+# any characters in $IFS.
graph_git_behavior() {
MSG=$1
DIR=$2
BRANCH=$3
COMPARE=$4
test_expect_success "check normal git operations: $MSG" '
- cd "$TRASH_DIRECTORY/$DIR" &&
- graph_git_two_modes "log --oneline $BRANCH" &&
- graph_git_two_modes "log --topo-order $BRANCH" &&
- graph_git_two_modes "log --graph $COMPARE..$BRANCH" &&
- graph_git_two_modes "branch -vv" &&
- graph_git_two_modes "merge-base -a $BRANCH $COMPARE"
+ graph_git_two_modes "${DIR:+-C $DIR} log --oneline $BRANCH" &&
+ graph_git_two_modes "${DIR:+-C $DIR} log --topo-order $BRANCH" &&
+ graph_git_two_modes "${DIR:+-C $DIR} log --graph $COMPARE..$BRANCH" &&
+ graph_git_two_modes "${DIR:+-C $DIR} branch -vv" &&
+ graph_git_two_modes "${DIR:+-C $DIR} merge-base -a $BRANCH $COMPARE"
'
}
graph_read_expect() {
OPTIONAL=""
NUM_CHUNKS=3
+ DIR="."
+ if test "$1" = -C
+ then
+ shift
+ DIR="$1"
+ shift
+ fi
if test -n "$2"
then
OPTIONAL=" $2"
@@ -47,12 +60,15 @@ graph_read_expect() {
then
OPTIONS=" read_generation_data"
fi
- cat >expect <<- EOF
+ cat >"$DIR/expect" <<-EOF
header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
num_commits: $1
chunks: oid_fanout oid_lookup commit_metadata$OPTIONAL
options:$OPTIONS
EOF
- test-tool read-graph >output &&
- test_cmp expect output
+ (
+ cd "$DIR" &&
+ test-tool read-graph >output &&
+ test_cmp expect output
+ )
}
diff --git a/t/lib-credential.sh b/t/lib-credential.sh
index 5ea8bc9f1d..15fc9a31e2 100644
--- a/t/lib-credential.sh
+++ b/t/lib-credential.sh
@@ -43,6 +43,13 @@ helper_test_clean() {
reject $1 https example.com store-user
reject $1 https example.com user1
reject $1 https example.com user2
+ reject $1 https example.com user-expiry
+ reject $1 https example.com user-expiry-overwrite
+ reject $1 https example.com user4
+ reject $1 https example.com user-distinct-pass
+ reject $1 https example.com user-overwrite
+ reject $1 https example.com user-erase1
+ reject $1 https example.com user-erase2
reject $1 http path.tld user
reject $1 https timeout.tld user
reject $1 https sso.tld
@@ -166,6 +173,49 @@ helper_test() {
EOF
'
+ test_expect_success "helper ($HELPER) overwrites on store" '
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-overwrite
+ password=pass1
+ EOF
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-overwrite
+ password=pass2
+ EOF
+ check fill $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-overwrite
+ --
+ protocol=https
+ host=example.com
+ username=user-overwrite
+ password=pass2
+ EOF
+ check reject $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-overwrite
+ password=pass2
+ EOF
+ check fill $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ username=user-overwrite
+ --
+ protocol=https
+ host=example.com
+ username=user-overwrite
+ password=askpass-password
+ --
+ askpass: Password for '\''https://user-overwrite@example.com'\'':
+ EOF
+ '
+
test_expect_success "helper ($HELPER) can forget host" '
check reject $HELPER <<-\EOF &&
protocol=https
@@ -220,6 +270,31 @@ helper_test() {
EOF
'
+ test_expect_success "helper ($HELPER) does not erase a password distinct from input" '
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-distinct-pass
+ password=pass1
+ EOF
+ check reject $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-distinct-pass
+ password=pass2
+ EOF
+ check fill $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ username=user-distinct-pass
+ --
+ protocol=https
+ host=example.com
+ username=user-distinct-pass
+ password=pass1
+ EOF
+ '
+
test_expect_success "helper ($HELPER) can forget user" '
check reject $HELPER <<-\EOF &&
protocol=https
@@ -270,6 +345,66 @@ helper_test() {
password=
EOF
'
+
+ test_expect_success "helper ($HELPER) erases all matching credentials" '
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-erase1
+ password=pass1
+ EOF
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-erase2
+ password=pass1
+ EOF
+ check reject $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ EOF
+ check fill $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ --
+ protocol=https
+ host=example.com
+ username=askpass-username
+ password=askpass-password
+ --
+ askpass: Username for '\''https://example.com'\'':
+ askpass: Password for '\''https://askpass-username@example.com'\'':
+ EOF
+ '
+
+ : ${GIT_TEST_LONG_CRED_BUFFER:=1024}
+ # 23 bytes accounts for "wwwauth[]=basic realm=" plus NUL
+ LONG_VALUE_LEN=$((GIT_TEST_LONG_CRED_BUFFER - 23))
+ LONG_VALUE=$(perl -e 'print "a" x shift' $LONG_VALUE_LEN)
+
+ test_expect_success "helper ($HELPER) not confused by long header" '
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=victim.example.com
+ username=user
+ password=to-be-stolen
+ EOF
+
+ check fill $HELPER <<-EOF
+ protocol=https
+ host=badguy.example.com
+ wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com
+ --
+ protocol=https
+ host=badguy.example.com
+ username=askpass-username
+ password=askpass-password
+ wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com
+ --
+ askpass: Username for '\''https://badguy.example.com'\'':
+ askpass: Password for '\''https://askpass-username@badguy.example.com'\'':
+ EOF
+ '
}
helper_test_timeout() {
@@ -298,6 +433,110 @@ helper_test_timeout() {
'
}
+helper_test_password_expiry_utc() {
+ HELPER=$1
+
+ test_expect_success "helper ($HELPER) stores password_expiry_utc" '
+ check approve $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ username=user-expiry
+ password=pass
+ password_expiry_utc=9999999999
+ EOF
+ '
+
+ test_expect_success "helper ($HELPER) gets password_expiry_utc" '
+ check fill $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ username=user-expiry
+ --
+ protocol=https
+ host=example.com
+ username=user-expiry
+ password=pass
+ password_expiry_utc=9999999999
+ --
+ EOF
+ '
+
+ test_expect_success "helper ($HELPER) overwrites when password_expiry_utc changes" '
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-expiry-overwrite
+ password=pass1
+ password_expiry_utc=9999999998
+ EOF
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-expiry-overwrite
+ password=pass2
+ password_expiry_utc=9999999999
+ EOF
+ check fill $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-expiry-overwrite
+ --
+ protocol=https
+ host=example.com
+ username=user-expiry-overwrite
+ password=pass2
+ password_expiry_utc=9999999999
+ EOF
+ check reject $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user-expiry-overwrite
+ password=pass2
+ EOF
+ check fill $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ username=user-expiry-overwrite
+ --
+ protocol=https
+ host=example.com
+ username=user-expiry-overwrite
+ password=askpass-password
+ --
+ askpass: Password for '\''https://user-expiry-overwrite@example.com'\'':
+ EOF
+ '
+}
+
+helper_test_oauth_refresh_token() {
+ HELPER=$1
+
+ test_expect_success "helper ($HELPER) stores oauth_refresh_token" '
+ check approve $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ username=user4
+ password=pass
+ oauth_refresh_token=xyzzy
+ EOF
+ '
+
+ test_expect_success "helper ($HELPER) gets oauth_refresh_token" '
+ check fill $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ username=user4
+ --
+ protocol=https
+ host=example.com
+ username=user4
+ password=pass
+ oauth_refresh_token=xyzzy
+ --
+ EOF
+ '
+}
+
write_script askpass <<\EOF
echo >&2 askpass: $*
what=$(echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z)
diff --git a/t/lib-diff-alternative.sh b/t/lib-diff-alternative.sh
index 8d1e408bb5..c4dc2d46dc 100644
--- a/t/lib-diff-alternative.sh
+++ b/t/lib-diff-alternative.sh
@@ -105,10 +105,67 @@ index $file1..$file2 100644
}
EOF
+ cat >expect_diffstat <<EOF
+ file1 => file2 | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+EOF
+
STRATEGY=$1
+ test_expect_success "setup attributes files for tests with $STRATEGY" '
+ git checkout -b master &&
+ echo "file* diff=driver" >.gitattributes &&
+ git add file1 file2 .gitattributes &&
+ git commit -m "adding files" &&
+ git checkout -b branchA &&
+ echo "file* diff=driverA" >.gitattributes &&
+ git add .gitattributes &&
+ git commit -m "adding driverA as diff driver" &&
+ git checkout master &&
+ git clone --bare --no-local . bare.git
+ '
+
+ test_expect_success "$STRATEGY diff from attributes" '
+ test_must_fail git -c diff.driver.algorithm=$STRATEGY diff --no-index file1 file2 > output &&
+ test_cmp expect output
+ '
+
+ test_expect_success "diff from attributes with bare repo with source" '
+ git -C bare.git --attr-source=branchA -c diff.driver.algorithm=myers \
+ -c diff.driverA.algorithm=$STRATEGY \
+ diff HEAD:file1 HEAD:file2 >output &&
+ test_cmp expect output
+ '
+
+ test_expect_success "diff from attributes with bare repo with invalid source" '
+ test_must_fail git -C bare.git --attr-source=invalid-branch diff \
+ HEAD:file1 HEAD:file2
+ '
+
+ test_expect_success "$STRATEGY diff from attributes has valid diffstat" '
+ echo "file* diff=driver" >.gitattributes &&
+ git config diff.driver.algorithm "$STRATEGY" &&
+ test_must_fail git diff --stat --no-index file1 file2 > output &&
+ test_cmp expect_diffstat output
+ '
+
test_expect_success "$STRATEGY diff" '
- test_must_fail git diff --no-index "--$STRATEGY" file1 file2 > output &&
+ test_must_fail git diff --no-index "--diff-algorithm=$STRATEGY" file1 file2 > output &&
+ test_cmp expect output
+ '
+
+ test_expect_success "$STRATEGY diff command line precedence before attributes" '
+ echo "file* diff=driver" >.gitattributes &&
+ git config diff.driver.algorithm myers &&
+ test_must_fail git diff --no-index "--diff-algorithm=$STRATEGY" file1 file2 > output &&
+ test_cmp expect output
+ '
+
+ test_expect_success "$STRATEGY diff attributes precedence before config" '
+ git config diff.algorithm default &&
+ echo "file* diff=driver" >.gitattributes &&
+ git config diff.driver.algorithm "$STRATEGY" &&
+ test_must_fail git diff --no-index file1 file2 > output &&
test_cmp expect output
'
diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh
index 114785586a..83b83c9abb 100644
--- a/t/lib-gpg.sh
+++ b/t/lib-gpg.sh
@@ -45,6 +45,28 @@ test_lazy_prereq GPG '
"$TEST_DIRECTORY"/lib-gpg/keyring.gpg &&
gpg --homedir "${GNUPGHOME}" --import-ownertrust \
"$TEST_DIRECTORY"/lib-gpg/ownertrust &&
+ gpg --homedir "${GNUPGHOME}" --update-trustdb &&
+ gpg --homedir "${GNUPGHOME}" </dev/null >/dev/null \
+ --sign -u committer@example.com
+ ;;
+ esac
+'
+
+test_lazy_prereq GPG2 '
+ gpg_version=$(gpg --version 2>&1)
+ test $? != 127 || exit 1
+
+ case "$gpg_version" in
+ "gpg (GnuPG) "[01].*)
+ say "This test requires a GPG version >= v2.0.0"
+ exit 1
+ ;;
+ *)
+ (gpgconf --kill all || : ) &&
+ gpg --homedir "${GNUPGHOME}" --import \
+ "$TEST_DIRECTORY"/lib-gpg/keyring.gpg &&
+ gpg --homedir "${GNUPGHOME}" --import-ownertrust \
+ "$TEST_DIRECTORY"/lib-gpg/ownertrust &&
gpg --homedir "${GNUPGHOME}" </dev/null >/dev/null \
--sign -u committer@example.com
;;
@@ -135,8 +157,9 @@ test_lazy_prereq GPGSSH '
'
test_lazy_prereq GPGSSH_VERIFYTIME '
+ test_have_prereq GPGSSH &&
# Check if ssh-keygen has a verify-time option by passing an invalid date to it
- ssh-keygen -Overify-time=INVALID -Y check-novalidate -s doesnotmatter 2>&1 | grep -q -F "Invalid \"verify-time\"" &&
+ ssh-keygen -Overify-time=INVALID -Y check-novalidate -n "git" -s doesnotmatter 2>&1 | grep -q -F "Invalid \"verify-time\"" &&
# Set up keys with key lifetimes
ssh-keygen -t ed25519 -N "" -C "timeboxed valid key" -f "${GPGSSH_KEY_TIMEBOXEDVALID}" >/dev/null &&
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index 1f6b9b08d1..2fb1b2ae56 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -25,6 +25,7 @@
# LIB_HTTPD_DAV enable DAV
# LIB_HTTPD_SVN enable SVN at given location (e.g. "svn")
# LIB_HTTPD_SSL enable SSL
+# LIB_HTTPD_PROXY enable proxy
#
# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
#
@@ -65,7 +66,8 @@ done
for DEFAULT_HTTPD_MODULE_PATH in '/usr/libexec/apache2' \
'/usr/lib/apache2/modules' \
'/usr/lib64/httpd/modules' \
- '/usr/lib/httpd/modules'
+ '/usr/lib/httpd/modules' \
+ '/usr/libexec/httpd'
do
if test -d "$DEFAULT_HTTPD_MODULE_PATH"
then
@@ -98,16 +100,19 @@ then
fi
HTTPD_VERSION=$($LIB_HTTPD_PATH -v | \
- sed -n 's/^Server version: Apache\/\([0-9]*\)\..*$/\1/p; q')
+ sed -n 's/^Server version: Apache\/\([0-9.]*\).*$/\1/p; q')
+HTTPD_VERSION_MAJOR=$(echo $HTTPD_VERSION | cut -d. -f1)
+HTTPD_VERSION_MINOR=$(echo $HTTPD_VERSION | cut -d. -f2)
-if test -n "$HTTPD_VERSION"
+if test -n "$HTTPD_VERSION_MAJOR"
then
if test -z "$LIB_HTTPD_MODULE_PATH"
then
- if ! test $HTTPD_VERSION -ge 2
+ if ! test "$HTTPD_VERSION_MAJOR" -eq 2 ||
+ ! test "$HTTPD_VERSION_MINOR" -ge 4
then
test_skip_or_die GIT_TEST_HTTPD \
- "at least Apache version 2 is required"
+ "at least Apache version 2.4 is required"
fi
if ! test -d "$DEFAULT_HTTPD_MODULE_PATH"
then
@@ -129,6 +134,7 @@ install_script () {
prepare_httpd() {
mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH"
cp "$TEST_PATH"/passwd "$HTTPD_ROOT_PATH"
+ cp "$TEST_PATH"/proxy-passwd "$HTTPD_ROOT_PATH"
install_script incomplete-length-upload-pack-v2-http.sh
install_script incomplete-body-upload-pack-v2-http.sh
install_script error-no-report.sh
@@ -136,6 +142,7 @@ prepare_httpd() {
install_script error-smart-http.sh
install_script error.sh
install_script apply-one-time-perl.sh
+ install_script nph-custom-auth.sh
ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
@@ -172,6 +179,30 @@ prepare_httpd() {
export LIB_HTTPD_SVN LIB_HTTPD_SVNPATH
fi
fi
+
+ if test -n "$LIB_HTTPD_PROXY"
+ then
+ HTTPD_PARA="$HTTPD_PARA -DPROXY"
+ fi
+}
+
+enable_http2 () {
+ HTTPD_PARA="$HTTPD_PARA -DHTTP2"
+ test_set_prereq HTTP2
+}
+
+enable_cgipassauth () {
+ # We are looking for 2.4.13 or more recent. Since we only support
+ # 2.4 and up, no need to check for older major/minor.
+ if test "$HTTPD_VERSION_MAJOR" = 2 &&
+ test "$HTTPD_VERSION_MINOR" = 4 &&
+ test "$(echo $HTTPD_VERSION | cut -d. -f3)" -lt 13
+ then
+ echo >&4 "apache $HTTPD_VERSION too old for CGIPassAuth"
+ return
+ fi
+ HTTPD_PARA="$HTTPD_PARA -DUSE_CGIPASSAUTH"
+ test_set_prereq CGIPASSAUTH
}
start_httpd() {
@@ -211,8 +242,12 @@ test_http_push_nonff () {
git commit -a -m path2 --amend &&
test_must_fail git push -v origin >output 2>&1 &&
- (cd "$REMOTE_REPO" &&
- test $HEAD = $(git rev-parse --verify HEAD))
+ (
+ cd "$REMOTE_REPO" &&
+ echo "$HEAD" >expect &&
+ git rev-parse --verify HEAD >actual &&
+ test_cmp expect actual
+ )
'
test_expect_success 'non-fast-forward push show ref status' '
@@ -274,11 +309,11 @@ expect_askpass() {
none)
;;
pass)
- echo "askpass: Password for 'http://$2@$dest': "
+ echo "askpass: Password for '$HTTPD_PROTO://$2@$dest': "
;;
both)
- echo "askpass: Username for 'http://$dest': "
- echo "askpass: Password for 'http://$2@$dest': "
+ echo "askpass: Username for '$HTTPD_PROTO://$dest': "
+ echo "askpass: Password for '$HTTPD_PROTO://$2@$dest': "
;;
*)
false
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 706799391b..a22d138605 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -29,17 +29,11 @@ ErrorLog error.log
LoadModule setenvif_module modules/mod_setenvif.so
</IfModule>
-<IfVersion < 2.4>
-LockFile accept.lock
-</IfVersion>
-
-<IfVersion < 2.1>
-<IfModule !mod_auth.c>
- LoadModule auth_module modules/mod_auth.so
-</IfModule>
-</IfVersion>
+<IfDefine HTTP2>
+LoadModule http2_module modules/mod_http2.so
+Protocols h2 h2c
+</IfDefine>
-<IfVersion >= 2.1>
<IfModule !mod_auth_basic.c>
LoadModule auth_basic_module modules/mod_auth_basic.so
</IfModule>
@@ -52,9 +46,23 @@ LockFile accept.lock
<IfModule !mod_authz_host.c>
LoadModule authz_host_module modules/mod_authz_host.so
</IfModule>
-</IfVersion>
-<IfVersion >= 2.4>
+<IfDefine PROXY>
+<IfModule !mod_proxy.c>
+ LoadModule proxy_module modules/mod_proxy.so
+</IfModule>
+<IfModule !mod_proxy_http.c>
+ LoadModule proxy_http_module modules/mod_proxy_http.so
+</IfModule>
+ProxyRequests On
+<Proxy "*">
+ AuthType Basic
+ AuthName "proxy-auth"
+ AuthUserFile proxy-passwd
+ Require valid-user
+</Proxy>
+</IfDefine>
+
<IfModule !mod_authn_core.c>
LoadModule authn_core_module modules/mod_authn_core.so
</IfModule>
@@ -64,13 +72,20 @@ LockFile accept.lock
<IfModule !mod_access_compat.c>
LoadModule access_compat_module modules/mod_access_compat.so
</IfModule>
-<IfModule !mod_mpm_prefork.c>
- LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
-</IfModule>
<IfModule !mod_unixd.c>
LoadModule unixd_module modules/mod_unixd.so
</IfModule>
-</IfVersion>
+
+<IfDefine HTTP2>
+<IfModule !mod_mpm_event.c>
+ LoadModule mpm_event_module modules/mod_mpm_event.so
+</IfModule>
+</IfDefine>
+<IfDefine !HTTP2>
+<IfModule !mod_mpm_prefork.c>
+ LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
+</IfModule>
+</IfDefine>
PassEnv GIT_VALGRIND
PassEnv GIT_VALGRIND_OPTIONS
@@ -86,6 +101,8 @@ PassEnv LC_ALL
Alias /dumb/ www/
Alias /auth/dumb/ www/auth/dumb/
+SetEnv PERL_PATH ${PERL_PATH}
+
<LocationMatch /smart/>
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
SetEnv GIT_HTTP_EXPORT_ALL
@@ -110,6 +127,10 @@ Alias /auth/dumb/ www/auth/dumb/
Header set Set-Cookie name=value
</LocationMatch>
<LocationMatch /smart_headers/>
+ <RequireAll>
+ Require expr %{HTTP:x-magic-one} == 'abra'
+ Require expr %{HTTP:x-magic-two} == 'cadabra'
+ </RequireAll>
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
SetEnv GIT_HTTP_EXPORT_ALL
</LocationMatch>
@@ -122,6 +143,13 @@ Alias /auth/dumb/ www/auth/dumb/
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv GIT_PROTOCOL
</LocationMatch>
+<LocationMatch /custom_auth/>
+ SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
+ SetEnv GIT_HTTP_EXPORT_ALL
+ <IfDefine USE_CGIPASSAUTH>
+ CGIPassAuth on
+ </IfDefine>
+</LocationMatch>
ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/
ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/
ScriptAlias /smart/no_report/git-receive-pack error-no-report.sh/
@@ -131,6 +159,7 @@ ScriptAlias /broken_smart/ broken-smart-http.sh/
ScriptAlias /error_smart/ error-smart-http.sh/
ScriptAlias /error/ error.sh/
ScriptAliasMatch /one_time_perl/(.*) apply-one-time-perl.sh/$1
+ScriptAliasMatch /custom_auth/(.*) nph-custom-auth.sh/$1
<Directory ${GIT_EXEC_PATH}>
Options FollowSymlinks
</Directory>
@@ -192,18 +221,6 @@ RewriteRule ^/intern-redir/(.*)/foo$ /smart/$1 [PT]
RewriteRule ^/redir-objects/(.*/info/refs)$ /dumb/$1 [PT]
RewriteRule ^/redir-objects/(.*/objects/.*)$ /dumb/$1 [R=301]
-# Apache 2.2 does not understand <RequireAll>, so we use RewriteCond.
-# And as RewriteCond does not allow testing for non-matches, we match
-# the desired case first (one has abra, two has cadabra), and let it
-# pass by marking the RewriteRule as [L], "last rule, do not process
-# any other matching RewriteRules after this"), and then have another
-# RewriteRule that matches all other cases and lets them fail via '[F]',
-# "fail the request".
-RewriteCond %{HTTP:x-magic-one} =abra
-RewriteCond %{HTTP:x-magic-two} =cadabra
-RewriteRule ^/smart_headers/.* - [L]
-RewriteRule ^/smart_headers/.* - [F]
-
<IfDefine SSL>
LoadModule ssl_module modules/mod_ssl.so
@@ -212,7 +229,6 @@ SSLCertificateKeyFile httpd.pem
SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect file:/dev/urandom 512
SSLSessionCache none
-SSLMutex file:ssl_mutex
SSLEngine On
</IfDefine>
diff --git a/t/lib-httpd/apply-one-time-perl.sh b/t/lib-httpd/apply-one-time-perl.sh
index 09a0abdff7..d7f9fed6ae 100644
--- a/t/lib-httpd/apply-one-time-perl.sh
+++ b/t/lib-httpd/apply-one-time-perl.sh
@@ -13,7 +13,7 @@ then
export LC_ALL
"$GIT_EXEC_PATH/git-http-backend" >out
- perl -pe "$(cat one-time-perl)" out >out_modified
+ "$PERL_PATH" -pe "$(cat one-time-perl)" out >out_modified
if cmp -s out out_modified
then
diff --git a/t/lib-httpd/nph-custom-auth.sh b/t/lib-httpd/nph-custom-auth.sh
new file mode 100644
index 0000000000..f5345e775e
--- /dev/null
+++ b/t/lib-httpd/nph-custom-auth.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+VALID_CREDS_FILE=custom-auth.valid
+CHALLENGE_FILE=custom-auth.challenge
+
+#
+# If $VALID_CREDS_FILE exists in $HTTPD_ROOT_PATH, consider each line as a valid
+# credential for the current request. Each line in the file is considered a
+# valid HTTP Authorization header value. For example:
+#
+# Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+#
+# If $CHALLENGE_FILE exists in $HTTPD_ROOT_PATH, output the contents as headers
+# in a 401 response if no valid authentication credentials were included in the
+# request. For example:
+#
+# WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
+# WWW-Authenticate: Basic realm="example.com"
+#
+
+if test -n "$HTTP_AUTHORIZATION" && \
+ grep -Fqsx "${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE"
+then
+ # Note that although git-http-backend returns a status line, it
+ # does so using a CGI 'Status' header. Because this script is an
+ # No Parsed Headers (NPH) script, we must return a real HTTP
+ # status line.
+ # This is only a test script, so we don't bother to check for
+ # the actual status from git-http-backend and always return 200.
+ echo 'HTTP/1.1 200 OK'
+ exec "$GIT_EXEC_PATH"/git-http-backend
+fi
+
+echo 'HTTP/1.1 401 Authorization Required'
+if test -f "$CHALLENGE_FILE"
+then
+ cat "$CHALLENGE_FILE"
+fi
+echo
diff --git a/t/lib-httpd/proxy-passwd b/t/lib-httpd/proxy-passwd
new file mode 100644
index 0000000000..77c25138e0
--- /dev/null
+++ b/t/lib-httpd/proxy-passwd
@@ -0,0 +1 @@
+proxuser:2x7tAukjAED5M
diff --git a/t/lib-httpd/ssl.cnf b/t/lib-httpd/ssl.cnf
index 6dab2579cb..812e8253f0 100644
--- a/t/lib-httpd/ssl.cnf
+++ b/t/lib-httpd/ssl.cnf
@@ -1,7 +1,7 @@
RANDFILE = $ENV::RANDFILE_PATH
[ req ]
-default_bits = 1024
+default_bits = 2048
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
diff --git a/t/lib-patch-mode.sh b/t/lib-patch-mode.sh
index cfd76bf987..89ca1f7805 100644
--- a/t/lib-patch-mode.sh
+++ b/t/lib-patch-mode.sh
@@ -29,8 +29,12 @@ set_and_save_state () {
# verify_state <path> <expected-worktree-content> <expected-index-content>
verify_state () {
- test "$(cat "$1")" = "$2" &&
- test "$(git show :"$1")" = "$3"
+ echo "$2" >expect &&
+ test_cmp expect "$1" &&
+
+ echo "$3" >expect &&
+ git show :"$1" >actual &&
+ test_cmp expect actual
}
# verify_saved_state <path>
@@ -46,5 +50,6 @@ save_head () {
}
verify_saved_head () {
- test "$(cat _head)" = "$(git rev-parse HEAD)"
+ git rev-parse HEAD >actual &&
+ test_cmp _head actual
}
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index b57541356b..11d2dc9fe3 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -8,18 +8,21 @@
# - check that non-commit messages have a certain line count with $EXPECT_COUNT
# - check the commit count in the commit message header with $EXPECT_HEADER_COUNT
# - rewrite a rebase -i script as directed by $FAKE_LINES.
-# $FAKE_LINES consists of a sequence of words separated by spaces.
-# The following word combinations are possible:
+# $FAKE_LINES consists of a sequence of words separated by spaces;
+# spaces inside the words are encoded as underscores.
+# The following words are possible:
#
-# "<lineno>" -- add a "pick" line with the SHA1 taken from the
-# specified line.
+# "<cmd>" -- override the command for the next line specification. Can be
+# "pick", "squash", "fixup[_-(c|C)]", "edit", "reword", "drop",
+# "merge[_-(c|C)_<rev>]", or "bad" for an invalid command.
#
-# "<cmd> <lineno>" -- add a line with the specified command
-# ("pick", "squash", "fixup"|"fixup_-C"|"fixup_-c", "edit", "reword" or "drop")
-# and the SHA1 taken from the specified line.
+# "<lineno>" -- add a command, using the specified line as a template.
+# If the command has not been overridden, the line will be copied
+# verbatim, usually resulting in a "pick" line.
#
-# "_" -- add a space, like "fixup_-C" implies "fixup -C" and
-# "exec_cmd_with_args" add an "exec cmd with args" line.
+# "fakesha" -- add a command ("pick" by default), using a fake SHA1.
+#
+# "exec_[command...]", "break" -- add the specified command.
#
# "#" -- Add a comment line.
#
@@ -49,7 +52,7 @@ set_fake_editor () {
action=\&
for line in $FAKE_LINES; do
case $line in
- pick|p|squash|s|fixup|f|edit|e|reword|r|drop|d|label|l|reset|r|merge|m)
+ pick|p|squash|s|fixup|f|edit|e|reword|r|drop|d|label|l|reset|t|merge|m)
action="$line";;
exec_*|x_*|break|b)
echo "$line" | sed 's/_/ /g' >> "$1";;
@@ -60,11 +63,11 @@ set_fake_editor () {
">")
echo >> "$1";;
bad)
- action="badcmd";;
+ action="pickled";;
fakesha)
test \& != "$action" || action=pick
echo "$action XXXXXXX False commit" >> "$1"
- action=pick;;
+ action=\&;;
*)
sed -n "${line}s/^[a-z][a-z]*/$action/p" < "$1".tmp >> "$1"
action=\&;;
@@ -211,6 +214,9 @@ check_reworded_commits () {
# usage: set_replace_editor <file>
#
# Replace the todo file with the exact contents of the given file.
+# N.B. sets GIT_SEQUENCE_EDITOR rather than EDITOR so it can be
+# combined with set_fake_editor to reword commits and replace the
+# todo list
set_replace_editor () {
cat >script <<-\EOF &&
cat FILENAME >"$1"
@@ -219,6 +225,7 @@ set_replace_editor () {
cat "$1"
EOF
- sed -e "s/FILENAME/$1/g" <script | write_script fake-editor.sh &&
- test_set_editor "$(pwd)/fake-editor.sh"
+ sed -e "s/FILENAME/$1/g" script |
+ write_script fake-sequence-editor.sh &&
+ test_set_sequence_editor "$(pwd)/fake-sequence-editor.sh"
}
diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh
index 2d31fcfda1..9acb0d5d19 100644
--- a/t/lib-submodule-update.sh
+++ b/t/lib-submodule-update.sh
@@ -168,20 +168,16 @@ replace_gitfile_with_git_dir () {
# Note that this only supports submodules at the root level of the
# superproject, with the default name, i.e. same as its path.
test_git_directory_is_unchanged () {
- (
- cd ".git/modules/$1" &&
- # does core.worktree point at the right place?
- test "$(git config core.worktree)" = "../../../$1" &&
- # remove it temporarily before comparing, as
- # "$1/.git/config" lacks it...
- git config --unset core.worktree
- ) &&
+ # does core.worktree point at the right place?
+ echo "../../../$1" >expect &&
+ git -C ".git/modules/$1" config core.worktree >actual &&
+ test_cmp expect actual &&
+ # remove it temporarily before comparing, as
+ # "$1/.git/config" lacks it...
+ git -C ".git/modules/$1" config --unset core.worktree &&
diff -r ".git/modules/$1" "$1/.git" &&
- (
- # ... and then restore.
- cd ".git/modules/$1" &&
- git config core.worktree "../../../$1"
- )
+ # ... and then restore.
+ git -C ".git/modules/$1" config core.worktree "../../../$1"
}
test_git_directory_exists () {
@@ -189,7 +185,9 @@ test_git_directory_exists () {
if test -f sub1/.git
then
# does core.worktree point at the right place?
- test "$(git -C .git/modules/$1 config core.worktree)" = "../../../$1"
+ echo "../../../$1" >expect &&
+ git -C ".git/modules/$1" config core.worktree >actual &&
+ test_cmp expect actual
fi
}
@@ -804,7 +802,7 @@ test_submodule_recursing_with_args_common () {
git branch -t no_submodule origin/no_submodule &&
$command no_submodule &&
test_superproject_content origin/no_submodule &&
- ! test_path_is_dir sub1 &&
+ test_path_is_missing sub1 &&
test_must_fail git config -f .git/modules/sub1/config core.worktree &&
test_must_fail git config -f .git/modules/sub1/modules/sub2/config core.worktree
)
diff --git a/t/perf/p0006-read-tree-checkout.sh b/t/perf/p0006-read-tree-checkout.sh
index c481c012d2..325566e18e 100755
--- a/t/perf/p0006-read-tree-checkout.sh
+++ b/t/perf/p0006-read-tree-checkout.sh
@@ -49,6 +49,14 @@ test_perf "read-tree br_base br_ballast ($nr_files)" '
git read-tree -n -m br_base br_ballast
'
+test_perf "read-tree br_ballast_plus_1 ($nr_files)" '
+ # Run read-tree 100 times for clearer performance results & comparisons
+ for i in $(test_seq 100)
+ do
+ git read-tree -n -m br_ballast_plus_1 || return 1
+ done
+'
+
test_perf "switch between br_base br_ballast ($nr_files)" '
git checkout -q br_base &&
git checkout -q br_ballast
diff --git a/t/perf/p0090-cache-tree.sh b/t/perf/p0090-cache-tree.sh
new file mode 100755
index 0000000000..a8eabca2c4
--- /dev/null
+++ b/t/perf/p0090-cache-tree.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+test_description="Tests performance of cache tree update operations"
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+test_checkout_worktree
+
+count=100
+
+test_expect_success 'setup cache tree' '
+ git write-tree
+'
+
+test_cache_tree () {
+ test_perf "$1, $3" "
+ for i in \$(test_seq $count)
+ do
+ test-tool cache-tree $4 $2
+ done
+ "
+}
+
+test_cache_tree_update_functions () {
+ test_cache_tree 'no-op' 'control' "$1" "$2"
+ test_cache_tree 'prime_cache_tree' 'prime' "$1" "$2"
+ test_cache_tree 'cache_tree_update' 'update' "$1" "$2"
+}
+
+test_cache_tree_update_functions "clean" ""
+test_cache_tree_update_functions "invalidate 2" "--invalidate 2"
+test_cache_tree_update_functions "invalidate 50" "--invalidate 50"
+test_cache_tree_update_functions "empty" "--empty"
+
+test_done
diff --git a/t/perf/p1500-graph-walks.sh b/t/perf/p1500-graph-walks.sh
new file mode 100755
index 0000000000..e14e7620cc
--- /dev/null
+++ b/t/perf/p1500-graph-walks.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='Commit walk performance tests'
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+test_expect_success 'setup' '
+ git for-each-ref --format="%(refname)" "refs/heads/*" "refs/tags/*" >allrefs &&
+ sort -r allrefs | head -n 50 >refs &&
+ for ref in $(cat refs)
+ do
+ git branch -f ref-$ref $ref &&
+ echo ref-$ref ||
+ return 1
+ done >branches &&
+ for ref in $(cat refs)
+ do
+ git tag -f tag-$ref $ref &&
+ echo tag-$ref ||
+ return 1
+ done >tags &&
+ git commit-graph write --reachable
+'
+
+test_perf 'ahead-behind counts: git for-each-ref' '
+ git for-each-ref --format="%(ahead-behind:HEAD)" --stdin <refs
+'
+
+test_perf 'ahead-behind counts: git branch' '
+ xargs git branch -l --format="%(ahead-behind:HEAD)" <branches
+'
+
+test_perf 'ahead-behind counts: git tag' '
+ xargs git tag -l --format="%(ahead-behind:HEAD)" <tags
+'
+
+test_perf 'contains: git for-each-ref --merged' '
+ git for-each-ref --merged=HEAD --stdin <refs
+'
+
+test_perf 'contains: git branch --merged' '
+ xargs git branch --merged=HEAD <branches
+'
+
+test_perf 'contains: git tag --merged' '
+ xargs git tag --merged=HEAD <tags
+'
+
+test_done
diff --git a/t/perf/p2000-sparse-operations.sh b/t/perf/p2000-sparse-operations.sh
index fce8151d41..39e92b0841 100755
--- a/t/perf/p2000-sparse-operations.sh
+++ b/t/perf/p2000-sparse-operations.sh
@@ -43,6 +43,7 @@ test_expect_success 'setup repo and indexes' '
done &&
git sparse-checkout init --cone &&
+ git tag -a v1.0 -m "Final" &&
git sparse-checkout set $SPARSE_CONE &&
git checkout -b wide $OLD_COMMIT &&
@@ -124,5 +125,15 @@ test_perf_on_all git read-tree -mu HEAD
test_perf_on_all git checkout-index -f --all
test_perf_on_all git update-index --add --remove $SPARSE_CONE/a
test_perf_on_all "git rm -f $SPARSE_CONE/a && git checkout HEAD -- $SPARSE_CONE/a"
+test_perf_on_all git grep --cached bogus -- "f2/f1/f1/*"
+test_perf_on_all git write-tree
+test_perf_on_all git describe --dirty
+test_perf_on_all 'echo >>new && git describe --dirty'
+test_perf_on_all git diff-files
+test_perf_on_all git diff-files -- $SPARSE_CONE/a
+test_perf_on_all git diff-tree HEAD
+test_perf_on_all git diff-tree HEAD -- $SPARSE_CONE/a
+test_perf_on_all "git worktree add ../temp && git worktree remove ../temp"
+test_perf_on_all git check-attr -a -- $SPARSE_CONE/a
test_done
diff --git a/t/perf/p5312-pack-bitmaps-revs.sh b/t/perf/p5312-pack-bitmaps-revs.sh
index 0684b690af..ceec60656b 100755
--- a/t/perf/p5312-pack-bitmaps-revs.sh
+++ b/t/perf/p5312-pack-bitmaps-revs.sh
@@ -12,8 +12,7 @@ test_lookup_pack_bitmap () {
test_perf_large_repo
test_expect_success 'setup bitmap config' '
- git config pack.writebitmaps true &&
- git config pack.writeReverseIndex true
+ git config pack.writebitmaps true
'
# we need to create the tag up front such that it is covered by the repack and
diff --git a/t/perf/p7102-reset.sh b/t/perf/p7102-reset.sh
new file mode 100755
index 0000000000..9b039e8691
--- /dev/null
+++ b/t/perf/p7102-reset.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+test_description='performance of reset'
+. ./perf-lib.sh
+
+test_perf_default_repo
+test_checkout_worktree
+
+test_perf 'reset --hard with change in tree' '
+ base=$(git rev-parse HEAD) &&
+ test_commit --no-tag A &&
+ new=$(git rev-parse HEAD) &&
+
+ for i in $(test_seq 10)
+ do
+ git reset --hard $new &&
+ git reset --hard $base || return $?
+ done
+'
+
+test_done
diff --git a/t/perf/p7822-grep-perl-character.sh b/t/perf/p7822-grep-perl-character.sh
new file mode 100755
index 0000000000..87009c60df
--- /dev/null
+++ b/t/perf/p7822-grep-perl-character.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+test_description="git-grep's perl regex
+
+If GIT_PERF_GREP_THREADS is set to a list of threads (e.g. '1 4 8'
+etc.) we will test the patterns under those numbers of threads.
+"
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+test_checkout_worktree
+
+if test -n "$GIT_PERF_GREP_THREADS"
+then
+ test_set_prereq PERF_GREP_ENGINES_THREADS
+fi
+
+for pattern in \
+ '\\bhow' \
+ '\\bÆvar' \
+ '\\d+ \\bÆvar' \
+ '\\bBelón\\b' \
+ '\\w{12}\\b'
+do
+ echo '$pattern' >pat
+ if ! test_have_prereq PERF_GREP_ENGINES_THREADS
+ then
+ test_perf "grep -P '$pattern'" --prereq PCRE "
+ git -P grep -f pat || :
+ "
+ else
+ for threads in $GIT_PERF_GREP_THREADS
+ do
+ test_perf "grep -P '$pattern' with $threads threads" --prereq PTHREADS,PCRE "
+ git -c grep.threads=$threads -P grep -f pat || :
+ "
+ done
+ fi
+done
+
+test_done
diff --git a/t/perf/run b/t/perf/run
index 33da4d2aba..34115edec3 100755
--- a/t/perf/run
+++ b/t/perf/run
@@ -232,10 +232,10 @@ then
)
elif test -n "$GIT_PERF_SUBSECTION"
then
- egrep "^$GIT_PERF_SUBSECTION\$" "$TEST_RESULTS_DIR"/run_subsections.names >/dev/null ||
+ grep -E "^$GIT_PERF_SUBSECTION\$" "$TEST_RESULTS_DIR"/run_subsections.names >/dev/null ||
die "subsection '$GIT_PERF_SUBSECTION' not found in '$GIT_PERF_CONFIG_FILE'"
- egrep "^$GIT_PERF_SUBSECTION\$" "$TEST_RESULTS_DIR"/run_subsections.names | while read -r subsec
+ grep -E "^$GIT_PERF_SUBSECTION\$" "$TEST_RESULTS_DIR"/run_subsections.names | while read -r subsec
do
(
GIT_PERF_SUBSECTION="$subsec"
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 502b4bcf9e..6e300be2ac 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -815,7 +815,8 @@ test_expect_success 'test_oid provides sane info by default' '
grep "^00*\$" actual &&
rawsz="$(test_oid rawsz)" &&
hexsz="$(test_oid hexsz)" &&
- test "$hexsz" -eq $(wc -c <actual) &&
+ # +1 accounts for the trailing newline
+ test $(( $hexsz + 1)) -eq $(wc -c <actual) &&
test $(( $rawsz * 2)) -eq "$hexsz"
'
@@ -826,7 +827,7 @@ test_expect_success 'test_oid can look up data for SHA-1' '
grep "^00*\$" actual &&
rawsz="$(test_oid rawsz)" &&
hexsz="$(test_oid hexsz)" &&
- test $(wc -c <actual) -eq 40 &&
+ test $(wc -c <actual) -eq 41 &&
test "$rawsz" -eq 20 &&
test "$hexsz" -eq 40
'
@@ -838,7 +839,7 @@ test_expect_success 'test_oid can look up data for SHA-256' '
grep "^00*\$" actual &&
rawsz="$(test_oid rawsz)" &&
hexsz="$(test_oid hexsz)" &&
- test $(wc -c <actual) -eq 64 &&
+ test $(wc -c <actual) -eq 65 &&
test "$rawsz" -eq 32 &&
test "$hexsz" -eq 64
'
@@ -1013,7 +1014,7 @@ test_expect_success 'validate object ID for a known tree' '
'
test_expect_success 'showing tree with git ls-tree' '
- git ls-tree $tree >current
+ git ls-tree $tree >current
'
test_expect_success 'git ls-tree output for a known tree' '
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index d479303efa..30a6edca1d 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -598,9 +598,14 @@ test_expect_success 'invalid default branch name' '
test_expect_success 'branch -m with the initial branch' '
git init rename-initial &&
git -C rename-initial branch -m renamed &&
- test renamed = $(git -C rename-initial symbolic-ref --short HEAD) &&
+ echo renamed >expect &&
+ git -C rename-initial symbolic-ref --short HEAD >actual &&
+ test_cmp expect actual &&
+
git -C rename-initial branch -m renamed again &&
- test again = $(git -C rename-initial symbolic-ref --short HEAD)
+ echo again >expect &&
+ git -C rename-initial symbolic-ref --short HEAD >actual &&
+ test_cmp expect actual
'
test_done
diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh
index 26eaca095a..e013d38f48 100755
--- a/t/t0002-gitfile.sh
+++ b/t/t0002-gitfile.sh
@@ -33,7 +33,9 @@ test_expect_success 'bad setup: invalid .git file path' '
test_expect_success 'final setup + check rev-parse --git-dir' '
echo "gitdir: $REAL" >.git &&
- test "$REAL" = "$(git rev-parse --git-dir)"
+ echo "$REAL" >expect &&
+ git rev-parse --git-dir >actual &&
+ test_cmp expect actual
'
test_expect_success 'check hash-object' '
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index d0284fe2d7..26e082f05b 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -25,7 +25,24 @@ attr_check_quote () {
git check-attr test -- "$path" >actual &&
echo "\"$quoted_path\": test: $expect" >expect &&
test_cmp expect actual
+}
+
+attr_check_source () {
+ path="$1" expect="$2" source="$3" git_opts="$4" &&
+
+ echo "$path: test: $expect" >expect &&
+ git $git_opts check-attr --source $source test -- "$path" >actual 2>err &&
+ test_cmp expect actual &&
+ test_must_be_empty err &&
+
+ git $git_opts --attr-source="$source" check-attr test -- "$path" >actual 2>err &&
+ test_cmp expect actual &&
+ test_must_be_empty err
+
+ GIT_ATTR_SOURCE="$source" git $git_opts check-attr test -- "$path" >actual 2>err &&
+ test_cmp expect actual &&
+ test_must_be_empty err
}
test_expect_success 'open-quoted pathname' '
@@ -33,7 +50,6 @@ test_expect_success 'open-quoted pathname' '
attr_check a unspecified
'
-
test_expect_success 'setup' '
mkdir -p a/b/d a/c b &&
(
@@ -80,12 +96,23 @@ test_expect_success 'setup' '
EOF
'
+test_expect_success 'setup branches' '
+ mkdir -p foo/bar &&
+ test_commit --printf "add .gitattributes" foo/bar/.gitattributes \
+ "f test=f\na/i test=n\n" tag-1 &&
+ test_commit --printf "add .gitattributes" foo/bar/.gitattributes \
+ "g test=g\na/i test=m\n" tag-2 &&
+ rm foo/bar/.gitattributes
+'
+
test_expect_success 'command line checks' '
test_must_fail git check-attr &&
test_must_fail git check-attr -- &&
test_must_fail git check-attr test &&
test_must_fail git check-attr test -- &&
test_must_fail git check-attr -- f &&
+ test_must_fail git check-attr --source &&
+ test_must_fail git check-attr --source not-a-valid-ref &&
echo "f" | test_must_fail git check-attr --stdin &&
echo "f" | test_must_fail git check-attr --stdin -- f &&
echo "f" | test_must_fail git check-attr --stdin test -- f &&
@@ -203,9 +230,12 @@ test_expect_success 'attribute test: read paths from stdin' '
test_cmp expect actual
'
-test_expect_success 'attribute test: --all option' '
+test_expect_success 'setup --all option' '
grep -v unspecified <expect-all | sort >specified-all &&
- sed -e "s/:.*//" <expect-all | uniq >stdin-all &&
+ sed -e "s/:.*//" <expect-all | uniq >stdin-all
+'
+
+test_expect_success 'attribute test: --all option' '
git check-attr --stdin --all <stdin-all >tmp &&
sort tmp >actual &&
test_cmp specified-all actual
@@ -284,6 +314,15 @@ test_expect_success 'using --git-dir and --work-tree' '
)
'
+test_expect_success 'using --source' '
+ attr_check_source foo/bar/f f tag-1 &&
+ attr_check_source foo/bar/a/i n tag-1 &&
+ attr_check_source foo/bar/f unspecified tag-2 &&
+ attr_check_source foo/bar/a/i m tag-2 &&
+ attr_check_source foo/bar/g g tag-2 &&
+ attr_check_source foo/bar/g unspecified tag-1
+'
+
test_expect_success 'setup bare' '
git clone --template= --bare . bare.git
'
@@ -303,6 +342,18 @@ test_expect_success 'bare repository: check that .gitattribute is ignored' '
)
'
+test_expect_success 'bare repository: with --source' '
+ (
+ cd bare.git &&
+ attr_check_source foo/bar/f f tag-1 &&
+ attr_check_source foo/bar/a/i n tag-1 &&
+ attr_check_source foo/bar/f unspecified tag-2 &&
+ attr_check_source foo/bar/a/i m tag-2 &&
+ attr_check_source foo/bar/g g tag-2 &&
+ attr_check_source foo/bar/g unspecified tag-1
+ )
+'
+
test_expect_success 'bare repository: check that --cached honors index' '
(
cd bare.git &&
@@ -400,7 +451,7 @@ test_expect_success 'large attributes line ignores trailing content in tree' '
test_expect_success EXPENSIVE 'large attributes file ignored in tree' '
test_when_finished "rm .gitattributes" &&
- dd if=/dev/zero of=.gitattributes bs=101M count=1 2>/dev/null &&
+ dd if=/dev/zero of=.gitattributes bs=1048576 count=101 2>/dev/null &&
git check-attr --all path >/dev/null 2>err &&
echo "warning: ignoring overly large gitattributes file ${SQ}.gitattributes${SQ}" >expect &&
test_cmp expect err
@@ -428,7 +479,7 @@ test_expect_success 'large attributes line ignores trailing content in index' '
test_expect_success EXPENSIVE 'large attributes file ignored in index' '
test_when_finished "git update-index --remove .gitattributes" &&
- blob=$(dd if=/dev/zero bs=101M count=1 2>/dev/null | git hash-object -w --stdin) &&
+ blob=$(dd if=/dev/zero bs=1048576 count=101 2>/dev/null | git hash-object -w --stdin) &&
git update-index --add --cacheinfo 100644,$blob,.gitattributes &&
git check-attr --cached --all path >/dev/null 2>err &&
echo "warning: ignoring overly large gitattributes blob ${SQ}.gitattributes${SQ}" >expect &&
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index 2490162071..e18b160286 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -88,6 +88,13 @@ check_parse 2008-02-14 bad
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000'
check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500'
check_parse '2008.02.14 20:30:45 -0500' '2008-02-14 20:30:45 -0500'
+check_parse '20080214T20:30:45' '2008-02-14 20:30:45 +0000'
+check_parse '20080214T20:30' '2008-02-14 20:30:00 +0000'
+check_parse '20080214T20' '2008-02-14 20:00:00 +0000'
+check_parse '20080214T203045' '2008-02-14 20:30:45 +0000'
+check_parse '20080214T2030' '2008-02-14 20:30:00 +0000'
+check_parse '20080214T000000.20' '2008-02-14 00:00:00 +0000'
+check_parse '20080214T00:00:00.20' '2008-02-14 00:00:00 +0000'
check_parse '20080214T203045-04:00' '2008-02-14 20:30:45 -0400'
check_parse '20080214T203045 -04:00' '2008-02-14 20:30:45 -0400'
check_parse '20080214T203045.019-04:00' '2008-02-14 20:30:45 -0400'
@@ -99,6 +106,7 @@ check_parse '2008-02-14 20:30:45 -05' '2008-02-14 20:30:45 -0500'
check_parse '2008-02-14 20:30:45 -:30' '2008-02-14 20:30:45 +0000'
check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
+check_parse 'Thu, 7 Apr 2005 15:14:13 -0700' '2005-04-07 15:14:13 -0700'
check_approxidate() {
echo "$1 -> $2 +0000" >expect
diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh
index e56f4b9ac5..ff4fd9348c 100755
--- a/t/t0007-git-var.sh
+++ b/t/t0007-git-var.sh
@@ -5,6 +5,12 @@ test_description='basic sanity checks for git var'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
+sane_unset_all_editors () {
+ sane_unset GIT_EDITOR &&
+ sane_unset VISUAL &&
+ sane_unset EDITOR
+}
+
test_expect_success 'get GIT_AUTHOR_IDENT' '
test_tick &&
echo "$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect &&
@@ -47,6 +53,178 @@ test_expect_success 'get GIT_DEFAULT_BRANCH with configuration' '
)
'
+test_expect_success 'get GIT_EDITOR without configuration' '
+ (
+ sane_unset_all_editors &&
+ test_expect_code 1 git var GIT_EDITOR >out &&
+ test_must_be_empty out
+ )
+'
+
+test_expect_success 'get GIT_EDITOR with configuration' '
+ test_config core.editor foo &&
+ (
+ sane_unset_all_editors &&
+ echo foo >expect &&
+ git var GIT_EDITOR >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'get GIT_EDITOR with environment variable GIT_EDITOR' '
+ (
+ sane_unset_all_editors &&
+ echo bar >expect &&
+ GIT_EDITOR=bar git var GIT_EDITOR >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'get GIT_EDITOR with environment variable EDITOR' '
+ (
+ sane_unset_all_editors &&
+ echo bar >expect &&
+ EDITOR=bar git var GIT_EDITOR >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'get GIT_EDITOR with configuration and environment variable GIT_EDITOR' '
+ test_config core.editor foo &&
+ (
+ sane_unset_all_editors &&
+ echo bar >expect &&
+ GIT_EDITOR=bar git var GIT_EDITOR >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'get GIT_EDITOR with configuration and environment variable EDITOR' '
+ test_config core.editor foo &&
+ (
+ sane_unset_all_editors &&
+ echo foo >expect &&
+ EDITOR=bar git var GIT_EDITOR >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'get GIT_SEQUENCE_EDITOR without configuration' '
+ (
+ sane_unset GIT_SEQUENCE_EDITOR &&
+ git var GIT_EDITOR >expect &&
+ git var GIT_SEQUENCE_EDITOR >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'get GIT_SEQUENCE_EDITOR with configuration' '
+ test_config sequence.editor foo &&
+ (
+ sane_unset GIT_SEQUENCE_EDITOR &&
+ echo foo >expect &&
+ git var GIT_SEQUENCE_EDITOR >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'get GIT_SEQUENCE_EDITOR with environment variable' '
+ (
+ sane_unset GIT_SEQUENCE_EDITOR &&
+ echo bar >expect &&
+ GIT_SEQUENCE_EDITOR=bar git var GIT_SEQUENCE_EDITOR >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'get GIT_SEQUENCE_EDITOR with configuration and environment variable' '
+ test_config sequence.editor foo &&
+ (
+ sane_unset GIT_SEQUENCE_EDITOR &&
+ echo bar >expect &&
+ GIT_SEQUENCE_EDITOR=bar git var GIT_SEQUENCE_EDITOR >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success POSIXPERM 'GIT_SHELL_PATH points to a valid executable' '
+ shellpath=$(git var GIT_SHELL_PATH) &&
+ test_path_is_executable "$shellpath"
+'
+
+# We know in this environment that our shell will be one of a few fixed values
+# that all end in "sh".
+test_expect_success MINGW 'GIT_SHELL_PATH points to a suitable shell' '
+ shellpath=$(git var GIT_SHELL_PATH) &&
+ case "$shellpath" in
+ *sh) ;;
+ *) return 1;;
+ esac
+'
+
+test_expect_success 'GIT_ATTR_SYSTEM produces expected output' '
+ test_must_fail env GIT_ATTR_NOSYSTEM=1 git var GIT_ATTR_SYSTEM &&
+ (
+ sane_unset GIT_ATTR_NOSYSTEM &&
+ systempath=$(git var GIT_ATTR_SYSTEM) &&
+ test "$systempath" != ""
+ )
+'
+
+test_expect_success 'GIT_ATTR_GLOBAL points to the correct location' '
+ TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" &&
+ globalpath=$(XDG_CONFIG_HOME="$TRASHDIR/.config" git var GIT_ATTR_GLOBAL) &&
+ test "$globalpath" = "$TRASHDIR/.config/git/attributes" &&
+ (
+ sane_unset XDG_CONFIG_HOME &&
+ globalpath=$(HOME="$TRASHDIR" git var GIT_ATTR_GLOBAL) &&
+ test "$globalpath" = "$TRASHDIR/.config/git/attributes"
+ )
+'
+
+test_expect_success 'GIT_CONFIG_SYSTEM points to the correct location' '
+ TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" &&
+ test_must_fail env GIT_CONFIG_NOSYSTEM=1 git var GIT_CONFIG_SYSTEM &&
+ (
+ sane_unset GIT_CONFIG_NOSYSTEM &&
+ systempath=$(git var GIT_CONFIG_SYSTEM) &&
+ test "$systempath" != "" &&
+ systempath=$(GIT_CONFIG_SYSTEM=/dev/null git var GIT_CONFIG_SYSTEM) &&
+ if test_have_prereq MINGW
+ then
+ test "$systempath" = "nul"
+ else
+ test "$systempath" = "/dev/null"
+ fi &&
+ systempath=$(GIT_CONFIG_SYSTEM="$TRASHDIR/gitconfig" git var GIT_CONFIG_SYSTEM) &&
+ test "$systempath" = "$TRASHDIR/gitconfig"
+ )
+'
+
+test_expect_success 'GIT_CONFIG_GLOBAL points to the correct location' '
+ TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" &&
+ HOME="$TRASHDIR" XDG_CONFIG_HOME="$TRASHDIR/foo" git var GIT_CONFIG_GLOBAL >actual &&
+ echo "$TRASHDIR/foo/git/config" >expected &&
+ echo "$TRASHDIR/.gitconfig" >>expected &&
+ test_cmp expected actual &&
+ (
+ sane_unset XDG_CONFIG_HOME &&
+ HOME="$TRASHDIR" git var GIT_CONFIG_GLOBAL >actual &&
+ echo "$TRASHDIR/.config/git/config" >expected &&
+ echo "$TRASHDIR/.gitconfig" >>expected &&
+ test_cmp expected actual &&
+ globalpath=$(GIT_CONFIG_GLOBAL=/dev/null git var GIT_CONFIG_GLOBAL) &&
+ if test_have_prereq MINGW
+ then
+ test "$globalpath" = "nul"
+ else
+ test "$globalpath" = "/dev/null"
+ fi &&
+ globalpath=$(GIT_CONFIG_GLOBAL="$TRASHDIR/gitconfig" git var GIT_CONFIG_GLOBAL) &&
+ test "$globalpath" = "$TRASHDIR/gitconfig"
+ )
+'
+
# For git var -l, we check only a representative variable;
# testing the whole output would make our test too brittle with
# respect to unrelated changes in the test suite's environment.
@@ -64,8 +242,39 @@ test_expect_success 'git var -l lists config' '
test_cmp expect actual.bare
'
+test_expect_success 'git var -l lists multiple global configs' '
+ TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" &&
+ HOME="$TRASHDIR" XDG_CONFIG_HOME="$TRASHDIR/foo" git var -l >actual &&
+ grep "^GIT_CONFIG_GLOBAL=" actual >filtered &&
+ echo "GIT_CONFIG_GLOBAL=$TRASHDIR/foo/git/config" >expected &&
+ echo "GIT_CONFIG_GLOBAL=$TRASHDIR/.gitconfig" >>expected &&
+ test_cmp expected filtered
+'
+
+test_expect_success 'git var -l does not split multiline editors' '
+ (
+ GIT_EDITOR="!f() {
+ echo Hello!
+ }; f" &&
+ export GIT_EDITOR &&
+ echo "GIT_EDITOR=$GIT_EDITOR" >expected &&
+ git var -l >var &&
+ sed -n -e "/^GIT_EDITOR/,\$p" var | head -n 3 >actual &&
+ test_cmp expected actual
+ )
+'
+
test_expect_success 'listing and asking for variables are exclusive' '
test_must_fail git var -l GIT_COMMITTER_IDENT
'
+test_expect_success '`git var -l` works even without HOME' '
+ (
+ XDG_CONFIG_HOME= &&
+ export XDG_CONFIG_HOME &&
+ unset HOME &&
+ git var -l
+ )
+'
+
test_done
diff --git a/t/t0013-sha1dc.sh b/t/t0013-sha1dc.sh
index 9ad76080aa..5324047689 100755
--- a/t/t0013-sha1dc.sh
+++ b/t/t0013-sha1dc.sh
@@ -6,9 +6,11 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
TEST_DATA="$TEST_DIRECTORY/t0013"
-if test -z "$DC_SHA1"
+test_lazy_prereq SHA1_IS_SHA1DC 'test-tool sha1-is-sha1dc'
+
+if ! test_have_prereq SHA1_IS_SHA1DC
then
- skip_all='skipping sha1 collision tests, DC_SHA1 not set'
+ skip_all='skipping sha1 collision tests, not using sha1collisiondetection'
test_done
fi
diff --git a/t/t0017-env-helper.sh b/t/t0017-env-helper.sh
index 2e42fba956..fc14ba091c 100755
--- a/t/t0017-env-helper.sh
+++ b/t/t0017-env-helper.sh
@@ -1,87 +1,87 @@
#!/bin/sh
-test_description='test env--helper'
+test_description='test test-tool env-helper'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
-test_expect_success 'env--helper usage' '
- test_must_fail git env--helper &&
- test_must_fail git env--helper --type=bool &&
- test_must_fail git env--helper --type=ulong &&
- test_must_fail git env--helper --type=bool &&
- test_must_fail git env--helper --type=bool --default &&
- test_must_fail git env--helper --type=bool --default= &&
- test_must_fail git env--helper --defaultxyz
+test_expect_success 'test-tool env-helper usage' '
+ test_must_fail test-tool env-helper &&
+ test_must_fail test-tool env-helper --type=bool &&
+ test_must_fail test-tool env-helper --type=ulong &&
+ test_must_fail test-tool env-helper --type=bool &&
+ test_must_fail test-tool env-helper --type=bool --default &&
+ test_must_fail test-tool env-helper --type=bool --default= &&
+ test_must_fail test-tool env-helper --defaultxyz
'
-test_expect_success 'env--helper bad default values' '
- test_must_fail git env--helper --type=bool --default=1xyz MISSING &&
- test_must_fail git env--helper --type=ulong --default=1xyz MISSING
+test_expect_success 'test-tool env-helper bad default values' '
+ test_must_fail test-tool env-helper --type=bool --default=1xyz MISSING &&
+ test_must_fail test-tool env-helper --type=ulong --default=1xyz MISSING
'
-test_expect_success 'env--helper --type=bool' '
+test_expect_success 'test-tool env-helper --type=bool' '
# Test various --default bool values
echo true >expected &&
- git env--helper --type=bool --default=1 MISSING >actual &&
+ test-tool env-helper --type=bool --default=1 MISSING >actual &&
test_cmp expected actual &&
- git env--helper --type=bool --default=yes MISSING >actual &&
+ test-tool env-helper --type=bool --default=yes MISSING >actual &&
test_cmp expected actual &&
- git env--helper --type=bool --default=true MISSING >actual &&
+ test-tool env-helper --type=bool --default=true MISSING >actual &&
test_cmp expected actual &&
echo false >expected &&
- test_must_fail git env--helper --type=bool --default=0 MISSING >actual &&
+ test_must_fail test-tool env-helper --type=bool --default=0 MISSING >actual &&
test_cmp expected actual &&
- test_must_fail git env--helper --type=bool --default=no MISSING >actual &&
+ test_must_fail test-tool env-helper --type=bool --default=no MISSING >actual &&
test_cmp expected actual &&
- test_must_fail git env--helper --type=bool --default=false MISSING >actual &&
+ test_must_fail test-tool env-helper --type=bool --default=false MISSING >actual &&
test_cmp expected actual &&
# No output with --exit-code
- git env--helper --type=bool --default=true --exit-code MISSING >actual.out 2>actual.err &&
+ test-tool env-helper --type=bool --default=true --exit-code MISSING >actual.out 2>actual.err &&
test_must_be_empty actual.out &&
test_must_be_empty actual.err &&
- test_must_fail git env--helper --type=bool --default=false --exit-code MISSING >actual.out 2>actual.err &&
+ test_must_fail test-tool env-helper --type=bool --default=false --exit-code MISSING >actual.out 2>actual.err &&
test_must_be_empty actual.out &&
test_must_be_empty actual.err &&
# Existing variable
- EXISTS=true git env--helper --type=bool --default=false --exit-code EXISTS >actual.out 2>actual.err &&
+ EXISTS=true test-tool env-helper --type=bool --default=false --exit-code EXISTS >actual.out 2>actual.err &&
test_must_be_empty actual.out &&
test_must_be_empty actual.err &&
test_must_fail \
env EXISTS=false \
- git env--helper --type=bool --default=true --exit-code EXISTS >actual.out 2>actual.err &&
+ test-tool env-helper --type=bool --default=true --exit-code EXISTS >actual.out 2>actual.err &&
test_must_be_empty actual.out &&
test_must_be_empty actual.err
'
-test_expect_success 'env--helper --type=ulong' '
+test_expect_success 'test-tool env-helper --type=ulong' '
echo 1234567890 >expected &&
- git env--helper --type=ulong --default=1234567890 MISSING >actual.out 2>actual.err &&
+ test-tool env-helper --type=ulong --default=1234567890 MISSING >actual.out 2>actual.err &&
test_cmp expected actual.out &&
test_must_be_empty actual.err &&
echo 0 >expected &&
- test_must_fail git env--helper --type=ulong --default=0 MISSING >actual &&
+ test_must_fail test-tool env-helper --type=ulong --default=0 MISSING >actual &&
test_cmp expected actual &&
- git env--helper --type=ulong --default=1234567890 --exit-code MISSING >actual.out 2>actual.err &&
+ test-tool env-helper --type=ulong --default=1234567890 --exit-code MISSING >actual.out 2>actual.err &&
test_must_be_empty actual.out &&
test_must_be_empty actual.err &&
- EXISTS=1234567890 git env--helper --type=ulong --default=0 EXISTS --exit-code >actual.out 2>actual.err &&
+ EXISTS=1234567890 test-tool env-helper --type=ulong --default=0 EXISTS --exit-code >actual.out 2>actual.err &&
test_must_be_empty actual.out &&
test_must_be_empty actual.err &&
echo 1234567890 >expected &&
- EXISTS=1234567890 git env--helper --type=ulong --default=0 EXISTS >actual.out 2>actual.err &&
+ EXISTS=1234567890 test-tool env-helper --type=ulong --default=0 EXISTS >actual.out 2>actual.err &&
test_cmp expected actual.out &&
test_must_be_empty actual.err
'
-test_expect_success 'env--helper reads config thanks to trace2' '
+test_expect_success 'test-tool env-helper reads config thanks to trace2' '
mkdir home &&
git config -f home/.gitconfig include.path cycle &&
git config -f home/cycle include.path .gitconfig &&
@@ -93,7 +93,7 @@ test_expect_success 'env--helper reads config thanks to trace2' '
test_must_fail \
env HOME="$(pwd)/home" GIT_TEST_ENV_HELPER=true \
- git -C cycle env--helper --type=bool --default=0 --exit-code GIT_TEST_ENV_HELPER 2>err &&
+ test-tool -C cycle env-helper --type=bool --default=0 --exit-code GIT_TEST_ENV_HELPER 2>err &&
grep "exceeded maximum include depth" err
'
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index 35cc8c3b39..81946e87cc 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -125,7 +125,7 @@ test_expect_success 'update with autocrlf=input' '
munge_cr append dir/two &&
git update-index -- one dir/two &&
differs=$(git diff-index --cached HEAD) &&
- verbose test -z "$differs"
+ test -z "$differs"
'
@@ -138,7 +138,7 @@ test_expect_success 'update with autocrlf=true' '
munge_cr append dir/two &&
git update-index -- one dir/two &&
differs=$(git diff-index --cached HEAD) &&
- verbose test -z "$differs"
+ test -z "$differs"
'
@@ -153,7 +153,7 @@ test_expect_success 'checkout with autocrlf=true' '
test "$one" = $(git hash-object --stdin <one) &&
test "$two" = $(git hash-object --stdin <dir/two) &&
differs=$(git diff-index --cached HEAD) &&
- verbose test -z "$differs"
+ test -z "$differs"
'
test_expect_success 'checkout with autocrlf=input' '
@@ -167,7 +167,7 @@ test_expect_success 'checkout with autocrlf=input' '
test "$one" = $(git hash-object --stdin <one) &&
test "$two" = $(git hash-object --stdin <dir/two) &&
differs=$(git diff-index --cached HEAD) &&
- verbose test -z "$differs"
+ test -z "$differs"
'
test_expect_success 'apply patch (autocrlf=input)' '
@@ -177,7 +177,7 @@ test_expect_success 'apply patch (autocrlf=input)' '
git read-tree --reset -u HEAD &&
git apply patch.file &&
- verbose test "$patched" = "$(git hash-object --stdin <one)"
+ test "$patched" = "$(git hash-object --stdin <one)"
'
test_expect_success 'apply patch --cached (autocrlf=input)' '
@@ -187,7 +187,7 @@ test_expect_success 'apply patch --cached (autocrlf=input)' '
git read-tree --reset -u HEAD &&
git apply --cached patch.file &&
- verbose test "$patched" = $(git rev-parse :one)
+ test "$patched" = $(git rev-parse :one)
'
test_expect_success 'apply patch --index (autocrlf=input)' '
@@ -197,8 +197,8 @@ test_expect_success 'apply patch --index (autocrlf=input)' '
git read-tree --reset -u HEAD &&
git apply --index patch.file &&
- verbose test "$patched" = $(git rev-parse :one) &&
- verbose test "$patched" = $(git hash-object --stdin <one)
+ test "$patched" = $(git rev-parse :one) &&
+ test "$patched" = $(git hash-object --stdin <one)
'
test_expect_success 'apply patch (autocrlf=true)' '
@@ -208,7 +208,7 @@ test_expect_success 'apply patch (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply patch.file &&
- verbose test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
+ test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
'
test_expect_success 'apply patch --cached (autocrlf=true)' '
@@ -218,7 +218,7 @@ test_expect_success 'apply patch --cached (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply --cached patch.file &&
- verbose test "$patched" = $(git rev-parse :one)
+ test "$patched" = $(git rev-parse :one)
'
test_expect_success 'apply patch --index (autocrlf=true)' '
@@ -228,8 +228,8 @@ test_expect_success 'apply patch --index (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply --index patch.file &&
- verbose test "$patched" = $(git rev-parse :one) &&
- verbose test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
+ test "$patched" = $(git rev-parse :one) &&
+ test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
'
test_expect_success '.gitattributes says two is binary' '
@@ -240,7 +240,7 @@ test_expect_success '.gitattributes says two is binary' '
git read-tree --reset -u HEAD &&
! has_cr dir/two &&
- verbose has_cr one &&
+ has_cr one &&
! has_cr three
'
@@ -259,8 +259,8 @@ test_expect_success '.gitattributes says two and three are text' '
echo "t* crlf" >.gitattributes &&
git read-tree --reset -u HEAD &&
- verbose has_cr dir/two &&
- verbose has_cr three
+ has_cr dir/two &&
+ has_cr three
'
test_expect_success 'in-tree .gitattributes (1)' '
@@ -273,7 +273,7 @@ test_expect_success 'in-tree .gitattributes (1)' '
git read-tree --reset -u HEAD &&
! has_cr one &&
- verbose has_cr three
+ has_cr three
'
test_expect_success 'in-tree .gitattributes (2)' '
@@ -283,7 +283,7 @@ test_expect_success 'in-tree .gitattributes (2)' '
git checkout-index -f -q -u -a &&
! has_cr one &&
- verbose has_cr three
+ has_cr three
'
test_expect_success 'in-tree .gitattributes (3)' '
@@ -294,7 +294,7 @@ test_expect_success 'in-tree .gitattributes (3)' '
git checkout-index -u one dir/two three &&
! has_cr one &&
- verbose has_cr three
+ has_cr three
'
test_expect_success 'in-tree .gitattributes (4)' '
@@ -305,7 +305,7 @@ test_expect_success 'in-tree .gitattributes (4)' '
git checkout-index -u .gitattributes &&
! has_cr one &&
- verbose has_cr three
+ has_cr three
'
test_expect_success 'checkout with existing .gitattributes' '
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index abecd75e4e..46abbeed68 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -8,8 +8,8 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
-TEST_ROOT="$PWD"
-PATH=$TEST_ROOT:$PATH
+PATH=$PWD:$PATH
+TEST_ROOT="$(pwd)"
write_script <<\EOF "$TEST_ROOT/rot13.sh"
tr \
diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index f9bbb91f64..575805513a 100755
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
@@ -2,6 +2,7 @@
test_description='Test am with auto.crlf'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >patchfile <<\EOF
diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh
index a94ac1eae3..2f57c8669c 100755
--- a/t/t0027-auto-crlf.sh
+++ b/t/t0027-auto-crlf.sh
@@ -70,7 +70,8 @@ create_NNO_MIX_files () {
cp CRLF ${pfx}_CRLF.txt &&
cp CRLF_mix_LF ${pfx}_CRLF_mix_LF.txt &&
cp LF_mix_CR ${pfx}_LF_mix_CR.txt &&
- cp CRLF_nul ${pfx}_CRLF_nul.txt
+ cp CRLF_nul ${pfx}_CRLF_nul.txt ||
+ return 1
done
done
done
@@ -101,7 +102,8 @@ commit_check_warn () {
do
fname=${pfx}_$f.txt &&
cp $f $fname &&
- git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err"
+ git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" ||
+ return 1
done &&
git commit -m "core.autocrlf $crlf" &&
check_warning "$lfname" ${pfx}_LF.err &&
@@ -121,15 +123,19 @@ commit_chk_wrnNNO () {
lfmixcr=$1 ; shift
crlfnul=$1 ; shift
pfx=NNO_attr_${attr}_aeol_${aeol}_${crlf}
- #Commit files on top of existing file
- create_gitattributes "$attr" $aeol &&
- for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
- do
- fname=${pfx}_$f.txt &&
- cp $f $fname &&
- printf Z >>"$fname" &&
- git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err"
- done
+
+ test_expect_success 'setup commit NNO files' '
+ #Commit files on top of existing file
+ create_gitattributes "$attr" $aeol &&
+ for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+ do
+ fname=${pfx}_$f.txt &&
+ cp $f $fname &&
+ printf Z >>"$fname" &&
+ git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" ||
+ return 1
+ done
+ '
test_expect_success "commit NNO files crlf=$crlf attr=$attr LF" '
check_warning "$lfwarn" ${pfx}_LF.err
@@ -163,15 +169,19 @@ commit_MIX_chkwrn () {
lfmixcr=$1 ; shift
crlfnul=$1 ; shift
pfx=MIX_attr_${attr}_aeol_${aeol}_${crlf}
- #Commit file with CLRF_mix_LF on top of existing file
- create_gitattributes "$attr" $aeol &&
- for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
- do
- fname=${pfx}_$f.txt &&
- cp CRLF_mix_LF $fname &&
- printf Z >>"$fname" &&
- git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err"
- done
+
+ test_expect_success 'setup commit file with mixed EOL' '
+ #Commit file with CLRF_mix_LF on top of existing file
+ create_gitattributes "$attr" $aeol &&
+ for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+ do
+ fname=${pfx}_$f.txt &&
+ cp CRLF_mix_LF $fname &&
+ printf Z >>"$fname" &&
+ git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" ||
+ return 1
+ done
+ '
test_expect_success "commit file with mixed EOL onto LF crlf=$crlf attr=$attr" '
check_warning "$lfwarn" ${pfx}_LF.err
@@ -289,17 +299,17 @@ checkout_files () {
lfmixcrlf=$1 ; shift
lfmixcr=$1 ; shift
crlfnul=$1 ; shift
- create_gitattributes "$attr" $ident $aeol &&
- git config core.autocrlf $crlf &&
+ test_expect_success "setup config for checkout attr=$attr ident=$ident aeol=$aeol core.autocrlf=$crlf" '
+ create_gitattributes "$attr" $ident $aeol &&
+ git config core.autocrlf $crlf
+ '
pfx=eol_${ceol}_crlf_${crlf}_attr_${attr}_ &&
for f in LF CRLF LF_mix_CR CRLF_mix_LF LF_nul
do
- rm crlf_false_attr__$f.txt &&
- if test -z "$ceol"; then
- git checkout -- crlf_false_attr__$f.txt
- else
- git -c core.eol=$ceol checkout -- crlf_false_attr__$f.txt
- fi
+ test_expect_success "setup $f checkout ${ceol:+ with -c core.eol=$ceol}" '
+ rm -f crlf_false_attr__$f.txt &&
+ git ${ceol:+-c core.eol=$ceol} checkout -- crlf_false_attr__$f.txt
+ '
done
test_expect_success "ls-files --eol attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol" '
diff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh
index 0a5713c524..d1b3be8725 100755
--- a/t/t0030-stripspace.sh
+++ b/t/t0030-stripspace.sh
@@ -17,396 +17,378 @@ printf_git_stripspace () {
printf "$1" | git stripspace
}
-test_expect_success \
- 'long lines without spaces should be unchanged' '
- echo "$ttt" >expect &&
- git stripspace <expect >actual &&
- test_cmp expect actual &&
-
- echo "$ttt$ttt" >expect &&
- git stripspace <expect >actual &&
- test_cmp expect actual &&
-
- echo "$ttt$ttt$ttt" >expect &&
- git stripspace <expect >actual &&
- test_cmp expect actual &&
-
- echo "$ttt$ttt$ttt$ttt" >expect &&
- git stripspace <expect >actual &&
- test_cmp expect actual
+test_expect_success 'long lines without spaces should be unchanged' '
+ echo "$ttt" >expect &&
+ git stripspace <expect >actual &&
+ test_cmp expect actual &&
+
+ echo "$ttt$ttt" >expect &&
+ git stripspace <expect >actual &&
+ test_cmp expect actual &&
+
+ echo "$ttt$ttt$ttt" >expect &&
+ git stripspace <expect >actual &&
+ test_cmp expect actual &&
+
+ echo "$ttt$ttt$ttt$ttt" >expect &&
+ git stripspace <expect >actual &&
+ test_cmp expect actual
'
-test_expect_success \
- 'lines with spaces at the beginning should be unchanged' '
- echo "$sss$ttt" >expect &&
- git stripspace <expect >actual &&
- test_cmp expect actual &&
+test_expect_success 'lines with spaces at the beginning should be unchanged' '
+ echo "$sss$ttt" >expect &&
+ git stripspace <expect >actual &&
+ test_cmp expect actual &&
- echo "$sss$sss$ttt" >expect &&
- git stripspace <expect >actual &&
- test_cmp expect actual &&
+ echo "$sss$sss$ttt" >expect &&
+ git stripspace <expect >actual &&
+ test_cmp expect actual &&
- echo "$sss$sss$sss$ttt" >expect &&
- git stripspace <expect >actual &&
- test_cmp expect actual
+ echo "$sss$sss$sss$ttt" >expect &&
+ git stripspace <expect >actual &&
+ test_cmp expect actual
'
-test_expect_success \
- 'lines with intermediate spaces should be unchanged' '
- echo "$ttt$sss$ttt" >expect &&
- git stripspace <expect >actual &&
- test_cmp expect actual &&
+test_expect_success 'lines with intermediate spaces should be unchanged' '
+ echo "$ttt$sss$ttt" >expect &&
+ git stripspace <expect >actual &&
+ test_cmp expect actual &&
- echo "$ttt$sss$sss$ttt" >expect &&
- git stripspace <expect >actual &&
- test_cmp expect actual
+ echo "$ttt$sss$sss$ttt" >expect &&
+ git stripspace <expect >actual &&
+ test_cmp expect actual
'
-test_expect_success \
- 'consecutive blank lines should be unified' '
- printf "$ttt\n\n$ttt\n" > expect &&
- printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+test_expect_success 'consecutive blank lines should be unified' '
+ printf "$ttt\n\n$ttt\n" > expect &&
+ printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt\n\n$ttt\n" > expect &&
- printf "$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt\n\n$ttt\n" > expect &&
+ printf "$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt$ttt\n\n$ttt\n" > expect &&
- printf "$ttt$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt$ttt\n\n$ttt\n" > expect &&
+ printf "$ttt$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n\n$ttt\n" > expect &&
- printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n\n$ttt\n" > expect &&
+ printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n\n$ttt$ttt\n" > expect &&
- printf "$ttt\n\n\n\n\n$ttt$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n\n$ttt$ttt\n" > expect &&
+ printf "$ttt\n\n\n\n\n$ttt$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n\n$ttt$ttt$ttt\n" > expect &&
- printf "$ttt\n\n\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n\n$ttt$ttt$ttt\n" > expect &&
+ printf "$ttt\n\n\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n\n$ttt\n" > expect &&
- printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n\n$ttt\n" > expect &&
+ printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt\n\n$ttt\n" > expect &&
- printf "$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt\n\n$ttt\n" > expect &&
+ printf "$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt$ttt\n\n$ttt\n" > expect &&
- printf "$ttt$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt$ttt\n\n$ttt\n" > expect &&
+ printf "$ttt$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n\n$ttt\n" > expect &&
- printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n\n$ttt\n" > expect &&
+ printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n\n$ttt$ttt\n" > expect &&
- printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n\n$ttt$ttt\n" > expect &&
+ printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n\n$ttt$ttt$ttt\n" > expect &&
- printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt$ttt\n" | git stripspace >actual &&
- test_cmp expect actual
+ printf "$ttt\n\n$ttt$ttt$ttt\n" > expect &&
+ printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual
'
-test_expect_success \
- 'only consecutive blank lines should be completely removed' '
+test_expect_success 'only consecutive blank lines should be completely removed' '
+ printf "\n" | git stripspace >actual &&
+ test_must_be_empty actual &&
- printf "\n" | git stripspace >actual &&
- test_must_be_empty actual &&
+ printf "\n\n\n" | git stripspace >actual &&
+ test_must_be_empty actual &&
- printf "\n\n\n" | git stripspace >actual &&
- test_must_be_empty actual &&
+ printf "$sss\n$sss\n$sss\n" | git stripspace >actual &&
+ test_must_be_empty actual &&
- printf "$sss\n$sss\n$sss\n" | git stripspace >actual &&
- test_must_be_empty actual &&
+ printf "$sss$sss\n$sss\n\n" | git stripspace >actual &&
+ test_must_be_empty actual &&
- printf "$sss$sss\n$sss\n\n" | git stripspace >actual &&
- test_must_be_empty actual &&
+ printf "\n$sss\n$sss$sss\n" | git stripspace >actual &&
+ test_must_be_empty actual &&
- printf "\n$sss\n$sss$sss\n" | git stripspace >actual &&
- test_must_be_empty actual &&
+ printf "$sss$sss$sss$sss\n\n\n" | git stripspace >actual &&
+ test_must_be_empty actual &&
- printf "$sss$sss$sss$sss\n\n\n" | git stripspace >actual &&
- test_must_be_empty actual &&
+ printf "\n$sss$sss$sss$sss\n\n" | git stripspace >actual &&
+ test_must_be_empty actual &&
- printf "\n$sss$sss$sss$sss\n\n" | git stripspace >actual &&
- test_must_be_empty actual &&
-
- printf "\n\n$sss$sss$sss$sss\n" | git stripspace >actual &&
- test_must_be_empty actual
+ printf "\n\n$sss$sss$sss$sss\n" | git stripspace >actual &&
+ test_must_be_empty actual
'
-test_expect_success \
- 'consecutive blank lines at the beginning should be removed' '
- printf "$ttt\n" > expect &&
- printf "\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+test_expect_success 'consecutive blank lines at the beginning should be removed' '
+ printf "$ttt\n" > expect &&
+ printf "\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n" > expect &&
- printf "\n\n\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n" > expect &&
+ printf "\n\n\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt\n" > expect &&
- printf "\n\n\n$ttt$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt\n" > expect &&
+ printf "\n\n\n$ttt$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt$ttt\n" > expect &&
- printf "\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt$ttt\n" > expect &&
+ printf "\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt$ttt$ttt\n" > expect &&
- printf "\n\n\n$ttt$ttt$ttt$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt$ttt$ttt\n" > expect &&
+ printf "\n\n\n$ttt$ttt$ttt$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n" > expect &&
+ printf "$ttt\n" > expect &&
- printf "$sss\n$sss\n$sss\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$sss\n$sss\n$sss\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "\n$sss\n$sss$sss\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "\n$sss\n$sss$sss\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$sss$sss\n$sss\n\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$sss$sss\n$sss\n\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$sss$sss$sss\n\n\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$sss$sss$sss\n\n\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "\n$sss$sss$sss\n\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "\n$sss$sss$sss\n\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "\n\n$sss$sss$sss\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual
+ printf "\n\n$sss$sss$sss\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual
'
-test_expect_success \
- 'consecutive blank lines at the end should be removed' '
- printf "$ttt\n" > expect &&
- printf "$ttt\n\n" | git stripspace >actual &&
- test_cmp expect actual &&
+test_expect_success 'consecutive blank lines at the end should be removed' '
+ printf "$ttt\n" > expect &&
+ printf "$ttt\n\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n" > expect &&
- printf "$ttt\n\n\n\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n" > expect &&
+ printf "$ttt\n\n\n\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt\n" > expect &&
- printf "$ttt$ttt\n\n\n\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt\n" > expect &&
+ printf "$ttt$ttt\n\n\n\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt$ttt\n" > expect &&
- printf "$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt$ttt\n" > expect &&
+ printf "$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt$ttt$ttt\n" > expect &&
- printf "$ttt$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt$ttt$ttt\n" > expect &&
+ printf "$ttt$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n" > expect &&
+ printf "$ttt\n" > expect &&
- printf "$ttt\n$sss\n$sss\n$sss\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n$sss\n$sss\n$sss\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n\n$sss\n$sss$sss\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n\n$sss\n$sss$sss\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n$sss$sss\n$sss\n\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n$sss$sss\n$sss\n\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n$sss$sss$sss\n\n\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n$sss$sss$sss\n\n\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n\n$sss$sss$sss\n\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n\n$sss$sss$sss\n\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n\n\n$sss$sss$sss\n" | git stripspace >actual &&
- test_cmp expect actual
+ printf "$ttt\n\n\n$sss$sss$sss\n" | git stripspace >actual &&
+ test_cmp expect actual
'
-test_expect_success \
- 'text without newline at end should end with newline' '
- test_stdout_line_count -gt 0 printf_git_stripspace "$ttt" &&
- test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt" &&
- test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt" &&
- test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt$ttt"
+test_expect_success 'text without newline at end should end with newline' '
+ test_stdout_line_count -gt 0 printf_git_stripspace "$ttt" &&
+ test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt" &&
+ test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt" &&
+ test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt$ttt"
'
# text plus spaces at the end:
-test_expect_success \
- 'text plus spaces without newline at end should end with newline' '
- test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss" &&
- test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$sss" &&
- test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt$sss" &&
- test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss$sss" &&
- test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$sss$sss" &&
- test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss$sss$sss"
+test_expect_success 'text plus spaces without newline at end should end with newline' '
+ test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss" &&
+ test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$sss" &&
+ test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt$sss" &&
+ test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss$sss" &&
+ test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$sss$sss" &&
+ test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss$sss$sss"
'
-test_expect_success \
- 'text plus spaces without newline at end should not show spaces' '
- printf "$ttt$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- printf "$ttt$ttt$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- printf "$ttt$ttt$ttt$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- printf "$ttt$sss$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- printf "$ttt$ttt$sss$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- printf "$ttt$sss$sss$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null
+test_expect_success 'text plus spaces without newline at end should not show spaces' '
+ printf "$ttt$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ printf "$ttt$ttt$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ printf "$ttt$ttt$ttt$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ printf "$ttt$sss$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ printf "$ttt$ttt$sss$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ printf "$ttt$sss$sss$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null
'
-test_expect_success \
- 'text plus spaces without newline should show the correct lines' '
- printf "$ttt\n" >expect &&
- printf "$ttt$sss" | git stripspace >actual &&
- test_cmp expect actual &&
+test_expect_success 'text plus spaces without newline should show the correct lines' '
+ printf "$ttt\n" >expect &&
+ printf "$ttt$sss" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n" >expect &&
- printf "$ttt$sss$sss" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n" >expect &&
+ printf "$ttt$sss$sss" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n" >expect &&
- printf "$ttt$sss$sss$sss" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n" >expect &&
+ printf "$ttt$sss$sss$sss" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt\n" >expect &&
- printf "$ttt$ttt$sss" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt\n" >expect &&
+ printf "$ttt$ttt$sss" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt\n" >expect &&
- printf "$ttt$ttt$sss$sss" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt\n" >expect &&
+ printf "$ttt$ttt$sss$sss" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt$ttt\n" >expect &&
- printf "$ttt$ttt$ttt$sss" | git stripspace >actual &&
- test_cmp expect actual
+ printf "$ttt$ttt$ttt\n" >expect &&
+ printf "$ttt$ttt$ttt$sss" | git stripspace >actual &&
+ test_cmp expect actual
'
-test_expect_success \
- 'text plus spaces at end should not show spaces' '
- echo "$ttt$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- echo "$ttt$ttt$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- echo "$ttt$ttt$ttt$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- echo "$ttt$sss$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- echo "$ttt$ttt$sss$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- echo "$ttt$sss$sss$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null
+test_expect_success 'text plus spaces at end should not show spaces' '
+ echo "$ttt$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ echo "$ttt$ttt$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ echo "$ttt$ttt$ttt$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ echo "$ttt$sss$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ echo "$ttt$ttt$sss$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ echo "$ttt$sss$sss$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null
'
-test_expect_success \
- 'text plus spaces at end should be cleaned and newline must remain' '
- echo "$ttt" >expect &&
- echo "$ttt$sss" | git stripspace >actual &&
- test_cmp expect actual &&
+test_expect_success 'text plus spaces at end should be cleaned and newline must remain' '
+ echo "$ttt" >expect &&
+ echo "$ttt$sss" | git stripspace >actual &&
+ test_cmp expect actual &&
- echo "$ttt" >expect &&
- echo "$ttt$sss$sss" | git stripspace >actual &&
- test_cmp expect actual &&
+ echo "$ttt" >expect &&
+ echo "$ttt$sss$sss" | git stripspace >actual &&
+ test_cmp expect actual &&
- echo "$ttt" >expect &&
- echo "$ttt$sss$sss$sss" | git stripspace >actual &&
- test_cmp expect actual &&
+ echo "$ttt" >expect &&
+ echo "$ttt$sss$sss$sss" | git stripspace >actual &&
+ test_cmp expect actual &&
- echo "$ttt$ttt" >expect &&
- echo "$ttt$ttt$sss" | git stripspace >actual &&
- test_cmp expect actual &&
+ echo "$ttt$ttt" >expect &&
+ echo "$ttt$ttt$sss" | git stripspace >actual &&
+ test_cmp expect actual &&
- echo "$ttt$ttt" >expect &&
- echo "$ttt$ttt$sss$sss" | git stripspace >actual &&
- test_cmp expect actual &&
+ echo "$ttt$ttt" >expect &&
+ echo "$ttt$ttt$sss$sss" | git stripspace >actual &&
+ test_cmp expect actual &&
- echo "$ttt$ttt$ttt" >expect &&
- echo "$ttt$ttt$ttt$sss" | git stripspace >actual &&
- test_cmp expect actual
+ echo "$ttt$ttt$ttt" >expect &&
+ echo "$ttt$ttt$ttt$sss" | git stripspace >actual &&
+ test_cmp expect actual
'
# spaces only:
-test_expect_success \
- 'spaces with newline at end should be replaced with empty string' '
- echo | git stripspace >actual &&
- test_must_be_empty actual &&
+test_expect_success 'spaces with newline at end should be replaced with empty string' '
+ echo | git stripspace >actual &&
+ test_must_be_empty actual &&
- echo "$sss" | git stripspace >actual &&
- test_must_be_empty actual &&
+ echo "$sss" | git stripspace >actual &&
+ test_must_be_empty actual &&
- echo "$sss$sss" | git stripspace >actual &&
- test_must_be_empty actual &&
+ echo "$sss$sss" | git stripspace >actual &&
+ test_must_be_empty actual &&
- echo "$sss$sss$sss" | git stripspace >actual &&
- test_must_be_empty actual &&
+ echo "$sss$sss$sss" | git stripspace >actual &&
+ test_must_be_empty actual &&
- echo "$sss$sss$sss$sss" | git stripspace >actual &&
- test_must_be_empty actual
+ echo "$sss$sss$sss$sss" | git stripspace >actual &&
+ test_must_be_empty actual
'
-test_expect_success \
- 'spaces without newline at end should not show spaces' '
- printf "" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- printf "$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- printf "$sss$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- printf "$sss$sss$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null &&
- printf "$sss$sss$sss$sss" | git stripspace >tmp &&
- ! grep " " tmp >/dev/null
+test_expect_success 'spaces without newline at end should not show spaces' '
+ printf "" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ printf "$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ printf "$sss$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ printf "$sss$sss$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null &&
+ printf "$sss$sss$sss$sss" | git stripspace >tmp &&
+ ! grep " " tmp >/dev/null
'
-test_expect_success \
- 'spaces without newline at end should be replaced with empty string' '
- printf "" | git stripspace >actual &&
- test_must_be_empty actual &&
+test_expect_success 'spaces without newline at end should be replaced with empty string' '
+ printf "" | git stripspace >actual &&
+ test_must_be_empty actual &&
- printf "$sss$sss" | git stripspace >actual &&
- test_must_be_empty actual &&
+ printf "$sss$sss" | git stripspace >actual &&
+ test_must_be_empty actual &&
- printf "$sss$sss$sss" | git stripspace >actual &&
- test_must_be_empty actual &&
+ printf "$sss$sss$sss" | git stripspace >actual &&
+ test_must_be_empty actual &&
- printf "$sss$sss$sss$sss" | git stripspace >actual &&
- test_must_be_empty actual
+ printf "$sss$sss$sss$sss" | git stripspace >actual &&
+ test_must_be_empty actual
'
-test_expect_success \
- 'consecutive text lines should be unchanged' '
- printf "$ttt$ttt\n$ttt\n" >expect &&
- printf "$ttt$ttt\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+test_expect_success 'consecutive text lines should be unchanged' '
+ printf "$ttt$ttt\n$ttt\n" >expect &&
+ printf "$ttt$ttt\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n$ttt$ttt\n$ttt\n" >expect &&
- printf "$ttt\n$ttt$ttt\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n$ttt$ttt\n$ttt\n" >expect &&
+ printf "$ttt\n$ttt$ttt\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" >expect &&
- printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" >expect &&
+ printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" >expect &&
- printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" >expect &&
+ printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" >expect &&
- printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" | git stripspace >actual &&
- test_cmp expect actual &&
+ printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" >expect &&
+ printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual &&
- printf "$ttt\n$ttt$ttt\n\n$ttt\n" >expect &&
- printf "$ttt\n$ttt$ttt\n\n$ttt\n" | git stripspace >actual &&
- test_cmp expect actual
+ printf "$ttt\n$ttt$ttt\n\n$ttt\n" >expect &&
+ printf "$ttt\n$ttt$ttt\n\n$ttt\n" | git stripspace >actual &&
+ test_cmp expect actual
'
test_expect_success 'strip comments, too' '
diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh
index aecb308cf6..dc3496897a 100755
--- a/t/t0033-safe-directory.sh
+++ b/t/t0033-safe-directory.sh
@@ -71,4 +71,13 @@ test_expect_success 'safe.directory=*, but is reset' '
expect_rejected_dir
'
+test_expect_success 'safe.directory in included file' '
+ cat >gitconfig-include <<-EOF &&
+ [safe]
+ directory = "$(pwd)"
+ EOF
+ git config --global --add include.path "$(pwd)/gitconfig-include" &&
+ git status
+'
+
test_done
diff --git a/t/t0035-safe-bare-repository.sh b/t/t0035-safe-bare-repository.sh
index ecbdc8238d..038b8b788d 100755
--- a/t/t0035-safe-bare-repository.sh
+++ b/t/t0035-safe-bare-repository.sh
@@ -7,13 +7,26 @@ TEST_PASSES_SANITIZE_LEAK=true
pwd="$(pwd)"
-expect_accepted () {
- git "$@" rev-parse --git-dir
+expect_accepted_implicit () {
+ test_when_finished 'rm "$pwd/trace.perf"' &&
+ GIT_TRACE2_PERF="$pwd/trace.perf" git "$@" rev-parse --git-dir &&
+ # Note: we're intentionally only checking that the bare repo has a
+ # directory *prefix* of $pwd
+ grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf"
+}
+
+expect_accepted_explicit () {
+ test_when_finished 'rm "$pwd/trace.perf"' &&
+ GIT_DIR="$1" GIT_TRACE2_PERF="$pwd/trace.perf" git rev-parse --git-dir &&
+ ! grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf"
}
expect_rejected () {
- test_must_fail git "$@" rev-parse --git-dir 2>err &&
- grep -F "cannot use bare repository" err
+ test_when_finished 'rm "$pwd/trace.perf"' &&
+ test_env GIT_TRACE2_PERF="$pwd/trace.perf" \
+ test_must_fail git "$@" rev-parse --git-dir 2>err &&
+ grep -F "cannot use bare repository" err &&
+ grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf"
}
test_expect_success 'setup bare repo in worktree' '
@@ -22,12 +35,13 @@ test_expect_success 'setup bare repo in worktree' '
'
test_expect_success 'safe.bareRepository unset' '
- expect_accepted -C outer-repo/bare-repo
+ test_unconfig --global safe.bareRepository &&
+ expect_accepted_implicit -C outer-repo/bare-repo
'
test_expect_success 'safe.bareRepository=all' '
test_config_global safe.bareRepository all &&
- expect_accepted -C outer-repo/bare-repo
+ expect_accepted_implicit -C outer-repo/bare-repo
'
test_expect_success 'safe.bareRepository=explicit' '
@@ -47,8 +61,21 @@ test_expect_success 'safe.bareRepository in the repository' '
test_expect_success 'safe.bareRepository on the command line' '
test_config_global safe.bareRepository explicit &&
- expect_accepted -C outer-repo/bare-repo \
+ expect_accepted_implicit -C outer-repo/bare-repo \
-c safe.bareRepository=all
'
+test_expect_success 'safe.bareRepository in included file' '
+ cat >gitconfig-include <<-\EOF &&
+ [safe]
+ bareRepository = explicit
+ EOF
+ git config --global --add include.path "$(pwd)/gitconfig-include" &&
+ expect_rejected -C outer-repo/bare-repo
+'
+
+test_expect_success 'no trace when GIT_DIR is explicitly provided' '
+ expect_accepted_explicit "$pwd/outer-repo/bare-repo"
+'
+
test_done
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 5cc62306e3..a0ad6192d6 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -13,29 +13,35 @@ usage: test-tool parse-options <options>
A helper function for the parse-options API.
- --yes get a boolean
+ --[no-]yes get a boolean
-D, --no-doubt begins with 'no-'
+ --doubt opposite of --no-doubt
-B, --no-fear be brave
- -b, --boolean increment by one
- -4, --or4 bitwise-or boolean with ...0100
- --neg-or4 same as --no-or4
+ -b, --[no-]boolean increment by one
+ -4, --[no-]or4 bitwise-or boolean with ...0100
+ --[no-]neg-or4 same as --no-or4
- -i, --integer <n> get a integer
+ -i, --[no-]integer <n>
+ get a integer
-j <n> get a integer, too
-m, --magnitude <n> get a magnitude
- --set23 set integer to 23
+ --[no-]set23 set integer to 23
--mode1 set integer to 1 (cmdmode option)
--mode2 set integer to 2 (cmdmode option)
- -L, --length <str> get length of <str>
- -F, --file <file> set file to <file>
+ -L, --[no-]length <str>
+ get length of <str>
+ -F, --[no-]file <file>
+ set file to <file>
String options
- -s, --string <string>
+ -s, --[no-]string <string>
get a string
- --string2 <str> get another string
- --st <st> get another string (pervert ordering)
+ --[no-]string2 <str> get another string
+ --[no-]st <st> get another string (pervert ordering)
-o <str> get another string
- --list <str> add str to list
+ --longhelp help text of this entry
+ spans multiple lines
+ --[no-]list <str> add str to list
Magic arguments
-NUM set integer to NUM
@@ -44,16 +50,17 @@ Magic arguments
--no-ambiguous negative ambiguity
Standard options
- --abbrev[=<n>] use <n> digits to display object names
- -v, --verbose be verbose
- -n, --dry-run dry run
- -q, --quiet be quiet
- --expect <string> expected output in the variable dump
+ --[no-]abbrev[=<n>] use <n> digits to display object names
+ -v, --[no-]verbose be verbose
+ -n, --[no-]dry-run dry run
+ -q, --[no-]quiet be quiet
+ --[no-]expect <string>
+ expected output in the variable dump
Alias
- -A, --alias-source <string>
+ -A, --[no-]alias-source <string>
get a string
- -Z, --alias-target <string>
+ -Z, --[no-]alias-target <string>
alias of --alias-source
EOF
@@ -709,4 +716,16 @@ test_expect_success 'subcommands are incompatible with KEEP_DASHDASH unless in c
grep ^BUG err
'
+test_expect_success 'negative magnitude' '
+ test_must_fail test-tool parse-options --magnitude -1 >out 2>err &&
+ grep "non-negative integer" err &&
+ test_must_be_empty out
+'
+
+test_expect_success 'magnitude with units but no numbers' '
+ test_must_fail test-tool parse-options --magnitude m >out 2>err &&
+ grep "non-negative integer" err &&
+ test_must_be_empty out
+'
+
test_done
diff --git a/t/t0041-usage.sh b/t/t0041-usage.sh
index c4fc34eb18..9ea974b0c6 100755
--- a/t/t0041-usage.sh
+++ b/t/t0041-usage.sh
@@ -5,6 +5,7 @@ test_description='Test commands behavior when given invalid argument value'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup ' '
diff --git a/t/t0055-beyond-symlinks.sh b/t/t0055-beyond-symlinks.sh
index 6bada37022..c3eb1158ef 100755
--- a/t/t0055-beyond-symlinks.sh
+++ b/t/t0055-beyond-symlinks.sh
@@ -15,12 +15,22 @@ test_expect_success SYMLINKS setup '
test_expect_success SYMLINKS 'update-index --add beyond symlinks' '
test_must_fail git update-index --add c/d &&
- ! ( git ls-files | grep c/d )
+ cat >expect <<-\EOF &&
+ a
+ b/d
+ EOF
+ git ls-files >actual &&
+ test_cmp expect actual
'
test_expect_success SYMLINKS 'add beyond symlinks' '
test_must_fail git add c/d &&
- ! ( git ls-files | grep c/d )
+ cat >expect <<-\EOF &&
+ a
+ b/d
+ EOF
+ git ls-files >actual &&
+ test_cmp expect actual
'
test_done
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 68e29c904a..0afa3d0d31 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -10,20 +10,27 @@ TEST_PASSES_SANITIZE_LEAK=true
norm_path() {
expected=$(test-tool path-utils print_path "$2")
- test_expect_success $3 "normalize path: $1 => $2" \
- "test \"\$(test-tool path-utils normalize_path_copy '$1')\" = '$expected'"
+ test_expect_success $3 "normalize path: $1 => $2" "
+ echo '$expected' >expect &&
+ test-tool path-utils normalize_path_copy '$1' >actual &&
+ test_cmp expect actual
+ "
}
relative_path() {
expected=$(test-tool path-utils print_path "$3")
- test_expect_success $4 "relative path: $1 $2 => $3" \
- "test \"\$(test-tool path-utils relative_path '$1' '$2')\" = '$expected'"
+ test_expect_success $4 "relative path: $1 $2 => $3" "
+ echo '$expected' >expect &&
+ test-tool path-utils relative_path '$1' '$2' >actual &&
+ test_cmp expect actual
+ "
}
test_submodule_relative_url() {
test_expect_success "test_submodule_relative_url: $1 $2 $3 => $4" "
- actual=\$(test-tool submodule resolve-relative-url '$1' '$2' '$3') &&
- test \"\$actual\" = '$4'
+ echo '$4' >expect &&
+ test-tool submodule resolve-relative-url '$1' '$2' '$3' >actual &&
+ test_cmp expect actual
"
}
@@ -64,9 +71,11 @@ ancestor() {
expected=$(($expected-$rootslash+$rootoff))
;;
esac
- test_expect_success $4 "longest ancestor: $1 $2 => $expected" \
- "actual=\$(test-tool path-utils longest_ancestor_length '$1' '$2') &&
- test \"\$actual\" = '$expected'"
+ test_expect_success $4 "longest ancestor: $1 $2 => $expected" "
+ echo '$expected' >expect &&
+ test-tool path-utils longest_ancestor_length '$1' '$2' >actual &&
+ test_cmp expect actual
+ "
}
# Some absolute path tests should be skipped on Windows due to path mangling
@@ -166,8 +175,10 @@ ancestor D:/Users/me C:/ -1 MINGW
ancestor //server/share/my-directory //server/share/ 14 MINGW
test_expect_success 'strip_path_suffix' '
- test c:/msysgit = $(test-tool path-utils strip_path_suffix \
- c:/msysgit/libexec//git-core libexec/git-core)
+ echo c:/msysgit >expect &&
+ test-tool path-utils strip_path_suffix \
+ c:/msysgit/libexec//git-core libexec/git-core >actual &&
+ test_cmp expect actual
'
test_expect_success 'absolute path rejects the empty string' '
@@ -188,35 +199,61 @@ test_expect_success 'real path rejects the empty string' '
'
test_expect_success POSIX 'real path works on absolute paths 1' '
+ echo / >expect &&
+ test-tool path-utils real_path "/" >actual &&
+ test_cmp expect actual &&
+
nopath="hopefully-absent-path" &&
- test "/" = "$(test-tool path-utils real_path "/")" &&
- test "/$nopath" = "$(test-tool path-utils real_path "/$nopath")"
+ echo "/$nopath" >expect &&
+ test-tool path-utils real_path "/$nopath" >actual &&
+ test_cmp expect actual
'
test_expect_success 'real path works on absolute paths 2' '
- nopath="hopefully-absent-path" &&
# Find an existing top-level directory for the remaining tests:
d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
- test "$d" = "$(test-tool path-utils real_path "$d")" &&
- test "$d/$nopath" = "$(test-tool path-utils real_path "$d/$nopath")"
+ echo "$d" >expect &&
+ test-tool path-utils real_path "$d" >actual &&
+ test_cmp expect actual &&
+
+ nopath="hopefully-absent-path" &&
+ echo "$d/$nopath" >expect &&
+ test-tool path-utils real_path "$d/$nopath" >actual &&
+ test_cmp expect actual
'
test_expect_success POSIX 'real path removes extra leading slashes' '
+ echo "/" >expect &&
+ test-tool path-utils real_path "///" >actual &&
+ test_cmp expect actual &&
+
nopath="hopefully-absent-path" &&
- test "/" = "$(test-tool path-utils real_path "///")" &&
- test "/$nopath" = "$(test-tool path-utils real_path "///$nopath")" &&
+ echo "/$nopath" >expect &&
+ test-tool path-utils real_path "///$nopath" >actual &&
+ test_cmp expect actual &&
+
# Find an existing top-level directory for the remaining tests:
d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
- test "$d" = "$(test-tool path-utils real_path "//$d")" &&
- test "$d/$nopath" = "$(test-tool path-utils real_path "//$d/$nopath")"
+ echo "$d" >expect &&
+ test-tool path-utils real_path "//$d" >actual &&
+ test_cmp expect actual &&
+
+ echo "$d/$nopath" >expect &&
+ test-tool path-utils real_path "//$d/$nopath" >actual &&
+ test_cmp expect actual
'
test_expect_success 'real path removes other extra slashes' '
- nopath="hopefully-absent-path" &&
# Find an existing top-level directory for the remaining tests:
d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") &&
- test "$d" = "$(test-tool path-utils real_path "$d///")" &&
- test "$d/$nopath" = "$(test-tool path-utils real_path "$d///$nopath")"
+ echo "$d" >expect &&
+ test-tool path-utils real_path "$d///" >actual &&
+ test_cmp expect actual &&
+
+ nopath="hopefully-absent-path" &&
+ echo "$d/$nopath" >expect &&
+ test-tool path-utils real_path "$d///$nopath" >actual &&
+ test_cmp expect actual
'
test_expect_success SYMLINKS 'real path works on symlinks' '
@@ -227,19 +264,29 @@ test_expect_success SYMLINKS 'real path works on symlinks' '
mkdir third &&
dir="$(cd .git && pwd -P)" &&
dir2=third/../second/other/.git &&
- test "$dir" = "$(test-tool path-utils real_path $dir2)" &&
+ echo "$dir" >expect &&
+ test-tool path-utils real_path $dir2 >actual &&
+ test_cmp expect actual &&
file="$dir"/index &&
- test "$file" = "$(test-tool path-utils real_path $dir2/index)" &&
+ echo "$file" >expect &&
+ test-tool path-utils real_path $dir2/index >actual &&
+ test_cmp expect actual &&
basename=blub &&
- test "$dir/$basename" = "$(cd .git && test-tool path-utils real_path "$basename")" &&
+ echo "$dir/$basename" >expect &&
+ test-tool -C .git path-utils real_path "$basename" >actual &&
+ test_cmp expect actual &&
ln -s ../first/file .git/syml &&
sym="$(cd first && pwd -P)"/file &&
- test "$sym" = "$(test-tool path-utils real_path "$dir2/syml")"
+ echo "$sym" >expect &&
+ test-tool path-utils real_path "$dir2/syml" >actual &&
+ test_cmp expect actual
'
test_expect_success SYMLINKS 'prefix_path works with absolute paths to work tree symlinks' '
ln -s target symlink &&
- test "$(test-tool path-utils prefix_path prefix "$(pwd)/symlink")" = "symlink"
+ echo "symlink" >expect &&
+ test-tool path-utils prefix_path prefix "$(pwd)/symlink" >actual &&
+ test_cmp expect actual
'
test_expect_success 'prefix_path works with only absolute path to work tree' '
@@ -255,7 +302,10 @@ test_expect_success 'prefix_path rejects absolute path to dir with same beginnin
test_expect_success SYMLINKS 'prefix_path works with absolute path to a symlink to work tree having same beginning as work tree' '
git init repo &&
ln -s repo repolink &&
- test "a" = "$(cd repo && test-tool path-utils prefix_path prefix "$(pwd)/../repolink/a")"
+ echo "a" >expect &&
+ repo_path="$(cd repo && pwd)" &&
+ test-tool -C repo path-utils prefix_path prefix "$repo_path/../repolink/a" >actual &&
+ test_cmp expect actual
'
relative_path /foo/a/b/c/ /foo/a/b/ c/
diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh
index 7b5423eebd..e2411f6a9b 100755
--- a/t/t0061-run-command.sh
+++ b/t/t0061-run-command.sh
@@ -130,7 +130,8 @@ World
EOF
test_expect_success 'run_command runs in parallel with more jobs available than tasks' '
- test-tool run-command run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>actual &&
+ test_must_be_empty out &&
test_cmp expect actual
'
@@ -141,7 +142,8 @@ test_expect_success 'run_command runs ungrouped in parallel with more jobs avail
'
test_expect_success 'run_command runs in parallel with as many jobs as tasks' '
- test-tool run-command run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>actual &&
+ test_must_be_empty out &&
test_cmp expect actual
'
@@ -152,7 +154,8 @@ test_expect_success 'run_command runs ungrouped in parallel with as many jobs as
'
test_expect_success 'run_command runs in parallel with more tasks than jobs available' '
- test-tool run-command run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>actual &&
+ test_must_be_empty out &&
test_cmp expect actual
'
@@ -172,7 +175,8 @@ asking for a quick stop
EOF
test_expect_success 'run_command is asked to abort gracefully' '
- test-tool run-command run-command-abort 3 false 2>actual &&
+ test-tool run-command run-command-abort 3 false >out 2>actual &&
+ test_must_be_empty out &&
test_cmp expect actual
'
@@ -187,7 +191,8 @@ no further jobs available
EOF
test_expect_success 'run_command outputs ' '
- test-tool run-command run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+ test-tool run-command run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" >out 2>actual &&
+ test_must_be_empty out &&
test_cmp expect actual
'
diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh
index 46d4839194..1fee6d9010 100755
--- a/t/t0063-string-list.sh
+++ b/t/t0063-string-list.sh
@@ -18,6 +18,14 @@ test_split () {
"
}
+test_split_in_place() {
+ cat >expected &&
+ test_expect_success "split (in place) $1 at $2, max $3" "
+ test-tool string-list split_in_place '$1' '$2' '$3' >actual &&
+ test_cmp expected actual
+ "
+}
+
test_split "foo:bar:baz" ":" "-1" <<EOF
3
[0]: "foo"
@@ -61,6 +69,49 @@ test_split ":" ":" "-1" <<EOF
[1]: ""
EOF
+test_split_in_place "foo:;:bar:;:baz:;:" ":;" "-1" <<EOF
+10
+[0]: "foo"
+[1]: ""
+[2]: ""
+[3]: "bar"
+[4]: ""
+[5]: ""
+[6]: "baz"
+[7]: ""
+[8]: ""
+[9]: ""
+EOF
+
+test_split_in_place "foo:;:bar:;:baz" ":;" "0" <<EOF
+1
+[0]: "foo:;:bar:;:baz"
+EOF
+
+test_split_in_place "foo:;:bar:;:baz" ":;" "1" <<EOF
+2
+[0]: "foo"
+[1]: ";:bar:;:baz"
+EOF
+
+test_split_in_place "foo:;:bar:;:baz" ":;" "2" <<EOF
+3
+[0]: "foo"
+[1]: ""
+[2]: ":bar:;:baz"
+EOF
+
+test_split_in_place "foo:;:bar:;:" ":;" "-1" <<EOF
+7
+[0]: "foo"
+[1]: ""
+[2]: ""
+[3]: "bar"
+[4]: ""
+[5]: ""
+[6]: ""
+EOF
+
test_expect_success "test filter_string_list" '
test "x-" = "x$(test-tool string-list filter - y)" &&
test "x-" = "x$(test-tool string-list filter no y)" &&
diff --git a/t/t0066-dir-iterator.sh b/t/t0066-dir-iterator.sh
index 04b811622b..7d0a0da8c0 100755
--- a/t/t0066-dir-iterator.sh
+++ b/t/t0066-dir-iterator.sh
@@ -106,13 +106,7 @@ test_expect_success SYMLINKS 'setup dirs with symlinks' '
ln -s d dir4/a/e &&
ln -s ../b dir4/a/f &&
- mkdir -p dir5/a/b &&
- mkdir -p dir5/a/c &&
- ln -s ../c dir5/a/b/d &&
- ln -s ../ dir5/a/b/e &&
- ln -s ../../ dir5/a/b/f &&
-
- ln -s dir4 dir6
+ ln -s dir4 dir5
'
test_expect_success SYMLINKS 'dir-iterator should not follow symlinks by default' '
@@ -131,44 +125,10 @@ test_expect_success SYMLINKS 'dir-iterator should not follow symlinks by default
test_cmp expected-no-follow-sorted-output actual-no-follow-sorted-output
'
-test_expect_success SYMLINKS 'dir-iterator should follow symlinks w/ follow flag' '
- cat >expected-follow-sorted-output <<-EOF &&
- [d] (a) [a] ./dir4/a
- [d] (a/f) [f] ./dir4/a/f
- [d] (a/f/c) [c] ./dir4/a/f/c
- [d] (b) [b] ./dir4/b
- [d] (b/c) [c] ./dir4/b/c
- [f] (a/d) [d] ./dir4/a/d
- [f] (a/e) [e] ./dir4/a/e
- EOF
-
- test-tool dir-iterator --follow-symlinks ./dir4 >out &&
- sort out >actual-follow-sorted-output &&
-
- test_cmp expected-follow-sorted-output actual-follow-sorted-output
-'
-
test_expect_success SYMLINKS 'dir-iterator does not resolve top-level symlinks' '
- test_must_fail test-tool dir-iterator ./dir6 >out &&
+ test_must_fail test-tool dir-iterator ./dir5 >out &&
grep "ENOTDIR" out
'
-test_expect_success SYMLINKS 'dir-iterator resolves top-level symlinks w/ follow flag' '
- cat >expected-follow-sorted-output <<-EOF &&
- [d] (a) [a] ./dir6/a
- [d] (a/f) [f] ./dir6/a/f
- [d] (a/f/c) [c] ./dir6/a/f/c
- [d] (b) [b] ./dir6/b
- [d] (b/c) [c] ./dir6/b/c
- [f] (a/d) [d] ./dir6/a/d
- [f] (a/e) [e] ./dir6/a/e
- EOF
-
- test-tool dir-iterator --follow-symlinks ./dir6 >out &&
- sort out >actual-follow-sorted-output &&
-
- test_cmp expected-follow-sorted-output actual-follow-sorted-output
-'
-
test_done
diff --git a/t/t0068-for-each-repo.sh b/t/t0068-for-each-repo.sh
index 4675e85251..4b90b74d5d 100755
--- a/t/t0068-for-each-repo.sh
+++ b/t/t0068-for-each-repo.sh
@@ -2,15 +2,18 @@
test_description='git for-each-repo builtin'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'run based on configured value' '
git init one &&
git init two &&
git init three &&
+ git init ~/four &&
git -C two commit --allow-empty -m "DID NOT RUN" &&
git config run.key "$TRASH_DIRECTORY/one" &&
git config --add run.key "$TRASH_DIRECTORY/three" &&
+ git config --add run.key "~/four" &&
git for-each-repo --config=run.key commit --allow-empty -m "ran" &&
git -C one log -1 --pretty=format:%s >message &&
grep ran message &&
@@ -18,12 +21,16 @@ test_expect_success 'run based on configured value' '
! grep ran message &&
git -C three log -1 --pretty=format:%s >message &&
grep ran message &&
+ git -C ~/four log -1 --pretty=format:%s >message &&
+ grep ran message &&
git for-each-repo --config=run.key -- commit --allow-empty -m "ran again" &&
git -C one log -1 --pretty=format:%s >message &&
grep again message &&
git -C two log -1 --pretty=format:%s >message &&
! grep again message &&
git -C three log -1 --pretty=format:%s >message &&
+ grep again message &&
+ git -C ~/four log -1 --pretty=format:%s >message &&
grep again message
'
@@ -33,4 +40,23 @@ test_expect_success 'do nothing on empty config' '
git for-each-repo --config=bogus.config -- help --no-such-option
'
+test_expect_success 'error on bad config keys' '
+ test_expect_code 129 git for-each-repo --config=a &&
+ test_expect_code 129 git for-each-repo --config=a.b. &&
+ test_expect_code 129 git for-each-repo --config="'\''.b"
+'
+
+test_expect_success 'error on NULL value for config keys' '
+ cat >>.git/config <<-\EOF &&
+ [empty]
+ key
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''empty.key'\''
+ EOF
+ test_expect_code 129 git for-each-repo --config=empty.key 2>actual.raw &&
+ grep ^error actual.raw >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh
index 8d59905ef0..574de34198 100755
--- a/t/t0070-fundamental.sh
+++ b/t/t0070-fundamental.sh
@@ -6,6 +6,7 @@ test_description='check that the most basic functions work
Verify wrappers and compatibility functions.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'character classes (isspace, isalpha etc.)' '
diff --git a/t/t0091-bugreport.sh b/t/t0091-bugreport.sh
index b6d2f591ac..f6998269be 100755
--- a/t/t0091-bugreport.sh
+++ b/t/t0091-bugreport.sh
@@ -5,29 +5,50 @@ test_description='git bugreport'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
-# Headers "[System Info]" will be followed by a non-empty line if we put some
-# information there; we can make sure all our headers were followed by some
-# information to check if the command was successful.
-HEADER_PATTERN="^\[.*\]$"
-
-check_all_headers_populated () {
- while read -r line
- do
- if test "$(grep "$HEADER_PATTERN" "$line")"
- then
- echo "$line"
- read -r nextline
- if test -z "$nextline"; then
- return 1;
- fi
- fi
- done
-}
-
-test_expect_success 'creates a report with content in the right places' '
- test_when_finished rm git-bugreport-check-headers.txt &&
- git bugreport -s check-headers &&
- check_all_headers_populated <git-bugreport-check-headers.txt
+test_expect_success 'create a report' '
+ git bugreport -s format &&
+ test_file_not_empty git-bugreport-format.txt
+'
+
+test_expect_success 'report contains wanted template (before first section)' '
+ sed -ne "/^\[/q;p" git-bugreport-format.txt >actual &&
+ cat >expect <<-\EOF &&
+ Thank you for filling out a Git bug report!
+ Please answer the following questions to help us understand your issue.
+
+ What did you do before the bug happened? (Steps to reproduce your issue)
+
+ What did you expect to happen? (Expected behavior)
+
+ What happened instead? (Actual behavior)
+
+ What'\''s different between what you expected and what actually happened?
+
+ Anything else you want to add:
+
+ Please review the rest of the bug report below.
+ You can delete any lines you don'\''t wish to share.
+
+
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'sanity check "System Info" section' '
+ test_when_finished rm -f git-bugreport-format.txt &&
+
+ sed -ne "/^\[System Info\]$/,/^$/p" <git-bugreport-format.txt >system &&
+
+ # The beginning should match "git version --build-info" verbatim,
+ # but rather than checking bit-for-bit equality, just test some basics.
+ grep "git version [0-9]." system &&
+ grep "shell-path: ." system &&
+
+ # After the version, there should be some more info.
+ # This is bound to differ from environment to environment,
+ # so we just do some rather high-level checks.
+ grep "uname: ." system &&
+ grep "compiler info: ." system
'
test_expect_success 'dies if file with same name as report already exists' '
diff --git a/t/t0100-previous.sh b/t/t0100-previous.sh
index a16cc3d298..70a3223f21 100755
--- a/t/t0100-previous.sh
+++ b/t/t0100-previous.sh
@@ -12,7 +12,9 @@ test_expect_success 'branch -d @{-1}' '
test_commit A &&
git checkout -b junk &&
git checkout - &&
- test "$(git symbolic-ref HEAD)" = refs/heads/main &&
+ echo refs/heads/main >expect &&
+ git symbolic-ref HEAD >actual &&
+ test_cmp expect actual &&
git branch -d @{-1} &&
test_must_fail git rev-parse --verify refs/heads/junk
'
@@ -21,7 +23,9 @@ test_expect_success 'branch -d @{-12} when there is not enough switches yet' '
git reflog expire --expire=now &&
git checkout -b junk2 &&
git checkout - &&
- test "$(git symbolic-ref HEAD)" = refs/heads/main &&
+ echo refs/heads/main >expect &&
+ git symbolic-ref HEAD >actual &&
+ test_cmp expect actual &&
test_must_fail git branch -d @{-12} &&
git rev-parse --verify refs/heads/main
'
diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh
index 22d0845544..cfba686132 100755
--- a/t/t0211-trace2-perf.sh
+++ b/t/t0211-trace2-perf.sh
@@ -173,4 +173,99 @@ test_expect_success 'using global config, perf stream, return code 0' '
test_cmp expect actual
'
+# Exercise the stopwatch timers in a loop and confirm that we have
+# as many start/stop intervals as expected. We cannot really test the
+# actual (total, min, max) timer values, so we have to assume that they
+# are good, but we can verify the interval count.
+#
+# The timer "test/test1" should only emit a global summary "timer" event.
+# The timer "test/test2" should emit per-thread "th_timer" events and a
+# global summary "timer" event.
+
+have_timer_event () {
+ thread=$1 event=$2 category=$3 name=$4 intervals=$5 file=$6 &&
+
+ pattern="d0|${thread}|${event}||||${category}|name:${name} intervals:${intervals}" &&
+
+ grep "${pattern}" ${file}
+}
+
+test_expect_success 'stopwatch timer test/test1' '
+ test_when_finished "rm trace.perf actual" &&
+ test_config_global trace2.perfBrief 1 &&
+ test_config_global trace2.perfTarget "$(pwd)/trace.perf" &&
+
+ # Use the timer "test1" 5 times from "main".
+ test-tool trace2 100timer 5 10 &&
+
+ perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
+
+ have_timer_event "main" "timer" "test" "test1" 5 actual
+'
+
+test_expect_success PTHREADS 'stopwatch timer test/test2' '
+ test_when_finished "rm trace.perf actual" &&
+ test_config_global trace2.perfBrief 1 &&
+ test_config_global trace2.perfTarget "$(pwd)/trace.perf" &&
+
+ # Use the timer "test2" 5 times each in 3 threads.
+ test-tool trace2 101timer 5 10 3 &&
+
+ perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
+
+ # So we should have 3 per-thread events of 5 each.
+ have_timer_event "th01:ut_101" "th_timer" "test" "test2" 5 actual &&
+ have_timer_event "th02:ut_101" "th_timer" "test" "test2" 5 actual &&
+ have_timer_event "th03:ut_101" "th_timer" "test" "test2" 5 actual &&
+
+ # And we should have 15 total uses.
+ have_timer_event "main" "timer" "test" "test2" 15 actual
+'
+
+# Exercise the global counters and confirm that we get the expected values.
+#
+# The counter "test/test1" should only emit a global summary "counter" event.
+# The counter "test/test2" could emit per-thread "th_counter" events and a
+# global summary "counter" event.
+
+have_counter_event () {
+ thread=$1 event=$2 category=$3 name=$4 value=$5 file=$6 &&
+
+ pattern="d0|${thread}|${event}||||${category}|name:${name} value:${value}" &&
+
+ grep "${patern}" ${file}
+}
+
+test_expect_success 'global counter test/test1' '
+ test_when_finished "rm trace.perf actual" &&
+ test_config_global trace2.perfBrief 1 &&
+ test_config_global trace2.perfTarget "$(pwd)/trace.perf" &&
+
+ # Use the counter "test1" and add n integers.
+ test-tool trace2 200counter 1 2 3 4 5 &&
+
+ perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
+
+ have_counter_event "main" "counter" "test" "test1" 15 actual
+'
+
+test_expect_success PTHREADS 'global counter test/test2' '
+ test_when_finished "rm trace.perf actual" &&
+ test_config_global trace2.perfBrief 1 &&
+ test_config_global trace2.perfTarget "$(pwd)/trace.perf" &&
+
+ # Add 2 integers to the counter "test2" in each of 3 threads.
+ test-tool trace2 201counter 7 13 3 &&
+
+ perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
+
+ # So we should have 3 per-thread events of 5 each.
+ have_counter_event "th01:ut_201" "th_counter" "test" "test2" 20 actual &&
+ have_counter_event "th02:ut_201" "th_counter" "test" "test2" 20 actual &&
+ have_counter_event "th03:ut_201" "th_counter" "test" "test2" 20 actual &&
+
+ # And we should have a single event with the total across all threads.
+ have_counter_event "main" "counter" "test" "test2" 60 actual
+'
+
test_done
diff --git a/t/t0211/scrub_perf.perl b/t/t0211/scrub_perf.perl
index 299999f0f8..7a50bae646 100644
--- a/t/t0211/scrub_perf.perl
+++ b/t/t0211/scrub_perf.perl
@@ -64,6 +64,12 @@ while (<>) {
goto SKIP_LINE;
}
}
+ elsif ($tokens[$col_event] =~ m/timer/) {
+ # This also captures "th_timer" events
+ $tokens[$col_rest] =~ s/ total:\d+\.\d*/ total:_T_TOTAL_/;
+ $tokens[$col_rest] =~ s/ min:\d+\.\d*/ min:_T_MIN_/;
+ $tokens[$col_rest] =~ s/ max:\d+\.\d*/ max:_T_MAX_/;
+ }
# t_abs and t_rel are either blank or a float. Replace the float
# with a constant for matching the HEREDOC in the test script.
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index 3485c0534e..a4f5bba507 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -35,6 +35,16 @@ test_expect_success 'setup helper scripts' '
test -z "$pass" || echo password=$pass
EOF
+ write_script git-credential-verbatim-with-expiry <<-\EOF &&
+ user=$1; shift
+ pass=$1; shift
+ pexpiry=$1; shift
+ . ./dump
+ test -z "$user" || echo username=$user
+ test -z "$pass" || echo password=$pass
+ test -z "$pexpiry" || echo password_expiry_utc=$pexpiry
+ EOF
+
PATH="$PWD:$PATH"
'
@@ -109,6 +119,43 @@ test_expect_success 'credential_fill continues through partial response' '
EOF
'
+test_expect_success 'credential_fill populates password_expiry_utc' '
+ check fill "verbatim-with-expiry one two 9999999999" <<-\EOF
+ protocol=http
+ host=example.com
+ --
+ protocol=http
+ host=example.com
+ username=one
+ password=two
+ password_expiry_utc=9999999999
+ --
+ verbatim-with-expiry: get
+ verbatim-with-expiry: protocol=http
+ verbatim-with-expiry: host=example.com
+ EOF
+'
+
+test_expect_success 'credential_fill ignores expired password' '
+ check fill "verbatim-with-expiry one two 5" "verbatim three four" <<-\EOF
+ protocol=http
+ host=example.com
+ --
+ protocol=http
+ host=example.com
+ username=three
+ password=four
+ --
+ verbatim-with-expiry: get
+ verbatim-with-expiry: protocol=http
+ verbatim-with-expiry: host=example.com
+ verbatim: get
+ verbatim: protocol=http
+ verbatim: host=example.com
+ verbatim: username=one
+ EOF
+'
+
test_expect_success 'credential_fill passes along metadata' '
check fill "verbatim one two" <<-\EOF
protocol=ftp
@@ -149,6 +196,42 @@ test_expect_success 'credential_approve calls all helpers' '
EOF
'
+test_expect_success 'credential_approve stores password expiry' '
+ check approve useless <<-\EOF
+ protocol=http
+ host=example.com
+ username=foo
+ password=bar
+ password_expiry_utc=9999999999
+ --
+ --
+ useless: store
+ useless: protocol=http
+ useless: host=example.com
+ useless: username=foo
+ useless: password=bar
+ useless: password_expiry_utc=9999999999
+ EOF
+'
+
+test_expect_success 'credential_approve stores oauth refresh token' '
+ check approve useless <<-\EOF
+ protocol=http
+ host=example.com
+ username=foo
+ password=bar
+ oauth_refresh_token=xyzzy
+ --
+ --
+ useless: store
+ useless: protocol=http
+ useless: host=example.com
+ useless: username=foo
+ useless: password=bar
+ useless: oauth_refresh_token=xyzzy
+ EOF
+'
+
test_expect_success 'do not bother storing password-less credential' '
check approve useless <<-\EOF
protocol=http
@@ -159,6 +242,17 @@ test_expect_success 'do not bother storing password-less credential' '
EOF
'
+test_expect_success 'credential_approve does not store expired password' '
+ check approve useless <<-\EOF
+ protocol=http
+ host=example.com
+ username=foo
+ password=bar
+ password_expiry_utc=5
+ --
+ --
+ EOF
+'
test_expect_success 'credential_reject calls all helpers' '
check reject useless "verbatim one two" <<-\EOF
@@ -181,6 +275,24 @@ test_expect_success 'credential_reject calls all helpers' '
EOF
'
+test_expect_success 'credential_reject erases credential regardless of expiry' '
+ check reject useless <<-\EOF
+ protocol=http
+ host=example.com
+ username=foo
+ password=bar
+ password_expiry_utc=5
+ --
+ --
+ useless: erase
+ useless: protocol=http
+ useless: host=example.com
+ useless: username=foo
+ useless: password=bar
+ useless: password_expiry_utc=5
+ EOF
+'
+
test_expect_success 'usernames can be preserved' '
check fill "verbatim \"\" three" <<-\EOF
protocol=http
@@ -714,7 +826,7 @@ test_expect_success 'credential config with partial URLs' '
git -c credential.$partial.helper=yep \
-c credential.with%0anewline.username=uh-oh \
- credential fill <stdin >stdout 2>stderr &&
+ credential fill <stdin 2>stderr &&
test_i18ngrep "skipping credential lookup for key" stderr
'
diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh
index 698b7159f0..8300faadea 100755
--- a/t/t0301-credential-cache.sh
+++ b/t/t0301-credential-cache.sh
@@ -29,6 +29,8 @@ test_atexit 'git credential-cache exit'
# test that the daemon works with no special setup
helper_test cache
+helper_test_password_expiry_utc cache
+helper_test_oauth_refresh_token cache
test_expect_success 'socket defaults to ~/.cache/git/credential/socket' '
test_when_finished "
diff --git a/t/t0303-credential-external.sh b/t/t0303-credential-external.sh
index f028fd1418..095574bfc6 100755
--- a/t/t0303-credential-external.sh
+++ b/t/t0303-credential-external.sh
@@ -45,6 +45,8 @@ test -z "$GIT_TEST_CREDENTIAL_HELPER_SETUP" ||
helper_test_clean "$GIT_TEST_CREDENTIAL_HELPER"
helper_test "$GIT_TEST_CREDENTIAL_HELPER"
+helper_test_password_expiry_utc "$GIT_TEST_CREDENTIAL_HELPER"
+helper_test_oauth_refresh_token "$GIT_TEST_CREDENTIAL_HELPER"
if test -z "$GIT_TEST_CREDENTIAL_HELPER_TIMEOUT"; then
say "# skipping timeout tests (GIT_TEST_CREDENTIAL_HELPER_TIMEOUT not set)"
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index 1e864cf317..5b7bee888d 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -215,6 +215,20 @@ test_expect_success 'fetching of missing objects' '
grep "$HASH" out
'
+test_expect_success 'fetching of a promised object that promisor remote no longer has' '
+ rm -f err &&
+ test_create_repo unreliable-server &&
+ git -C unreliable-server config uploadpack.allowanysha1inwant 1 &&
+ git -C unreliable-server config uploadpack.allowfilter 1 &&
+ test_commit -C unreliable-server foo &&
+
+ git clone --filter=blob:none --no-checkout "file://$(pwd)/unreliable-server" unreliable-client &&
+
+ rm -rf unreliable-server/.git/objects/* &&
+ test_must_fail git -C unreliable-client checkout HEAD 2>err &&
+ grep "could not fetch.*from promisor remote" err
+'
+
test_expect_success 'fetching of missing objects works with ref-in-want enabled' '
# ref-in-want requires protocol version 2
git -C server config protocol.version 2 &&
diff --git a/t/t0450-txt-doc-vs-help.sh b/t/t0450-txt-doc-vs-help.sh
new file mode 100755
index 0000000000..cd3969e852
--- /dev/null
+++ b/t/t0450-txt-doc-vs-help.sh
@@ -0,0 +1,172 @@
+#!/bin/sh
+
+test_description='assert (unbuilt) Documentation/*.txt and -h output
+
+Run this with --debug to see a summary of where we still fail to make
+the two versions consistent with one another.'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success 'setup: list of builtins' '
+ git --list-cmds=builtins >builtins
+'
+
+test_expect_success 'list of txt and help mismatches is sorted' '
+ sort -u "$TEST_DIRECTORY"/t0450/txt-help-mismatches >expect &&
+ if ! test_cmp expect "$TEST_DIRECTORY"/t0450/txt-help-mismatches
+ then
+ BUG "please keep the list of txt and help mismatches sorted"
+ fi
+'
+
+help_to_synopsis () {
+ builtin="$1" &&
+ out_dir="out/$builtin" &&
+ out="$out_dir/help.synopsis" &&
+ if test -f "$out"
+ then
+ echo "$out" &&
+ return 0
+ fi &&
+ mkdir -p "$out_dir" &&
+ test_expect_code 129 git $builtin -h >"$out.raw" 2>&1 &&
+ sed -n \
+ -e '1,/^$/ {
+ /^$/d;
+ s/^usage: //;
+ s/^ *or: //;
+ p;
+ }' <"$out.raw" >"$out" &&
+ echo "$out"
+}
+
+builtin_to_txt () {
+ echo "$GIT_BUILD_DIR/Documentation/git-$1.txt"
+}
+
+txt_to_synopsis () {
+ builtin="$1" &&
+ out_dir="out/$builtin" &&
+ out="$out_dir/txt.synopsis" &&
+ if test -f "$out"
+ then
+ echo "$out" &&
+ return 0
+ fi &&
+ b2t="$(builtin_to_txt "$builtin")" &&
+ sed -n \
+ -e '/^\[verse\]$/,/^$/ {
+ /^$/d;
+ /^\[verse\]$/d;
+
+ s/{litdd}/--/g;
+ s/'\''\(git[ a-z-]*\)'\''/\1/g;
+
+ p;
+ }' \
+ <"$b2t" >"$out" &&
+ echo "$out"
+}
+
+check_dashed_labels () {
+ ! grep -E "<[^>_-]+_" "$1"
+}
+
+HT=" "
+
+align_after_nl () {
+ builtin="$1" &&
+ len=$(printf "git %s " "$builtin" | wc -c) &&
+ pad=$(printf "%${len}s" "") &&
+
+ sed "s/^[ $HT][ $HT]*/$pad/"
+}
+
+test_debug '>failing'
+while read builtin
+do
+ # -h output assertions
+ test_expect_success "$builtin -h output has no \t" '
+ h2s="$(help_to_synopsis "$builtin")" &&
+ ! grep "$HT" "$h2s"
+ '
+
+ test_expect_success "$builtin -h output has dashed labels" '
+ check_dashed_labels "$(help_to_synopsis "$builtin")"
+ '
+
+ test_expect_success "$builtin -h output has consistent spacing" '
+ h2s="$(help_to_synopsis "$builtin")" &&
+ sed -n \
+ -e "/^ / {
+ s/[^ ].*//;
+ p;
+ }" \
+ <"$h2s" >help &&
+ sort -u help >help.ws &&
+ if test -s help.ws
+ then
+ test_line_count = 1 help.ws
+ fi
+ '
+
+ txt="$(builtin_to_txt "$builtin")" &&
+ preq="$(echo BUILTIN_TXT_$builtin | tr '[:lower:]-' '[:upper:]_')" &&
+
+ if test -f "$txt"
+ then
+ test_set_prereq "$preq"
+ fi &&
+
+ # *.txt output assertions
+ test_expect_success "$preq" "$builtin *.txt SYNOPSIS has dashed labels" '
+ check_dashed_labels "$(txt_to_synopsis "$builtin")"
+ '
+
+ # *.txt output consistency assertions
+ result=
+ if grep -q "^$builtin$" "$TEST_DIRECTORY"/t0450/txt-help-mismatches
+ then
+ result=failure
+ else
+ result=success
+ fi &&
+ test_expect_$result "$preq" "$builtin -h output and SYNOPSIS agree" '
+ t2s="$(txt_to_synopsis "$builtin")" &&
+ if test "$builtin" = "merge-tree"
+ then
+ test_when_finished "rm -f t2s.new" &&
+ sed -e '\''s/ (deprecated)$//g'\'' <"$t2s" >t2s.new
+ t2s=t2s.new
+ fi &&
+ h2s="$(help_to_synopsis "$builtin")" &&
+
+ # The *.txt and -h use different spacing for the
+ # alignment of continued usage output, normalize it.
+ align_after_nl "$builtin" <"$t2s" >txt &&
+ align_after_nl "$builtin" <"$h2s" >help &&
+ test_cmp txt help
+ '
+
+ if test_have_prereq "$preq" && test -e txt && test -e help
+ then
+ test_debug '
+ if test_cmp txt help >cmp 2>/dev/null
+ then
+ echo "=== DONE: $builtin ==="
+ else
+ echo "=== TODO: $builtin ===" &&
+ cat cmp
+ fi >>failing
+ '
+
+ # Not in test_expect_success in case --run is being
+ # used with --debug
+ rm -f txt help tmp 2>/dev/null
+ fi
+done <builtins
+
+test_debug 'say "$(cat failing)"'
+
+test_done
diff --git a/t/t0450/txt-help-mismatches b/t/t0450/txt-help-mismatches
new file mode 100644
index 0000000000..a0777acd66
--- /dev/null
+++ b/t/t0450/txt-help-mismatches
@@ -0,0 +1,58 @@
+add
+am
+apply
+archive
+bisect
+blame
+branch
+check-ref-format
+checkout
+checkout-index
+clone
+column
+config
+credential
+credential-cache
+credential-store
+fast-export
+fast-import
+fetch-pack
+fmt-merge-msg
+for-each-ref
+format-patch
+fsck-objects
+fsmonitor--daemon
+gc
+grep
+index-pack
+init-db
+log
+ls-files
+ls-tree
+mailinfo
+mailsplit
+maintenance
+merge
+merge-file
+merge-index
+merge-one-file
+multi-pack-index
+name-rev
+notes
+pack-objects
+push
+range-diff
+rebase
+remote
+remote-ext
+remote-fd
+repack
+reset
+restore
+rev-parse
+show
+stage
+switch
+update-index
+update-ref
+whatchanged
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 516a6112fd..88c524f655 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -26,7 +26,7 @@ TEST_PASSES_SANITIZE_LEAK=true
. "$TEST_DIRECTORY"/lib-read-tree.sh
read_tree_twoway () {
- git read-tree -m "$1" "$2" && git ls-files --stage
+ git read-tree -m "$1" "$2" && git ls-files --stage
}
compare_change () {
@@ -370,7 +370,7 @@ test_expect_success 'read-tree supports the super-prefix' '
cat <<-EOF >expect &&
error: Updating '\''fictional/a'\'' would lose untracked files in it
EOF
- test_must_fail git --super-prefix fictional/ read-tree -u -m "$treeH" "$treeM" 2>actual &&
+ test_must_fail git read-tree --super-prefix fictional/ -u -m "$treeH" "$treeM" 2>actual &&
test_cmp expect actual
'
diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh
index bd5313caec..a7c2ed0d7c 100755
--- a/t/t1002-read-tree-m-u-2way.sh
+++ b/t/t1002-read-tree-m-u-2way.sh
@@ -37,315 +37,312 @@ check_cache_at () {
esac
}
-test_expect_success \
- setup \
- 'echo frotz >frotz &&
- echo nitfol >nitfol &&
- echo bozbar >bozbar &&
- echo rezrov >rezrov &&
- git update-index --add nitfol bozbar rezrov &&
- treeH=$(git write-tree) &&
- echo treeH $treeH &&
- git ls-tree $treeH &&
-
- echo gnusto >bozbar &&
- git update-index --add frotz bozbar --force-remove rezrov &&
- git ls-files --stage >M.out &&
- treeM=$(git write-tree) &&
- echo treeM $treeM &&
- git ls-tree $treeM &&
- cp bozbar bozbar.M &&
- cp frotz frotz.M &&
- cp nitfol nitfol.M &&
- git diff-tree $treeH $treeM'
-
-test_expect_success \
- '1, 2, 3 - no carry forward' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >1-3.out &&
- cmp M.out 1-3.out &&
- test_cmp bozbar.M bozbar &&
- test_cmp frotz.M frotz &&
- test_cmp nitfol.M nitfol &&
- check_cache_at bozbar clean &&
- check_cache_at frotz clean &&
- check_cache_at nitfol clean'
-
-test_expect_success \
- '4 - carry forward local addition.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo "+100644 X 0 yomin" >expected &&
- echo yomin >yomin &&
- git update-index --add yomin &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >4.out &&
- test_might_fail git diff -U0 --no-index M.out 4.out >4diff.out &&
- compare_change 4diff.out expected &&
- check_cache_at yomin clean &&
- test_cmp bozbar.M bozbar &&
- test_cmp frotz.M frotz &&
- test_cmp nitfol.M nitfol &&
- echo yomin >yomin1 &&
- diff yomin yomin1 &&
- rm -f yomin1'
-
-test_expect_success \
- '5 - carry forward local addition.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- read_tree_u_must_succeed -m -u $treeH &&
- echo yomin >yomin &&
- git update-index --add yomin &&
- echo yomin yomin >yomin &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >5.out &&
- test_might_fail git diff -U0 --no-index M.out 5.out >5diff.out &&
- compare_change 5diff.out expected &&
- check_cache_at yomin dirty &&
- test_cmp bozbar.M bozbar &&
- test_cmp frotz.M frotz &&
- test_cmp nitfol.M nitfol &&
- : dirty index should have prevented -u from checking it out. &&
- echo yomin yomin >yomin1 &&
- diff yomin yomin1 &&
- rm -f yomin1'
-
-test_expect_success \
- '6 - local addition already has the same.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo frotz >frotz &&
- git update-index --add frotz &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >6.out &&
- test_cmp M.out 6.out &&
- check_cache_at frotz clean &&
- test_cmp bozbar.M bozbar &&
- test_cmp frotz.M frotz &&
- test_cmp nitfol.M nitfol &&
- echo frotz >frotz1 &&
- diff frotz frotz1 &&
- rm -f frotz1'
-
-test_expect_success \
- '7 - local addition already has the same.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo frotz >frotz &&
- git update-index --add frotz &&
- echo frotz frotz >frotz &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >7.out &&
- test_cmp M.out 7.out &&
- check_cache_at frotz dirty &&
- test_cmp bozbar.M bozbar &&
- test_cmp nitfol.M nitfol &&
- : dirty index should have prevented -u from checking it out. &&
- echo frotz frotz >frotz1 &&
- diff frotz frotz1 &&
- rm -f frotz1'
-
-test_expect_success \
- '8 - conflicting addition.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo frotz frotz >frotz &&
- git update-index --add frotz &&
- if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'
-
-test_expect_success \
- '9 - conflicting addition.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo frotz frotz >frotz &&
- git update-index --add frotz &&
- echo frotz >frotz &&
- if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'
-
-test_expect_success \
- '10 - path removed.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo rezrov >rezrov &&
- git update-index --add rezrov &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >10.out &&
- cmp M.out 10.out &&
- test_cmp bozbar.M bozbar &&
- test_cmp frotz.M frotz &&
- test_cmp nitfol.M nitfol
+test_expect_success setup '
+ echo frotz >frotz &&
+ echo nitfol >nitfol &&
+ echo bozbar >bozbar &&
+ echo rezrov >rezrov &&
+ git update-index --add nitfol bozbar rezrov &&
+ treeH=$(git write-tree) &&
+ echo treeH $treeH &&
+ git ls-tree $treeH &&
+
+ echo gnusto >bozbar &&
+ git update-index --add frotz bozbar --force-remove rezrov &&
+ git ls-files --stage >M.out &&
+ treeM=$(git write-tree) &&
+ echo treeM $treeM &&
+ git ls-tree $treeM &&
+ cp bozbar bozbar.M &&
+ cp frotz frotz.M &&
+ cp nitfol nitfol.M &&
+ git diff-tree $treeH $treeM
'
-test_expect_success \
- '11 - dirty path removed.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo rezrov >rezrov &&
- git update-index --add rezrov &&
- echo rezrov rezrov >rezrov &&
- if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'
-
-test_expect_success \
- '12 - unmatching local changes being removed.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo rezrov rezrov >rezrov &&
- git update-index --add rezrov &&
- if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'
-
-test_expect_success \
- '13 - unmatching local changes being removed.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo rezrov rezrov >rezrov &&
- git update-index --add rezrov &&
- echo rezrov >rezrov &&
- if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'
+test_expect_success '1, 2, 3 - no carry forward' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >1-3.out &&
+ cmp M.out 1-3.out &&
+ test_cmp bozbar.M bozbar &&
+ test_cmp frotz.M frotz &&
+ test_cmp nitfol.M nitfol &&
+ check_cache_at bozbar clean &&
+ check_cache_at frotz clean &&
+ check_cache_at nitfol clean
+'
+
+test_expect_success '4 - carry forward local addition.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo "+100644 X 0 yomin" >expected &&
+ echo yomin >yomin &&
+ git update-index --add yomin &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >4.out &&
+ test_might_fail git diff -U0 --no-index M.out 4.out >4diff.out &&
+ compare_change 4diff.out expected &&
+ check_cache_at yomin clean &&
+ test_cmp bozbar.M bozbar &&
+ test_cmp frotz.M frotz &&
+ test_cmp nitfol.M nitfol &&
+ echo yomin >yomin1 &&
+ diff yomin yomin1 &&
+ rm -f yomin1
+'
+
+test_expect_success '5 - carry forward local addition.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ read_tree_u_must_succeed -m -u $treeH &&
+ echo yomin >yomin &&
+ git update-index --add yomin &&
+ echo yomin yomin >yomin &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >5.out &&
+ test_might_fail git diff -U0 --no-index M.out 5.out >5diff.out &&
+ compare_change 5diff.out expected &&
+ check_cache_at yomin dirty &&
+ test_cmp bozbar.M bozbar &&
+ test_cmp frotz.M frotz &&
+ test_cmp nitfol.M nitfol &&
+ : dirty index should have prevented -u from checking it out. &&
+ echo yomin yomin >yomin1 &&
+ diff yomin yomin1 &&
+ rm -f yomin1
+'
+
+test_expect_success '6 - local addition already has the same.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo frotz >frotz &&
+ git update-index --add frotz &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >6.out &&
+ test_cmp M.out 6.out &&
+ check_cache_at frotz clean &&
+ test_cmp bozbar.M bozbar &&
+ test_cmp frotz.M frotz &&
+ test_cmp nitfol.M nitfol &&
+ echo frotz >frotz1 &&
+ diff frotz frotz1 &&
+ rm -f frotz1
+'
+
+test_expect_success '7 - local addition already has the same.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo frotz >frotz &&
+ git update-index --add frotz &&
+ echo frotz frotz >frotz &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >7.out &&
+ test_cmp M.out 7.out &&
+ check_cache_at frotz dirty &&
+ test_cmp bozbar.M bozbar &&
+ test_cmp nitfol.M nitfol &&
+ : dirty index should have prevented -u from checking it out. &&
+ echo frotz frotz >frotz1 &&
+ diff frotz frotz1 &&
+ rm -f frotz1
+'
+
+test_expect_success '8 - conflicting addition.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo frotz frotz >frotz &&
+ git update-index --add frotz &&
+ ! read_tree_u_must_succeed -m -u $treeH $treeM
+'
+
+test_expect_success '9 - conflicting addition.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo frotz frotz >frotz &&
+ git update-index --add frotz &&
+ echo frotz >frotz &&
+ ! read_tree_u_must_succeed -m -u $treeH $treeM
+'
+
+test_expect_success '10 - path removed.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo rezrov >rezrov &&
+ git update-index --add rezrov &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >10.out &&
+ cmp M.out 10.out &&
+ test_cmp bozbar.M bozbar &&
+ test_cmp frotz.M frotz &&
+ test_cmp nitfol.M nitfol
+'
+
+test_expect_success '11 - dirty path removed.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo rezrov >rezrov &&
+ git update-index --add rezrov &&
+ echo rezrov rezrov >rezrov &&
+ ! read_tree_u_must_succeed -m -u $treeH $treeM
+'
+
+test_expect_success '12 - unmatching local changes being removed.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo rezrov rezrov >rezrov &&
+ git update-index --add rezrov &&
+ ! read_tree_u_must_succeed -m -u $treeH $treeM
+'
+
+test_expect_success '13 - unmatching local changes being removed.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo rezrov rezrov >rezrov &&
+ git update-index --add rezrov &&
+ echo rezrov >rezrov &&
+ ! read_tree_u_must_succeed -m -u $treeH $treeM
+'
cat >expected <<EOF
-100644 X 0 nitfol
+100644 X 0 nitfol
EOF
-test_expect_success \
- '14 - unchanged in two heads.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo nitfol nitfol >nitfol &&
- git update-index --add nitfol &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >14.out &&
- test_must_fail git diff -U0 --no-index M.out 14.out >14diff.out &&
- compare_change 14diff.out expected &&
- test_cmp bozbar.M bozbar &&
- test_cmp frotz.M frotz &&
- check_cache_at nitfol clean &&
- echo nitfol nitfol >nitfol1 &&
- diff nitfol nitfol1 &&
- rm -f nitfol1'
-
-test_expect_success \
- '15 - unchanged in two heads.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo nitfol nitfol >nitfol &&
- git update-index --add nitfol &&
- echo nitfol nitfol nitfol >nitfol &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >15.out &&
- test_must_fail git diff -U0 --no-index M.out 15.out >15diff.out &&
- compare_change 15diff.out expected &&
- check_cache_at nitfol dirty &&
- test_cmp bozbar.M bozbar &&
- test_cmp frotz.M frotz &&
- echo nitfol nitfol nitfol >nitfol1 &&
- diff nitfol nitfol1 &&
- rm -f nitfol1'
-
-test_expect_success \
- '16 - conflicting local change.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo bozbar bozbar >bozbar &&
- git update-index --add bozbar &&
- if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'
-
-test_expect_success \
- '17 - conflicting local change.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo bozbar bozbar >bozbar &&
- git update-index --add bozbar &&
- echo bozbar bozbar bozbar >bozbar &&
- if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'
-
-test_expect_success \
- '18 - local change already having a good result.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo gnusto >bozbar &&
- git update-index --add bozbar &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >18.out &&
- test_cmp M.out 18.out &&
- check_cache_at bozbar clean &&
- test_cmp bozbar.M bozbar &&
- test_cmp frotz.M frotz &&
- test_cmp nitfol.M nitfol
+test_expect_success '14 - unchanged in two heads.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo nitfol nitfol >nitfol &&
+ git update-index --add nitfol &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >14.out &&
+ test_must_fail git diff -U0 --no-index M.out 14.out >14diff.out &&
+ compare_change 14diff.out expected &&
+ test_cmp bozbar.M bozbar &&
+ test_cmp frotz.M frotz &&
+ check_cache_at nitfol clean &&
+ echo nitfol nitfol >nitfol1 &&
+ diff nitfol nitfol1 &&
+ rm -f nitfol1
'
-test_expect_success \
- '19 - local change already having a good result, further modified.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo gnusto >bozbar &&
- git update-index --add bozbar &&
- echo gnusto gnusto >bozbar &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >19.out &&
- test_cmp M.out 19.out &&
- check_cache_at bozbar dirty &&
- test_cmp frotz.M frotz &&
- test_cmp nitfol.M nitfol &&
- echo gnusto gnusto >bozbar1 &&
- diff bozbar bozbar1 &&
- rm -f bozbar1'
-
-test_expect_success \
- '20 - no local change, use new tree.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo bozbar >bozbar &&
- git update-index --add bozbar &&
- read_tree_u_must_succeed -m -u $treeH $treeM &&
- git ls-files --stage >20.out &&
- test_cmp M.out 20.out &&
- check_cache_at bozbar clean &&
- test_cmp bozbar.M bozbar &&
- test_cmp frotz.M frotz &&
- test_cmp nitfol.M nitfol
+test_expect_success '15 - unchanged in two heads.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo nitfol nitfol >nitfol &&
+ git update-index --add nitfol &&
+ echo nitfol nitfol nitfol >nitfol &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >15.out &&
+ test_must_fail git diff -U0 --no-index M.out 15.out >15diff.out &&
+ compare_change 15diff.out expected &&
+ check_cache_at nitfol dirty &&
+ test_cmp bozbar.M bozbar &&
+ test_cmp frotz.M frotz &&
+ echo nitfol nitfol nitfol >nitfol1 &&
+ diff nitfol nitfol1 &&
+ rm -f nitfol1
'
-test_expect_success \
- '21 - no local change, dirty cache.' \
- 'rm -f .git/index nitfol bozbar rezrov frotz &&
- read_tree_u_must_succeed --reset -u $treeH &&
- echo bozbar >bozbar &&
- git update-index --add bozbar &&
- echo gnusto gnusto >bozbar &&
- if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'
+test_expect_success '16 - conflicting local change.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo bozbar bozbar >bozbar &&
+ git update-index --add bozbar &&
+ ! read_tree_u_must_succeed -m -u $treeH $treeM
+'
+
+test_expect_success '17 - conflicting local change.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo bozbar bozbar >bozbar &&
+ git update-index --add bozbar &&
+ echo bozbar bozbar bozbar >bozbar &&
+ ! read_tree_u_must_succeed -m -u $treeH $treeM
+'
+
+test_expect_success '18 - local change already having a good result.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo gnusto >bozbar &&
+ git update-index --add bozbar &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >18.out &&
+ test_cmp M.out 18.out &&
+ check_cache_at bozbar clean &&
+ test_cmp bozbar.M bozbar &&
+ test_cmp frotz.M frotz &&
+ test_cmp nitfol.M nitfol
+'
+
+test_expect_success '19 - local change already having a good result, further modified.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo gnusto >bozbar &&
+ git update-index --add bozbar &&
+ echo gnusto gnusto >bozbar &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >19.out &&
+ test_cmp M.out 19.out &&
+ check_cache_at bozbar dirty &&
+ test_cmp frotz.M frotz &&
+ test_cmp nitfol.M nitfol &&
+ echo gnusto gnusto >bozbar1 &&
+ diff bozbar bozbar1 &&
+ rm -f bozbar1
+'
+
+test_expect_success '20 - no local change, use new tree.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo bozbar >bozbar &&
+ git update-index --add bozbar &&
+ read_tree_u_must_succeed -m -u $treeH $treeM &&
+ git ls-files --stage >20.out &&
+ test_cmp M.out 20.out &&
+ check_cache_at bozbar clean &&
+ test_cmp bozbar.M bozbar &&
+ test_cmp frotz.M frotz &&
+ test_cmp nitfol.M nitfol
+'
+
+test_expect_success '21 - no local change, dirty cache.' '
+ rm -f .git/index nitfol bozbar rezrov frotz &&
+ read_tree_u_must_succeed --reset -u $treeH &&
+ echo bozbar >bozbar &&
+ git update-index --add bozbar &&
+ echo gnusto gnusto >bozbar &&
+ ! read_tree_u_must_succeed -m -u $treeH $treeM
+'
# Also make sure we did not break DF vs DF/DF case.
-test_expect_success \
- 'DF vs DF/DF case setup.' \
- 'rm -f .git/index &&
- echo DF >DF &&
- git update-index --add DF &&
- treeDF=$(git write-tree) &&
- echo treeDF $treeDF &&
- git ls-tree $treeDF &&
-
- rm -f DF &&
- mkdir DF &&
- echo DF/DF >DF/DF &&
- git update-index --add --remove DF DF/DF &&
- treeDFDF=$(git write-tree) &&
- echo treeDFDF $treeDFDF &&
- git ls-tree $treeDFDF &&
- git ls-files --stage >DFDF.out'
-
-test_expect_success \
- 'DF vs DF/DF case test.' \
- 'rm -f .git/index &&
- rm -fr DF &&
- echo DF >DF &&
- git update-index --add DF &&
- read_tree_u_must_succeed -m -u $treeDF $treeDFDF &&
- git ls-files --stage >DFDFcheck.out &&
- test_cmp DFDF.out DFDFcheck.out &&
- check_cache_at DF/DF clean'
+test_expect_success 'DF vs DF/DF case setup.' '
+ rm -f .git/index &&
+ echo DF >DF &&
+ git update-index --add DF &&
+ treeDF=$(git write-tree) &&
+ echo treeDF $treeDF &&
+ git ls-tree $treeDF &&
+
+ rm -f DF &&
+ mkdir DF &&
+ echo DF/DF >DF/DF &&
+ git update-index --add --remove DF DF/DF &&
+ treeDFDF=$(git write-tree) &&
+ echo treeDFDF $treeDFDF &&
+ git ls-tree $treeDFDF &&
+ git ls-files --stage >DFDF.out
+'
+
+test_expect_success 'DF vs DF/DF case test.' '
+ rm -f .git/index &&
+ rm -fr DF &&
+ echo DF >DF &&
+ git update-index --add DF &&
+ read_tree_u_must_succeed -m -u $treeDF $treeDFDF &&
+ git ls-files --stage >DFDFcheck.out &&
+ test_cmp DFDF.out DFDFcheck.out &&
+ check_cache_at DF/DF clean
+'
test_done
diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh
index 12e30d77d0..26be4a2b5a 100755
--- a/t/t1005-read-tree-reset.sh
+++ b/t/t1005-read-tree-reset.sh
@@ -41,7 +41,8 @@ test_expect_success 'reset should remove remnants from a failed merge' '
git ls-files -s &&
read_tree_u_must_succeed --reset -u HEAD &&
git ls-files -s >actual &&
- ! test -f old
+ ! test -f old &&
+ test_cmp expect actual
'
test_expect_success 'two-way reset should remove remnants too' '
@@ -56,7 +57,8 @@ test_expect_success 'two-way reset should remove remnants too' '
git ls-files -s &&
read_tree_u_must_succeed --reset -u HEAD HEAD &&
git ls-files -s >actual &&
- ! test -f old
+ ! test -f old &&
+ test_cmp expect actual
'
test_expect_success 'Porcelain reset should remove remnants too' '
@@ -71,7 +73,8 @@ test_expect_success 'Porcelain reset should remove remnants too' '
git ls-files -s &&
git reset --hard &&
git ls-files -s >actual &&
- ! test -f old
+ ! test -f old &&
+ test_cmp expect actual
'
test_expect_success 'Porcelain checkout -f should remove remnants too' '
@@ -86,7 +89,8 @@ test_expect_success 'Porcelain checkout -f should remove remnants too' '
git ls-files -s &&
git checkout -f &&
git ls-files -s >actual &&
- ! test -f old
+ ! test -f old &&
+ test_cmp expect actual
'
test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' '
@@ -101,7 +105,8 @@ test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' '
git ls-files -s &&
git checkout -f HEAD &&
git ls-files -s >actual &&
- ! test -f old
+ ! test -f old &&
+ test_cmp expect actual
'
test_done
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 23b8942edb..d73a0be1b9 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -89,7 +89,8 @@ done
for opt in --buffer \
--follow-symlinks \
--batch-all-objects \
- -z
+ -z \
+ -Z
do
test_expect_success "usage: bad option combination: $opt without batch mode" '
test_incompatible_usage git cat-file $opt &&
@@ -109,26 +110,12 @@ strlen () {
echo_without_newline "$1" | wc -c | sed -e 's/^ *//'
}
-maybe_remove_timestamp () {
- if test -z "$2"; then
- echo_without_newline "$1"
- else
- echo_without_newline "$(printf '%s\n' "$1" | remove_timestamp)"
- fi
-}
-
-remove_timestamp () {
- sed -e 's/ [0-9][0-9]* [-+][0-9][0-9][0-9][0-9]$//'
-}
-
-
run_tests () {
type=$1
sha1=$2
size=$3
content=$4
pretty_content=$5
- no_ts=$6
batch_output="$sha1 $type $size
$content"
@@ -163,21 +150,21 @@ $content"
test -z "$content" ||
test_expect_success "Content of $type is correct" '
- maybe_remove_timestamp "$content" $no_ts >expect &&
- maybe_remove_timestamp "$(git cat-file $type $sha1)" $no_ts >actual &&
+ echo_without_newline "$content" >expect &&
+ git cat-file $type $sha1 >actual &&
test_cmp expect actual
'
test_expect_success "Pretty content of $type is correct" '
- maybe_remove_timestamp "$pretty_content" $no_ts >expect &&
- maybe_remove_timestamp "$(git cat-file -p $sha1)" $no_ts >actual &&
+ echo_without_newline "$pretty_content" >expect &&
+ git cat-file -p $sha1 >actual &&
test_cmp expect actual
'
test -z "$content" ||
test_expect_success "--batch output of $type is correct" '
- maybe_remove_timestamp "$batch_output" $no_ts >expect &&
- maybe_remove_timestamp "$(echo $sha1 | git cat-file --batch)" $no_ts >actual &&
+ echo "$batch_output" >expect &&
+ echo $sha1 | git cat-file --batch >actual &&
test_cmp expect actual
'
@@ -191,9 +178,8 @@ $content"
do
test -z "$content" ||
test_expect_success "--batch-command $opt output of $type content is correct" '
- maybe_remove_timestamp "$batch_output" $no_ts >expect &&
- maybe_remove_timestamp "$(test_write_lines "contents $sha1" |
- git cat-file --batch-command $opt)" $no_ts >actual &&
+ echo "$batch_output" >expect &&
+ test_write_lines "contents $sha1" | git cat-file --batch-command $opt >actual &&
test_cmp expect actual
'
@@ -228,10 +214,9 @@ $content"
test_expect_success "--batch without type ($type)" '
{
echo "$size" &&
- maybe_remove_timestamp "$content" $no_ts
+ echo "$content"
} >expect &&
- echo $sha1 | git cat-file --batch="%(objectsize)" >actual.full &&
- maybe_remove_timestamp "$(cat actual.full)" $no_ts >actual &&
+ echo $sha1 | git cat-file --batch="%(objectsize)" >actual &&
test_cmp expect actual
'
@@ -239,10 +224,9 @@ $content"
test_expect_success "--batch without size ($type)" '
{
echo "$type" &&
- maybe_remove_timestamp "$content" $no_ts
+ echo "$content"
} >expect &&
- echo $sha1 | git cat-file --batch="%(objecttype)" >actual.full &&
- maybe_remove_timestamp "$(cat actual.full)" $no_ts >actual &&
+ echo $sha1 | git cat-file --batch="%(objecttype)" >actual &&
test_cmp expect actual
'
}
@@ -284,7 +268,7 @@ test_expect_success '--batch-check without %(rest) considers whole line' '
tree_sha1=$(git write-tree)
tree_size=$(($(test_oid rawsz) + 13))
-tree_pretty_content="100644 blob $hello_sha1 hello"
+tree_pretty_content="100644 blob $hello_sha1 hello${LF}"
run_tests 'tree' $tree_sha1 $tree_size "" "$tree_pretty_content"
@@ -292,30 +276,32 @@ commit_message="Initial commit"
commit_sha1=$(echo_without_newline "$commit_message" | git commit-tree $tree_sha1)
commit_size=$(($(test_oid hexsz) + 137))
commit_content="tree $tree_sha1
-author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0000000000 +0000
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0000000000 +0000
+author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
$commit_message"
-run_tests 'commit' $commit_sha1 $commit_size "$commit_content" "$commit_content" 1
+run_tests 'commit' $commit_sha1 $commit_size "$commit_content" "$commit_content"
tag_header_without_timestamp="object $hello_sha1
type blob
tag hellotag
tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
tag_description="This is a tag"
-tag_content="$tag_header_without_timestamp 0000000000 +0000
+tag_content="$tag_header_without_timestamp 0 +0000
$tag_description"
tag_sha1=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w)
tag_size=$(strlen "$tag_content")
-run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
+run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content"
-test_expect_success \
- "Reach a blob from a tag pointing to it" \
- "test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\""
+test_expect_success "Reach a blob from a tag pointing to it" '
+ echo_without_newline "$hello_content" >expect &&
+ git cat-file blob $tag_sha1 >actual &&
+ test_cmp expect actual
+'
for batch in batch batch-check batch-command
do
@@ -351,30 +337,47 @@ do
done
test_expect_success "--batch-check for a non-existent named object" '
- test "foobar42 missing
-foobar84 missing" = \
- "$( ( echo foobar42 && echo_without_newline foobar84 ) | git cat-file --batch-check)"
+ cat >expect <<-EOF &&
+ foobar42 missing
+ foobar84 missing
+ EOF
+
+ printf "foobar42\nfoobar84" >in &&
+ git cat-file --batch-check <in >actual &&
+ test_cmp expect actual
'
test_expect_success "--batch-check for a non-existent hash" '
- test "0000000000000000000000000000000000000042 missing
-0000000000000000000000000000000000000084 missing" = \
- "$( ( echo 0000000000000000000000000000000000000042 &&
- echo_without_newline 0000000000000000000000000000000000000084 ) |
- git cat-file --batch-check)"
+ cat >expect <<-EOF &&
+ 0000000000000000000000000000000000000042 missing
+ 0000000000000000000000000000000000000084 missing
+ EOF
+
+ printf "0000000000000000000000000000000000000042\n0000000000000000000000000000000000000084" >in &&
+ git cat-file --batch-check <in >actual &&
+ test_cmp expect actual
'
test_expect_success "--batch for an existent and a non-existent hash" '
- test "$tag_sha1 tag $tag_size
-$tag_content
-0000000000000000000000000000000000000000 missing" = \
- "$( ( echo $tag_sha1 &&
- echo_without_newline 0000000000000000000000000000000000000000 ) |
- git cat-file --batch)"
+ cat >expect <<-EOF &&
+ $tag_sha1 tag $tag_size
+ $tag_content
+ 0000000000000000000000000000000000000000 missing
+ EOF
+
+ printf "$tag_sha1\n0000000000000000000000000000000000000000" >in &&
+ git cat-file --batch <in >actual &&
+ test_cmp expect actual
'
test_expect_success "--batch-check for an empty line" '
- test " missing" = "$(echo | git cat-file --batch-check)"
+ cat >expect <<-EOF &&
+ missing
+ EOF
+
+ echo >in &&
+ git cat-file --batch-check <in >actual &&
+ test_cmp expect actual
'
test_expect_success 'empty --batch-check notices missing object' '
@@ -390,23 +393,34 @@ deadbeef
"
-batch_output="$hello_sha1 blob $hello_size
-$hello_content
-$commit_sha1 commit $commit_size
-$commit_content
-$tag_sha1 tag $tag_size
-$tag_content
-deadbeef missing
- missing"
+printf "%s\0" \
+ "$hello_sha1 blob $hello_size" \
+ "$hello_content" \
+ "$commit_sha1 commit $commit_size" \
+ "$commit_content" \
+ "$tag_sha1 tag $tag_size" \
+ "$tag_content" \
+ "deadbeef missing" \
+ " missing" >batch_output
test_expect_success '--batch with multiple sha1s gives correct format' '
- test "$(maybe_remove_timestamp "$batch_output" 1)" = "$(maybe_remove_timestamp "$(echo_without_newline "$batch_input" | git cat-file --batch)" 1)"
+ tr "\0" "\n" <batch_output >expect &&
+ echo_without_newline "$batch_input" >in &&
+ git cat-file --batch <in >actual &&
+ test_cmp expect actual
'
test_expect_success '--batch, -z with multiple sha1s gives correct format' '
echo_without_newline_nul "$batch_input" >in &&
- test "$(maybe_remove_timestamp "$batch_output" 1)" = \
- "$(maybe_remove_timestamp "$(git cat-file --batch -z <in)" 1)"
+ tr "\0" "\n" <batch_output >expect &&
+ git cat-file --batch -z <in >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--batch, -Z with multiple sha1s gives correct format' '
+ echo_without_newline_nul "$batch_input" >in &&
+ git cat-file --batch -Z <in >actual &&
+ test_cmp batch_output actual
'
batch_check_input="$hello_sha1
@@ -417,36 +431,55 @@ deadbeef
"
-batch_check_output="$hello_sha1 blob $hello_size
-$tree_sha1 tree $tree_size
-$commit_sha1 commit $commit_size
-$tag_sha1 tag $tag_size
-deadbeef missing
- missing"
+printf "%s\0" \
+ "$hello_sha1 blob $hello_size" \
+ "$tree_sha1 tree $tree_size" \
+ "$commit_sha1 commit $commit_size" \
+ "$tag_sha1 tag $tag_size" \
+ "deadbeef missing" \
+ " missing" >batch_check_output
test_expect_success "--batch-check with multiple sha1s gives correct format" '
- test "$batch_check_output" = \
- "$(echo_without_newline "$batch_check_input" | git cat-file --batch-check)"
+ tr "\0" "\n" <batch_check_output >expect &&
+ echo_without_newline "$batch_check_input" >in &&
+ git cat-file --batch-check <in >actual &&
+ test_cmp expect actual
'
test_expect_success "--batch-check, -z with multiple sha1s gives correct format" '
- echo_without_newline_nul "$batch_check_input" >in &&
- test "$batch_check_output" = "$(git cat-file --batch-check -z <in)"
+ tr "\0" "\n" <batch_check_output >expect &&
+ echo_without_newline_nul "$batch_check_input" >in &&
+ git cat-file --batch-check -z <in >actual &&
+ test_cmp expect actual
'
-test_expect_success FUNNYNAMES '--batch-check, -z with newline in input' '
+test_expect_success "--batch-check, -Z with multiple sha1s gives correct format" '
+ echo_without_newline_nul "$batch_check_input" >in &&
+ git cat-file --batch-check -Z <in >actual &&
+ test_cmp batch_check_output actual
+'
+
+test_expect_success FUNNYNAMES 'setup with newline in input' '
touch -- "newline${LF}embedded" &&
git add -- "newline${LF}embedded" &&
git commit -m "file with newline embedded" &&
test_tick &&
- printf "HEAD:newline${LF}embedded" >in &&
- git cat-file --batch-check -z <in >actual &&
+ printf "HEAD:newline${LF}embedded" >in
+'
+test_expect_success FUNNYNAMES '--batch-check, -z with newline in input' '
+ git cat-file --batch-check -z <in >actual &&
echo "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect &&
test_cmp expect actual
'
+test_expect_success FUNNYNAMES '--batch-check, -Z with newline in input' '
+ git cat-file --batch-check -Z <in >actual &&
+ printf "%s\0" "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect &&
+ test_cmp expect actual
+'
+
batch_command_multiple_info="info $hello_sha1
info $tree_sha1
info $commit_sha1
@@ -470,7 +503,13 @@ test_expect_success '--batch-command with multiple info calls gives correct form
echo "$batch_command_multiple_info" | tr "\n" "\0" >in &&
git cat-file --batch-command --buffer -z <in >actual &&
- test_cmp expect actual
+ test_cmp expect actual &&
+
+ echo "$batch_command_multiple_info" | tr "\n" "\0" >in &&
+ tr "\n" "\0" <expect >expect_nul &&
+ git cat-file --batch-command --buffer -Z <in >actual &&
+
+ test_cmp expect_nul actual
'
batch_command_multiple_contents="contents $hello_sha1
@@ -480,27 +519,30 @@ contents deadbeef
flush"
test_expect_success '--batch-command with multiple command calls gives correct format' '
- remove_timestamp >expect <<-EOF &&
- $hello_sha1 blob $hello_size
- $hello_content
- $commit_sha1 commit $commit_size
- $commit_content
- $tag_sha1 tag $tag_size
- $tag_content
- deadbeef missing
- EOF
+ printf "%s\0" \
+ "$hello_sha1 blob $hello_size" \
+ "$hello_content" \
+ "$commit_sha1 commit $commit_size" \
+ "$commit_content" \
+ "$tag_sha1 tag $tag_size" \
+ "$tag_content" \
+ "deadbeef missing" >expect_nul &&
+ tr "\0" "\n" <expect_nul >expect &&
echo "$batch_command_multiple_contents" >in &&
- git cat-file --batch-command --buffer <in >actual_raw &&
+ git cat-file --batch-command --buffer <in >actual &&
- remove_timestamp <actual_raw >actual &&
test_cmp expect actual &&
echo "$batch_command_multiple_contents" | tr "\n" "\0" >in &&
- git cat-file --batch-command --buffer -z <in >actual_raw &&
+ git cat-file --batch-command --buffer -z <in >actual &&
- remove_timestamp <actual_raw >actual &&
- test_cmp expect actual
+ test_cmp expect actual &&
+
+ echo "$batch_command_multiple_contents" | tr "\n" "\0" >in &&
+ git cat-file --batch-command --buffer -Z <in >actual &&
+
+ test_cmp expect_nul actual
'
test_expect_success 'setup blobs which are likely to delta' '
@@ -603,7 +645,8 @@ do
fatal: Not a valid object name $(test_oid deadbeef_short)
EOF
test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef_short) >out 2>err.actual &&
- test_must_be_empty out
+ test_must_be_empty out &&
+ test_cmp expect.err err.actual
'
test_expect_success "cat-file $arg1 $arg2 error on missing full OID" '
@@ -839,6 +882,13 @@ test_expect_success 'git cat-file --batch-check --follow-symlinks works for brok
test_cmp expect actual
'
+test_expect_success 'git cat-file --batch-check --follow-symlinks -Z works for broken in-repo, same-dir links' '
+ printf "HEAD:broken-same-dir-link\0" >in &&
+ printf "dangling 25\0HEAD:broken-same-dir-link\0" >expect &&
+ git cat-file --batch-check --follow-symlinks -Z <in >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'git cat-file --batch-check --follow-symlinks works for same-dir links-to-links' '
echo HEAD:link-to-link | git cat-file --batch-check --follow-symlinks >actual &&
test_cmp found actual
@@ -853,6 +903,15 @@ test_expect_success 'git cat-file --batch-check --follow-symlinks works for pare
test_cmp expect actual
'
+test_expect_success 'git cat-file --batch-check --follow-symlinks -Z works for parent-dir links' '
+ echo HEAD:dir/parent-dir-link | git cat-file --batch-check --follow-symlinks >actual &&
+ test_cmp found actual &&
+ printf "notdir 29\0HEAD:dir/parent-dir-link/nope\0" >expect &&
+ printf "HEAD:dir/parent-dir-link/nope\0" >in &&
+ git cat-file --batch-check --follow-symlinks -Z <in >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'git cat-file --batch-check --follow-symlinks works for .. links' '
echo dangling 22 >expect &&
echo HEAD:dir/link-dir/nope >>expect &&
@@ -967,6 +1026,13 @@ test_expect_success 'git cat-file --batch-check --follow-symlink breaks loops' '
test_cmp expect actual
'
+test_expect_success 'git cat-file --batch-check --follow-symlink -Z breaks loops' '
+ printf "loop 10\0HEAD:loop1\0" >expect &&
+ printf "HEAD:loop1\0" >in &&
+ git cat-file --batch-check --follow-symlinks -Z <in >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'git cat-file --batch --follow-symlink returns correct sha and mode' '
echo HEAD:morx | git cat-file --batch >expect &&
echo HEAD:morx | git cat-file --batch --follow-symlinks >actual &&
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index ac5ad8c740..ac3d173767 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -203,23 +203,34 @@ done
test_expect_success 'too-short tree' '
echo abc >malformed-tree &&
test_must_fail git hash-object -t tree malformed-tree 2>err &&
- test_i18ngrep "too-short tree object" err
+ grep "too-short tree object" err
'
test_expect_success 'malformed mode in tree' '
- hex_sha1=$(echo foo | git hash-object --stdin -w) &&
- bin_sha1=$(echo $hex_sha1 | hex2oct) &&
- printf "9100644 \0$bin_sha1" >tree-with-malformed-mode &&
+ hex_oid=$(echo foo | git hash-object --stdin -w) &&
+ bin_oid=$(echo $hex_oid | hex2oct) &&
+ printf "9100644 \0$bin_oid" >tree-with-malformed-mode &&
test_must_fail git hash-object -t tree tree-with-malformed-mode 2>err &&
- test_i18ngrep "malformed mode in tree entry" err
+ grep "malformed mode in tree entry" err
'
test_expect_success 'empty filename in tree' '
- hex_sha1=$(echo foo | git hash-object --stdin -w) &&
- bin_sha1=$(echo $hex_sha1 | hex2oct) &&
- printf "100644 \0$bin_sha1" >tree-with-empty-filename &&
+ hex_oid=$(echo foo | git hash-object --stdin -w) &&
+ bin_oid=$(echo $hex_oid | hex2oct) &&
+ printf "100644 \0$bin_oid" >tree-with-empty-filename &&
test_must_fail git hash-object -t tree tree-with-empty-filename 2>err &&
- test_i18ngrep "empty filename in tree entry" err
+ grep "empty filename in tree entry" err
+'
+
+test_expect_success 'duplicate filename in tree' '
+ hex_oid=$(echo foo | git hash-object --stdin -w) &&
+ bin_oid=$(echo $hex_oid | hex2oct) &&
+ {
+ printf "100644 file\0$bin_oid" &&
+ printf "100644 file\0$bin_oid"
+ } >tree-with-duplicate-filename &&
+ test_must_fail git hash-object -t tree tree-with-duplicate-filename 2>err &&
+ grep "duplicateEntries" err
'
test_expect_success 'corrupt commit' '
diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh
index 3c08194526..22875ba598 100755
--- a/t/t1010-mktree.sh
+++ b/t/t1010-mktree.sh
@@ -60,11 +60,11 @@ test_expect_success 'allow missing object with --missing' '
'
test_expect_success 'mktree refuses to read ls-tree -r output (1)' '
- test_must_fail git mktree <all >actual
+ test_must_fail git mktree <all
'
test_expect_success 'mktree refuses to read ls-tree -r output (2)' '
- test_must_fail git mktree <all.withsub >actual
+ test_must_fail git mktree <all.withsub
'
test_done
diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh
index 742f0fa909..595b24c0ad 100755
--- a/t/t1011-read-tree-sparse-checkout.sh
+++ b/t/t1011-read-tree-sparse-checkout.sh
@@ -12,6 +12,7 @@ test_description='sparse checkout tests
'
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-read-tree.sh
diff --git a/t/t1022-read-tree-partial-clone.sh b/t/t1022-read-tree-partial-clone.sh
index a9953b6a71..cca4380e43 100755
--- a/t/t1022-read-tree-partial-clone.sh
+++ b/t/t1022-read-tree-partial-clone.sh
@@ -3,7 +3,7 @@
test_description='git read-tree in partial clones'
TEST_NO_CREATE_REPO=1
-
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'read-tree in partial clone prefetches in one batch' '
@@ -19,7 +19,7 @@ test_expect_success 'read-tree in partial clone prefetches in one batch' '
git -C server config uploadpack.allowfilter 1 &&
git -C server config uploadpack.allowanysha1inwant 1 &&
git clone --bare --filter=blob:none "file://$(pwd)/server" client &&
- GIT_TRACE_PACKET="$(pwd)/trace" git -C client read-tree $TREE &&
+ GIT_TRACE_PACKET="$(pwd)/trace" git -C client read-tree $TREE $TREE &&
# "done" marks the end of negotiation (once per fetch). Expect that
# only one fetch occurs.
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 4f3aa17c99..c71932b024 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -5,6 +5,12 @@ test_description='adding and checking out large blobs'
. ./test-lib.sh
+test_expect_success 'core.bigFileThreshold must be non-negative' '
+ test_must_fail git -c core.bigFileThreshold=-1 rev-parse >out 2>err &&
+ grep "bad numeric config value" err &&
+ test_must_be_empty out
+'
+
test_expect_success setup '
# clone does not allow us to pass core.bigfilethreshold to
# new repos, so set core.bigfilethreshold globally
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index b563d6c263..9ceb17f911 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -238,7 +238,7 @@ test_expect_success 'cone mode: match patterns' '
test_expect_success 'cone mode: warn on bad pattern' '
test_when_finished mv sparse-checkout repo/.git/info/ &&
cp repo/.git/info/sparse-checkout . &&
- echo "!/deep/deeper/*" >>repo/.git/info/sparse-checkout &&
+ echo "!/deep/deeper/*/" >>repo/.git/info/sparse-checkout &&
git -C repo read-tree -mu HEAD 2>err &&
test_i18ngrep "unrecognized negative pattern" err
'
@@ -555,7 +555,7 @@ test_expect_success 'cone mode: set with core.ignoreCase=true' '
check_files repo a folder1
'
-test_expect_success 'interaction with submodules' '
+test_expect_success 'setup submodules' '
git clone repo super &&
(
cd super &&
@@ -566,11 +566,22 @@ test_expect_success 'interaction with submodules' '
git commit -m "add submodule" &&
git sparse-checkout init --cone &&
git sparse-checkout set folder1
- ) &&
+ )
+'
+
+test_expect_success 'interaction with submodules' '
check_files super a folder1 modules &&
check_files super/modules/child a deep folder1 folder2
'
+test_expect_success 'check-rules interaction with submodules' '
+ git -C super ls-tree --name-only -r HEAD >all-files &&
+ git -C super sparse-checkout check-rules >check-rules-matches <all-files &&
+
+ test_i18ngrep ! "modules/" check-rules-matches &&
+ test_i18ngrep "folder1/" check-rules-matches
+'
+
test_expect_success 'different sparse-checkouts with worktrees' '
git -C repo sparse-checkout set --cone deep folder1 &&
git -C repo worktree add --detach ../worktree &&
@@ -667,6 +678,15 @@ test_expect_success 'pattern-checks: starting "*"' '
check_read_tree_errors repo "a deep" "disabling cone pattern matching"
'
+test_expect_success 'pattern-checks: non directory pattern' '
+ cat >repo/.git/info/sparse-checkout <<-\EOF &&
+ /deep/deeper1/a
+ EOF
+ check_read_tree_errors repo deep "disabling cone pattern matching" &&
+ check_files repo/deep deeper1 &&
+ check_files repo/deep/deeper1 a
+'
+
test_expect_success 'pattern-checks: contained glob characters' '
for c in "[a]" "\\" "?" "*"
do
@@ -873,4 +893,156 @@ test_expect_success 'by default, non-cone mode will warn on individual files' '
grep "pass a leading slash before paths.*if you want a single file" warning
'
+test_expect_success 'setup bare repo' '
+ git clone --bare "file://$(pwd)/repo" bare
+'
+test_expect_success 'list fails outside work tree' '
+ test_must_fail git -C bare sparse-checkout list 2>err &&
+ test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'add fails outside work tree' '
+ test_must_fail git -C bare sparse-checkout add deeper 2>err &&
+ test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'set fails outside work tree' '
+ test_must_fail git -C bare sparse-checkout set deeper 2>err &&
+ test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'init fails outside work tree' '
+ test_must_fail git -C bare sparse-checkout init 2>err &&
+ test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'reapply fails outside work tree' '
+ test_must_fail git -C bare sparse-checkout reapply 2>err &&
+ test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'disable fails outside work tree' '
+ test_must_fail git -C bare sparse-checkout disable 2>err &&
+ test_i18ngrep "this operation must be run in a work tree" err
+'
+
+test_expect_success 'setup clean' '
+ git -C repo clean -fdx
+'
+
+test_expect_success 'check-rules cone mode' '
+ cat >rules <<-\EOF &&
+ folder1
+ deep/deeper1/deepest
+ EOF
+
+ git -C bare ls-tree -r --name-only HEAD >all-files &&
+ git -C bare sparse-checkout check-rules --cone \
+ --rules-file ../rules >check-rules-file <all-files &&
+
+ git -C repo sparse-checkout set --cone --stdin <rules&&
+ git -C repo ls-files -t >out &&
+ sed -n "/^S /!s/^. //p" out >ls-files &&
+
+ git -C repo sparse-checkout check-rules >check-rules-default <all-files &&
+
+ test_i18ngrep "deep/deeper1/deepest/a" check-rules-file &&
+ test_i18ngrep ! "deep/deeper2" check-rules-file &&
+
+ test_cmp check-rules-file ls-files &&
+ test_cmp check-rules-file check-rules-default
+'
+
+test_expect_success 'check-rules non-cone mode' '
+ cat >rules <<-\EOF &&
+ deep/deeper1/deepest/a
+ EOF
+
+ git -C bare ls-tree -r --name-only HEAD >all-files &&
+ git -C bare sparse-checkout check-rules --no-cone --rules-file ../rules\
+ >check-rules-file <all-files &&
+
+ cat rules | git -C repo sparse-checkout set --no-cone --stdin &&
+ git -C repo ls-files -t >out &&
+ sed -n "/^S /!s/^. //p" out >ls-files &&
+
+ git -C repo sparse-checkout check-rules >check-rules-default <all-files &&
+
+ cat >expect <<-\EOF &&
+ deep/deeper1/deepest/a
+ EOF
+
+ test_cmp expect check-rules-file &&
+ test_cmp check-rules-file ls-files &&
+ test_cmp check-rules-file check-rules-default
+'
+
+test_expect_success 'check-rules cone mode is default' '
+ cat >rules <<-\EOF &&
+ folder1
+ EOF
+
+ cat >all-files <<-\EOF &&
+ toplevel
+ folder2/file
+ folder1/file
+ EOF
+
+ cat >expect <<-\EOF &&
+ toplevel
+ folder1/file
+ EOF
+
+ git -C repo sparse-checkout set --no-cone &&
+ git -C repo sparse-checkout check-rules \
+ --rules-file ../rules >actual <all-files &&
+
+ git -C bare sparse-checkout check-rules \
+ --rules-file ../rules >actual-bare <all-files &&
+
+ test_cmp expect actual &&
+ test_cmp expect actual-bare
+'
+
+test_expect_success 'check-rules quoting' '
+ cat >rules <<-EOF &&
+ "folder\" a"
+ EOF
+ cat >files <<-EOF &&
+ "folder\" a/file"
+ "folder\" b/file"
+ EOF
+ cat >expect <<-EOF &&
+ "folder\" a/file"
+ EOF
+ git sparse-checkout check-rules --cone \
+ --rules-file rules >actual <files &&
+
+ test_cmp expect actual
+'
+
+test_expect_success 'check-rules null termination' '
+ cat >rules <<-EOF &&
+ "folder\" a"
+ EOF
+
+ lf_to_nul >files <<-EOF &&
+ folder" a/a
+ folder" a/b
+ folder" b/fileQ
+ EOF
+
+ cat >expect <<-EOF &&
+ folder" a/aQfolder" a/bQ
+ EOF
+
+ git sparse-checkout check-rules --cone -z \
+ --rules-file rules >actual.nul <files &&
+ nul_to_q <actual.nul >actual &&
+ echo >>actual &&
+
+ test_cmp expect actual
+'
+
+
test_done
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 4844922e57..2a4f35e984 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -162,6 +162,19 @@ init_repos () {
git -C sparse-index sparse-checkout set deep
}
+init_repos_as_submodules () {
+ git reset --hard &&
+ init_repos &&
+ git submodule add ./full-checkout &&
+ git submodule add ./sparse-checkout &&
+ git submodule add ./sparse-index &&
+
+ git submodule status >actual &&
+ grep full-checkout actual &&
+ grep sparse-checkout actual &&
+ grep sparse-index actual
+}
+
run_on_sparse () {
(
cd sparse-checkout &&
@@ -1364,7 +1377,7 @@ test_expect_success 'index.sparse disabled inline uses full index' '
! test_region index ensure_full_index trace2.txt
'
-ensure_not_expanded () {
+run_sparse_index_trace2 () {
rm -f trace2.txt &&
if test -z "$WITHOUT_UNTRACKED_TXT"
then
@@ -1384,7 +1397,16 @@ ensure_not_expanded () {
git -C sparse-index "$@" \
>sparse-index-out \
2>sparse-index-error || return 1
- fi &&
+ fi
+}
+
+ensure_expanded () {
+ run_sparse_index_trace2 "$@" &&
+ test_region index ensure_full_index trace2.txt
+}
+
+ensure_not_expanded () {
+ run_sparse_index_trace2 "$@" &&
test_region ! index ensure_full_index trace2.txt
}
@@ -1501,6 +1523,31 @@ test_expect_success 'sparse-index is not expanded: stash' '
ensure_not_expanded stash pop
'
+test_expect_success 'describe tested on all' '
+ init_repos &&
+
+ # Add tag to be read by describe
+
+ run_on_all git tag -a v1.0 -m "Version 1" &&
+ test_all_match git describe --dirty &&
+ run_on_all rm g &&
+ test_all_match git describe --dirty
+'
+
+
+test_expect_success 'sparse-index is not expanded: describe' '
+ init_repos &&
+
+ # Add tag to be read by describe
+
+ git -C sparse-index tag -a v1.0 -m "Version 1" &&
+
+ ensure_not_expanded describe --dirty &&
+ echo "test" >>sparse-index/g &&
+ ensure_not_expanded describe --dirty &&
+ ensure_not_expanded describe
+'
+
test_expect_success 'sparse index is not expanded: diff' '
init_repos &&
@@ -1983,4 +2030,305 @@ test_expect_success 'sparse index is not expanded: rm' '
ensure_not_expanded rm -r deep
'
+test_expect_success 'grep with and --cached' '
+ init_repos &&
+
+ test_all_match git grep --cached a &&
+ test_all_match git grep --cached a -- "folder1/*"
+'
+
+test_expect_success 'grep is not expanded' '
+ init_repos &&
+
+ ensure_not_expanded grep a &&
+ ensure_not_expanded grep a -- deep/* &&
+
+ # All files within the folder1/* pathspec are sparse,
+ # so this command does not find any matches
+ ensure_not_expanded ! grep a -- folder1/* &&
+
+ # test out-of-cone pathspec with or without wildcard
+ ensure_not_expanded grep --cached a -- "folder1/a" &&
+ ensure_not_expanded grep --cached a -- "folder1/*" &&
+
+ # test in-cone pathspec with or without wildcard
+ ensure_not_expanded grep --cached a -- "deep/a" &&
+ ensure_not_expanded grep --cached a -- "deep/*"
+'
+
+# NEEDSWORK: when running `grep` in the superproject with --recurse-submodules,
+# Git expands the index of the submodules unexpectedly. Even though `grep`
+# builtin is marked as "command_requires_full_index = 0", this config is only
+# useful for the superproject. Namely, the submodules have their own configs,
+# which are _not_ populated by the one-time sparse-index feature switch.
+test_expect_failure 'grep within submodules is not expanded' '
+ init_repos_as_submodules &&
+
+ # do not use ensure_not_expanded() here, becasue `grep` should be
+ # run in the superproject, not in "./sparse-index"
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git grep --cached --recurse-submodules a -- "*/folder1/*" &&
+ test_region ! index ensure_full_index trace2.txt
+'
+
+# NEEDSWORK: this test is not actually testing the code. The design purpose
+# of this test is to verify the grep result when the submodules are using a
+# sparse-index. Namely, we want "folder1/" as a tree (a sparse directory); but
+# because of the index expansion, we are now grepping the "folder1/a" blob.
+# Because of the problem stated above 'grep within submodules is not expanded',
+# we don't have the ideal test environment yet.
+test_expect_success 'grep sparse directory within submodules' '
+ init_repos_as_submodules &&
+
+ cat >expect <<-\EOF &&
+ full-checkout/folder1/a:a
+ sparse-checkout/folder1/a:a
+ sparse-index/folder1/a:a
+ EOF
+ git grep --cached --recurse-submodules a -- "*/folder1/*" >actual &&
+ test_cmp actual expect
+'
+
+test_expect_success 'write-tree' '
+ init_repos &&
+
+ test_all_match git write-tree &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>"$1"
+ EOF
+
+ # make a change inside the sparse cone
+ run_on_all ../edit-contents deep/a &&
+ test_all_match git update-index deep/a &&
+ test_all_match git write-tree &&
+ test_all_match git status --porcelain=v2 &&
+
+ # make a change outside the sparse cone
+ run_on_all mkdir -p folder1 &&
+ run_on_all cp a folder1/a &&
+ run_on_all ../edit-contents folder1/a &&
+ test_all_match git update-index folder1/a &&
+ test_all_match git write-tree &&
+ test_all_match git status --porcelain=v2 &&
+
+ # check that SKIP_WORKTREE files are not materialized
+ test_path_is_missing sparse-checkout/folder2/a &&
+ test_path_is_missing sparse-index/folder2/a
+'
+
+test_expect_success 'sparse-index is not expanded: write-tree' '
+ init_repos &&
+
+ ensure_not_expanded write-tree &&
+
+ echo "test1" >>sparse-index/a &&
+ git -C sparse-index update-index a &&
+ ensure_not_expanded write-tree
+'
+
+test_expect_success 'diff-files with pathspec inside sparse definition' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>"$1"
+ EOF
+
+ run_on_all ../edit-contents deep/a &&
+
+ test_all_match git diff-files &&
+
+ test_all_match git diff-files -- deep/a &&
+
+ # test wildcard
+ test_all_match git diff-files -- "deep/*"
+'
+
+test_expect_success 'diff-files with pathspec outside sparse definition' '
+ init_repos &&
+
+ test_sparse_match git diff-files -- folder2/a &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>"$1"
+ EOF
+
+ # The directory "folder1" is outside the cone of interest
+ # and will not exist in the sparse checkout repositories.
+ # Create it as needed, add file "folder1/a" there with
+ # contents that is different from the staged version.
+ run_on_all mkdir -p folder1 &&
+ run_on_all cp a folder1/a &&
+
+ run_on_all ../edit-contents folder1/a &&
+ test_all_match git diff-files &&
+ test_all_match git diff-files -- folder1/a &&
+ test_all_match git diff-files -- "folder*/a"
+'
+
+test_expect_success 'sparse index is not expanded: diff-files' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>"$1"
+ EOF
+
+ run_on_all ../edit-contents deep/a &&
+
+ ensure_not_expanded diff-files &&
+ ensure_not_expanded diff-files -- deep/a &&
+ ensure_not_expanded diff-files -- "deep/*"
+'
+
+test_expect_success 'diff-tree' '
+ init_repos &&
+
+ # Test change inside sparse cone
+ tree1=$(git -C sparse-index rev-parse HEAD^{tree}) &&
+ tree2=$(git -C sparse-index rev-parse update-deep^{tree}) &&
+ test_all_match git diff-tree $tree1 $tree2 &&
+ test_all_match git diff-tree $tree1 $tree2 -- deep/a &&
+ test_all_match git diff-tree HEAD update-deep &&
+ test_all_match git diff-tree HEAD update-deep -- deep/a &&
+
+ # Test change outside sparse cone
+ tree3=$(git -C sparse-index rev-parse update-folder1^{tree}) &&
+ test_all_match git diff-tree $tree1 $tree3 &&
+ test_all_match git diff-tree $tree1 $tree3 -- folder1/a &&
+ test_all_match git diff-tree HEAD update-folder1 &&
+ test_all_match git diff-tree HEAD update-folder1 -- folder1/a &&
+
+ # Check that SKIP_WORKTREE files are not materialized
+ test_path_is_missing sparse-checkout/folder1/a &&
+ test_path_is_missing sparse-index/folder1/a &&
+ test_path_is_missing sparse-checkout/folder2/a &&
+ test_path_is_missing sparse-index/folder2/a
+'
+
+test_expect_success 'sparse-index is not expanded: diff-tree' '
+ init_repos &&
+
+ tree1=$(git -C sparse-index rev-parse HEAD^{tree}) &&
+ tree2=$(git -C sparse-index rev-parse update-deep^{tree}) &&
+ tree3=$(git -C sparse-index rev-parse update-folder1^{tree}) &&
+
+ ensure_not_expanded diff-tree $tree1 $tree2 &&
+ ensure_not_expanded diff-tree $tree1 $tree2 -- deep/a &&
+ ensure_not_expanded diff-tree HEAD update-deep &&
+ ensure_not_expanded diff-tree HEAD update-deep -- deep/a &&
+ ensure_not_expanded diff-tree $tree1 $tree3 &&
+ ensure_not_expanded diff-tree $tree1 $tree3 -- folder1/a &&
+ ensure_not_expanded diff-tree HEAD update-folder1 &&
+ ensure_not_expanded diff-tree HEAD update-folder1 -- folder1/a
+'
+
+test_expect_success 'worktree' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>"$1"
+ EOF
+
+ for repo in full-checkout sparse-checkout sparse-index
+ do
+ worktree=${repo}-wt &&
+ git -C $repo worktree add ../$worktree &&
+
+ # Compare worktree content with "ls"
+ (cd $repo && ls) >worktree_contents &&
+ (cd $worktree && ls) >new_worktree_contents &&
+ test_cmp worktree_contents new_worktree_contents &&
+
+ # Compare index content with "ls-files --sparse"
+ git -C $repo ls-files --sparse >index_contents &&
+ git -C $worktree ls-files --sparse >new_index_contents &&
+ test_cmp index_contents new_index_contents &&
+
+ git -C $repo worktree remove ../$worktree || return 1
+ done &&
+
+ test_all_match git worktree add .worktrees/hotfix &&
+ run_on_all ../edit-contents .worktrees/hotfix/deep/a &&
+ test_all_match test_must_fail git worktree remove .worktrees/hotfix
+'
+
+test_expect_success 'worktree is not expanded' '
+ init_repos &&
+
+ ensure_not_expanded worktree add .worktrees/hotfix &&
+ ensure_not_expanded worktree remove .worktrees/hotfix
+'
+
+test_expect_success 'check-attr with pathspec inside sparse definition' '
+ init_repos &&
+
+ echo "a -crlf myAttr" >>.gitattributes &&
+ run_on_all cp ../.gitattributes ./deep &&
+
+ test_all_match git check-attr -a -- deep/a &&
+
+ test_all_match git add deep/.gitattributes &&
+ test_all_match git check-attr -a --cached -- deep/a
+'
+
+test_expect_success 'check-attr with pathspec outside sparse definition' '
+ init_repos &&
+
+ echo "a -crlf myAttr" >>.gitattributes &&
+ run_on_sparse mkdir folder1 &&
+ run_on_all cp ../.gitattributes ./folder1 &&
+ run_on_all cp a folder1/a &&
+
+ test_all_match git check-attr -a -- folder1/a &&
+
+ git -C full-checkout add folder1/.gitattributes &&
+ test_sparse_match git add --sparse folder1/.gitattributes &&
+ test_all_match git commit -m "add .gitattributes" &&
+ test_sparse_match git sparse-checkout reapply &&
+ test_all_match git check-attr -a --cached -- folder1/a
+'
+
+# NEEDSWORK: The 'diff --check' test is left as 'test_expect_failure' due
+# to an underlying issue in oneway_diff() within diff-lib.c.
+# 'do_oneway_diff()' is not called as expected for paths that could match
+# inside of a sparse directory. Specifically, the 'ce_path_match()' function
+# fails to recognize files inside a sparse directory (e.g., when 'folder1/'
+# is a sparse directory, 'folder1/a' cannot be recognized). The goal is to
+# proceed with 'do_oneway_diff()' if the pathspec could match inside of a
+# sparse directory.
+test_expect_failure 'diff --check with pathspec outside sparse definition' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo "a " >"$1"
+ EOF
+
+ test_all_match git config core.whitespace -trailing-space,-space-before-tab &&
+
+ echo "a whitespace=trailing-space,space-before-tab" >>.gitattributes &&
+ run_on_all mkdir -p folder1 &&
+ run_on_all cp ../.gitattributes ./folder1 &&
+ test_all_match git add --sparse folder1/.gitattributes &&
+ run_on_all ../edit-contents folder1/a &&
+ test_all_match git add --sparse folder1/a &&
+
+ test_sparse_match git sparse-checkout reapply &&
+ test_all_match test_must_fail git diff --check --cached -- folder1/a
+'
+
+test_expect_success 'sparse-index is not expanded: check-attr' '
+ init_repos &&
+
+ echo "a -crlf myAttr" >>.gitattributes &&
+ mkdir ./sparse-index/folder1 &&
+ cp ./sparse-index/a ./sparse-index/folder1/a &&
+ cp .gitattributes ./sparse-index/deep &&
+ cp .gitattributes ./sparse-index/folder1 &&
+
+ git -C sparse-index add deep/.gitattributes &&
+ git -C sparse-index add --sparse folder1/.gitattributes &&
+ ensure_not_expanded check-attr -a --cached -- deep/a &&
+ ensure_not_expanded check-attr -a --cached -- folder1/a
+'
+
test_done
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index e8505bd39c..387d336c91 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -98,6 +98,23 @@ test_expect_success 'subsections are not canonicalized by git-config' '
test_cmp_config two section.SubSection.key
'
+test_missing_key () {
+ local key="$1" &&
+ local title="$2" &&
+ test_expect_success "value for $title is not printed" '
+ test_must_fail git config "$key" >out 2>err &&
+ test_must_be_empty out &&
+ test_must_be_empty err
+ '
+}
+
+test_missing_key 'missingsection.missingkey' 'missing section and missing key'
+test_missing_key 'missingsection.penguin' 'missing section and existing key'
+test_missing_key 'section.missingkey' 'existing section and missing key'
+test_missing_key 'section.MissingSubSection.missingkey' 'missing subsection and missing key'
+test_missing_key 'section.SubSection.missingkey' 'existing subsection and missing key'
+test_missing_key 'section.MissingSubSection.key' 'missing subsection and existing key'
+
cat > .git/config <<\EOF
[alpha]
bar = foo
@@ -1488,35 +1505,29 @@ test_expect_success 'git config ignores pairs without count' '
test_must_be_empty error
'
-test_expect_success 'git config ignores pairs with zero count' '
- test_must_fail env \
- GIT_CONFIG_COUNT=0 \
- GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
- git config pair.one
-'
-
test_expect_success 'git config ignores pairs exceeding count' '
GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="value" \
- git config --get-regexp "pair.*" >actual &&
+ git config --get-regexp "pair.*" >actual 2>error &&
cat >expect <<-EOF &&
pair.one value
EOF
- test_cmp expect actual
+ test_cmp expect actual &&
+ test_must_be_empty error
'
test_expect_success 'git config ignores pairs with zero count' '
test_must_fail env \
GIT_CONFIG_COUNT=0 GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
- git config pair.one >error &&
+ git config pair.one 2>error &&
test_must_be_empty error
'
test_expect_success 'git config ignores pairs with empty count' '
test_must_fail env \
GIT_CONFIG_COUNT= GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
- git config pair.one >error &&
+ git config pair.one 2>error &&
test_must_be_empty error
'
@@ -1601,11 +1612,11 @@ test_expect_success 'git config --edit respects core.editor' '
# malformed configuration files
test_expect_success 'barf on syntax error' '
cat >.git/config <<-\EOF &&
- # broken section line
+ # broken key=value
[section]
key garbage
EOF
- test_must_fail git config --get section.key >actual 2>error &&
+ test_must_fail git config --get section.key 2>error &&
test_i18ngrep " line 3 " error
'
@@ -1615,17 +1626,17 @@ test_expect_success 'barf on incomplete section header' '
[section
key = value
EOF
- test_must_fail git config --get section.key >actual 2>error &&
+ test_must_fail git config --get section.key 2>error &&
test_i18ngrep " line 2 " error
'
test_expect_success 'barf on incomplete string' '
cat >.git/config <<-\EOF &&
- # broken section line
+ # broken value string
[section]
key = "value string
EOF
- test_must_fail git config --get section.key >actual 2>error &&
+ test_must_fail git config --get section.key 2>error &&
test_i18ngrep " line 3 " error
'
@@ -1657,6 +1668,21 @@ test_expect_success 'urlmatch' '
test_cmp expect actual
'
+test_expect_success 'urlmatch with --show-scope' '
+ cat >.git/config <<-\EOF &&
+ [http "https://weak.example.com"]
+ sslVerify = false
+ cookieFile = /tmp/cookie.txt
+ EOF
+
+ cat >expect <<-EOF &&
+ local http.cookiefile /tmp/cookie.txt
+ local http.sslverify false
+ EOF
+ git config --get-urlmatch --show-scope HTTP https://weak.example.com >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'urlmatch favors more specific URLs' '
cat >.git/config <<-\EOF &&
[http "https://example.com/"]
@@ -2044,6 +2070,12 @@ test_expect_success '--show-origin blob ref' '
test_cmp expect output
'
+test_expect_success '--show-origin with --default' '
+ git config --show-origin --default foo some.key >actual &&
+ echo "command line: foo" >expect &&
+ test_cmp expect actual
+'
+
test_expect_success '--show-scope with --list' '
cat >expect <<-EOF &&
global user.global=true
@@ -2112,6 +2144,12 @@ test_expect_success '--show-scope with --show-origin' '
test_cmp expect output
'
+test_expect_success '--show-scope with --default' '
+ git config --show-scope --default foo some.key >actual &&
+ echo "command foo" >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'override global and system config' '
test_when_finished rm -f \"\$HOME\"/.gitconfig &&
cat >"$HOME"/.gitconfig <<-EOF &&
@@ -2258,6 +2296,12 @@ test_expect_success '--type rejects unknown specifiers' '
test_i18ngrep "unrecognized --type argument" error
'
+test_expect_success '--type=int requires at least one digit' '
+ test_must_fail git config --type int --default m some.key >out 2>error &&
+ grep "bad numeric config value" error &&
+ test_must_be_empty out
+'
+
test_expect_success '--replace-all does not invent newlines' '
q_to_tab >.git/config <<-\EOF &&
[abc]key
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 93a2f91f8a..e5a0d65caa 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -8,6 +8,8 @@ test_description='Test shared repository initialization'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Remove a default ACL from the test dir if possible.
@@ -25,6 +27,7 @@ test_expect_success 'shared = 0400 (faulty permission u-w)' '
for u in 002 022
do
test_expect_success POSIXPERM "shared=1 does not clear bits preset by umask $u" '
+ test_when_finished "rm -rf sub" &&
mkdir sub && (
cd sub &&
umask $u &&
@@ -42,16 +45,35 @@ do
;;
esac
'
- rm -rf sub
done
test_expect_success 'shared=all' '
- mkdir sub &&
- cd sub &&
git init --template= --shared=all &&
test 2 = $(git config core.sharedrepository)
'
+test_expect_failure 'template can set core.bare' '
+ test_when_finished "rm -rf subdir" &&
+ test_when_finished "rm -rf templates" &&
+ test_config core.bare true &&
+ umask 0022 &&
+ mkdir -p templates/ &&
+ cp .git/config templates/config &&
+ git init --template=templates subdir &&
+ test_path_exists subdir/HEAD
+'
+
+test_expect_success 'template can set core.bare but overridden by command line' '
+ test_when_finished "rm -rf subdir" &&
+ test_when_finished "rm -rf templates" &&
+ test_config core.bare true &&
+ umask 0022 &&
+ mkdir -p templates/ &&
+ cp .git/config templates/config &&
+ git init --no-bare --template=templates subdir &&
+ test_path_exists subdir/.git/HEAD
+'
+
test_expect_success POSIXPERM 'update-server-info honors core.sharedRepository' '
: > a1 &&
git add a1 &&
@@ -89,7 +111,7 @@ do
rm -f .git/info/refs &&
git update-server-info &&
actual="$(test_modebits .git/info/refs)" &&
- verbose test "x$actual" = "x-$y"
+ test "x$actual" = "x-$y"
'
@@ -99,7 +121,7 @@ do
rm -f .git/info/refs &&
git update-server-info &&
actual="$(test_modebits .git/info/refs)" &&
- verbose test "x$actual" = "x-$x"
+ test "x$actual" = "x-$x"
'
@@ -132,6 +154,7 @@ test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' '
'
test_expect_success POSIXPERM 'forced modes' '
+ test_when_finished "rm -rf new" &&
mkdir -p templates/hooks &&
echo update-server-info >templates/hooks/post-update &&
chmod +x templates/hooks/post-update &&
@@ -140,7 +163,8 @@ test_expect_success POSIXPERM 'forced modes' '
(
cd new &&
umask 002 &&
- git init --shared=0660 --template=templates &&
+ git init --shared=0660 --template=../templates &&
+ test_path_is_file .git/hooks/post-update &&
>frotz &&
git add frotz &&
git commit -a -m initial &&
@@ -173,6 +197,7 @@ test_expect_success POSIXPERM 'forced modes' '
'
test_expect_success POSIXPERM 'remote init does not use config from cwd' '
+ test_when_finished "rm -rf child.git" &&
git config core.sharedrepository 0666 &&
umask 0022 &&
git init --bare child.git &&
@@ -192,7 +217,7 @@ test_expect_success POSIXPERM 're-init respects core.sharedrepository (local)' '
'
test_expect_success POSIXPERM 're-init respects core.sharedrepository (remote)' '
- rm -rf child.git &&
+ test_when_finished "rm -rf child.git" &&
umask 0022 &&
git init --bare --shared=0666 child.git &&
test_path_is_missing child.git/foo &&
@@ -203,7 +228,7 @@ test_expect_success POSIXPERM 're-init respects core.sharedrepository (remote)'
'
test_expect_success POSIXPERM 'template can set core.sharedrepository' '
- rm -rf child.git &&
+ test_when_finished "rm -rf child.git" &&
umask 0022 &&
git config core.sharedrepository 0666 &&
cp .git/config templates/config &&
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 0acabb6d11..179474fa65 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -5,6 +5,7 @@
test_description='Test repository version check'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
@@ -27,7 +28,7 @@ test_expect_success 'setup' '
'
test_expect_success 'gitdir selection on normal repos' '
- echo $(test_oid version) >expect &&
+ test_oid version >expect &&
git config core.repositoryformatversion >actual &&
git -C test config core.repositoryformatversion >actual2 &&
test_cmp expect actual &&
@@ -36,7 +37,7 @@ test_expect_success 'gitdir selection on normal repos' '
test_expect_success 'gitdir selection on unsupported repo' '
# Make sure it would stop at test2, not trash
- test_expect_code 1 git -C test2 config core.repositoryformatversion >actual
+ test_expect_code 1 git -C test2 config core.repositoryformatversion
'
test_expect_success 'gitdir not required mode' '
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
index 335d3f3211..31b89dd969 100755
--- a/t/t1304-default-acl.sh
+++ b/t/t1304-default-acl.sh
@@ -9,6 +9,7 @@ test_description='Test repository with default ACL'
# => this must come before . ./test-lib.sh
umask 077
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# We need an arbitrary other user give permission to using ACLs. root
@@ -18,7 +19,7 @@ test_expect_success 'checking for a working acl setup' '
if setfacl -m d:m:rwx -m u:root:rwx . &&
getfacl . | grep user:root:rwx &&
touch should-have-readable-acl &&
- getfacl should-have-readable-acl | egrep "mask::?rw-"
+ getfacl should-have-readable-acl | grep -E "mask::?rw-"
then
test_set_prereq SETFACL
fi
@@ -34,7 +35,7 @@ check_perms_and_acl () {
getfacl "$1" > actual &&
grep -q "user:root:rwx" actual &&
grep -q "user:${LOGNAME}:rwx" actual &&
- egrep "mask::?r--" actual > /dev/null 2>&1 &&
+ grep -E "mask::?r--" actual > /dev/null 2>&1 &&
grep -q "group::---" actual || false
}
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index b38e158d3b..777648722c 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -58,6 +58,8 @@ test_expect_success 'setup default config' '
skin = false
nose = 1
horns
+ [value]
+ less
EOF
'
@@ -116,10 +118,53 @@ test_expect_success 'find value with the highest priority' '
check_config get_value case.baz "hask"
'
+test_expect_success 'return value for an existing key' '
+ test-tool config get lamb.chop >out 2>err &&
+ test_must_be_empty out &&
+ test_must_be_empty err
+'
+
+test_expect_success 'return value for value-less key' '
+ test-tool config get value.less >out 2>err &&
+ test_must_be_empty out &&
+ test_must_be_empty err
+'
+
+test_expect_success 'return value for a missing key' '
+ cat >expect <<-\EOF &&
+ Value not found for "missing.key"
+ EOF
+ test_expect_code 1 test-tool config get missing.key >actual 2>err &&
+ test_cmp actual expect &&
+ test_must_be_empty err
+'
+
+test_expect_success 'return value for a bad key: CONFIG_INVALID_KEY' '
+ cat >expect <<-\EOF &&
+ Key "fails.iskeychar.-" is invalid
+ EOF
+ test_expect_code 1 test-tool config get fails.iskeychar.- >actual 2>err &&
+ test_cmp actual expect &&
+ test_must_be_empty out
+'
+
+test_expect_success 'return value for a bad key: CONFIG_NO_SECTION_OR_NAME' '
+ cat >expect <<-\EOF &&
+ Key "keynosection" has no section
+ EOF
+ test_expect_code 1 test-tool config get keynosection >actual 2>err &&
+ test_cmp actual expect &&
+ test_must_be_empty out
+'
+
test_expect_success 'find integer value for a key' '
check_config get_int lamb.chop 65
'
+test_expect_success 'parse integer value during iteration' '
+ check_config git_config_int lamb.chop 65
+'
+
test_expect_success 'find string value for a key' '
check_config get_string case.baz hask &&
check_config expect_code 1 get_string case.ba "Value not found for \"case.ba\""
@@ -134,6 +179,11 @@ test_expect_success 'find integer if value is non parse-able' '
check_config expect_code 128 get_int lamb.head
'
+test_expect_success 'non parse-able integer value during iteration' '
+ check_config expect_code 128 git_config_int lamb.head 2>result &&
+ grep "fatal: bad numeric config value .* in file \.git/config" result
+'
+
test_expect_success 'find bool value for the entered key' '
check_config get_bool goat.head 1 &&
check_config get_bool goat.skin 0 &&
@@ -146,6 +196,71 @@ test_expect_success 'find multiple values' '
check_config get_value_multi case.baz sam bat hask
'
+test_NULL_in_multi () {
+ local op="$1" &&
+ local file="$2" &&
+
+ test_expect_success "$op: NULL value in config${file:+ in $file}" '
+ config="$file" &&
+ if test -z "$config"
+ then
+ config=.git/config &&
+ test_when_finished "mv $config.old $config" &&
+ mv "$config" "$config".old
+ fi &&
+
+ # Value-less in the middle of a list
+ cat >"$config" <<-\EOF &&
+ [a]key=x
+ [a]key
+ [a]key=y
+ EOF
+ case "$op" in
+ *_multi)
+ cat >expect <<-\EOF
+ x
+ (NULL)
+ y
+ EOF
+ ;;
+ *)
+ cat >expect <<-\EOF
+ y
+ EOF
+ ;;
+ esac &&
+ test-tool config "$op" a.key $file >actual &&
+ test_cmp expect actual &&
+
+ # Value-less at the end of a least
+ cat >"$config" <<-\EOF &&
+ [a]key=x
+ [a]key=y
+ [a]key
+ EOF
+ case "$op" in
+ *_multi)
+ cat >expect <<-\EOF
+ x
+ y
+ (NULL)
+ EOF
+ ;;
+ *)
+ cat >expect <<-\EOF
+ (NULL)
+ EOF
+ ;;
+ esac &&
+ test-tool config "$op" a.key $file >actual &&
+ test_cmp expect actual
+ '
+}
+
+test_NULL_in_multi "get_value_multi"
+test_NULL_in_multi "configset_get_value" "my.config"
+test_NULL_in_multi "configset_get_value_multi" "my.config"
+
test_expect_success 'find value from a configset' '
cat >config2 <<-\EOF &&
[case]
@@ -207,7 +322,7 @@ test_expect_success 'proper error on error in default config files' '
cp .git/config .git/config.old &&
test_when_finished "mv .git/config.old .git/config" &&
echo "[" >>.git/config &&
- echo "fatal: bad config line 34 in file .git/config" >expect &&
+ echo "fatal: bad config line 36 in file .git/config" >expect &&
test_expect_code 128 test-tool config get_value foo.bar 2>actual &&
test_cmp expect actual
'
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index cf58cf025c..4d66cd7f4a 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -1568,6 +1568,7 @@ test_expect_success 'transaction can create and delete' '
EOF
git update-ref --stdin <stdin >actual &&
printf "%s: ok\n" start commit start commit >expect &&
+ test_cmp expect actual &&
test_must_fail git show-ref --verify refs/heads/create-and-delete
'
@@ -1595,6 +1596,8 @@ test_expect_success 'transaction cannot restart ongoing transaction' '
commit
EOF
test_must_fail git update-ref --stdin <stdin >actual &&
+ printf "%s: ok\n" start >expect &&
+ test_cmp expect actual &&
test_must_fail git show-ref --verify refs/heads/restart
'
diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh
index 0c204089b8..c7745e1bf6 100755
--- a/t/t1401-symbolic-ref.sh
+++ b/t/t1401-symbolic-ref.sh
@@ -33,7 +33,8 @@ test_expect_success 'symbolic-ref refuses non-ref for HEAD' '
reset_to_sane
test_expect_success 'symbolic-ref refuses bare sha1' '
- test_must_fail git symbolic-ref HEAD $(git rev-parse HEAD)
+ rev=$(git rev-parse HEAD) &&
+ test_must_fail git symbolic-ref HEAD "$rev"
'
reset_to_sane
@@ -175,4 +176,52 @@ test_expect_success 'symbolic-ref allows top-level target for non-HEAD' '
test_cmp_rev top-level HEAD
'
+test_expect_success 'symbolic-ref pointing at another' '
+ git update-ref refs/heads/maint-2.37 HEAD &&
+ git symbolic-ref refs/heads/maint refs/heads/maint-2.37 &&
+ git checkout maint &&
+
+ git symbolic-ref HEAD >actual &&
+ echo refs/heads/maint-2.37 >expect &&
+ test_cmp expect actual &&
+
+ git symbolic-ref --no-recurse HEAD >actual &&
+ echo refs/heads/maint >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'symbolic-ref --short handles complex utf8 case' '
+ name="测试-加-增加-加-增加" &&
+ git symbolic-ref TEST_SYMREF "refs/heads/$name" &&
+ # In the real world, we saw problems with this case only
+ # when the locale includes UTF-8. Set it here to try to make things as
+ # hard as possible for us to pass, but in practice we should do the
+ # right thing regardless (and of course some platforms may not even
+ # have this locale).
+ LC_ALL=en_US.UTF-8 git symbolic-ref --short TEST_SYMREF >actual &&
+ echo "$name" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'symbolic-ref --short handles name with suffix' '
+ git symbolic-ref TEST_SYMREF "refs/remotes/origin/HEAD" &&
+ git symbolic-ref --short TEST_SYMREF >actual &&
+ echo "origin" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'symbolic-ref --short handles almost-matching name' '
+ git symbolic-ref TEST_SYMREF "refs/headsXfoo" &&
+ git symbolic-ref --short TEST_SYMREF >actual &&
+ echo "headsXfoo" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'symbolic-ref --short handles name with percent' '
+ git symbolic-ref TEST_SYMREF "refs/heads/%foo" &&
+ git symbolic-ref --short TEST_SYMREF >actual &&
+ echo "%foo" >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh
index 13c2b43bba..937ae0d733 100755
--- a/t/t1404-update-ref-errors.sh
+++ b/t/t1404-update-ref-errors.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='Test git update-ref error handling'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Create some references, perhaps run pack-refs --all, then try to
@@ -549,7 +551,6 @@ test_expect_success REFFILES 'no bogus intermediate values during delete' '
git update-ref $prefix/foo $C &&
git pack-refs --all &&
git update-ref $prefix/foo $D &&
- git for-each-ref $prefix >unchanged &&
# Now try to update the reference, but hold the `packed-refs` lock
# for a while to see what happens while the process is blocked:
: >.git/packed-refs.lock &&
diff --git a/t/t1408-packed-refs.sh b/t/t1408-packed-refs.sh
index 41ba1f1d7f..9469c79a58 100755
--- a/t/t1408-packed-refs.sh
+++ b/t/t1408-packed-refs.sh
@@ -5,6 +5,7 @@ test_description='packed-refs entries are covered by loose refs'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t1409-avoid-packing-refs.sh b/t/t1409-avoid-packing-refs.sh
index be12fb6350..f23c0152a8 100755
--- a/t/t1409-avoid-packing-refs.sh
+++ b/t/t1409-avoid-packing-refs.sh
@@ -2,6 +2,7 @@
test_description='avoid rewriting packed-refs unnecessarily'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Add an identifying mark to the packed-refs file header line. This
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index aa59954f6c..6c45965b1e 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -7,6 +7,7 @@ test_description='Test prune and reflog expiration'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_have () {
diff --git a/t/t1413-reflog-detach.sh b/t/t1413-reflog-detach.sh
index 934688a1ee..d2a4822d46 100755
--- a/t/t1413-reflog-detach.sh
+++ b/t/t1413-reflog-detach.sh
@@ -4,6 +4,7 @@ test_description='Test reflog interaction with detached HEAD'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
reset_state () {
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 27731722a5..b32ca798f9 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -5,6 +5,7 @@ test_description='reference transaction hooks'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t1419-exclude-refs.sh b/t/t1419-exclude-refs.sh
new file mode 100755
index 0000000000..5d8c86b657
--- /dev/null
+++ b/t/t1419-exclude-refs.sh
@@ -0,0 +1,122 @@
+#!/bin/sh
+
+test_description='test exclude_patterns functionality in main ref store'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+for_each_ref__exclude () {
+ GIT_TRACE2_PERF=1 test-tool ref-store main \
+ for-each-ref--exclude "$@" >actual.raw
+ cut -d ' ' -f 2 actual.raw
+}
+
+for_each_ref () {
+ git for-each-ref --format='%(refname)' "$@"
+}
+
+assert_jumps () {
+ local nr="$1"
+ local trace="$2"
+
+ grep -q "name:jumps_made value:$nr$" $trace
+}
+
+assert_no_jumps () {
+ ! assert_jumps ".*" "$1"
+}
+
+test_expect_success 'setup' '
+ test_commit --no-tag base &&
+ base="$(git rev-parse HEAD)" &&
+
+ for name in foo bar baz quux
+ do
+ for i in 1 2 3
+ do
+ echo "create refs/heads/$name/$i $base" || return 1
+ done || return 1
+ done >in &&
+ echo "delete refs/heads/main" >>in &&
+
+ git update-ref --stdin <in &&
+ git pack-refs --all
+'
+
+test_expect_success 'excluded region in middle' '
+ for_each_ref__exclude refs/heads refs/heads/foo >actual 2>perf &&
+ for_each_ref refs/heads/bar refs/heads/baz refs/heads/quux >expect &&
+
+ test_cmp expect actual &&
+ assert_jumps 1 perf
+'
+
+test_expect_success 'excluded region at beginning' '
+ for_each_ref__exclude refs/heads refs/heads/bar >actual 2>perf &&
+ for_each_ref refs/heads/baz refs/heads/foo refs/heads/quux >expect &&
+
+ test_cmp expect actual &&
+ assert_jumps 1 perf
+'
+
+test_expect_success 'excluded region at end' '
+ for_each_ref__exclude refs/heads refs/heads/quux >actual 2>perf &&
+ for_each_ref refs/heads/foo refs/heads/bar refs/heads/baz >expect &&
+
+ test_cmp expect actual &&
+ assert_jumps 1 perf
+'
+
+test_expect_success 'disjoint excluded regions' '
+ for_each_ref__exclude refs/heads refs/heads/bar refs/heads/quux >actual 2>perf &&
+ for_each_ref refs/heads/baz refs/heads/foo >expect &&
+
+ test_cmp expect actual &&
+ assert_jumps 2 perf
+'
+
+test_expect_success 'adjacent, non-overlapping excluded regions' '
+ for_each_ref__exclude refs/heads refs/heads/bar refs/heads/baz >actual 2>perf &&
+ for_each_ref refs/heads/foo refs/heads/quux >expect &&
+
+ test_cmp expect actual &&
+ assert_jumps 1 perf
+'
+
+test_expect_success 'overlapping excluded regions' '
+ for_each_ref__exclude refs/heads refs/heads/ba refs/heads/baz >actual 2>perf &&
+ for_each_ref refs/heads/foo refs/heads/quux >expect &&
+
+ test_cmp expect actual &&
+ assert_jumps 1 perf
+'
+
+test_expect_success 'several overlapping excluded regions' '
+ for_each_ref__exclude refs/heads \
+ refs/heads/bar refs/heads/baz refs/heads/foo >actual 2>perf &&
+ for_each_ref refs/heads/quux >expect &&
+
+ test_cmp expect actual &&
+ assert_jumps 1 perf
+'
+
+test_expect_success 'non-matching excluded section' '
+ for_each_ref__exclude refs/heads refs/heads/does/not/exist >actual 2>perf &&
+ for_each_ref >expect &&
+
+ test_cmp expect actual &&
+ assert_no_jumps perf
+'
+
+test_expect_success 'meta-characters are discarded' '
+ for_each_ref__exclude refs/heads "refs/heads/ba*" >actual 2>perf &&
+ for_each_ref >expect &&
+
+ test_cmp expect actual &&
+ assert_no_jumps perf
+'
+
+test_done
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index de0f6d5e7f..10a539158c 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -212,7 +212,7 @@ test_expect_success 'email without @ is okay' '
test_expect_success 'email with embedded > is not okay' '
git cat-file commit HEAD >basis &&
sed "s/@[a-z]/&>/" basis >bad-email &&
- new=$(git hash-object -t commit -w --stdin <bad-email) &&
+ new=$(git hash-object --literally -t commit -w --stdin <bad-email) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -223,7 +223,7 @@ test_expect_success 'email with embedded > is not okay' '
test_expect_success 'missing < email delimiter is reported nicely' '
git cat-file commit HEAD >basis &&
sed "s/<//" basis >bad-email-2 &&
- new=$(git hash-object -t commit -w --stdin <bad-email-2) &&
+ new=$(git hash-object --literally -t commit -w --stdin <bad-email-2) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -234,7 +234,7 @@ test_expect_success 'missing < email delimiter is reported nicely' '
test_expect_success 'missing email is reported nicely' '
git cat-file commit HEAD >basis &&
sed "s/[a-z]* <[^>]*>//" basis >bad-email-3 &&
- new=$(git hash-object -t commit -w --stdin <bad-email-3) &&
+ new=$(git hash-object --literally -t commit -w --stdin <bad-email-3) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -245,7 +245,7 @@ test_expect_success 'missing email is reported nicely' '
test_expect_success '> in name is reported' '
git cat-file commit HEAD >basis &&
sed "s/ </> </" basis >bad-email-4 &&
- new=$(git hash-object -t commit -w --stdin <bad-email-4) &&
+ new=$(git hash-object --literally -t commit -w --stdin <bad-email-4) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -258,7 +258,7 @@ test_expect_success 'integer overflow in timestamps is reported' '
git cat-file commit HEAD >basis &&
sed "s/^\\(author .*>\\) [0-9]*/\\1 18446744073709551617/" \
<basis >bad-timestamp &&
- new=$(git hash-object -t commit -w --stdin <bad-timestamp) &&
+ new=$(git hash-object --literally -t commit -w --stdin <bad-timestamp) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -269,7 +269,7 @@ test_expect_success 'integer overflow in timestamps is reported' '
test_expect_success 'commit with NUL in header' '
git cat-file commit HEAD >basis &&
sed "s/author ./author Q/" <basis | q_to_nul >commit-NUL-header &&
- new=$(git hash-object -t commit -w --stdin <commit-NUL-header) &&
+ new=$(git hash-object --literally -t commit -w --stdin <commit-NUL-header) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -292,7 +292,7 @@ test_expect_success 'tree object with duplicate entries' '
git cat-file tree $T &&
git cat-file tree $T
) |
- git hash-object -w -t tree --stdin
+ git hash-object --literally -w -t tree --stdin
) &&
test_must_fail git fsck 2>out &&
test_i18ngrep "error in tree .*contains duplicate file entries" out
@@ -426,7 +426,7 @@ test_expect_success 'tag with incorrect tag name & missing tagger' '
This is an invalid tag.
EOF
- tag=$(git hash-object -t tag -w --stdin <wrong-tag) &&
+ tag=$(git hash-object --literally -t tag -w --stdin <wrong-tag) &&
test_when_finished "remove_object $tag" &&
echo $tag >.git/refs/tags/wrong &&
test_when_finished "git update-ref -d refs/tags/wrong" &&
@@ -558,7 +558,7 @@ test_expect_success 'rev-list --verify-objects with commit graph (parent)' '
test_expect_success 'force fsck to ignore double author' '
git cat-file commit HEAD >basis &&
sed "s/^author .*/&,&/" <basis | tr , \\n >multiple-authors &&
- new=$(git hash-object -t commit -w --stdin <multiple-authors) &&
+ new=$(git hash-object --literally -t commit -w --stdin <multiple-authors) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
@@ -573,7 +573,7 @@ test_expect_success 'fsck notices blob entry pointing to null sha1' '
(git init null-blob &&
cd null-blob &&
sha=$(printf "100644 file$_bz$_bzoid" |
- git hash-object -w --stdin -t tree) &&
+ git hash-object --literally -w --stdin -t tree) &&
git fsck 2>out &&
test_i18ngrep "warning.*null sha1" out
)
@@ -583,12 +583,22 @@ test_expect_success 'fsck notices submodule entry pointing to null sha1' '
(git init null-commit &&
cd null-commit &&
sha=$(printf "160000 submodule$_bz$_bzoid" |
- git hash-object -w --stdin -t tree) &&
+ git hash-object --literally -w --stdin -t tree) &&
git fsck 2>out &&
test_i18ngrep "warning.*null sha1" out
)
'
+test_expect_success 'fsck notices excessively large tree entry name' '
+ git init large-name &&
+ (
+ cd large-name &&
+ test_commit a-long-name &&
+ git -c fsck.largePathname=warn:10 fsck 2>out &&
+ grep "warning.*large pathname" out
+ )
+'
+
while read name path pretty; do
while read mode type; do
: ${pretty:=$path}
@@ -648,7 +658,7 @@ test_expect_success 'NUL in commit' '
git commit --allow-empty -m "initial commitQNUL after message" &&
git cat-file commit HEAD >original &&
q_to_nul <original >munged &&
- git hash-object -w -t commit --stdin <munged >name &&
+ git hash-object --literally -w -t commit --stdin <munged >name &&
git branch bad $(cat name) &&
test_must_fail git -c fsck.nulInCommit=error fsck 2>warn.1 &&
@@ -794,8 +804,8 @@ test_expect_success 'fsck errors in packed objects' '
git cat-file commit HEAD >basis &&
sed "s/</one/" basis >one &&
sed "s/</foo/" basis >two &&
- one=$(git hash-object -t commit -w one) &&
- two=$(git hash-object -t commit -w two) &&
+ one=$(git hash-object --literally -t commit -w one) &&
+ two=$(git hash-object --literally -t commit -w two) &&
pack=$(
{
echo $one &&
@@ -989,10 +999,7 @@ test_expect_success 'fsck error and recovery on invalid object type' '
garbage_blob=$(git hash-object --stdin -w -t garbage --literally </dev/null) &&
- cat >err.expect <<-\EOF &&
- fatal: invalid object type
- EOF
- test_must_fail git fsck >out 2>err &&
+ test_must_fail git fsck 2>err &&
grep -e "^error" -e "^fatal" err >errors &&
test_line_count = 1 errors &&
grep "$garbage_blob: object is of unknown type '"'"'garbage'"'"':" err
@@ -1023,4 +1030,34 @@ test_expect_success 'fsck error on gitattributes with excessive size' '
test_cmp expected actual
'
+test_expect_success 'fsck detects problems in worktree index' '
+ test_when_finished "git worktree remove -f wt" &&
+ git worktree add wt &&
+
+ echo "this will be removed to break the worktree index" >wt/file &&
+ git -C wt add file &&
+ blob=$(git -C wt rev-parse :file) &&
+ remove_object $blob &&
+
+ test_must_fail git fsck --name-objects >actual 2>&1 &&
+ cat >expect <<-EOF &&
+ missing blob $blob (.git/worktrees/wt/index:file)
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'fsck reports problems in current worktree index without filename' '
+ test_when_finished "rm -f .git/index && git read-tree HEAD" &&
+ echo "this object will be removed to break current worktree index" >file &&
+ git add file &&
+ blob=$(git rev-parse :file) &&
+ remove_object $blob &&
+
+ test_must_fail git fsck --name-objects >actual 2>&1 &&
+ cat >expect <<-EOF &&
+ missing blob $blob (:file)
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1451-fsck-buffer.sh b/t/t1451-fsck-buffer.sh
new file mode 100755
index 0000000000..3413da40e4
--- /dev/null
+++ b/t/t1451-fsck-buffer.sh
@@ -0,0 +1,142 @@
+#!/bin/sh
+
+test_description='fsck on buffers without NUL termination
+
+The goal here is to make sure that the various fsck parsers never look
+past the end of the buffer they are given, even when encountering broken
+or truncated objects.
+
+We have to use "hash-object" for this because most code paths that read objects
+append an extra NUL for safety after the buffer. But hash-object, since it is
+reading straight from a file (and possibly even mmap-ing it) cannot always do
+so.
+
+These tests _might_ catch such overruns in normal use, but should be run with
+ASan or valgrind for more confidence.
+'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+# the general idea for tags and commits is to build up the "base" file
+# progressively, and then test new truncations on top of it.
+reset () {
+ test_expect_success 'reset input to empty' '
+ >base
+ '
+}
+
+add () {
+ content="$1"
+ type=${content%% *}
+ test_expect_success "add $type line" '
+ echo "$content" >>base
+ '
+}
+
+check () {
+ type=$1
+ fsck=$2
+ content=$3
+ test_expect_success "truncated $type ($fsck, \"$content\")" '
+ # do not pipe into hash-object here; we want to increase
+ # the chance that it uses a fixed-size buffer or mmap,
+ # and a pipe would be read into a strbuf.
+ {
+ cat base &&
+ echo "$content"
+ } >input &&
+ test_must_fail git hash-object -t "$type" input 2>err &&
+ grep "$fsck" err
+ '
+}
+
+test_expect_success 'create valid objects' '
+ git commit --allow-empty -m foo &&
+ commit=$(git rev-parse --verify HEAD) &&
+ tree=$(git rev-parse --verify HEAD^{tree})
+'
+
+reset
+check commit missingTree ""
+check commit missingTree "tr"
+check commit missingTree "tree"
+check commit badTreeSha1 "tree "
+check commit badTreeSha1 "tree 1234"
+add "tree $tree"
+
+# these expect missingAuthor because "parent" is optional
+check commit missingAuthor ""
+check commit missingAuthor "par"
+check commit missingAuthor "parent"
+check commit badParentSha1 "parent "
+check commit badParentSha1 "parent 1234"
+add "parent $commit"
+
+check commit missingAuthor ""
+check commit missingAuthor "au"
+check commit missingAuthor "author"
+ident_checks () {
+ check $1 missingEmail "$2 "
+ check $1 missingEmail "$2 name"
+ check $1 badEmail "$2 name <"
+ check $1 badEmail "$2 name <email"
+ check $1 missingSpaceBeforeDate "$2 name <email>"
+ check $1 badDate "$2 name <email> "
+ check $1 badDate "$2 name <email> 1234"
+ check $1 badTimezone "$2 name <email> 1234 "
+ check $1 badTimezone "$2 name <email> 1234 +"
+}
+ident_checks commit author
+add "author name <email> 1234 +0000"
+
+check commit missingCommitter ""
+check commit missingCommitter "co"
+check commit missingCommitter "committer"
+ident_checks commit committer
+add "committer name <email> 1234 +0000"
+
+reset
+check tag missingObject ""
+check tag missingObject "obj"
+check tag missingObject "object"
+check tag badObjectSha1 "object "
+check tag badObjectSha1 "object 1234"
+add "object $commit"
+
+check tag missingType ""
+check tag missingType "ty"
+check tag missingType "type"
+check tag badType "type "
+check tag badType "type com"
+add "type commit"
+
+check tag missingTagEntry ""
+check tag missingTagEntry "ta"
+check tag missingTagEntry "tag"
+check tag badTagName "tag "
+add "tag foo"
+
+check tag missingTagger ""
+check tag missingTagger "ta"
+check tag missingTagger "tagger"
+ident_checks tag tagger
+
+# trees are a binary format and can't use our earlier helpers
+test_expect_success 'truncated tree (short hash)' '
+ printf "100644 foo\0\1\1\1\1" >input &&
+ test_must_fail git hash-object -t tree input 2>err &&
+ grep badTree err
+'
+
+test_expect_success 'truncated tree (missing nul)' '
+ # these two things are indistinguishable to the parser. The important
+ # thing about this is example is that there are enough bytes to
+ # make up a hash, and that there is no NUL (and we confirm that the
+ # parser does not walk past the end of the buffer).
+ printf "100644 a long filename, or a hash with missing nul?" >input &&
+ test_must_fail git hash-object -t tree input 2>err &&
+ grep badTree err
+'
+
+test_done
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 81de584ea2..37ee5091b5 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -195,7 +195,7 @@ test_expect_success 'rev-parse --is-shallow-repository in non-shallow repo' '
'
test_expect_success 'rev-parse --show-object-format in repo' '
- echo "$(test_oid algo)" >expect &&
+ test_oid algo >expect &&
git rev-parse --show-object-format >actual &&
test_cmp expect actual &&
git rev-parse --show-object-format=storage >actual &&
diff --git a/t/t1501-work-tree.sh b/t/t1501-work-tree.sh
index b75558040f..ae6528aece 100755
--- a/t/t1501-work-tree.sh
+++ b/t/t1501-work-tree.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test separate work tree'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index de1d48f3ba..f0737593c3 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -3,13 +3,29 @@
test_description='test git rev-parse --parseopt'
. ./test-lib.sh
+check_invalid_long_option () {
+ spec="$1"
+ opt="$2"
+ test_expect_success "test --parseopt invalid switch $opt help output for $spec" '
+ {
+ cat <<-\EOF &&
+ error: unknown option `'${opt#--}\''
+ EOF
+ sed -e 1d -e \$d <"$TEST_DIRECTORY/t1502/$spec.help"
+ } >expect &&
+ test_expect_code 129 git rev-parse --parseopt -- $opt \
+ 2>output <"$TEST_DIRECTORY/t1502/$spec" &&
+ test_cmp expect output
+ '
+}
+
test_expect_success 'setup optionspec' '
sed -e "s/^|//" >optionspec <<\EOF
|some-command [options] <args>...
|
|some-command does foo and bar!
|--
-|h,help show the help
+|h,help! show the help
|
|foo some nifty option --foo
|bar= some cool option --bar with an argument
@@ -58,44 +74,8 @@ EOF
'
test_expect_success 'test --parseopt help output' '
- sed -e "s/^|//" >expect <<\END_EXPECT &&
-|cat <<\EOF
-|usage: some-command [options] <args>...
-|
-| some-command does foo and bar!
-|
-| -h, --help show the help
-| --foo some nifty option --foo
-| --bar ... some cool option --bar with an argument
-| -b, --baz a short and long option
-|
-|An option group Header
-| -C[...] option C with an optional argument
-| -d, --data[=...] short and long option with an optional argument
-|
-|Argument hints
-| -B <arg> short option required argument
-| --bar2 <arg> long option required argument
-| -e, --fuz <with-space>
-| short and long option required argument
-| -s[<some>] short option optional argument
-| --long[=<data>] long option optional argument
-| -g, --fluf[=<path>] short and long option optional argument
-| --longest <very-long-argument-hint>
-| a very long argument hint
-| --pair <key=value> with an equals sign in the hint
-| --aswitch help te=t contains? fl*g characters!`
-| --bswitch <hint> hint has trailing tab character
-| --cswitch switch has trailing tab character
-| --short-hint <a> with a one symbol hint
-|
-|Extras
-| --extra1 line above used to cause a segfault but no longer does
-|
-|EOF
-END_EXPECT
test_expect_code 129 git rev-parse --parseopt -- -h > output < optionspec &&
- test_cmp expect output
+ test_cmp "$TEST_DIRECTORY/t1502/optionspec.help" output
'
test_expect_success 'test --parseopt help output no switches' '
@@ -131,7 +111,7 @@ test_expect_success 'test --parseopt help-all output hidden switches' '
|
| some-command does foo and bar!
|
-| --hidden1 A hidden switch
+| --[no-]hidden1 A hidden switch
|
|EOF
END_EXPECT
@@ -140,41 +120,12 @@ END_EXPECT
'
test_expect_success 'test --parseopt invalid switch help output' '
- sed -e "s/^|//" >expect <<\END_EXPECT &&
-|error: unknown option `does-not-exist'\''
-|usage: some-command [options] <args>...
-|
-| some-command does foo and bar!
-|
-| -h, --help show the help
-| --foo some nifty option --foo
-| --bar ... some cool option --bar with an argument
-| -b, --baz a short and long option
-|
-|An option group Header
-| -C[...] option C with an optional argument
-| -d, --data[=...] short and long option with an optional argument
-|
-|Argument hints
-| -B <arg> short option required argument
-| --bar2 <arg> long option required argument
-| -e, --fuz <with-space>
-| short and long option required argument
-| -s[<some>] short option optional argument
-| --long[=<data>] long option optional argument
-| -g, --fluf[=<path>] short and long option optional argument
-| --longest <very-long-argument-hint>
-| a very long argument hint
-| --pair <key=value> with an equals sign in the hint
-| --aswitch help te=t contains? fl*g characters!`
-| --bswitch <hint> hint has trailing tab character
-| --cswitch switch has trailing tab character
-| --short-hint <a> with a one symbol hint
-|
-|Extras
-| --extra1 line above used to cause a segfault but no longer does
-|
-END_EXPECT
+ {
+ cat <<-\EOF &&
+ error: unknown option `does-not-exist'\''
+ EOF
+ sed -e 1d -e \$d <"$TEST_DIRECTORY/t1502/optionspec.help"
+ } >expect &&
test_expect_code 129 git rev-parse --parseopt -- --does-not-exist 1>/dev/null 2>output < optionspec &&
test_cmp expect output
'
@@ -288,7 +239,7 @@ test_expect_success 'test --parseopt help output: "wrapped" options normal "or:"
| [--another-option]
|cmd [--yet-another-option]
|--
- |h,help show the help
+ |h,help! show the help
EOF
sed -e "s/^|//" >expect <<-\END_EXPECT &&
@@ -302,14 +253,14 @@ test_expect_success 'test --parseopt help output: "wrapped" options normal "or:"
|EOF
END_EXPECT
- test_must_fail git rev-parse --parseopt -- -h >out <spec >actual &&
+ test_must_fail git rev-parse --parseopt -- -h <spec >actual &&
test_cmp expect actual
'
test_expect_success 'test --parseopt invalid opt-spec' '
test_write_lines x -- "=, x" >spec &&
echo "fatal: missing opt-spec before option flags" >expect &&
- test_must_fail git rev-parse --parseopt -- >out <spec 2>err &&
+ test_must_fail git rev-parse --parseopt -- <spec 2>err &&
test_cmp expect err
'
@@ -322,7 +273,7 @@ test_expect_success 'test --parseopt help output: multi-line blurb after empty l
|line
|blurb
|--
- |h,help show the help
+ |h,help! show the help
EOF
sed -e "s/^|//" >expect <<-\END_EXPECT &&
@@ -339,8 +290,36 @@ test_expect_success 'test --parseopt help output: multi-line blurb after empty l
|EOF
END_EXPECT
- test_must_fail git rev-parse --parseopt -- -h >out <spec >actual &&
+ test_must_fail git rev-parse --parseopt -- -h <spec >actual &&
test_cmp expect actual
'
+test_expect_success 'test --parseopt help output for optionspec-neg' '
+ test_expect_code 129 git rev-parse --parseopt -- \
+ -h >output <"$TEST_DIRECTORY/t1502/optionspec-neg" &&
+ test_cmp "$TEST_DIRECTORY/t1502/optionspec-neg.help" output
+'
+
+test_expect_success 'test --parseopt valid options for optionspec-neg' '
+ cat >expect <<-\EOF &&
+ set -- --foo --no-foo --no-bar --positive-only --no-negative --
+ EOF
+ git rev-parse --parseopt -- <"$TEST_DIRECTORY/t1502/optionspec-neg" >output \
+ --foo --no-foo --no-bar --positive-only --no-negative &&
+ test_cmp expect output
+'
+
+test_expect_success 'test --parseopt positivated option for optionspec-neg' '
+ cat >expect <<-\EOF &&
+ set -- --no-no-bar --no-no-bar --
+ EOF
+ git rev-parse --parseopt -- <"$TEST_DIRECTORY/t1502/optionspec-neg" >output \
+ --no-no-bar --bar &&
+ test_cmp expect output
+'
+
+check_invalid_long_option optionspec-neg --no-positive-only
+check_invalid_long_option optionspec-neg --negative
+check_invalid_long_option optionspec-neg --no-no-negative
+
test_done
diff --git a/t/t1502/.gitattributes b/t/t1502/.gitattributes
new file mode 100644
index 0000000000..562b12e16e
--- /dev/null
+++ b/t/t1502/.gitattributes
@@ -0,0 +1 @@
+* -whitespace
diff --git a/t/t1502/optionspec-neg b/t/t1502/optionspec-neg
new file mode 100644
index 0000000000..392f43eb0b
--- /dev/null
+++ b/t/t1502/optionspec-neg
@@ -0,0 +1,8 @@
+some-command [options] <args>...
+
+some-command does foo and bar!
+--
+foo can be negated
+no-bar can be positivated
+positive-only! cannot be negated
+no-negative! cannot be positivated
diff --git a/t/t1502/optionspec-neg.help b/t/t1502/optionspec-neg.help
new file mode 100644
index 0000000000..7a29f8cb03
--- /dev/null
+++ b/t/t1502/optionspec-neg.help
@@ -0,0 +1,12 @@
+cat <<\EOF
+usage: some-command [options] <args>...
+
+ some-command does foo and bar!
+
+ --[no-]foo can be negated
+ --no-bar can be positivated
+ --bar opposite of --no-bar
+ --positive-only cannot be negated
+ --no-negative cannot be positivated
+
+EOF
diff --git a/t/t1502/optionspec.help b/t/t1502/optionspec.help
new file mode 100755
index 0000000000..cbdd54d41b
--- /dev/null
+++ b/t/t1502/optionspec.help
@@ -0,0 +1,36 @@
+cat <<\EOF
+usage: some-command [options] <args>...
+
+ some-command does foo and bar!
+
+ -h, --help show the help
+ --[no-]foo some nifty option --foo
+ --[no-]bar ... some cool option --bar with an argument
+ -b, --[no-]baz a short and long option
+
+An option group Header
+ -C[...] option C with an optional argument
+ -d, --[no-]data[=...] short and long option with an optional argument
+
+Argument hints
+ -B <arg> short option required argument
+ --[no-]bar2 <arg> long option required argument
+ -e, --[no-]fuz <with-space>
+ short and long option required argument
+ -s[<some>] short option optional argument
+ --[no-]long[=<data>] long option optional argument
+ -g, --[no-]fluf[=<path>]
+ short and long option optional argument
+ --[no-]longest <very-long-argument-hint>
+ a very long argument hint
+ --[no-]pair <key=value>
+ with an equals sign in the hint
+ --[no-]aswitch help te=t contains? fl*g characters!`
+ --[no-]bswitch <hint> hint has trailing tab character
+ --[no-]cswitch switch has trailing tab character
+ --[no-]short-hint <a> with a one symbol hint
+
+Extras
+ --[no-]extra1 line above used to cause a segfault but no longer does
+
+EOF
diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh
index 0fafcf9dde..c1679e31d8 100755
--- a/t/t1504-ceiling-dirs.sh
+++ b/t/t1504-ceiling-dirs.sh
@@ -6,8 +6,12 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_prefix() {
- test_expect_success "$1" \
- "test '$2' = \"\$(git rev-parse --show-prefix)\""
+ local expect="$2" &&
+ test_expect_success "$1: git rev-parse --show-prefix is '$2'" '
+ echo "$expect" >expect &&
+ git rev-parse --show-prefix >actual &&
+ test_cmp expect actual
+ '
}
test_fail() {
diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
index c34714ffe3..b9af6b3ac0 100755
--- a/t/t1507-rev-parse-upstream.sh
+++ b/t/t1507-rev-parse-upstream.sh
@@ -5,6 +5,7 @@ test_description='test <branch>@{upstream} syntax'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
@@ -97,7 +98,8 @@ test_expect_success 'my-side@{u} resolves to correct commit' '
commit_subject my-side >actual &&
test_cmp expect actual &&
echo 5 >expect &&
- commit_subject my-side@{u} >actual
+ commit_subject my-side@{u} >actual &&
+ test_cmp expect actual
'
test_expect_success 'not-tracking@{u} fails' '
@@ -183,6 +185,11 @@ test_expect_success '@{u} error message when no upstream' '
test_cmp expect actual
'
+test_expect_success '@{u} silent error when no upstream' '
+ test_must_fail git rev-parse --verify --quiet @{u} 2>actual &&
+ test_must_be_empty actual
+'
+
test_expect_success 'branch@{u} error message with misspelt branch' '
cat >expect <<-EOF &&
fatal: no such branch: ${SQ}no-such-branch${SQ}
@@ -258,7 +265,8 @@ test_expect_success '@{reflog}-parsing does not look beyond colon' '
git add @{yesterday} &&
git commit -m "funny reflog file" &&
git hash-object @{yesterday} >expect &&
- git rev-parse HEAD:@{yesterday} >actual
+ git rev-parse HEAD:@{yesterday} >actual &&
+ test_cmp expect actual
'
test_expect_success '@{upstream}-parsing does not look beyond colon' '
@@ -266,7 +274,8 @@ test_expect_success '@{upstream}-parsing does not look beyond colon' '
git add @{upstream} &&
git commit -m "funny upstream file" &&
git hash-object @{upstream} >expect &&
- git rev-parse HEAD:@{upstream} >actual
+ git rev-parse HEAD:@{upstream} >actual &&
+ test_cmp expect actual
'
test_done
diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh
index 87a4286414..e841309d0e 100755
--- a/t/t1508-at-combinations.sh
+++ b/t/t1508-at-combinations.sh
@@ -4,6 +4,7 @@ test_description='test various @{X} syntax combinations together'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check() {
diff --git a/t/t1509-root-work-tree.sh b/t/t1509-root-work-tree.sh
index 553a3f601b..c799f5b6ac 100755
--- a/t/t1509-root-work-tree.sh
+++ b/t/t1509-root-work-tree.sh
@@ -221,7 +221,8 @@ test_expect_success 'setup' '
rm -rf /.git &&
echo "Initialized empty Git repository in /.git/" > expected &&
git init > result &&
- test_cmp expected result
+ test_cmp expected result &&
+ git config --global --add safe.directory /
'
test_vars 'auto gitdir, root' ".git" "/" ""
@@ -242,7 +243,7 @@ say "auto bare gitdir"
# DESTROYYYYY!!!!!
test_expect_success 'setup' '
rm -rf /refs /objects /info /hooks &&
- rm -f /expected /ls.expected /me /result &&
+ rm -f /HEAD /expected /ls.expected /me /result &&
cd / &&
echo "Initialized empty Git repository in /" > expected &&
git init --bare > result &&
@@ -255,4 +256,9 @@ test_expect_success 'go to /foo' 'cd /foo'
test_vars 'auto gitdir, root' "/" "" ""
+test_expect_success 'cleanup root' '
+ rm -rf /.git /refs /objects /info /hooks /branches /foo &&
+ rm -f /HEAD /config /description /expected /ls.expected /me /result
+'
+
test_done
diff --git a/t/t1514-rev-parse-push.sh b/t/t1514-rev-parse-push.sh
index d868a08110..a835a196aa 100755
--- a/t/t1514-rev-parse-push.sh
+++ b/t/t1514-rev-parse-push.sh
@@ -4,6 +4,7 @@ test_description='test <branch>@{push} syntax'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
resolve () {
diff --git a/t/t1600-index.sh b/t/t1600-index.sh
index 010989f90e..62e7fd1596 100755
--- a/t/t1600-index.sh
+++ b/t/t1600-index.sh
@@ -65,6 +65,37 @@ test_expect_success 'out of bounds index.version issues warning' '
)
'
+test_expect_success 'index.skipHash config option' '
+ rm -f .git/index &&
+ git -c index.skipHash=true add a &&
+ test_trailing_hash .git/index >hash &&
+ echo $(test_oid zero) >expect &&
+ test_cmp expect hash &&
+ git fsck &&
+
+ rm -f .git/index &&
+ git -c feature.manyFiles=true add a &&
+ test_trailing_hash .git/index >hash &&
+ cmp expect hash &&
+
+ rm -f .git/index &&
+ git -c feature.manyFiles=true \
+ -c index.skipHash=false add a &&
+ test_trailing_hash .git/index >hash &&
+ ! cmp expect hash &&
+
+ test_commit start &&
+ git -c protocol.file.allow=always submodule add ./ sub &&
+ git config index.skipHash false &&
+ git -C sub config index.skipHash true &&
+ rm -f .git/modules/sub/index &&
+ >sub/file &&
+ git -C sub add a &&
+ test_trailing_hash .git/modules/sub/index >hash &&
+ test_cmp expect hash &&
+ git -C sub fsck
+'
+
test_index_version () {
INDEX_VERSION_CONFIG=$1 &&
FEATURE_MANY_FILES=$2 &&
@@ -87,7 +118,7 @@ test_index_version () {
fi &&
git add a &&
echo $EXPECTED_OUTPUT_VERSION >expect &&
- test-tool index-version <.git/index >actual &&
+ git update-index --show-index-version >actual &&
test_cmp expect actual
)
}
diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh
index b4ab166369..a7b7263b35 100755
--- a/t/t1700-split-index.sh
+++ b/t/t1700-split-index.sh
@@ -43,7 +43,7 @@ test_expect_success 'enable split index' '
git config splitIndex.maxPercentChange 100 &&
git update-index --split-index &&
test-tool dump-split-index .git/index >actual &&
- indexversion=$(test-tool index-version <.git/index) &&
+ indexversion=$(git update-index --show-index-version) &&
# NEEDSWORK: Stop hard-coding checksums.
if test "$indexversion" = "4"
diff --git a/t/t1800-hook.sh b/t/t1800-hook.sh
index 43fcb7c0bf..8b0234cf2d 100755
--- a/t/t1800-hook.sh
+++ b/t/t1800-hook.sh
@@ -95,7 +95,7 @@ test_expect_success 'git hook run -- out-of-repo runs excluded' '
test_expect_success 'git -c core.hooksPath=<PATH> hook run' '
mkdir my-hooks &&
write_script my-hooks/test-hook <<-\EOF &&
- echo Hook ran $1 >>actual
+ echo Hook ran $1
EOF
cat >expect <<-\EOF &&
@@ -156,24 +156,32 @@ test_expect_success 'git hook run a hook with a bad shebang' '
mkdir bad-hooks &&
write_script bad-hooks/test-hook "/bad/path/no/spaces" </dev/null &&
- # TODO: We should emit the same (or at least a more similar)
- # error on MINGW (essentially Git for Windows) and all other
- # platforms.. See the OS-specific code in start_command()
- if test_have_prereq !MINGW
- then
- cat >expect <<-\EOF
- fatal: cannot run bad-hooks/test-hook: ...
- EOF
- else
- cat >expect <<-\EOF
- error: cannot spawn bad-hooks/test-hook: ...
- EOF
- fi &&
test_expect_code 1 git \
-c core.hooksPath=bad-hooks \
hook run test-hook >out 2>err &&
test_must_be_empty out &&
- sed -e "s/test-hook: .*/test-hook: .../" <err >actual &&
+
+ # TODO: We should emit the same (or at least a more similar)
+ # error on MINGW (essentially Git for Windows) and all other
+ # platforms.. See the OS-specific code in start_command()
+ grep -E "^(error|fatal): cannot (exec|spawn) .*bad-hooks/test-hook" err
+'
+
+test_expect_success 'stdin to hooks' '
+ write_script .git/hooks/test-hook <<-\EOF &&
+ echo BEGIN stdin
+ cat
+ echo END stdin
+ EOF
+
+ cat >expect <<-EOF &&
+ BEGIN stdin
+ hello
+ END stdin
+ EOF
+
+ echo hello >input &&
+ git hook run --to-stdin=input test-hook 2>actual &&
test_cmp expect actual
'
diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh
index b16d69ca4a..45dd1bc858 100755
--- a/t/t2004-checkout-cache-temp.sh
+++ b/t/t2004-checkout-cache-temp.sh
@@ -117,6 +117,26 @@ test_expect_success 'checkout all stages/one file to temporary files' '
test $(cat $s3) = tree3path1)
'
+test_expect_success '--stage=all implies --temp' '
+ rm -f path* .merge_* actual &&
+ git checkout-index --stage=all -- path1 &&
+ test_path_is_missing path1
+'
+
+test_expect_success 'overriding --stage=all resets implied --temp' '
+ rm -f path* .merge_* actual &&
+ git checkout-index --stage=all --stage=2 -- path1 &&
+ echo tree2path1 >expect &&
+ test_cmp expect path1
+'
+
+test_expect_success '--stage=all --no-temp is rejected' '
+ rm -f path* .merge_* actual &&
+ test_must_fail git checkout-index --stage=all --no-temp -- path1 2>err &&
+ grep -v "already exists" err &&
+ grep "options .--stage=all. and .--no-temp. cannot be used together" err
+'
+
test_expect_success 'checkout some stages/one file to temporary files' '
rm -f path* .merge_* actual &&
git checkout-index --stage=all --temp -- path2 >actual &&
diff --git a/t/t2005-checkout-index-symlinks.sh b/t/t2005-checkout-index-symlinks.sh
index 112682a45a..67d18cfa10 100755
--- a/t/t2005-checkout-index-symlinks.sh
+++ b/t/t2005-checkout-index-symlinks.sh
@@ -22,8 +22,10 @@ test_expect_success \
git checkout-index symlink &&
test -f symlink'
-test_expect_success \
-'the file must be the blob we added during the setup' '
-test "$(git hash-object -t blob symlink)" = $l'
+test_expect_success 'the file must be the blob we added during the setup' '
+ echo "$l" >expect &&
+ git hash-object -t blob symlink >actual &&
+ test_cmp expect actual
+'
test_done
diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh
index 1f6c4ed042..4b6372f4c3 100755
--- a/t/t2012-checkout-last.sh
+++ b/t/t2012-checkout-last.sh
@@ -5,6 +5,7 @@ test_description='checkout can switch to last branch and merge base'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2015-checkout-unborn.sh b/t/t2015-checkout-unborn.sh
index 9425aae639..fb0e13881c 100755
--- a/t/t2015-checkout-unborn.sh
+++ b/t/t2015-checkout-unborn.sh
@@ -9,11 +9,12 @@ TEST_PASSES_SANITIZE_LEAK=true
test_expect_success 'setup' '
mkdir parent &&
- (cd parent &&
- git init &&
- echo content >file &&
- git add file &&
- git commit -m base
+ (
+ cd parent &&
+ git init &&
+ echo content >file &&
+ git add file &&
+ git commit -m base
) &&
git fetch parent main:origin
'
diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh
index a5822e41af..747eb5563e 100755
--- a/t/t2016-checkout-patch.sh
+++ b/t/t2016-checkout-patch.sh
@@ -4,12 +4,6 @@ test_description='git checkout --patch'
. ./lib-patch-mode.sh
-if ! test_have_prereq ADD_I_USE_BUILTIN && ! test_have_prereq PERL
-then
- skip_all='skipping interactive add tests, PERL not set'
- test_done
-fi
-
test_expect_success 'setup' '
mkdir dir &&
echo parent > dir/foo &&
diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh
index 771c3c3c50..8581ad3437 100755
--- a/t/t2018-checkout-branch.sh
+++ b/t/t2018-checkout-branch.sh
@@ -3,6 +3,7 @@
test_description='checkout'
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Arguments: [!] <branch> <oid> [<checkout options>]
diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh
index 2c8c926b4d..9540588664 100755
--- a/t/t2019-checkout-ambiguous-ref.sh
+++ b/t/t2019-checkout-ambiguous-ref.sh
@@ -16,7 +16,7 @@ test_expect_success 'setup ambiguous refs' '
'
test_expect_success 'checkout ambiguous ref succeeds' '
- git checkout ambiguity >stdout 2>stderr
+ git checkout ambiguity 2>stderr
'
test_expect_success 'checkout produces ambiguity warning' '
@@ -37,7 +37,7 @@ test_expect_success 'checkout reports switch to branch' '
'
test_expect_success 'checkout vague ref succeeds' '
- git checkout vagueness >stdout 2>stderr &&
+ git checkout vagueness 2>stderr &&
test_set_prereq VAGUENESS_SUCCESS
'
diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh
index 713c3fa603..ecfacf0f7f 100755
--- a/t/t2021-checkout-overwrite.sh
+++ b/t/t2021-checkout-overwrite.sh
@@ -50,10 +50,13 @@ test_expect_success 'checkout commit with dir must not remove untracked a/b' '
test_expect_success SYMLINKS 'the symlink remained' '
- test_when_finished "rm a/b" &&
test -h a/b
'
+test_expect_success 'cleanup after previous symlink tests' '
+ rm a/b
+'
+
test_expect_success SYMLINKS 'checkout -f must not follow symlinks when removing entries' '
git checkout -f start &&
mkdir dir &&
@@ -66,4 +69,15 @@ test_expect_success SYMLINKS 'checkout -f must not follow symlinks when removing
test_path_is_file untracked/f
'
+test_expect_success 'checkout --overwrite-ignore should succeed if only ignored files in the way' '
+ git checkout -b df_conflict &&
+ test_commit contents some_dir &&
+ git checkout start &&
+ mkdir some_dir &&
+ echo autogenerated information >some_dir/ignore &&
+ echo ignore >.git/info/exclude &&
+ git checkout --overwrite-ignore df_conflict &&
+ test_path_is_file some_dir
+'
+
test_done
diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh
index 4a1c901456..74049a9812 100755
--- a/t/t2024-checkout-dwim.sh
+++ b/t/t2024-checkout-dwim.sh
@@ -305,10 +305,13 @@ test_expect_success 'loosely defined local base branch is reported correctly' '
test_config branch.strict.merge refs/heads/main &&
test_config branch.loose.merge main &&
- git checkout strict | sed -e "s/strict/BRANCHNAME/g" >expect &&
+ git checkout strict >expect.raw 2>&1 &&
+ sed -e "s/strict/BRANCHNAME/g" <expect.raw >expect &&
status_uno_is_clean &&
- git checkout loose | sed -e "s/loose/BRANCHNAME/g" >actual &&
+ git checkout loose >actual.raw 2>&1 &&
+ sed -e "s/loose/BRANCHNAME/g" <actual.raw >actual &&
status_uno_is_clean &&
+ grep BRANCHNAME actual &&
test_cmp expect actual
'
diff --git a/t/t2025-checkout-no-overlay.sh b/t/t2025-checkout-no-overlay.sh
index 8f13341cf8..3832c3de81 100755
--- a/t/t2025-checkout-no-overlay.sh
+++ b/t/t2025-checkout-no-overlay.sh
@@ -2,6 +2,7 @@
test_description='checkout --no-overlay <tree-ish> -- <pathspec>'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2027-checkout-track.sh b/t/t2027-checkout-track.sh
index dca35aa3e3..a8bbc60954 100755
--- a/t/t2027-checkout-track.sh
+++ b/t/t2027-checkout-track.sh
@@ -5,6 +5,7 @@ test_description='tests for git branch --track'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2060-switch.sh b/t/t2060-switch.sh
index 5a7caf958c..e247a4735b 100755
--- a/t/t2060-switch.sh
+++ b/t/t2060-switch.sh
@@ -146,4 +146,33 @@ test_expect_success 'tracking info copied with autoSetupMerge=inherit' '
test_cmp_config "" --default "" branch.main2.merge
'
+test_expect_success 'switch back when temporarily detached and checked out elsewhere ' '
+ test_when_finished "
+ git worktree remove wt1 ||:
+ git worktree remove wt2 ||:
+ git checkout - ||:
+ git branch -D shared ||:
+ " &&
+ git checkout -b shared &&
+ test_commit shared-first &&
+ HASH1=$(git rev-parse --verify HEAD) &&
+ test_commit shared-second &&
+ test_commit shared-third &&
+ HASH2=$(git rev-parse --verify HEAD) &&
+ git worktree add wt1 -f shared &&
+ git -C wt1 bisect start &&
+ git -C wt1 bisect good $HASH1 &&
+ git -C wt1 bisect bad $HASH2 &&
+ git worktree add wt2 -f shared &&
+ git -C wt2 bisect start &&
+ git -C wt2 bisect good $HASH1 &&
+ git -C wt2 bisect bad $HASH2 &&
+ # we test in both worktrees to ensure that works
+ # as expected with "first" and "next" worktrees
+ test_must_fail git -C wt1 switch shared &&
+ git -C wt1 switch --ignore-other-worktrees shared &&
+ test_must_fail git -C wt2 switch shared &&
+ git -C wt2 switch --ignore-other-worktrees shared
+'
+
test_done
diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh
index 7c43ddf1d9..c5d19dd973 100755
--- a/t/t2070-restore.sh
+++ b/t/t2070-restore.sh
@@ -137,4 +137,20 @@ test_expect_success 'restore --staged invalidates cache tree for deletions' '
test_must_fail git rev-parse HEAD:new1
'
+test_expect_success 'restore with merge options rejects --staged' '
+ for opts in \
+ "--staged --ours" \
+ "--staged --theirs" \
+ "--staged --merge" \
+ "--staged --conflict=diff3" \
+ "--staged --worktree --ours" \
+ "--staged --worktree --theirs" \
+ "--staged --worktree --merge" \
+ "--staged --worktree --conflict=zdiff3"
+ do
+ test_must_fail git restore $opts . 2>err &&
+ grep "cannot be used with --staged" err || return
+ done
+'
+
test_done
diff --git a/t/t2104-update-index-skip-worktree.sh b/t/t2104-update-index-skip-worktree.sh
index b8686aabd3..0bab134d71 100755
--- a/t/t2104-update-index-skip-worktree.sh
+++ b/t/t2104-update-index-skip-worktree.sh
@@ -39,7 +39,7 @@ test_expect_success 'setup' '
'
test_expect_success 'index is at version 2' '
- test "$(test-tool index-version < .git/index)" = 2
+ test "$(git update-index --show-index-version)" = 2
'
test_expect_success 'update-index --skip-worktree' '
@@ -48,7 +48,7 @@ test_expect_success 'update-index --skip-worktree' '
'
test_expect_success 'index is at version 3 after having some skip-worktree entries' '
- test "$(test-tool index-version < .git/index)" = 3
+ test "$(git update-index --show-index-version)" = 3
'
test_expect_success 'ls-files -t' '
@@ -61,7 +61,7 @@ test_expect_success 'update-index --no-skip-worktree' '
'
test_expect_success 'index version is back to 2 when there is no skip-worktree entry' '
- test "$(test-tool index-version < .git/index)" = 2
+ test "$(git update-index --show-index-version)" = 2
'
test_done
diff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh
index 07e6de84e6..22f4c92399 100755
--- a/t/t2107-update-index-basic.sh
+++ b/t/t2107-update-index-basic.sh
@@ -83,7 +83,7 @@ test_expect_success '.lock files cleaned up' '
cd repo &&
git config core.worktree ../../worktree &&
# --refresh triggers late setup_work_tree,
- # active_cache_changed is zero, rollback_lock_file fails
+ # the_index.cache_changed is zero, rollback_lock_file fails
git update-index --refresh --verbose >out &&
test_must_be_empty out &&
! test -f .git/index.lock
@@ -111,4 +111,35 @@ test_expect_success '--chmod=+x and chmod=-x in the same argument list' '
test_cmp expect actual
'
+test_expect_success '--index-version' '
+ git commit --allow-empty -m snap &&
+ git reset --hard &&
+ git rm -f -r --cached . &&
+
+ # The default index version is 2 --- update this test
+ # when you change it in the code
+ git update-index --show-index-version >actual &&
+ echo 2 >expect &&
+ test_cmp expect actual &&
+
+ # The next test wants us to be using version 2
+ git update-index --index-version 2 &&
+
+ git update-index --index-version 4 --verbose >actual &&
+ echo "index-version: was 2, set to 4" >expect &&
+ test_cmp expect actual &&
+
+ git update-index --index-version 4 --verbose >actual &&
+ echo "index-version: was 4, set to 4" >expect &&
+ test_cmp expect actual &&
+
+ git update-index --index-version 2 --verbose >actual &&
+ echo "index-version: was 4, set to 2" >expect &&
+ test_cmp expect actual &&
+
+ # non-verbose should be silent
+ git update-index --index-version 4 >actual &&
+ test_must_be_empty actual
+'
+
test_done
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
index be394f1131..c01492f33f 100755
--- a/t/t2200-add-update.sh
+++ b/t/t2200-add-update.sh
@@ -197,4 +197,15 @@ test_expect_success '"add -u non-existent" should fail' '
! grep "non-existent" actual
'
+test_expect_success '"commit -a" implies "add -u" if index becomes empty' '
+ git rm -rf \* &&
+ git commit -m clean-slate &&
+ test_commit file1 &&
+ rm file1.t &&
+ test_tick &&
+ git commit -a -m remove &&
+ git ls-tree HEAD: >out &&
+ test_must_be_empty out
+'
+
test_done
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index d587e0b20d..df4aff7825 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -121,7 +121,8 @@ test_expect_success '"add" worktree creating new branch' '
test_expect_success 'die the same branch is already checked out' '
(
cd here &&
- test_must_fail git checkout newmain
+ test_must_fail git checkout newmain 2>actual &&
+ grep "already used by worktree at" actual
)
'
@@ -298,17 +299,24 @@ test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' '
test_must_fail git -C mish/mash symbolic-ref HEAD
'
-test_expect_success '"add" -b/-B mutually exclusive' '
- test_must_fail git worktree add -b poodle -B poodle bamboo main
-'
-
-test_expect_success '"add" -b/--detach mutually exclusive' '
- test_must_fail git worktree add -b poodle --detach bamboo main
-'
+# Helper function to test mutually exclusive options.
+#
+# Note: Quoted arguments containing spaces are not supported.
+test_wt_add_excl () {
+ local opts="$*" &&
+ test_expect_success "'worktree add' with '$opts' has mutually exclusive options" '
+ test_must_fail git worktree add $opts 2>actual &&
+ grep -E "fatal:( options)? .* cannot be used together" actual
+ '
+}
-test_expect_success '"add" -B/--detach mutually exclusive' '
- test_must_fail git worktree add -B poodle --detach bamboo main
-'
+test_wt_add_excl -b poodle -B poodle bamboo main
+test_wt_add_excl -b poodle --detach bamboo main
+test_wt_add_excl -B poodle --detach bamboo main
+test_wt_add_excl --orphan --detach bamboo
+test_wt_add_excl --orphan --no-checkout bamboo
+test_wt_add_excl --orphan bamboo main
+test_wt_add_excl --orphan -b bamboo wtdir/ main
test_expect_success '"add -B" fails if the branch is checked out' '
git rev-parse newmain >before &&
@@ -326,10 +334,111 @@ test_expect_success 'add -B' '
'
test_expect_success 'add --quiet' '
+ test_when_finished "git worktree remove -f -f another-worktree" &&
git worktree add --quiet another-worktree main 2>actual &&
test_must_be_empty actual
'
+test_expect_success 'add --quiet -b' '
+ test_when_finished "git branch -D quietnewbranch" &&
+ test_when_finished "git worktree remove -f -f another-worktree" &&
+ git worktree add --quiet -b quietnewbranch another-worktree 2>actual &&
+ test_must_be_empty actual
+'
+
+test_expect_success '"add --orphan"' '
+ test_when_finished "git worktree remove -f -f orphandir" &&
+ git worktree add --orphan -b neworphan orphandir &&
+ echo refs/heads/neworphan >expected &&
+ git -C orphandir symbolic-ref HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '"add --orphan (no -b)"' '
+ test_when_finished "git worktree remove -f -f neworphan" &&
+ git worktree add --orphan neworphan &&
+ echo refs/heads/neworphan >expected &&
+ git -C neworphan symbolic-ref HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '"add --orphan --quiet"' '
+ test_when_finished "git worktree remove -f -f orphandir" &&
+ git worktree add --quiet --orphan -b neworphan orphandir 2>log.actual &&
+ test_must_be_empty log.actual &&
+ echo refs/heads/neworphan >expected &&
+ git -C orphandir symbolic-ref HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '"add --orphan" fails if the branch already exists' '
+ test_when_finished "git branch -D existingbranch" &&
+ git worktree add -b existingbranch orphandir main &&
+ git worktree remove orphandir &&
+ test_must_fail git worktree add --orphan -b existingbranch orphandir
+'
+
+test_expect_success '"add --orphan" with empty repository' '
+ test_when_finished "rm -rf empty_repo" &&
+ echo refs/heads/newbranch >expected &&
+ GIT_DIR="empty_repo" git init --bare &&
+ git -C empty_repo worktree add --orphan -b newbranch worktreedir &&
+ git -C empty_repo/worktreedir symbolic-ref HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '"add" worktree with orphan branch and lock' '
+ git worktree add --lock --orphan -b orphanbr orphan-with-lock &&
+ test_when_finished "git worktree unlock orphan-with-lock || :" &&
+ test -f .git/worktrees/orphan-with-lock/locked
+'
+
+test_expect_success '"add" worktree with orphan branch, lock, and reason' '
+ lock_reason="why not" &&
+ git worktree add --detach --lock --reason "$lock_reason" orphan-with-lock-reason main &&
+ test_when_finished "git worktree unlock orphan-with-lock-reason || :" &&
+ test -f .git/worktrees/orphan-with-lock-reason/locked &&
+ echo "$lock_reason" >expect &&
+ test_cmp expect .git/worktrees/orphan-with-lock-reason/locked
+'
+
+# Note: Quoted arguments containing spaces are not supported.
+test_wt_add_orphan_hint () {
+ local context="$1" &&
+ local use_branch=$2 &&
+ shift 2 &&
+ local opts="$*" &&
+ test_expect_success "'worktree add' show orphan hint in bad/orphan HEAD w/ $context" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (cd repo && test_commit commit) &&
+ git -C repo switch --orphan noref &&
+ test_must_fail git -C repo worktree add $opts foobar/ 2>actual &&
+ ! grep "error: unknown switch" actual &&
+ grep "hint: If you meant to create a worktree containing a new orphan branch" actual &&
+ if [ $use_branch -eq 1 ]
+ then
+ grep -E "^hint: +git worktree add --orphan -b [^ ]+ [^ ]+$" actual
+ else
+ grep -E "^hint: +git worktree add --orphan [^ ]+$" actual
+ fi
+
+ '
+}
+
+test_wt_add_orphan_hint 'no opts' 0
+test_wt_add_orphan_hint '-b' 1 -b foobar_branch
+test_wt_add_orphan_hint '-B' 1 -B foobar_branch
+
+test_expect_success "'worktree add' doesn't show orphan hint in bad/orphan HEAD w/ --quiet" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (cd repo && test_commit commit) &&
+ test_must_fail git -C repo worktree add --quiet foobar_branch foobar/ 2>actual &&
+ ! grep "error: unknown switch" actual &&
+ ! grep "hint: If you meant to create a worktree containing a new orphan branch" actual
+'
+
test_expect_success 'local clone from linked checkout' '
git clone --local here here-clone &&
( cd here-clone && git fsck )
@@ -446,6 +555,14 @@ setup_remote_repo () {
)
}
+test_expect_success '"add" <path> <remote/branch> w/ no HEAD' '
+ test_when_finished rm -rf repo_upstream repo_local foo &&
+ setup_remote_repo repo_upstream repo_local &&
+ git -C repo_local config --bool core.bare true &&
+ git -C repo_local branch -D main &&
+ git -C repo_local worktree add ./foo repo_upstream/foo
+'
+
test_expect_success '--no-track avoids setting up tracking' '
test_when_finished rm -rf repo_upstream repo_local foo &&
setup_remote_repo repo_upstream repo_local &&
@@ -528,6 +645,35 @@ test_expect_success 'git worktree add --guess-remote sets up tracking' '
test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
)
'
+test_expect_success 'git worktree add --guess-remote sets up tracking (quiet)' '
+ test_when_finished rm -rf repo_a repo_b foo &&
+ setup_remote_repo repo_a repo_b &&
+ (
+ cd repo_b &&
+ git worktree add --quiet --guess-remote ../foo 2>actual &&
+ test_must_be_empty actual
+ ) &&
+ (
+ cd foo &&
+ test_branch_upstream foo repo_a foo &&
+ test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
+ )
+'
+
+test_expect_success 'git worktree --no-guess-remote (quiet)' '
+ test_when_finished rm -rf repo_a repo_b foo &&
+ setup_remote_repo repo_a repo_b &&
+ (
+ cd repo_b &&
+ git worktree add --quiet --no-guess-remote ../foo
+ ) &&
+ (
+ cd foo &&
+ test_must_fail git config "branch.foo.remote" &&
+ test_must_fail git config "branch.foo.merge" &&
+ test_cmp_rev ! refs/remotes/repo_a/foo refs/heads/foo
+ )
+'
test_expect_success 'git worktree add with worktree.guessRemote sets up tracking' '
test_when_finished rm -rf repo_a repo_b foo &&
@@ -560,6 +706,348 @@ test_expect_success 'git worktree --no-guess-remote option overrides config' '
)
'
+test_dwim_orphan () {
+ local info_text="No possible source branch, inferring '--orphan'" &&
+ local fetch_error_text="fatal: No local or remote refs exist despite at least one remote" &&
+ local orphan_hint="hint: If you meant to create a worktree containing a new orphan branch" &&
+ local invalid_ref_regex="^fatal: invalid reference: " &&
+ local bad_combo_regex="^fatal: '[-a-z]*' and '[-a-z]*' cannot be used together" &&
+
+ local git_ns="repo" &&
+ local dashc_args="-C $git_ns" &&
+ local use_cd=0 &&
+
+ local bad_head=0 &&
+ local empty_repo=1 &&
+ local local_ref=0 &&
+ local use_quiet=0 &&
+ local remote=0 &&
+ local remote_ref=0 &&
+ local use_detach=0 &&
+ local use_new_branch=0 &&
+
+ local outcome="$1" &&
+ local outcome_text &&
+ local success &&
+ shift &&
+ local args="" &&
+ local context="" &&
+ case "$outcome" in
+ "infer")
+ success=1 &&
+ outcome_text='"add" DWIM infer --orphan'
+ ;;
+ "no_infer")
+ success=1 &&
+ outcome_text='"add" DWIM doesnt infer --orphan'
+ ;;
+ "fetch_error")
+ success=0 &&
+ outcome_text='"add" error need fetch'
+ ;;
+ "fatal_orphan_bad_combo")
+ success=0 &&
+ outcome_text='"add" error inferred "--orphan" gives illegal opts combo'
+ ;;
+ "warn_bad_head")
+ success=0 &&
+ outcome_text='"add" error, warn on bad HEAD, hint use orphan'
+ ;;
+ *)
+ echo "test_dwim_orphan(): invalid outcome: '$outcome'" >&2 &&
+ return 1
+ ;;
+ esac &&
+ while [ $# -gt 0 ]
+ do
+ case "$1" in
+ # How and from where to create the worktree
+ "-C_repo")
+ use_cd=0 &&
+ git_ns="repo" &&
+ dashc_args="-C $git_ns" &&
+ context="$context, 'git -C repo'"
+ ;;
+ "-C_wt")
+ use_cd=0 &&
+ git_ns="wt" &&
+ dashc_args="-C $git_ns" &&
+ context="$context, 'git -C wt'"
+ ;;
+ "cd_repo")
+ use_cd=1 &&
+ git_ns="repo" &&
+ dashc_args="" &&
+ context="$context, 'cd repo && git'"
+ ;;
+ "cd_wt")
+ use_cd=1 &&
+ git_ns="wt" &&
+ dashc_args="" &&
+ context="$context, 'cd wt && git'"
+ ;;
+
+ # Bypass the "pull first" warning
+ "force")
+ args="$args --force" &&
+ context="$context, --force"
+ ;;
+
+ # Try to use remote refs when DWIM
+ "guess_remote")
+ args="$args --guess-remote" &&
+ context="$context, --guess-remote"
+ ;;
+ "no_guess_remote")
+ args="$args --no-guess-remote" &&
+ context="$context, --no-guess-remote"
+ ;;
+
+ # Whether there is at least one local branch present
+ "local_ref")
+ empty_repo=0 &&
+ local_ref=1 &&
+ context="$context, >=1 local branches"
+ ;;
+ "no_local_ref")
+ empty_repo=0 &&
+ context="$context, 0 local branches"
+ ;;
+
+ # Whether the HEAD points at a valid ref (skip this opt when no refs)
+ "good_head")
+ # requires: local_ref
+ context="$context, valid HEAD"
+ ;;
+ "bad_head")
+ bad_head=1 &&
+ context="$context, invalid (or orphan) HEAD"
+ ;;
+
+ # Whether the code path is tested with the base add command, -b, or --detach
+ "no_-b")
+ use_new_branch=0 &&
+ context="$context, no --branch"
+ ;;
+ "-b")
+ use_new_branch=1 &&
+ context="$context, --branch"
+ ;;
+ "detach")
+ use_detach=1 &&
+ context="$context, --detach"
+ ;;
+
+ # Whether to check that all output is suppressed (except errors)
+ # or that the output is as expected
+ "quiet")
+ use_quiet=1 &&
+ args="$args --quiet" &&
+ context="$context, --quiet"
+ ;;
+ "no_quiet")
+ use_quiet=0 &&
+ context="$context, no --quiet (expect output)"
+ ;;
+
+ # Whether there is at least one remote attached to the repo
+ "remote")
+ empty_repo=0 &&
+ remote=1 &&
+ context="$context, >=1 remotes"
+ ;;
+ "no_remote")
+ empty_repo=0 &&
+ remote=0 &&
+ context="$context, 0 remotes"
+ ;;
+
+ # Whether there is at least one valid remote ref
+ "remote_ref")
+ # requires: remote
+ empty_repo=0 &&
+ remote_ref=1 &&
+ context="$context, >=1 fetched remote branches"
+ ;;
+ "no_remote_ref")
+ empty_repo=0 &&
+ remote_ref=0 &&
+ context="$context, 0 fetched remote branches"
+ ;;
+
+ # Options or flags that become illegal when --orphan is inferred
+ "no_checkout")
+ args="$args --no-checkout" &&
+ context="$context, --no-checkout"
+ ;;
+ "track")
+ args="$args --track" &&
+ context="$context, --track"
+ ;;
+
+ # All other options are illegal
+ *)
+ echo "test_dwim_orphan(): invalid arg: '$1'" >&2 &&
+ return 1
+ ;;
+ esac &&
+ shift
+ done &&
+ context="${context#', '}" &&
+ if [ $use_new_branch -eq 1 ]
+ then
+ args="$args -b foo"
+ elif [ $use_detach -eq 1 ]
+ then
+ args="$args --detach"
+ else
+ context="DWIM (no --branch), $context"
+ fi &&
+ if [ $empty_repo -eq 1 ]
+ then
+ context="empty repo, $context"
+ fi &&
+ args="$args ../foo" &&
+ context="${context%', '}" &&
+ test_expect_success "$outcome_text w/ $context" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ if [ $local_ref -eq 1 ] && [ "$git_ns" = "repo" ]
+ then
+ (cd repo && test_commit commit) &&
+ if [ $bad_head -eq 1 ]
+ then
+ git -C repo symbolic-ref HEAD refs/heads/badbranch
+ fi
+ elif [ $local_ref -eq 1 ] && [ "$git_ns" = "wt" ]
+ then
+ test_when_finished "git -C repo worktree remove -f ../wt" &&
+ git -C repo worktree add --orphan -b main ../wt &&
+ (cd wt && test_commit commit) &&
+ if [ $bad_head -eq 1 ]
+ then
+ git -C wt symbolic-ref HEAD refs/heads/badbranch
+ fi
+ elif [ $local_ref -eq 0 ] && [ "$git_ns" = "wt" ]
+ then
+ test_when_finished "git -C repo worktree remove -f ../wt" &&
+ git -C repo worktree add --orphan -b orphanbranch ../wt
+ fi &&
+
+ if [ $remote -eq 1 ]
+ then
+ test_when_finished "rm -rf upstream" &&
+ git init upstream &&
+ (cd upstream && test_commit commit) &&
+ git -C upstream switch -c foo &&
+ git -C repo remote add upstream ../upstream
+ fi &&
+
+ if [ $remote_ref -eq 1 ]
+ then
+ git -C repo fetch
+ fi &&
+ if [ $success -eq 1 ]
+ then
+ test_when_finished git -C repo worktree remove ../foo
+ fi &&
+ (
+ if [ $use_cd -eq 1 ]
+ then
+ cd $git_ns
+ fi &&
+ if [ "$outcome" = "infer" ]
+ then
+ git $dashc_args worktree add $args 2>actual &&
+ if [ $use_quiet -eq 1 ]
+ then
+ test_must_be_empty actual
+ else
+ grep "$info_text" actual
+ fi
+ elif [ "$outcome" = "no_infer" ]
+ then
+ git $dashc_args worktree add $args 2>actual &&
+ if [ $use_quiet -eq 1 ]
+ then
+ test_must_be_empty actual
+ else
+ ! grep "$info_text" actual
+ fi
+ elif [ "$outcome" = "fetch_error" ]
+ then
+ test_must_fail git $dashc_args worktree add $args 2>actual &&
+ grep "$fetch_error_text" actual
+ elif [ "$outcome" = "fatal_orphan_bad_combo" ]
+ then
+ test_must_fail git $dashc_args worktree add $args 2>actual &&
+ if [ $use_quiet -eq 1 ]
+ then
+ ! grep "$info_text" actual
+ else
+ grep "$info_text" actual
+ fi &&
+ grep "$bad_combo_regex" actual
+ elif [ "$outcome" = "warn_bad_head" ]
+ then
+ test_must_fail git $dashc_args worktree add $args 2>actual &&
+ if [ $use_quiet -eq 1 ]
+ then
+ grep "$invalid_ref_regex" actual &&
+ ! grep "$orphan_hint" actual
+ else
+ headpath=$(git $dashc_args rev-parse --path-format=absolute --git-path HEAD) &&
+ headcontents=$(cat "$headpath") &&
+ grep "HEAD points to an invalid (or orphaned) reference" actual &&
+ grep "HEAD path: .$headpath." actual &&
+ grep "HEAD contents: .$headcontents." actual &&
+ grep "$orphan_hint" actual &&
+ ! grep "$info_text" actual
+ fi &&
+ grep "$invalid_ref_regex" actual
+ else
+ # Unreachable
+ false
+ fi
+ ) &&
+ if [ $success -ne 1 ]
+ then
+ test_path_is_missing foo
+ fi
+ '
+}
+
+for quiet_mode in "no_quiet" "quiet"
+do
+ for changedir_type in "cd_repo" "cd_wt" "-C_repo" "-C_wt"
+ do
+ dwim_test_args="$quiet_mode $changedir_type"
+ test_dwim_orphan 'infer' $dwim_test_args no_-b
+ test_dwim_orphan 'no_infer' $dwim_test_args no_-b local_ref good_head
+ test_dwim_orphan 'infer' $dwim_test_args no_-b no_local_ref no_remote no_remote_ref no_guess_remote
+ test_dwim_orphan 'infer' $dwim_test_args no_-b no_local_ref remote no_remote_ref no_guess_remote
+ test_dwim_orphan 'fetch_error' $dwim_test_args no_-b no_local_ref remote no_remote_ref guess_remote
+ test_dwim_orphan 'infer' $dwim_test_args no_-b no_local_ref remote no_remote_ref guess_remote force
+ test_dwim_orphan 'no_infer' $dwim_test_args no_-b no_local_ref remote remote_ref guess_remote
+
+ test_dwim_orphan 'infer' $dwim_test_args -b
+ test_dwim_orphan 'no_infer' $dwim_test_args -b local_ref good_head
+ test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref no_remote no_remote_ref no_guess_remote
+ test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote no_remote_ref no_guess_remote
+ test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote no_remote_ref guess_remote
+ test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote remote_ref guess_remote
+
+ test_dwim_orphan 'warn_bad_head' $dwim_test_args no_-b local_ref bad_head
+ test_dwim_orphan 'warn_bad_head' $dwim_test_args -b local_ref bad_head
+ test_dwim_orphan 'warn_bad_head' $dwim_test_args detach local_ref bad_head
+ done
+
+ test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode no_-b no_checkout
+ test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode no_-b track
+ test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode -b no_checkout
+ test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode -b track
+done
+
post_checkout_hook () {
test_when_finished "rm -rf .git/hooks" &&
mkdir .git/hooks &&
diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
index 3d28c7f06b..568a47ec42 100755
--- a/t/t2401-worktree-prune.sh
+++ b/t/t2401-worktree-prune.sh
@@ -5,6 +5,7 @@ test_description='prune $GIT_DIR/worktrees'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success initialize '
diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh
index 79e0fce2d9..9ad9be0c20 100755
--- a/t/t2402-worktree-list.sh
+++ b/t/t2402-worktree-list.sh
@@ -5,6 +5,7 @@ test_description='test git worktree list'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh
index 5c44453e1c..8970780efc 100755
--- a/t/t2406-worktree-repair.sh
+++ b/t/t2406-worktree-repair.sh
@@ -2,6 +2,7 @@
test_description='test git worktree repair'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t2407-worktree-heads.sh b/t/t2407-worktree-heads.sh
index 019a40df2c..469443d8ae 100755
--- a/t/t2407-worktree-heads.sh
+++ b/t/t2407-worktree-heads.sh
@@ -58,7 +58,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in bisect' '
git -C wt-4 bisect good wt-1 &&
test_must_fail git branch -f wt-4 HEAD 2>err &&
- grep "cannot force update the branch '\''wt-4'\'' checked out at.*wt-4" err
+ grep "cannot force update the branch '\''wt-4'\'' used by worktree at.*wt-4" err
'
test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (apply)' '
@@ -68,7 +68,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (app
test_must_fail git -C wt-2 rebase --apply conflict-2 &&
test_must_fail git branch -f wt-2 HEAD 2>err &&
- grep "cannot force update the branch '\''wt-2'\'' checked out at.*wt-2" err
+ grep "cannot force update the branch '\''wt-2'\'' used by worktree at.*wt-2" err
'
test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (merge)' '
@@ -78,7 +78,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (mer
test_must_fail git -C wt-2 rebase conflict-2 &&
test_must_fail git branch -f wt-2 HEAD 2>err &&
- grep "cannot force update the branch '\''wt-2'\'' checked out at.*wt-2" err
+ grep "cannot force update the branch '\''wt-2'\'' used by worktree at.*wt-2" err
'
test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase with --update-refs' '
@@ -90,7 +90,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase with
for i in 3 4
do
test_must_fail git branch -f can-be-updated HEAD 2>err &&
- grep "cannot force update the branch '\''can-be-updated'\'' checked out at.*wt-3" err ||
+ grep "cannot force update the branch '\''can-be-updated'\'' used by worktree at.*wt-3" err ||
return 1
done
'
@@ -150,7 +150,7 @@ test_expect_success 'refuse to overwrite when in error states' '
for i in 1 2
do
test_must_fail git branch -f fake-$i HEAD 2>err &&
- grep "cannot force update the branch '\''fake-$i'\'' checked out at" err ||
+ grep "cannot force update the branch '\''fake-$i'\'' used by worktree at" err ||
return 1
done
'
diff --git a/t/t3007-ls-files-recurse-submodules.sh b/t/t3007-ls-files-recurse-submodules.sh
index dd7770e85d..7308a3d4e2 100755
--- a/t/t3007-ls-files-recurse-submodules.sh
+++ b/t/t3007-ls-files-recurse-submodules.sh
@@ -299,6 +299,39 @@ test_expect_success '--recurse-submodules does not support --error-unmatch' '
test_i18ngrep "does not support --error-unmatch" actual
'
+test_expect_success '--recurse-submodules parses submodule repo config' '
+ test_config -C submodule index.sparse "invalid non-boolean value" &&
+ test_must_fail git ls-files --recurse-submodules 2>err &&
+ grep "bad boolean config value" err
+'
+
+test_expect_success '--recurse-submodules parses submodule worktree config' '
+ test_config -C submodule extensions.worktreeConfig true &&
+ test_config -C submodule --worktree index.sparse "invalid non-boolean value" &&
+
+ test_must_fail git ls-files --recurse-submodules 2>err &&
+ grep "bad boolean config value" err
+'
+
+test_expect_success '--recurse-submodules submodules ignore super project worktreeConfig extension' '
+ # Enable worktree config in both super project & submodule, set an
+ # invalid config in the submodule worktree config
+ test_config extensions.worktreeConfig true &&
+ test_config -C submodule extensions.worktreeConfig true &&
+ test_config -C submodule --worktree index.sparse "invalid non-boolean value" &&
+
+ # Now, disable the worktree config in the submodule. Note that we need
+ # to manually re-enable extensions.worktreeConfig when the test is
+ # finished, otherwise the test_unconfig of index.sparse will not work.
+ test_unconfig -C submodule extensions.worktreeConfig &&
+ test_when_finished "git -C submodule config extensions.worktreeConfig true" &&
+
+ # With extensions.worktreeConfig disabled in the submodule, the invalid
+ # worktree config is not picked up.
+ git ls-files --recurse-submodules 2>err &&
+ ! grep "bad boolean config value" err
+'
+
test_incompatible_with_recurse_submodules () {
test_expect_success "--recurse-submodules and $1 are incompatible" "
test_must_fail git ls-files --recurse-submodules $1 2>actual &&
diff --git a/t/t3009-ls-files-others-nonsubmodule.sh b/t/t3009-ls-files-others-nonsubmodule.sh
index 963f3462b7..14218b3424 100755
--- a/t/t3009-ls-files-others-nonsubmodule.sh
+++ b/t/t3009-ls-files-others-nonsubmodule.sh
@@ -18,6 +18,7 @@ This test runs git ls-files --others with the following working tree:
git repository with a commit and an untracked file
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup: directories' '
diff --git a/t/t3010-ls-files-killed-modified.sh b/t/t3010-ls-files-killed-modified.sh
index 580e158f99..054178703d 100755
--- a/t/t3010-ls-files-killed-modified.sh
+++ b/t/t3010-ls-files-killed-modified.sh
@@ -41,6 +41,8 @@ Also for modification test, the cache and working tree have:
We should report path0, path1, path2/file2, path3/file3, path7 and path8
modified without reporting path9 and path10. submod1 is also modified.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'git update-index --add to add various paths.' '
diff --git a/t/t3013-ls-files-format.sh b/t/t3013-ls-files-format.sh
index efb7450bf1..6e6ea0b6f3 100755
--- a/t/t3013-ls-files-format.sh
+++ b/t/t3013-ls-files-format.sh
@@ -38,6 +38,41 @@ test_expect_success 'git ls-files --format objectname v.s. -s' '
test_cmp expect actual
'
+test_expect_success 'git ls-files --format objecttype' '
+ git ls-files --format="%(objectname)" o1.txt o4.txt o6.txt >objectname &&
+ git cat-file --batch-check="%(objecttype)" >expect <objectname &&
+ git ls-files --format="%(objecttype)" o1.txt o4.txt o6.txt >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git ls-files --format objectsize' '
+ cat>expect <<-\EOF &&
+26
+29
+27
+26
+-
+26
+ EOF
+ git ls-files --format="%(objectsize)" >actual &&
+
+ test_cmp expect actual
+'
+
+test_expect_success 'git ls-files --format objectsize:padded' '
+ cat>expect <<-\EOF &&
+ 26
+ 29
+ 27
+ 26
+ -
+ 26
+ EOF
+ git ls-files --format="%(objectsize:padded)" >actual &&
+
+ test_cmp expect actual
+'
+
test_expect_success 'git ls-files --format v.s. --eol' '
git ls-files --eol >tmp &&
sed -e "s/ / /g" -e "s/ */ /g" tmp >expect 2>err &&
@@ -54,6 +89,22 @@ test_expect_success 'git ls-files --format path v.s. -s' '
test_cmp expect actual
'
+test_expect_success 'git ls-files --format with relative path' '
+ cat >expect <<-\EOF &&
+ ../o1.txt
+ ../o2.txt
+ ../o3.txt
+ ../o4.txt
+ ../o5.txt
+ ../o6.txt
+ EOF
+ mkdir sub &&
+ cd sub &&
+ git ls-files --format="%(path)" ":/" >../actual &&
+ cd .. &&
+ test_cmp expect actual
+'
+
test_expect_success 'git ls-files --format with -m' '
echo change >o1.txt &&
cat >expect <<-\EOF &&
diff --git a/t/t3050-subprojects-fetch.sh b/t/t3050-subprojects-fetch.sh
index f1f09abdd9..3884694165 100755
--- a/t/t3050-subprojects-fetch.sh
+++ b/t/t3050-subprojects-fetch.sh
@@ -2,6 +2,7 @@
test_description='fetching and pushing project with subproject'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3060-ls-files-with-tree.sh b/t/t3060-ls-files-with-tree.sh
index 52f76f7b57..5a06732ca7 100755
--- a/t/t3060-ls-files-with-tree.sh
+++ b/t/t3060-ls-files-with-tree.sh
@@ -8,6 +8,8 @@ test_description='git ls-files test (--with-tree).
This test runs git ls-files --with-tree and in particular in
a scenario known to trigger a crash with some versions of git.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
@@ -38,7 +40,7 @@ test_expect_success 'setup' '
git commit -a -m "remove them all" &&
# The bug also requires some entry before our directory so that
- # prune_path will modify the_index.cache
+ # prune_index will modify the_repository->index.cache
mkdir a_directory_that_sorts_before_sub &&
>a_directory_that_sorts_before_sub/file &&
@@ -54,7 +56,7 @@ test_expect_success 'usage' '
'
test_expect_success 'git ls-files --with-tree should succeed from subdir' '
- # We have to run from a sub-directory to trigger prune_path
+ # We have to run from a sub-directory to trigger prune_index
# Then we finally get to run our --with-tree test
(
cd sub &&
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 5d871fde96..4dd42df38c 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -431,4 +431,15 @@ match 1 1 1 1 'a' '[B-a]'
match 0 1 0 1 'z' '[Z-y]'
match 1 1 1 1 'Z' '[Z-y]'
+test_expect_success 'matching does not exhibit exponential behavior' '
+ {
+ test-tool wildmatch wildmatch \
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab \
+ "*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a" &
+ pid=$!
+ } &&
+ sleep 2 &&
+ ! kill $!
+'
+
test_done
diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh
index 217006d1bf..5af2dac0e4 100755
--- a/t/t3101-ls-tree-dirname.sh
+++ b/t/t3101-ls-tree-dirname.sh
@@ -154,6 +154,14 @@ EOF
test_output
'
+test_expect_success 'ls-tree --no-full-name' '
+ git -C path0 ls-tree --no-full-name $tree a >current &&
+ cat >expected <<-EOF &&
+ 040000 tree X a
+ EOF
+ test_output
+'
+
test_expect_success 'ls-tree --full-tree' '
(
cd path1/b/c &&
diff --git a/t/t3104-ls-tree-format.sh b/t/t3104-ls-tree-format.sh
index 383896667b..3adb206a93 100755
--- a/t/t3104-ls-tree-format.sh
+++ b/t/t3104-ls-tree-format.sh
@@ -20,7 +20,6 @@ test_ls_tree_format () {
format=$1 &&
opts=$2 &&
fmtopts=$3 &&
- shift 2 &&
test_expect_success "ls-tree '--format=<$format>' is like options '$opts $fmtopts'" '
git ls-tree $opts -r HEAD >expect &&
@@ -36,6 +35,12 @@ test_ls_tree_format () {
'
}
+test_expect_success "ls-tree --format='%(path) %(path) %(path)' HEAD top-file" '
+ git ls-tree --format="%(path) %(path) %(path)" HEAD top-file.t >actual &&
+ echo top-file.t top-file.t top-file.t >expect &&
+ test_cmp expect actual
+'
+
test_ls_tree_format \
"%(objectmode) %(objecttype) %(objectname)%x09%(path)" \
""
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index c7ec1c7520..080e4f24a6 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -8,6 +8,7 @@ test_description='git branch assorted tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
@@ -201,8 +202,8 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou
test_expect_success 'git branch -M baz bam should add entries to .git/logs/HEAD' '
msg="Branch: renamed refs/heads/baz to refs/heads/bam" &&
- grep " 0\{40\}.*$msg$" .git/logs/HEAD &&
- grep "^0\{40\}.*$msg$" .git/logs/HEAD
+ grep " $ZERO_OID.*$msg$" .git/logs/HEAD &&
+ grep "^$ZERO_OID.*$msg$" .git/logs/HEAD
'
test_expect_success 'git branch -M should leave orphaned HEAD alone' '
@@ -239,15 +240,34 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou
git worktree prune
'
+test_expect_success 'git branch -M fails if updating any linked working tree fails' '
+ git worktree add -b baz bazdir1 &&
+ git worktree add -f bazdir2 baz &&
+ touch .git/worktrees/bazdir1/HEAD.lock &&
+ test_must_fail git branch -M baz bam &&
+ test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam &&
+ git branch -M bam baz &&
+ rm .git/worktrees/bazdir1/HEAD.lock &&
+ touch .git/worktrees/bazdir2/HEAD.lock &&
+ test_must_fail git branch -M baz bam &&
+ test $(git -C bazdir1 rev-parse --abbrev-ref HEAD) = bam &&
+ rm -rf bazdir1 bazdir2 &&
+ git worktree prune
+'
+
test_expect_success 'git branch -M baz bam should succeed within a worktree in which baz is checked out' '
git checkout -b baz &&
git worktree add -f bazdir baz &&
(
cd bazdir &&
git branch -M baz bam &&
- test $(git rev-parse --abbrev-ref HEAD) = bam
+ echo bam >expect &&
+ git rev-parse --abbrev-ref HEAD >actual &&
+ test_cmp expect actual
) &&
- test $(git rev-parse --abbrev-ref HEAD) = bam &&
+ echo bam >expect &&
+ git rev-parse --abbrev-ref HEAD >actual &&
+ test_cmp expect actual &&
rm -r bazdir &&
git worktree prune
'
@@ -268,6 +288,67 @@ test_expect_success 'git branch -M topic topic should work when main is checked
git branch -M topic topic
'
+test_expect_success 'git branch -M and -C fail on detached HEAD' '
+ git checkout HEAD^{} &&
+ test_when_finished git checkout - &&
+ echo "fatal: cannot rename the current branch while not on any." >expect &&
+ test_must_fail git branch -M must-fail 2>err &&
+ test_cmp expect err &&
+ echo "fatal: cannot copy the current branch while not on any." >expect &&
+ test_must_fail git branch -C must-fail 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success 'git branch -m should work with orphan branches' '
+ test_when_finished git checkout - &&
+ test_when_finished git worktree remove -f wt &&
+ git worktree add wt --detach &&
+ # rename orphan in another worktreee
+ git -C wt checkout --orphan orphan-foo-wt &&
+ git branch -m orphan-foo-wt orphan-bar-wt &&
+ test orphan-bar-wt=$(git -C orphan-worktree branch --show-current) &&
+ # rename orphan in the current worktree
+ git checkout --orphan orphan-foo &&
+ git branch -m orphan-foo orphan-bar &&
+ test orphan-bar=$(git branch --show-current)
+'
+
+test_expect_success 'git branch -d on orphan HEAD (merged)' '
+ test_when_finished git checkout main &&
+ git checkout --orphan orphan &&
+ test_when_finished "rm -rf .git/objects/commit-graph*" &&
+ git commit-graph write --reachable &&
+ git branch --track to-delete main &&
+ git branch -d to-delete
+'
+
+test_expect_success 'git branch -d on orphan HEAD (merged, graph)' '
+ test_when_finished git checkout main &&
+ git checkout --orphan orphan &&
+ git branch --track to-delete main &&
+ git branch -d to-delete
+'
+
+test_expect_success 'git branch -d on orphan HEAD (unmerged)' '
+ test_when_finished git checkout main &&
+ git checkout --orphan orphan &&
+ test_when_finished "git branch -D to-delete" &&
+ git branch to-delete main &&
+ test_must_fail git branch -d to-delete 2>err &&
+ grep "not fully merged" err
+'
+
+test_expect_success 'git branch -d on orphan HEAD (unmerged, graph)' '
+ test_when_finished git checkout main &&
+ git checkout --orphan orphan &&
+ test_when_finished "git branch -D to-delete" &&
+ git branch to-delete main &&
+ test_when_finished "rm -rf .git/objects/commit-graph*" &&
+ git commit-graph write --reachable &&
+ test_must_fail git branch -d to-delete 2>err &&
+ grep "not fully merged" err
+'
+
test_expect_success 'git branch -v -d t should work' '
git branch t &&
git rev-parse --verify refs/heads/t &&
@@ -861,7 +942,19 @@ test_expect_success 'test deleting branch without config' '
test_expect_success 'deleting currently checked out branch fails' '
git worktree add -b my7 my7 &&
test_must_fail git -C my7 branch -d my7 &&
- test_must_fail git branch -d my7 &&
+ test_must_fail git branch -d my7 2>actual &&
+ grep "^error: Cannot delete branch .my7. used by worktree at " actual &&
+ rm -r my7 &&
+ git worktree prune
+'
+
+test_expect_success 'deleting in-use branch fails' '
+ git worktree add my7 &&
+ test_commit -C my7 bt7 &&
+ git -C my7 bisect start HEAD HEAD~2 &&
+ test_must_fail git -C my7 branch -d my7 &&
+ test_must_fail git branch -d my7 2>actual &&
+ grep "^error: Cannot delete branch .my7. used by worktree at " actual &&
rm -r my7 &&
git worktree prune
'
@@ -1383,7 +1476,7 @@ test_expect_success 'branch --delete --force removes dangling branch' '
test_expect_success 'use --edit-description' '
EDITOR=: git branch --edit-description &&
- test_must_fail git config branch.main.description &&
+ test_expect_code 1 git config branch.main.description &&
write_script editor <<-\EOF &&
echo "New contents" >"$1"
diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh
index ea7cfd1951..b17f388f56 100755
--- a/t/t3202-show-branch.sh
+++ b/t/t3202-show-branch.sh
@@ -119,6 +119,22 @@ test_expect_success 'show branch --remotes' '
test_must_be_empty actual.out
'
+test_expect_success 'show-branch --sparse' '
+ test_when_finished "git checkout branch10 && git branch -D branchA" &&
+ git checkout -b branchA branch10 &&
+ git merge -s ours -m "merge 1 and 10 to make A" branch1 &&
+ git commit --allow-empty -m "another" &&
+
+ git show-branch --sparse >out &&
+ grep "merge 1 and 10 to make A" out &&
+
+ git show-branch >out &&
+ ! grep "merge 1 and 10 to make A" out &&
+
+ git show-branch --no-sparse >out &&
+ ! grep "merge 1 and 10 to make A" out
+'
+
test_expect_success 'setup show branch --list' '
sed "s/^> //" >expect <<-\EOF
> [branch1] branch1
@@ -197,6 +213,15 @@ done <<\EOF
--reflog --current
EOF
+# unnegatable options
+for opt in topo-order date-order reflog
+do
+ test_expect_success "show-branch --no-$opt (should fail)" '
+ test_must_fail git show-branch --no-$opt 2>err &&
+ grep "unknown option .no-$opt." err
+ '
+done
+
test_expect_success 'error descriptions on non-existent branch' '
cat >expect <<-EOF &&
error: No branch named '\''non-existent'\'.'
@@ -221,4 +246,22 @@ test_expect_success 'fatal descriptions on non-existent branch' '
test_cmp expect actual
'
+test_expect_success 'error descriptions on orphan branch' '
+ test_when_finished git worktree remove -f wt &&
+ git worktree add wt --detach &&
+ git -C wt checkout --orphan orphan-branch &&
+ test_branch_op_in_wt() {
+ test_orphan_error() {
+ test_must_fail git $* 2>actual &&
+ test_i18ngrep "No commit on branch .orphan-branch. yet.$" actual
+ } &&
+ test_orphan_error -C wt branch $1 $2 && # implicit branch
+ test_orphan_error -C wt branch $1 orphan-branch $2 && # explicit branch
+ test_orphan_error branch $1 orphan-branch $2 # different worktree
+ } &&
+ test_branch_op_in_wt --edit-description &&
+ test_branch_op_in_wt --set-upstream-to=ne &&
+ test_branch_op_in_wt -c new-branch
+'
+
test_done
diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
index d34d77f893..758963b189 100755
--- a/t/t3203-branch-output.sh
+++ b/t/t3203-branch-output.sh
@@ -55,9 +55,17 @@ cat >expect <<'EOF'
EOF
test_expect_success 'git branch -r shows remote branches' '
git branch -r >actual &&
+ test_cmp expect actual &&
+
+ git branch --remotes >actual &&
test_cmp expect actual
'
+test_expect_success 'git branch --no-remotes is rejected' '
+ test_must_fail git branch --no-remotes 2>err &&
+ grep "unknown option .no-remotes." err
+'
+
cat >expect <<'EOF'
branch-one
branch-two
@@ -68,9 +76,17 @@ cat >expect <<'EOF'
EOF
test_expect_success 'git branch -a shows local and remote branches' '
git branch -a >actual &&
+ test_cmp expect actual &&
+
+ git branch --all >actual &&
test_cmp expect actual
'
+test_expect_success 'git branch --no-all is rejected' '
+ test_must_fail git branch --no-all 2>err &&
+ grep "unknown option .no-all." err
+'
+
cat >expect <<'EOF'
two
one
@@ -337,10 +353,48 @@ test_expect_success 'git branch --format option' '
test_cmp expect actual
'
+test_expect_success 'git branch --format with ahead-behind' '
+ cat >expect <<-\EOF &&
+ (HEAD detached from fromtag) 0 0
+ refs/heads/ambiguous 0 0
+ refs/heads/branch-one 1 0
+ refs/heads/branch-two 0 0
+ refs/heads/main 1 0
+ refs/heads/ref-to-branch 1 0
+ refs/heads/ref-to-remote 1 0
+ EOF
+ git branch --format="%(refname) %(ahead-behind:HEAD)" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'git branch with --format=%(rest) must fail' '
test_must_fail git branch --format="%(rest)" >actual
'
+test_expect_success 'git branch --format --omit-empty' '
+ cat >expect <<-\EOF &&
+ Refname is (HEAD detached from fromtag)
+ Refname is refs/heads/ambiguous
+ Refname is refs/heads/branch-one
+ Refname is refs/heads/branch-two
+
+ Refname is refs/heads/ref-to-branch
+ Refname is refs/heads/ref-to-remote
+ EOF
+ git branch --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual &&
+ test_cmp expect actual &&
+ cat >expect <<-\EOF &&
+ Refname is (HEAD detached from fromtag)
+ Refname is refs/heads/ambiguous
+ Refname is refs/heads/branch-one
+ Refname is refs/heads/branch-two
+ Refname is refs/heads/ref-to-branch
+ Refname is refs/heads/ref-to-remote
+ EOF
+ git branch --omit-empty --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'worktree colors correct' '
cat >expect <<-EOF &&
* <GREEN>(HEAD detached from fromtag)<RESET>
diff --git a/t/t3204-branch-name-interpretation.sh b/t/t3204-branch-name-interpretation.sh
index 993a6b5eff..594e3e43e1 100755
--- a/t/t3204-branch-name-interpretation.sh
+++ b/t/t3204-branch-name-interpretation.sh
@@ -9,6 +9,7 @@ This script aims to check the behavior of those corner cases.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
expect_branch() {
@@ -57,6 +58,16 @@ test_expect_success 'create branch with pseudo-qualified name' '
expect_branch refs/heads/refs/heads/qualified two
'
+test_expect_success 'force-copy a branch to itself via @{-1} is no-op' '
+ git branch -t copiable main &&
+ git checkout copiable &&
+ git checkout - &&
+ git branch -C @{-1} copiable &&
+ git config --get-all branch.copiable.merge >actual &&
+ echo refs/heads/main >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'delete branch via @{-1}' '
git branch previous-del &&
@@ -133,4 +144,28 @@ test_expect_success 'checkout does not treat remote @{upstream} as a branch' '
expect_branch HEAD one
'
+test_expect_success 'edit-description via @{-1}' '
+ git checkout -b desc-branch &&
+ git checkout -b non-desc-branch &&
+ write_script editor <<-\EOF &&
+ echo "Branch description" >"$1"
+ EOF
+ EDITOR=./editor git branch --edit-description @{-1} &&
+ test_must_fail git config branch.non-desc-branch.description &&
+ git config branch.desc-branch.description >actual &&
+ printf "Branch description\n\n" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'modify branch upstream via "@{-1}" and "@{-1}@{upstream}"' '
+ git checkout -b upstream-branch &&
+ git checkout -b upstream-other -t upstream-branch &&
+ git branch --set-upstream-to upstream-other @{-1} &&
+ git config branch.upstream-branch.merge >actual &&
+ echo "refs/heads/upstream-other" >expect &&
+ test_cmp expect actual &&
+ git branch --unset-upstream @{-1}@{upstream} &&
+ test_must_fail git config branch.upstream-other.merge
+'
+
test_done
diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh
index 84dd0cd26d..b5f4d6a653 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -33,6 +33,26 @@ test_expect_success 'setup' '
u3 sha256:736c4bc
u4 sha256:673e77d
+ # topic (abbrev=10)
+ t1_abbrev sha1:4de457d2c0
+ t2_abbrev sha1:fccce22f8c
+ t3_abbrev sha1:147e64ef53
+ t4_abbrev sha1:a63e992599
+ t1_abbrev sha256:b89f8b9092
+ t2_abbrev sha256:5f12aadf34
+ t3_abbrev sha256:ea8b273a6c
+ t4_abbrev sha256:14b73361fc
+
+ # unmodified (abbrev=10)
+ u1_abbrev sha1:35b9b25f76
+ u2_abbrev sha1:de345ab3de
+ u3_abbrev sha1:9af6654000
+ u4_abbrev sha1:2901f773f3
+ u1_abbrev sha256:e3731be242
+ u2_abbrev sha256:14fadf8cee
+ u3_abbrev sha256:736c4bcb44
+ u4_abbrev sha256:673e77d589
+
# reordered
r1 sha1:aca177a
r2 sha1:14ad629
@@ -153,6 +173,18 @@ test_expect_success 'simple A B C (unmodified)' '
test_cmp expect actual
'
+test_expect_success 'simple A..B A..C (unmodified) with --abbrev' '
+ git range-diff --no-color --abbrev=10 main..topic main..unmodified \
+ >actual &&
+ cat >expect <<-EOF &&
+ 1: $(test_oid t1_abbrev) = 1: $(test_oid u1_abbrev) s/5/A/
+ 2: $(test_oid t2_abbrev) = 2: $(test_oid u2_abbrev) s/4/A/
+ 3: $(test_oid t3_abbrev) = 3: $(test_oid u3_abbrev) s/11/B/
+ 4: $(test_oid t4_abbrev) = 4: $(test_oid u4_abbrev) s/12/B/
+ EOF
+ test_cmp expect actual
+'
+
test_expect_success 'A^! and A^-<n> (unmodified)' '
git range-diff --no-color topic^! unmodified^-1 >actual &&
cat >expect <<-EOF &&
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 577f32dc71..7326adb70f 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -12,107 +12,145 @@ semantic is still the same.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'enable reflogs' '
git config core.logallrefupdates true
'
-test_expect_success \
- 'prepare a trivial repository' \
- 'echo Hello > A &&
- git update-index --add A &&
- git commit -m "Initial commit." &&
- HEAD=$(git rev-parse --verify HEAD)'
+test_expect_success 'prepare a trivial repository' '
+ echo Hello > A &&
+ git update-index --add A &&
+ git commit -m "Initial commit." &&
+ HEAD=$(git rev-parse --verify HEAD)
+'
SHA1=
-test_expect_success \
- 'see if git show-ref works as expected' \
- 'git branch a &&
- SHA1=$(cat .git/refs/heads/a) &&
- echo "$SHA1 refs/heads/a" >expect &&
- git show-ref a >result &&
- test_cmp expect result'
-
-test_expect_success \
- 'see if a branch still exists when packed' \
- 'git branch b &&
- git pack-refs --all &&
- rm -f .git/refs/heads/b &&
- echo "$SHA1 refs/heads/b" >expect &&
- git show-ref b >result &&
- test_cmp expect result'
+test_expect_success 'see if git show-ref works as expected' '
+ git branch a &&
+ SHA1=$(cat .git/refs/heads/a) &&
+ echo "$SHA1 refs/heads/a" >expect &&
+ git show-ref a >result &&
+ test_cmp expect result
+'
+
+test_expect_success 'see if a branch still exists when packed' '
+ git branch b &&
+ git pack-refs --all &&
+ rm -f .git/refs/heads/b &&
+ echo "$SHA1 refs/heads/b" >expect &&
+ git show-ref b >result &&
+ test_cmp expect result
+'
test_expect_success 'git branch c/d should barf if branch c exists' '
- git branch c &&
- git pack-refs --all &&
- rm -f .git/refs/heads/c &&
- test_must_fail git branch c/d
+ git branch c &&
+ git pack-refs --all &&
+ rm -f .git/refs/heads/c &&
+ test_must_fail git branch c/d
'
-test_expect_success \
- 'see if a branch still exists after git pack-refs --prune' \
- 'git branch e &&
- git pack-refs --all --prune &&
- echo "$SHA1 refs/heads/e" >expect &&
- git show-ref e >result &&
- test_cmp expect result'
+test_expect_success 'see if a branch still exists after git pack-refs --prune' '
+ git branch e &&
+ git pack-refs --all --prune &&
+ echo "$SHA1 refs/heads/e" >expect &&
+ git show-ref e >result &&
+ test_cmp expect result
+'
test_expect_success 'see if git pack-refs --prune remove ref files' '
- git branch f &&
- git pack-refs --all --prune &&
- ! test -f .git/refs/heads/f
+ git branch f &&
+ git pack-refs --all --prune &&
+ ! test -f .git/refs/heads/f
'
test_expect_success 'see if git pack-refs --prune removes empty dirs' '
- git branch r/s/t &&
- git pack-refs --all --prune &&
- ! test -e .git/refs/heads/r
+ git branch r/s/t &&
+ git pack-refs --all --prune &&
+ ! test -e .git/refs/heads/r
'
-test_expect_success \
- 'git branch g should work when git branch g/h has been deleted' \
- 'git branch g/h &&
- git pack-refs --all --prune &&
- git branch -d g/h &&
- git branch g &&
- git pack-refs --all &&
- git branch -d g'
+test_expect_success 'git branch g should work when git branch g/h has been deleted' '
+ git branch g/h &&
+ git pack-refs --all --prune &&
+ git branch -d g/h &&
+ git branch g &&
+ git pack-refs --all &&
+ git branch -d g
+'
test_expect_success 'git branch i/j/k should barf if branch i exists' '
- git branch i &&
- git pack-refs --all --prune &&
- test_must_fail git branch i/j/k
+ git branch i &&
+ git pack-refs --all --prune &&
+ test_must_fail git branch i/j/k
+'
+
+test_expect_success 'test git branch k after branch k/l/m and k/lm have been deleted' '
+ git branch k/l &&
+ git branch k/lm &&
+ git branch -d k/l &&
+ git branch k/l/m &&
+ git branch -d k/l/m &&
+ git branch -d k/lm &&
+ git branch k
'
-test_expect_success \
- 'test git branch k after branch k/l/m and k/lm have been deleted' \
- 'git branch k/l &&
- git branch k/lm &&
- git branch -d k/l &&
- git branch k/l/m &&
- git branch -d k/l/m &&
- git branch -d k/lm &&
- git branch k'
-
-test_expect_success \
- 'test git branch n after some branch deletion and pruning' \
- 'git branch n/o &&
- git branch n/op &&
- git branch -d n/o &&
- git branch n/o/p &&
- git branch -d n/op &&
- git pack-refs --all --prune &&
- git branch -d n/o/p &&
- git branch n'
-
-test_expect_success \
- 'see if up-to-date packed refs are preserved' \
- 'git branch q &&
- git pack-refs --all --prune &&
- git update-ref refs/heads/q refs/heads/q &&
- ! test -f .git/refs/heads/q'
+test_expect_success 'test git branch n after some branch deletion and pruning' '
+ git branch n/o &&
+ git branch n/op &&
+ git branch -d n/o &&
+ git branch n/o/p &&
+ git branch -d n/op &&
+ git pack-refs --all --prune &&
+ git branch -d n/o/p &&
+ git branch n
+'
+
+test_expect_success 'test excluded refs are not packed' '
+ git branch dont_pack1 &&
+ git branch dont_pack2 &&
+ git branch pack_this &&
+ git pack-refs --all --exclude "refs/heads/dont_pack*" &&
+ test -f .git/refs/heads/dont_pack1 &&
+ test -f .git/refs/heads/dont_pack2 &&
+ ! test -f .git/refs/heads/pack_this'
+
+test_expect_success 'test --no-exclude refs clears excluded refs' '
+ git branch dont_pack3 &&
+ git branch dont_pack4 &&
+ git pack-refs --all --exclude "refs/heads/dont_pack*" --no-exclude &&
+ ! test -f .git/refs/heads/dont_pack3 &&
+ ! test -f .git/refs/heads/dont_pack4'
+
+test_expect_success 'test only included refs are packed' '
+ git branch pack_this1 &&
+ git branch pack_this2 &&
+ git tag dont_pack5 &&
+ git pack-refs --include "refs/heads/pack_this*" &&
+ test -f .git/refs/tags/dont_pack5 &&
+ ! test -f .git/refs/heads/pack_this1 &&
+ ! test -f .git/refs/heads/pack_this2'
+
+test_expect_success 'test --no-include refs clears included refs' '
+ git branch pack1 &&
+ git branch pack2 &&
+ git pack-refs --include "refs/heads/pack*" --no-include &&
+ test -f .git/refs/heads/pack1 &&
+ test -f .git/refs/heads/pack2'
+
+test_expect_success 'test --exclude takes precedence over --include' '
+ git branch dont_pack5 &&
+ git pack-refs --include "refs/heads/pack*" --exclude "refs/heads/pack*" &&
+ test -f .git/refs/heads/dont_pack5'
+
+test_expect_success 'see if up-to-date packed refs are preserved' '
+ git branch q &&
+ git pack-refs --all --prune &&
+ git update-ref refs/heads/q refs/heads/q &&
+ ! test -f .git/refs/heads/q
+'
test_expect_success 'pack, prune and repack' '
git tag foo &&
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 3288aaec7d..d734000d2f 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -362,6 +362,7 @@ test_expect_success 'do not create empty note with -m ""' '
'
test_expect_success 'create note with combination of -m and -F' '
+ test_when_finished git notes remove HEAD &&
cat >expect-combine_m_and_F <<-EOF &&
foo
@@ -380,6 +381,41 @@ test_expect_success 'create note with combination of -m and -F' '
test_cmp expect-combine_m_and_F actual
'
+test_expect_success 'create note with combination of -m and -F and --separator' '
+ test_when_finished git notes remove HEAD &&
+ cat >expect-combine_m_and_F <<-\EOF &&
+ foo
+ -------
+ xyzzy
+ -------
+ bar
+ -------
+ zyxxy
+ -------
+ baz
+ EOF
+ echo "xyzzy" >note_a &&
+ echo "zyxxy" >note_b &&
+ git notes add -m "foo" -F note_a -m "bar" -F note_b -m "baz" --separator="-------" &&
+ git notes show >actual &&
+ test_cmp expect-combine_m_and_F actual
+'
+
+test_expect_success 'create note with combination of -m and -F and --no-separator' '
+ cat >expect-combine_m_and_F <<-\EOF &&
+ foo
+ xyzzy
+ bar
+ zyxxy
+ baz
+ EOF
+ echo "xyzzy" >note_a &&
+ echo "zyxxy" >note_b &&
+ git notes add -m "foo" -F note_a -m "bar" -F note_b -m "baz" --no-separator &&
+ git notes show >actual &&
+ test_cmp expect-combine_m_and_F actual
+'
+
test_expect_success 'remove note with "git notes remove"' '
git notes remove HEAD^ &&
git notes remove &&
@@ -521,6 +557,112 @@ test_expect_success 'listing non-existing notes fails' '
test_must_be_empty actual
'
+test_expect_success 'append: specify a separator with an empty arg' '
+ test_when_finished git notes remove HEAD &&
+ cat >expect <<-\EOF &&
+ notes-1
+
+ notes-2
+ EOF
+
+ git notes add -m "notes-1" &&
+ git notes append --separator="" -m "notes-2" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append: specify a separator without arg' '
+ test_when_finished git notes remove HEAD &&
+ cat >expect <<-\EOF &&
+ notes-1
+
+ notes-2
+ EOF
+
+ git notes add -m "notes-1" &&
+ git notes append --separator -m "notes-2" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append: specify as --no-separator' '
+ test_when_finished git notes remove HEAD &&
+ cat >expect <<-\EOF &&
+ notes-1
+ notes-2
+ EOF
+
+ git notes add -m "notes-1" &&
+ git notes append --no-separator -m "notes-2" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append: specify separator with line break' '
+ test_when_finished git notes remove HEAD &&
+ cat >expect <<-\EOF &&
+ notes-1
+ -------
+ notes-2
+ EOF
+
+ git notes add -m "notes-1" &&
+ git notes append --separator="-------$LF" -m "notes-2" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append: specify separator without line break' '
+ test_when_finished git notes remove HEAD &&
+ cat >expect <<-\EOF &&
+ notes-1
+ -------
+ notes-2
+ EOF
+
+ git notes add -m "notes-1" &&
+ git notes append --separator="-------" -m "notes-2" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append: specify separator with multiple messages' '
+ test_when_finished git notes remove HEAD &&
+ cat >expect <<-\EOF &&
+ notes-1
+ -------
+ notes-2
+ -------
+ notes-3
+ EOF
+
+ git notes add -m "notes-1" &&
+ git notes append --separator="-------" -m "notes-2" -m "notes-3" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append note with combination of -m and -F and --separator' '
+ test_when_finished git notes remove HEAD &&
+ cat >expect-combine_m_and_F <<-\EOF &&
+ m-notes-1
+ -------
+ f-notes-1
+ -------
+ m-notes-2
+ -------
+ f-notes-2
+ -------
+ m-notes-3
+ EOF
+
+ echo "f-notes-1" >note_a &&
+ echo "f-notes-2" >note_b &&
+ git notes append -m "m-notes-1" -F note_a -m "m-notes-2" -F note_b -m "m-notes-3" --separator="-------" &&
+ git notes show >actual &&
+ test_cmp expect-combine_m_and_F actual
+'
+
test_expect_success 'append to existing note with "git notes append"' '
cat >expect <<-EOF &&
Initial set of notes
@@ -818,6 +960,33 @@ test_expect_success 'create note from blob with "git notes add -C" reuses blob i
test_cmp blob actual
'
+test_expect_success 'create note from blob with "-C", also specify "-m", "-F" and "--separator"' '
+ # 8th will be reuseed in following tests, so rollback when the test is done
+ test_when_finished "git notes remove && git notes add -C $(cat blob)" &&
+ commit=$(git rev-parse HEAD) &&
+ cat >expect <<-EOF &&
+ commit $commit
+ Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:20:13 2005 -0700
+
+ ${indent}8th
+
+ Notes:
+ ${indent}This is a blob object
+ ${indent}-------
+ ${indent}This is created by -m
+ ${indent}-------
+ ${indent}This is created by -F
+ EOF
+
+ git notes remove &&
+ echo "This is a blob object" | git hash-object -w --stdin >blob &&
+ echo "This is created by -F" >note_a &&
+ git notes add -C $(cat blob) -m "This is created by -m" -F note_a --separator="-------" &&
+ git log -1 >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'create note from other note with "git notes add -c"' '
test_commit 9th &&
commit=$(git rev-parse HEAD) &&
diff --git a/t/t3305-notes-fanout.sh b/t/t3305-notes-fanout.sh
index 22ffe5bcb9..1ec1fb6715 100755
--- a/t/t3305-notes-fanout.sh
+++ b/t/t3305-notes-fanout.sh
@@ -9,7 +9,7 @@ path_has_fanout() {
path=$1 &&
fanout=$2 &&
after_last_slash=$(($(test_oid hexsz) - $fanout * 2)) &&
- echo $path | grep -q "^\([0-9a-f]\{2\}/\)\{$fanout\}[0-9a-f]\{$after_last_slash\}$"
+ echo $path | grep -q -E "^([0-9a-f]{2}/){$fanout}[0-9a-f]{$after_last_slash}$"
}
touched_one_note_with_fanout() {
diff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh
index 141d3e4ca4..9bd5dbf341 100755
--- a/t/t3309-notes-merge-auto-resolve.sh
+++ b/t/t3309-notes-merge-auto-resolve.sh
@@ -360,7 +360,12 @@ test_expect_success 'merge z into y with invalid strategy => Fail/No changes' '
test_expect_success 'merge z into y with invalid configuration option => Fail/No changes' '
git config core.notesRef refs/notes/y &&
- test_must_fail git -c notes.mergeStrategy="foo" notes merge z &&
+ cat >expect <<-\EOF &&
+ error: unknown notes merge strategy foo
+ fatal: unable to parse '\''notes.mergeStrategy'\'' from command-line config
+ EOF
+ test_must_fail git -c notes.mergeStrategy="foo" notes merge z 2>actual &&
+ test_cmp expect actual &&
# Verify no changes (y)
verify_notes y y
'
diff --git a/t/t3321-notes-stripspace.sh b/t/t3321-notes-stripspace.sh
new file mode 100755
index 0000000000..36abdca5ee
--- /dev/null
+++ b/t/t3321-notes-stripspace.sh
@@ -0,0 +1,578 @@
+#!/bin/sh
+#
+# Copyright (c) 2023 Teng Long
+#
+
+test_description='Test commit notes with stripspace behavior'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+MULTI_LF="$LF$LF$LF"
+write_script fake_editor <<\EOF
+echo "$MSG" >"$1"
+echo "$MSG" >&2
+EOF
+GIT_EDITOR=./fake_editor
+export GIT_EDITOR
+
+test_expect_success 'setup the commit' '
+ test_commit 1st
+'
+
+test_expect_success 'add note by editor' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes add &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add note by specifying single "-m", "--stripspace" is the default behavior' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ git notes add -m "${LF}first-line${MULTI_LF}second-line${LF}" &&
+ git notes show >actual &&
+ test_cmp expect actual &&
+ git notes remove &&
+ git notes add --stripspace -m "${LF}first-line${MULTI_LF}second-line${LF}" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add note by specifying single "-m" and "--no-stripspace" ' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ ${LF}first-line${MULTI_LF}second-line
+ EOF
+
+ git notes add --no-stripspace \
+ -m "${LF}first-line${MULTI_LF}second-line${LF}" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add note by specifying multiple "-m", "--stripspace" is the default behavior' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ git notes add -m "${LF}" \
+ -m "first-line" \
+ -m "${MULTI_LF}" \
+ -m "second-line" \
+ -m "${LF}" &&
+ git notes show >actual &&
+ test_cmp expect actual &&
+ git notes remove &&
+ git notes add --stripspace -m "${LF}" \
+ -m "first-line" \
+ -m "${MULTI_LF}" \
+ -m "second-line" \
+ -m "${LF}" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add notes by specifying multiple "-m" and "--no-stripspace"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ ${LF}
+ first-line
+ ${MULTI_LF}
+ second-line${LF}
+ EOF
+
+ git notes add --no-stripspace \
+ -m "${LF}" \
+ -m "first-line" \
+ -m "${MULTI_LF}" \
+ -m "second-line" \
+ -m "${LF}" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add note by specifying single "-F", "--stripspace" is the default behavior' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ cat >note-file <<-EOF &&
+ ${LF}
+ first-line
+ ${MULTI_LF}
+ second-line
+ ${LF}
+ EOF
+
+ git notes add -F note-file &&
+ git notes show >actual &&
+ test_cmp expect actual &&
+ git notes remove &&
+ git notes add --stripspace -F note-file &&
+ git notes show >actual
+'
+
+test_expect_success 'add note by specifying single "-F" and "--no-stripspace"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ ${LF}
+ first-line
+ ${MULTI_LF}
+ second-line
+ ${LF}
+ EOF
+
+ cat >note-file <<-EOF &&
+ ${LF}
+ first-line
+ ${MULTI_LF}
+ second-line
+ ${LF}
+ EOF
+
+ git notes add --no-stripspace -F note-file &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add note by specifying multiple "-F", "--stripspace" is the default behavior' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ file-1-first-line
+
+ file-1-second-line
+
+ file-2-first-line
+
+ file-2-second-line
+ EOF
+
+ cat >note-file-1 <<-EOF &&
+ ${LF}
+ file-1-first-line
+ ${MULTI_LF}
+ file-1-second-line
+ ${LF}
+ EOF
+
+ cat >note-file-2 <<-EOF &&
+ ${LF}
+ file-2-first-line
+ ${MULTI_LF}
+ file-2-second-line
+ ${LF}
+ EOF
+
+ git notes add -F note-file-1 -F note-file-2 &&
+ git notes show >actual &&
+ test_cmp expect actual &&
+ git notes remove &&
+ git notes add --stripspace -F note-file-1 -F note-file-2 &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add note by specifying multiple "-F" with "--no-stripspace"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ ${LF}
+ file-1-first-line
+ ${MULTI_LF}
+ file-1-second-line
+ ${LF}
+
+ ${LF}
+ file-2-first-line
+ ${MULTI_LF}
+ file-2-second-line
+ ${LF}
+ EOF
+
+ cat >note-file-1 <<-EOF &&
+ ${LF}
+ file-1-first-line
+ ${MULTI_LF}
+ file-1-second-line
+ ${LF}
+ EOF
+
+ cat >note-file-2 <<-EOF &&
+ ${LF}
+ file-2-first-line
+ ${MULTI_LF}
+ file-2-second-line
+ ${LF}
+ EOF
+
+ git notes add --no-stripspace -F note-file-1 -F note-file-2 &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append note by editor' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ git notes add -m "first-line" &&
+ MSG="${MULTI_LF}second-line${LF}" git notes append &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append note by specifying single "-m"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ git notes add -m "${LF}first-line" &&
+ git notes append -m "${MULTI_LF}second-line${LF}" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append note by specifying multiple "-m"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ git notes add -m "${LF}first-line" &&
+ git notes append -m "${MULTI_LF}" \
+ -m "second-line" \
+ -m "${LF}" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add note by specifying single "-F"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ cat >note-file <<-EOF &&
+ ${LF}
+ first-line
+ ${MULTI_LF}
+ second-line
+ ${LF}
+ EOF
+
+ git notes add -F note-file &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add notes by specifying multiple "-F"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ file-1-first-line
+
+ file-1-second-line
+
+ file-2-first-line
+
+ file-2-second-line
+ EOF
+
+ cat >note-file-1 <<-EOF &&
+ ${LF}
+ file-1-first-line
+ ${MULTI_LF}
+ file-1-second-line
+ ${LF}
+ EOF
+
+ cat >note-file-2 <<-EOF &&
+ ${LF}
+ file-2-first-line
+ ${MULTI_LF}
+ file-2-second-line
+ ${LF}
+ EOF
+
+ git notes add -F note-file-1 -F note-file-2 &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append note by specifying single "-F"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ initial-line
+
+ first-line
+
+ second-line
+ EOF
+
+ cat >note-file <<-EOF &&
+ ${LF}
+ first-line
+ ${MULTI_LF}
+ second-line
+ ${LF}
+ EOF
+
+ git notes add -m "initial-line" &&
+ git notes append -F note-file &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append notes by specifying multiple "-F"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ initial-line
+
+ file-1-first-line
+
+ file-1-second-line
+
+ file-2-first-line
+
+ file-2-second-line
+ EOF
+
+ cat >note-file-1 <<-EOF &&
+ ${LF}
+ file-1-first-line
+ ${MULTI_LF}
+ file-1-second-line
+ ${LF}
+ EOF
+
+ cat >note-file-2 <<-EOF &&
+ ${LF}
+ file-2-first-line
+ ${MULTI_LF}
+ file-2-second-line
+ ${LF}
+ EOF
+
+ git notes add -m "initial-line" &&
+ git notes append -F note-file-1 -F note-file-2 &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'append note by specifying multiple "-F" with "--no-stripspace"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ initial-line
+ ${LF}${LF}
+ file-1-first-line
+ ${MULTI_LF}
+ file-1-second-line
+ ${LF}
+
+ ${LF}
+ file-2-first-line
+ ${MULTI_LF}
+ file-2-second-line
+ ${LF}
+ EOF
+
+ cat >note-file-1 <<-EOF &&
+ ${LF}
+ file-1-first-line
+ ${MULTI_LF}
+ file-1-second-line
+ ${LF}
+ EOF
+
+ cat >note-file-2 <<-EOF &&
+ ${LF}
+ file-2-first-line
+ ${MULTI_LF}
+ file-2-second-line
+ ${LF}
+ EOF
+
+ git notes add -m "initial-line" &&
+ git notes append --no-stripspace -F note-file-1 -F note-file-2 &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add notes with empty messages' '
+ rev=$(git rev-parse HEAD) &&
+ git notes add -m "${LF}" \
+ -m "${MULTI_LF}" \
+ -m "${LF}" >actual 2>&1 &&
+ test_i18ngrep "Removing note for object" actual
+'
+
+test_expect_success 'add note by specifying "-C", "--no-stripspace" is the default behavior' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ ${LF}
+ first-line
+ ${MULTI_LF}
+ second-line
+ ${LF}
+ EOF
+
+ cat expect | git hash-object -w --stdin >blob &&
+ git notes add -C $(cat blob) &&
+ git notes show >actual &&
+ test_cmp expect actual &&
+ git notes remove &&
+ git notes add --no-stripspace -C $(cat blob) &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'reuse note by specifying "-C" and "--stripspace"' '
+ test_when_finished "git notes remove" &&
+ cat >data <<-EOF &&
+ ${LF}
+ first-line
+ ${MULTI_LF}
+ second-line
+ ${LF}
+ EOF
+
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ cat data | git hash-object -w --stdin >blob &&
+ git notes add --stripspace -C $(cat blob) &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'reuse with "-C" and add note with "-m", "-m" will stripspace all together' '
+ test_when_finished "git notes remove" &&
+ cat >data <<-EOF &&
+ ${LF}
+ first-line
+ ${MULTI_LF}
+ second-line
+ ${LF}
+ EOF
+
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+
+ third-line
+ EOF
+
+ cat data | git hash-object -w --stdin >blob &&
+ git notes add -C $(cat blob) -m "third-line" &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add note with "-m" and reuse note with "-C", "-C" will not stripspace all together' '
+ test_when_finished "git notes remove" &&
+ cat >data <<-EOF &&
+
+ second-line
+ EOF
+
+ cat >expect <<-EOF &&
+ first-line
+ ${LF}
+ second-line
+ EOF
+
+ cat data | git hash-object -w --stdin >blob &&
+ git notes add -m "first-line" -C $(cat blob) &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add note by specifying "-c", "--stripspace" is the default behavior' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ echo "initial-line" | git hash-object -w --stdin >blob &&
+ MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes add -c $(cat blob) &&
+ git notes show >actual &&
+ test_cmp expect actual &&
+ git notes remove &&
+ MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes add --stripspace -c $(cat blob) &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'add note by specifying "-c" with "--no-stripspace"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ ${LF}first-line${MULTI_LF}second-line${LF}
+ EOF
+
+ echo "initial-line" | git hash-object -w --stdin >blob &&
+ MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes add --no-stripspace -c $(cat blob) &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'edit note by specifying "-c", "--stripspace" is the default behavior' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ first-line
+
+ second-line
+ EOF
+
+ MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes edit &&
+ git notes show >actual &&
+ test_cmp expect actual &&
+ git notes remove &&
+ MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes edit --stripspace &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'edit note by specifying "-c" with "--no-stripspace"' '
+ test_when_finished "git notes remove" &&
+ cat >expect <<-EOF &&
+ ${LF}first-line${MULTI_LF}second-line${LF}
+ EOF
+
+ MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes add --no-stripspace &&
+ git notes show >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index d5a8ee39fc..d3df19a51f 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -388,6 +388,20 @@ test_expect_success 'switch to branch checked out here' '
git rebase main main
'
+test_expect_success 'switch to branch checked out elsewhere fails' '
+ test_when_finished "
+ git worktree remove wt1 &&
+ git worktree remove wt2 &&
+ git branch -d shared
+ " &&
+ git worktree add wt1 -b shared &&
+ git worktree add wt2 -f shared &&
+ # we test in both worktrees to ensure that works
+ # as expected with "first" and "next" worktrees
+ test_must_fail git -C wt1 rebase shared shared &&
+ test_must_fail git -C wt2 rebase shared shared
+'
+
test_expect_success 'switch to branch not checked out' '
git checkout main &&
git branch other &&
@@ -407,7 +421,7 @@ test_expect_success 'refuse to switch to branch checked out elsewhere' '
git checkout main &&
git worktree add wt &&
test_must_fail git -C wt rebase main main 2>err &&
- test_i18ngrep "already checked out" err
+ test_i18ngrep "already used by worktree at" err
'
test_expect_success MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink' '
diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh
index 7e46f4ca85..e9e03ca4b5 100755
--- a/t/t3402-rebase-merge.sh
+++ b/t/t3402-rebase-merge.sh
@@ -8,6 +8,7 @@ test_description='git rebase --merge test'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
T="A quick brown fox
@@ -131,27 +132,6 @@ test_expect_success 'picking rebase' '
esac
'
-test_expect_success 'rebase -s funny -Xopt' '
- test_when_finished "rm -fr test-bin funny.was.run" &&
- mkdir test-bin &&
- cat >test-bin/git-merge-funny <<-EOF &&
- #!$SHELL_PATH
- case "\$1" in --opt) ;; *) exit 2 ;; esac
- shift &&
- >funny.was.run &&
- exec git merge-recursive "\$@"
- EOF
- chmod +x test-bin/git-merge-funny &&
- git reset --hard &&
- git checkout -b test-funny main^ &&
- test_commit funny &&
- (
- PATH=./test-bin:$PATH &&
- git rebase -s funny -Xopt main
- ) &&
- test -f funny.was.run
-'
-
test_expect_success 'rebase --skip works with two conflicts in a row' '
git checkout second-side &&
tr "[A-Z]" "[a-z]" <newfile >tmp &&
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index f0a0a54fba..8ea2bf1302 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -604,7 +604,8 @@ test_expect_success 'clean error after failed "exec"' '
echo "edited again" > file7 &&
git add file7 &&
test_must_fail git rebase --continue 2>error &&
- test_i18ngrep "you have staged changes in your working tree" error
+ test_i18ngrep "you have staged changes in your working tree" error &&
+ test_i18ngrep ! "could not open.*for reading" error
'
test_expect_success 'rebase a detached HEAD' '
@@ -758,7 +759,7 @@ test_expect_success 'reword' '
git show HEAD~2 | grep "C changed"
'
-test_expect_success 'no uncommited changes when rewording the todo list is reloaded' '
+test_expect_success 'no uncommitted changes when rewording and the todo list is reloaded' '
git checkout E &&
test_when_finished "git checkout @{-1}" &&
(
@@ -1244,9 +1245,9 @@ test_expect_success 'short commit ID collide' '
test $colliding_id = "$(git rev-parse HEAD | cut -c 1-4)" &&
grep "^pick $colliding_id " \
.git/rebase-merge/git-rebase-todo.tmp &&
- grep "^pick [0-9a-f]\{$hexsz\}" \
+ grep -E "^pick [0-9a-f]{$hexsz}" \
.git/rebase-merge/git-rebase-todo &&
- grep "^pick [0-9a-f]\{$hexsz\}" \
+ grep -E "^pick [0-9a-f]{$hexsz}" \
.git/rebase-merge/git-rebase-todo.backup &&
git rebase --continue
) &&
@@ -1261,7 +1262,7 @@ test_expect_success 'respect core.abbrev' '
set_cat_todo_editor &&
test_must_fail git rebase -i HEAD~4 >todo-list
) &&
- test 4 = $(grep -c "pick [0-9a-f]\{12,\}" todo-list)
+ test 4 = $(grep -c -E "pick [0-9a-f]{12,}" todo-list)
'
test_expect_success 'todo count' '
@@ -1276,20 +1277,34 @@ test_expect_success 'todo count' '
'
test_expect_success 'rebase -i commits that overwrite untracked files (pick)' '
- git checkout --force branch2 &&
+ git checkout --force A &&
git clean -f &&
+ cat >todo <<-EOF &&
+ exec >file2
+ pick $(git rev-parse B) B
+ pick $(git rev-parse C) C
+ pick $(git rev-parse D) D
+ exec cat .git/rebase-merge/done >actual
+ EOF
(
- set_fake_editor &&
- FAKE_LINES="edit 1 2" git rebase -i A
- ) &&
- test_cmp_rev HEAD F &&
- test_path_is_missing file6 &&
- >file6 &&
- test_must_fail git rebase --continue &&
- test_cmp_rev HEAD F &&
- rm file6 &&
+ set_replace_editor todo &&
+ test_must_fail git rebase -i A
+ ) &&
+ test_cmp_rev HEAD B &&
+ test_cmp_rev REBASE_HEAD C &&
+ head -n3 todo >expect &&
+ test_cmp expect .git/rebase-merge/done &&
+ rm file2 &&
+ test_path_is_missing .git/rebase-merge/patch &&
+ echo changed >file1 &&
+ git add file1 &&
+ test_must_fail git rebase --continue 2>err &&
+ grep "error: you have staged changes in your working tree" err &&
+ git reset --hard HEAD &&
git rebase --continue &&
- test_cmp_rev HEAD I
+ test_cmp_rev HEAD D &&
+ tail -n3 todo >>expect &&
+ test_cmp expect actual
'
test_expect_success 'rebase -i commits that overwrite untracked files (squash)' '
@@ -1305,7 +1320,14 @@ test_expect_success 'rebase -i commits that overwrite untracked files (squash)'
>file6 &&
test_must_fail git rebase --continue &&
test_cmp_rev HEAD F &&
+ test_cmp_rev REBASE_HEAD I &&
rm file6 &&
+ test_path_is_missing .git/rebase-merge/patch &&
+ echo changed >file1 &&
+ git add file1 &&
+ test_must_fail git rebase --continue 2>err &&
+ grep "error: you have staged changes in your working tree" err &&
+ git reset --hard HEAD &&
git rebase --continue &&
test $(git cat-file commit HEAD | sed -ne \$p) = I &&
git reset --hard original-branch2
@@ -1323,7 +1345,14 @@ test_expect_success 'rebase -i commits that overwrite untracked files (no ff)' '
>file6 &&
test_must_fail git rebase --continue &&
test $(git cat-file commit HEAD | sed -ne \$p) = F &&
+ test_cmp_rev REBASE_HEAD I &&
rm file6 &&
+ test_path_is_missing .git/rebase-merge/patch &&
+ echo changed >file1 &&
+ git add file1 &&
+ test_must_fail git rebase --continue 2>err &&
+ grep "error: you have staged changes in your working tree" err &&
+ git reset --hard HEAD &&
git rebase --continue &&
test $(git cat-file commit HEAD | sed -ne \$p) = I
'
@@ -1449,14 +1478,15 @@ test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = ig
test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = warn' '
cat >expect <<-EOF &&
- error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4)
+ error: invalid command '\''pickled'\''
+ error: invalid line 1: pickled $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4)
Warning: some commits may have been dropped accidentally.
Dropped commits (newer to older):
- $(git rev-list --pretty=oneline --abbrev-commit -1 primary)
- $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4)
To avoid this message, use "drop" to explicitly remove a commit.
EOF
- head -n4 expect >expect.2 &&
+ head -n5 expect >expect.2 &&
tail -n1 expect >>expect.2 &&
tail -n4 expect.2 >expect.3 &&
test_config rebase.missingCommitsCheck warn &&
@@ -1467,7 +1497,7 @@ test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = wa
git rebase -i --root &&
cp .git/rebase-merge/git-rebase-todo.backup orig &&
FAKE_LINES="2 3 4" git rebase --edit-todo 2>actual.2 &&
- head -n6 actual.2 >actual &&
+ head -n7 actual.2 >actual &&
test_cmp expect actual &&
cp orig .git/rebase-merge/git-rebase-todo &&
FAKE_LINES="1 2 3 4" git rebase --edit-todo 2>actual.2 &&
@@ -1483,7 +1513,8 @@ test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = wa
test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = error' '
cat >expect <<-EOF &&
- error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4)
+ error: invalid command '\''pickled'\''
+ error: invalid line 1: pickled $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4)
Warning: some commits may have been dropped accidentally.
Dropped commits (newer to older):
- $(git rev-list --pretty=oneline --abbrev-commit -1 primary)
@@ -1583,7 +1614,7 @@ test_expect_success 'static check of bad command' '
set_fake_editor &&
test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \
git rebase -i --root 2>actual &&
- test_i18ngrep "badcmd $(git rev-list --oneline -1 primary~1)" \
+ test_i18ngrep "pickled $(git rev-list --oneline -1 primary~1)" \
actual &&
test_i18ngrep "You can fix this with .git rebase --edit-todo.." \
actual &&
@@ -1594,6 +1625,32 @@ test_expect_success 'static check of bad command' '
test C = $(git cat-file commit HEAD^ | sed -ne \$p)
'
+test_expect_success 'the first command cannot be a fixup' '
+ rebase_setup_and_clean fixup-first &&
+
+ cat >orig <<-EOF &&
+ fixup $(git log -1 --format="%h %s" B)
+ pick $(git log -1 --format="%h %s" C)
+ EOF
+
+ (
+ set_replace_editor orig &&
+ test_must_fail git rebase -i A 2>actual
+ ) &&
+ grep "cannot .fixup. without a previous commit" actual &&
+ grep "You can fix this with .git rebase --edit-todo.." actual &&
+ # verify that the todo list has not been truncated
+ grep -v "^#" .git/rebase-merge/git-rebase-todo >actual &&
+ test_cmp orig actual &&
+
+ test_must_fail git rebase --edit-todo 2>actual &&
+ grep "cannot .fixup. without a previous commit" actual &&
+ grep "You can fix this with .git rebase --edit-todo.." actual &&
+ # verify that the todo list has not been truncated
+ grep -v "^#" .git/rebase-merge/git-rebase-todo >actual &&
+ test_cmp orig actual
+'
+
test_expect_success 'tabs and spaces are accepted in the todolist' '
rebase_setup_and_clean indented-comment &&
write_script add-indent.sh <<-\EOF &&
@@ -2072,6 +2129,7 @@ test_expect_success '--update-refs: --edit-todo with no update-ref lines' '
'
test_expect_success '--update-refs: check failed ref update' '
+ test_when_finished "test_might_fail git rebase --abort" &&
git checkout -B update-refs-error no-conflict-branch &&
git branch -f base HEAD~4 &&
git branch -f first HEAD~3 &&
@@ -2123,6 +2181,28 @@ test_expect_success '--update-refs: check failed ref update' '
test_cmp expect err.trimmed
'
+test_expect_success 'bad labels and refs rejected when parsing todo list' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ cat >todo <<-\EOF &&
+ exec >execed
+ label #
+ label :invalid
+ update-ref :bad
+ update-ref topic
+ EOF
+ rm -f execed &&
+ (
+ set_replace_editor todo &&
+ test_must_fail git rebase -i HEAD 2>err
+ ) &&
+ grep "'\''#'\'' is not a valid label" err &&
+ grep "'\'':invalid'\'' is not a valid label" err &&
+ grep "'\'':bad'\'' is not a valid refname" err &&
+ grep "update-ref requires a fully qualified refname e.g. refs/heads/topic" \
+ err &&
+ test_path_is_missing execed
+'
+
# This must be the last test in this file
test_expect_success '$EDITOR and friends are unchanged' '
test_editor_unchanged
diff --git a/t/t3405-rebase-malformed.sh b/t/t3405-rebase-malformed.sh
index 2524331861..8979bc3407 100755
--- a/t/t3405-rebase-malformed.sh
+++ b/t/t3405-rebase-malformed.sh
@@ -5,6 +5,7 @@ test_description='rebase should handle arbitrary git message'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index d17b450e81..ceca160005 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -10,10 +10,16 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
test_expect_success 'setup' '
test_commit O fileO &&
test_commit X fileX &&
+ git branch fast-forward &&
test_commit A fileA &&
test_commit B fileB &&
test_commit Y fileY &&
+ git checkout -b conflicts O &&
+ test_commit P &&
+ test_commit conflict-X fileX &&
+ test_commit Q &&
+
git checkout -b topic O &&
git cherry-pick A B &&
test_commit Z fileZ &&
@@ -79,54 +85,165 @@ test_expect_success 'error out early upon -C<n> or --whitespace=<bad>' '
test_i18ngrep "Invalid whitespace option" err
'
-test_expect_success 'GIT_REFLOG_ACTION' '
- git checkout start &&
- test_commit reflog-onto &&
- git checkout -b reflog-topic start &&
- test_commit reflog-to-rebase &&
+write_reflog_expect () {
+ if test $mode = --apply
+ then
+ sed 's/(continue)/(pick)/'
+ else
+ cat
+ fi >expect
+}
- git rebase reflog-onto &&
- git log -g --format=%gs -3 >actual &&
- cat >expect <<-\EOF &&
- rebase (finish): returning to refs/heads/reflog-topic
- rebase (pick): reflog-to-rebase
- rebase (start): checkout reflog-onto
+test_reflog () {
+ mode=$1
+ reflog_action="$2"
+
+ test_expect_success "rebase $mode reflog${reflog_action:+ GIT_REFLOG_ACTION=$reflog_action}" '
+ git checkout conflicts &&
+ test_when_finished "git reset --hard Q" &&
+
+ (
+ if test -n "$reflog_action"
+ then
+ GIT_REFLOG_ACTION="$reflog_action" &&
+ export GIT_REFLOG_ACTION
+ fi &&
+ test_must_fail git rebase $mode main &&
+ echo resolved >fileX &&
+ git add fileX &&
+ git rebase --continue
+ ) &&
+
+ git log -g --format=%gs -5 >actual &&
+ write_reflog_expect <<-EOF &&
+ ${reflog_action:-rebase} (finish): returning to refs/heads/conflicts
+ ${reflog_action:-rebase} (pick): Q
+ ${reflog_action:-rebase} (continue): conflict-X
+ ${reflog_action:-rebase} (pick): P
+ ${reflog_action:-rebase} (start): checkout main
EOF
test_cmp expect actual &&
- git checkout -b reflog-prefix reflog-to-rebase &&
- GIT_REFLOG_ACTION=change-the-reflog git rebase reflog-onto &&
- git log -g --format=%gs -3 >actual &&
- cat >expect <<-\EOF &&
- change-the-reflog (finish): returning to refs/heads/reflog-prefix
- change-the-reflog (pick): reflog-to-rebase
- change-the-reflog (start): checkout reflog-onto
+ git log -g --format=%gs -1 conflicts >actual &&
+ write_reflog_expect <<-EOF &&
+ ${reflog_action:-rebase} (finish): refs/heads/conflicts onto $(git rev-parse main)
+ EOF
+ test_cmp expect actual &&
+
+ # check there is only one new entry in the branch reflog
+ test_cmp_rev conflicts@{1} Q
+ '
+
+ test_expect_success "rebase $mode fast-forward reflog${reflog_action:+ GIT_REFLOG_ACTION=$reflog_action}" '
+ git checkout fast-forward &&
+ test_when_finished "git reset --hard X" &&
+
+ (
+ if test -n "$reflog_action"
+ then
+ GIT_REFLOG_ACTION="$reflog_action" &&
+ export GIT_REFLOG_ACTION
+ fi &&
+ git rebase $mode main
+ ) &&
+
+ git log -g --format=%gs -2 >actual &&
+ write_reflog_expect <<-EOF &&
+ ${reflog_action:-rebase} (finish): returning to refs/heads/fast-forward
+ ${reflog_action:-rebase} (start): checkout main
+ EOF
+ test_cmp expect actual &&
+
+ git log -g --format=%gs -1 fast-forward >actual &&
+ write_reflog_expect <<-EOF &&
+ ${reflog_action:-rebase} (finish): refs/heads/fast-forward onto $(git rev-parse main)
+ EOF
+ test_cmp expect actual &&
+
+ # check there is only one new entry in the branch reflog
+ test_cmp_rev fast-forward@{1} X
+ '
+
+ test_expect_success "rebase $mode --skip reflog${reflog_action:+ GIT_REFLOG_ACTION=$reflog_action}" '
+ git checkout conflicts &&
+ test_when_finished "git reset --hard Q" &&
+
+ (
+ if test -n "$reflog_action"
+ then
+ GIT_REFLOG_ACTION="$reflog_action" &&
+ export GIT_REFLOG_ACTION
+ fi &&
+ test_must_fail git rebase $mode main &&
+ git rebase --skip
+ ) &&
+
+ git log -g --format=%gs -4 >actual &&
+ write_reflog_expect <<-EOF &&
+ ${reflog_action:-rebase} (finish): returning to refs/heads/conflicts
+ ${reflog_action:-rebase} (pick): Q
+ ${reflog_action:-rebase} (pick): P
+ ${reflog_action:-rebase} (start): checkout main
EOF
test_cmp expect actual
-'
+ '
-test_expect_success 'rebase --apply reflog' '
- git checkout -b reflog-apply start &&
- old_head_reflog="$(git log -g --format=%gs -1 HEAD)" &&
+ test_expect_success "rebase $mode --abort reflog${reflog_action:+ GIT_REFLOG_ACTION=$reflog_action}" '
+ git checkout conflicts &&
+ test_when_finished "git reset --hard Q" &&
- git rebase --apply Y &&
+ git log -g -1 conflicts >branch-expect &&
+ (
+ if test -n "$reflog_action"
+ then
+ GIT_REFLOG_ACTION="$reflog_action" &&
+ export GIT_REFLOG_ACTION
+ fi &&
+ test_must_fail git rebase $mode main &&
+ git rebase --abort
+ ) &&
- git log -g --format=%gs -4 HEAD >actual &&
- cat >expect <<-EOF &&
- rebase finished: returning to refs/heads/reflog-apply
- rebase: Z
- rebase: checkout Y
- $old_head_reflog
+ git log -g --format=%gs -3 >actual &&
+ write_reflog_expect <<-EOF &&
+ ${reflog_action:-rebase} (abort): returning to refs/heads/conflicts
+ ${reflog_action:-rebase} (pick): P
+ ${reflog_action:-rebase} (start): checkout main
EOF
test_cmp expect actual &&
- git log -g --format=%gs -2 reflog-apply >actual &&
- cat >expect <<-EOF &&
- rebase finished: refs/heads/reflog-apply onto $(git rev-parse Y)
- branch: Created from start
+ # check branch reflog is unchanged
+ git log -g -1 conflicts >branch-actual &&
+ test_cmp branch-expect branch-actual
+ '
+
+ test_expect_success "rebase $mode --abort detached HEAD reflog${reflog_action:+ GIT_REFLOG_ACTION=$reflog_action}" '
+ git checkout Q &&
+ test_when_finished "git reset --hard Q" &&
+
+ (
+ if test -n "$reflog_action"
+ then
+ GIT_REFLOG_ACTION="$reflog_action" &&
+ export GIT_REFLOG_ACTION
+ fi &&
+ test_must_fail git rebase $mode main &&
+ git rebase --abort
+ ) &&
+
+ git log -g --format=%gs -3 >actual &&
+ write_reflog_expect <<-EOF &&
+ ${reflog_action:-rebase} (abort): returning to $(git rev-parse Q)
+ ${reflog_action:-rebase} (pick): P
+ ${reflog_action:-rebase} (start): checkout main
EOF
test_cmp expect actual
-'
+ '
+}
+
+test_reflog --merge
+test_reflog --merge my-reflog-action
+test_reflog --apply
+test_reflog --apply my-reflog-action
test_expect_success 'rebase -i onto unrelated history' '
git init unrelated &&
diff --git a/t/t3409-rebase-environ.sh b/t/t3409-rebase-environ.sh
index 83ffb39d9f..acaf5558db 100755
--- a/t/t3409-rebase-environ.sh
+++ b/t/t3409-rebase-environ.sh
@@ -2,6 +2,7 @@
test_description='git rebase interactive environment'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh
index 58371d8a54..e75b3d0e07 100755
--- a/t/t3412-rebase-root.sh
+++ b/t/t3412-rebase-root.sh
@@ -7,6 +7,7 @@ Tests if git rebase --root --onto <newparent> can rebase the root commit.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
log_with_names () {
diff --git a/t/t3413-rebase-hook.sh b/t/t3413-rebase-hook.sh
index 9fab0d779b..e8456831e8 100755
--- a/t/t3413-rebase-hook.sh
+++ b/t/t3413-rebase-hook.sh
@@ -5,6 +5,7 @@ test_description='git rebase with its hook(s)'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3416-rebase-onto-threedots.sh b/t/t3416-rebase-onto-threedots.sh
index 3e04802cb0..f8c4ed78c9 100755
--- a/t/t3416-rebase-onto-threedots.sh
+++ b/t/t3416-rebase-onto-threedots.sh
@@ -5,6 +5,7 @@ test_description='git rebase --onto A...B'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-rebase.sh"
@@ -79,8 +80,10 @@ test_expect_success 'rebase -i --onto main...topic' '
git reset --hard &&
git checkout topic &&
git reset --hard G &&
- set_fake_editor &&
- EXPECT_COUNT=1 git rebase -i --onto main...topic F &&
+ (
+ set_fake_editor &&
+ EXPECT_COUNT=1 git rebase -i --onto main...topic F
+ ) &&
git rev-parse HEAD^1 >actual &&
git rev-parse C^0 >expect &&
test_cmp expect actual
@@ -90,20 +93,22 @@ test_expect_success 'rebase -i --onto main...' '
git reset --hard &&
git checkout topic &&
git reset --hard G &&
- set_fake_editor &&
- EXPECT_COUNT=1 git rebase -i --onto main... F &&
+ (
+ set_fake_editor &&
+ EXPECT_COUNT=1 git rebase -i --onto main... F
+ ) &&
git rev-parse HEAD^1 >actual &&
git rev-parse C^0 >expect &&
test_cmp expect actual
'
-test_expect_success 'rebase -i --onto main...side' '
+test_expect_success 'rebase --onto main...side requires a single merge-base' '
git reset --hard &&
git checkout side &&
git reset --hard K &&
- set_fake_editor &&
- test_must_fail git rebase -i --onto main...side J
+ test_must_fail git rebase -i --onto main...side J 2>err &&
+ grep "need exactly one merge base" err
'
test_expect_success 'rebase --keep-base --onto incompatible' '
@@ -156,8 +161,10 @@ test_expect_success 'rebase -i --keep-base main from topic' '
git checkout topic &&
git reset --hard G &&
- set_fake_editor &&
- EXPECT_COUNT=2 git rebase -i --keep-base main &&
+ (
+ set_fake_editor &&
+ EXPECT_COUNT=2 git rebase -i --keep-base main
+ ) &&
git rev-parse C >base.expect &&
git merge-base main HEAD >base.actual &&
test_cmp base.expect base.actual &&
@@ -171,8 +178,10 @@ test_expect_success 'rebase -i --keep-base main topic from main' '
git checkout main &&
git branch -f topic G &&
- set_fake_editor &&
- EXPECT_COUNT=2 git rebase -i --keep-base main topic &&
+ (
+ set_fake_editor &&
+ EXPECT_COUNT=2 git rebase -i --keep-base main topic
+ ) &&
git rev-parse C >base.expect &&
git merge-base main HEAD >base.actual &&
test_cmp base.expect base.actual &&
@@ -182,13 +191,39 @@ test_expect_success 'rebase -i --keep-base main topic from main' '
test_cmp expect actual
'
-test_expect_success 'rebase -i --keep-base main from side' '
+test_expect_success 'rebase --keep-base requires a single merge base' '
git reset --hard &&
git checkout side &&
git reset --hard K &&
- set_fake_editor &&
- test_must_fail git rebase -i --keep-base main
+ test_must_fail git rebase -i --keep-base main 2>err &&
+ grep "need exactly one merge base with branch" err
+'
+
+test_expect_success 'rebase --keep-base keeps cherry picks' '
+ git checkout -f -B main E &&
+ git cherry-pick F &&
+ (
+ set_fake_editor &&
+ EXPECT_COUNT=2 git rebase -i --keep-base HEAD G
+ ) &&
+ test_cmp_rev HEAD G
+'
+
+test_expect_success 'rebase --keep-base --no-reapply-cherry-picks' '
+ git checkout -f -B main E &&
+ git cherry-pick F &&
+ (
+ set_fake_editor &&
+ EXPECT_COUNT=1 git rebase -i --keep-base \
+ --no-reapply-cherry-picks HEAD G
+ ) &&
+ test_cmp_rev HEAD^ C
+'
+
+# This must be the last test in this file
+test_expect_success '$EDITOR and friends are unchanged' '
+ test_editor_unchanged
'
test_done
diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index 130e2f9b55..c4e2fcac67 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -62,61 +62,39 @@ test_expect_success 'rebase --continue remembers merge strategy and options' '
rm -fr .git/rebase-* &&
git reset --hard commit-new-file-F2-on-topic-branch &&
test_commit "commit-new-file-F3-on-topic-branch" F3 32 &&
- test_when_finished "rm -fr test-bin funny.was.run" &&
+ test_when_finished "rm -fr test-bin" &&
mkdir test-bin &&
- cat >test-bin/git-merge-funny <<-EOF &&
- #!$SHELL_PATH
- case "\$1" in --opt) ;; *) exit 2 ;; esac
- shift &&
- >funny.was.run &&
- exec git merge-recursive "\$@"
+
+ write_script test-bin/git-merge-funny <<-\EOF &&
+ printf "[%s]\n" $# "$1" "$2" "$3" "$5" >actual
+ shift 3 &&
+ exec git merge-recursive "$@"
EOF
- chmod +x test-bin/git-merge-funny &&
- (
- PATH=./test-bin:$PATH &&
- test_must_fail git rebase -s funny -Xopt main topic
- ) &&
- test -f funny.was.run &&
- rm funny.was.run &&
- echo "Resolved" >F2 &&
- git add F2 &&
- (
- PATH=./test-bin:$PATH &&
- git rebase --continue
- ) &&
- test -f funny.was.run
-'
-test_expect_success 'rebase -i --continue handles merge strategy and options' '
- rm -fr .git/rebase-* &&
- git reset --hard commit-new-file-F2-on-topic-branch &&
- test_commit "commit-new-file-F3-on-topic-branch-for-dash-i" F3 32 &&
- test_when_finished "rm -fr test-bin funny.was.run funny.args" &&
- mkdir test-bin &&
- cat >test-bin/git-merge-funny <<-EOF &&
- #!$SHELL_PATH
- echo "\$@" >>funny.args
- case "\$1" in --opt) ;; *) exit 2 ;; esac
- case "\$2" in --foo) ;; *) exit 2 ;; esac
- case "\$4" in --) ;; *) exit 2 ;; esac
- shift 2 &&
- >funny.was.run &&
- exec git merge-recursive "\$@"
+ cat >expect <<-\EOF &&
+ [7]
+ [--option=arg with space]
+ [--op"tion\]
+ [--new
+ line ]
+ [--]
EOF
- chmod +x test-bin/git-merge-funny &&
+
+ rm -f actual &&
(
PATH=./test-bin:$PATH &&
- test_must_fail git rebase -i -s funny -Xopt -Xfoo main topic
+ test_must_fail git rebase -s funny -X"option=arg with space" \
+ -Xop\"tion\\ -X"new${LF}line " main topic
) &&
- test -f funny.was.run &&
- rm funny.was.run &&
+ test_cmp expect actual &&
+ rm actual &&
echo "Resolved" >F2 &&
git add F2 &&
(
PATH=./test-bin:$PATH &&
git rebase --continue
) &&
- test -f funny.was.run
+ test_cmp expect actual
'
test_expect_success 'rebase -r passes merge strategy options correctly' '
@@ -137,15 +115,23 @@ test_expect_success '--skip after failed fixup cleans commit message' '
test_when_finished "test_might_fail git rebase --abort" &&
git checkout -b with-conflicting-fixup &&
test_commit wants-fixup &&
- test_commit "fixup! wants-fixup" wants-fixup.t 1 wants-fixup-1 &&
- test_commit "fixup! wants-fixup" wants-fixup.t 2 wants-fixup-2 &&
- test_commit "fixup! wants-fixup" wants-fixup.t 3 wants-fixup-3 &&
+ test_commit "fixup 1" wants-fixup.t 1 wants-fixup-1 &&
+ test_commit "fixup 2" wants-fixup.t 2 wants-fixup-2 &&
+ test_commit "fixup 3" wants-fixup.t 3 wants-fixup-3 &&
test_must_fail env FAKE_LINES="1 fixup 2 squash 4" \
git rebase -i HEAD~4 &&
: now there is a conflict, and comments in the commit message &&
- git show HEAD >out &&
- grep "fixup! wants-fixup" out &&
+ test_commit_message HEAD <<-\EOF &&
+ # This is a combination of 2 commits.
+ # This is the 1st commit message:
+
+ wants-fixup
+
+ # The commit message #2 will be skipped:
+
+ # fixup 1
+ EOF
: skip and continue &&
echo "cp \"\$1\" .git/copy.txt" | write_script copy-editor.sh &&
@@ -155,33 +141,49 @@ test_expect_success '--skip after failed fixup cleans commit message' '
test_path_is_missing .git/copy.txt &&
: now the comments in the commit message should have been cleaned up &&
- git show HEAD >out &&
- ! grep "fixup! wants-fixup" out &&
+ test_commit_message HEAD -m wants-fixup &&
: now, let us ensure that "squash" is handled correctly &&
git reset --hard wants-fixup-3 &&
- test_must_fail env FAKE_LINES="1 squash 4 squash 2 squash 4" \
+ test_must_fail env FAKE_LINES="1 squash 2 squash 1 squash 3 squash 1" \
git rebase -i HEAD~4 &&
- : the first squash failed, but there are two more in the chain &&
+ : the second squash failed, but there are two more in the chain &&
(test_set_editor "$PWD/copy-editor.sh" &&
test_must_fail git rebase --skip) &&
: not the final squash, no need to edit the commit message &&
test_path_is_missing .git/copy.txt &&
- : The first squash was skipped, therefore: &&
- git show HEAD >out &&
- test_i18ngrep "# This is a combination of 2 commits" out &&
- test_i18ngrep "# This is the commit message #2:" out &&
+ : The first and third squashes succeeded, therefore: &&
+ test_commit_message HEAD <<-\EOF &&
+ # This is a combination of 3 commits.
+ # This is the 1st commit message:
+
+ wants-fixup
+
+ # This is the commit message #2:
+
+ fixup 1
+
+ # This is the commit message #3:
+
+ fixup 2
+ EOF
(test_set_editor "$PWD/copy-editor.sh" && git rebase --skip) &&
- git show HEAD >out &&
- test_i18ngrep ! "# This is a combination" out &&
+ test_commit_message HEAD <<-\EOF &&
+ wants-fixup
+
+ fixup 1
+
+ fixup 2
+ EOF
: Final squash failed, but there was still a squash &&
- test_i18ngrep "# This is a combination of 2 commits" .git/copy.txt &&
- test_i18ngrep "# This is the commit message #2:" .git/copy.txt
+ head -n1 .git/copy.txt >first-line &&
+ test_i18ngrep "# This is a combination of 3 commits" first-line &&
+ test_i18ngrep "# This is the commit message #3:" .git/copy.txt
'
test_expect_success 'setup rerere database' '
@@ -266,6 +268,24 @@ test_expect_success 'the todo command "break" works' '
test_path_is_file execed
'
+test_expect_success 'patch file is removed before break command' '
+ test_when_finished "git rebase --abort" &&
+ cat >todo <<-\EOF &&
+ pick commit-new-file-F2-on-topic-branch
+ break
+ EOF
+
+ (
+ set_replace_editor todo &&
+ test_must_fail git rebase -i --onto commit-new-file-F2 HEAD
+ ) &&
+ test_path_is_file .git/rebase-merge/patch &&
+ echo 22>F2 &&
+ git add F2 &&
+ git rebase --continue &&
+ test_path_is_missing .git/rebase-merge/patch
+'
+
test_expect_success '--reschedule-failed-exec' '
test_when_finished "git rebase --abort" &&
test_must_fail git rebase -x false --reschedule-failed-exec HEAD^ &&
diff --git a/t/t3419-rebase-patch-id.sh b/t/t3419-rebase-patch-id.sh
index 295040f2fe..6c61f240cf 100755
--- a/t/t3419-rebase-patch-id.sh
+++ b/t/t3419-rebase-patch-id.sh
@@ -5,6 +5,7 @@ test_description='git rebase - test patch id computation'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
scramble () {
@@ -43,15 +44,26 @@ test_expect_success 'setup: 500 lines' '
git add newfile &&
git commit -q -m "add small file" &&
- git cherry-pick main >/dev/null 2>&1
-'
+ git cherry-pick main >/dev/null 2>&1 &&
+
+ git branch -f squashed main &&
+ git checkout -q -f squashed &&
+ git reset -q --soft HEAD~2 &&
+ git commit -q -m squashed &&
+
+ git branch -f mode main &&
+ git checkout -q -f mode &&
+ test_chmod +x file &&
+ git commit -q -a --amend &&
-test_expect_success 'setup attributes' '
- echo "file binary" >.gitattributes
+ git branch -f modeother other &&
+ git checkout -q -f modeother &&
+ test_chmod +x file &&
+ git commit -q -a --amend
'
test_expect_success 'detect upstream patch' '
- git checkout -q main &&
+ git checkout -q main^{} &&
scramble file &&
git add file &&
git commit -q -m "change big file again" &&
@@ -61,14 +73,46 @@ test_expect_success 'detect upstream patch' '
test_must_be_empty revs
'
+test_expect_success 'detect upstream patch binary' '
+ echo "file binary" >.gitattributes &&
+ git checkout -q other^{} &&
+ git rebase main &&
+ git rev-list main...HEAD~ >revs &&
+ test_must_be_empty revs &&
+ test_when_finished "rm .gitattributes"
+'
+
+test_expect_success 'detect upstream patch modechange' '
+ git checkout -q modeother^{} &&
+ git rebase mode &&
+ git rev-list mode...HEAD~ >revs &&
+ test_must_be_empty revs
+'
+
test_expect_success 'do not drop patch' '
- git branch -f squashed main &&
- git checkout -q -f squashed &&
- git reset -q --soft HEAD~2 &&
- git commit -q -m squashed &&
git checkout -q other^{} &&
test_must_fail git rebase squashed &&
- git rebase --quit
+ test_when_finished "git rebase --abort"
+'
+
+test_expect_success 'do not drop patch binary' '
+ echo "file binary" >.gitattributes &&
+ git checkout -q other^{} &&
+ test_must_fail git rebase squashed &&
+ test_when_finished "git rebase --abort" &&
+ test_when_finished "rm .gitattributes"
+'
+
+test_expect_success 'do not drop patch modechange' '
+ git checkout -q modeother^{} &&
+ git rebase other &&
+ cat >expected <<-\EOF &&
+ diff --git a/file b/file
+ old mode 100644
+ new mode 100755
+ EOF
+ git diff HEAD~ >modediff &&
+ test_cmp expected modediff
'
test_done
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 6dabb05a2a..2eba00bdf5 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -25,11 +25,11 @@ test_expect_success 'setup' '
'
#
-# Rebase has lots of useful options like --whitepsace=fix, which are
-# actually all built in terms of flags to git-am. Since neither
-# --merge nor --interactive (nor any options that imply those two) use
-# git-am, using them together will result in flags like --whitespace=fix
-# being ignored. Make sure rebase warns the user and aborts instead.
+# Rebase has a couple options which are specific to the apply backend,
+# and several options which are specific to the merge backend. Flags
+# from the different sets cannot work together, and we do not want to
+# just ignore one of the sets of flags. Make sure rebase warns the
+# user and aborts instead.
#
test_rebase_am_only () {
@@ -50,6 +50,11 @@ test_rebase_am_only () {
test_must_fail git rebase $opt --strategy-option=ours A
"
+ test_expect_success "$opt incompatible with --autosquash" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --autosquash A
+ "
+
test_expect_success "$opt incompatible with --interactive" "
git checkout B^0 &&
test_must_fail git rebase $opt --interactive A
@@ -60,9 +65,82 @@ test_rebase_am_only () {
test_must_fail git rebase $opt --exec 'true' A
"
+ test_expect_success "$opt incompatible with --keep-empty" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --keep-empty A
+ "
+
+ test_expect_success "$opt incompatible with --empty=..." "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --empty=ask A
+ "
+
+ test_expect_success "$opt incompatible with --no-reapply-cherry-picks" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --no-reapply-cherry-picks A
+ "
+
+ test_expect_success "$opt incompatible with --reapply-cherry-picks" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --reapply-cherry-picks A
+ "
+
+ test_expect_success "$opt incompatible with --rebase-merges" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --rebase-merges A
+ "
+
+ test_expect_success "$opt incompatible with --update-refs" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --update-refs A
+ "
+
+ test_expect_success "$opt incompatible with --root without --onto" "
+ git checkout B^0 &&
+ test_must_fail git rebase $opt --root A
+ "
+
+ test_expect_success "$opt incompatible with rebase.autosquash" "
+ git checkout B^0 &&
+ test_must_fail git -c rebase.autosquash=true rebase $opt A 2>err &&
+ grep -e --no-autosquash err
+ "
+
+ test_expect_success "$opt incompatible with rebase.rebaseMerges" "
+ git checkout B^0 &&
+ test_must_fail git -c rebase.rebaseMerges=true rebase $opt A 2>err &&
+ grep -e --no-rebase-merges err
+ "
+
+ test_expect_success "$opt incompatible with rebase.updateRefs" "
+ git checkout B^0 &&
+ test_must_fail git -c rebase.updateRefs=true rebase $opt A 2>err &&
+ grep -e --no-update-refs err
+ "
+
+ test_expect_success "$opt okay with overridden rebase.autosquash" "
+ test_when_finished \"git reset --hard B^0\" &&
+ git checkout B^0 &&
+ git -c rebase.autosquash=true rebase --no-autosquash $opt A
+ "
+
+ test_expect_success "$opt okay with overridden rebase.rebaseMerges" "
+ test_when_finished \"git reset --hard B^0\" &&
+ git checkout B^0 &&
+ git -c rebase.rebaseMerges=true rebase --no-rebase-merges $opt A
+ "
+
+ test_expect_success "$opt okay with overridden rebase.updateRefs" "
+ test_when_finished \"git reset --hard B^0\" &&
+ git checkout B^0 &&
+ git -c rebase.updateRefs=true rebase --no-update-refs $opt A
+ "
}
+# Check options which imply --apply
test_rebase_am_only --whitespace=fix
test_rebase_am_only -C4
+# Also check an explicit --apply
+test_rebase_am_only --apply
test_done
diff --git a/t/t3423-rebase-reword.sh b/t/t3423-rebase-reword.sh
index 4859bb8f72..2fab703d61 100755
--- a/t/t3423-rebase-reword.sh
+++ b/t/t3423-rebase-reword.sh
@@ -2,6 +2,7 @@
test_description='git rebase interactive with rewording'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3425-rebase-topology-merges.sh b/t/t3425-rebase-topology-merges.sh
index 63acc1ea4d..a16428bdf5 100755
--- a/t/t3425-rebase-topology-merges.sh
+++ b/t/t3425-rebase-topology-merges.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='rebase topology tests with merges'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh
index 48b76f8232..1b3e97c875 100755
--- a/t/t3427-rebase-subtree.sh
+++ b/t/t3427-rebase-subtree.sh
@@ -74,9 +74,9 @@ test_expect_success 'Rebase -Xsubtree --empty=ask --onto commit' '
test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --onto files-main main &&
: first pick results in no changes &&
git rebase --skip &&
- verbose test "$(commit_message HEAD~2)" = "topic_4" &&
- verbose test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
- verbose test "$(commit_message HEAD)" = "Empty commit"
+ test "$(commit_message HEAD~2)" = "topic_4" &&
+ test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
+ test "$(commit_message HEAD)" = "Empty commit"
'
test_expect_success 'Rebase -Xsubtree --empty=ask --rebase-merges --onto commit' '
@@ -85,9 +85,9 @@ test_expect_success 'Rebase -Xsubtree --empty=ask --rebase-merges --onto commit'
test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --rebase-merges --onto files-main --root &&
: first pick results in no changes &&
git rebase --skip &&
- verbose test "$(commit_message HEAD~2)" = "topic_4" &&
- verbose test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
- verbose test "$(commit_message HEAD)" = "Empty commit"
+ test "$(commit_message HEAD~2)" = "topic_4" &&
+ test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
+ test "$(commit_message HEAD)" = "Empty commit"
'
test_done
diff --git a/t/t3428-rebase-signoff.sh b/t/t3428-rebase-signoff.sh
index f6993b7e14..e1b1e94764 100755
--- a/t/t3428-rebase-signoff.sh
+++ b/t/t3428-rebase-signoff.sh
@@ -5,6 +5,7 @@ test_description='git rebase --signoff
This test runs git rebase --signoff and make sure that it works.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# A simple file to commit
diff --git a/t/t3429-rebase-edit-todo.sh b/t/t3429-rebase-edit-todo.sh
index abd66f3602..8e0d03969a 100755
--- a/t/t3429-rebase-edit-todo.sh
+++ b/t/t3429-rebase-edit-todo.sh
@@ -2,6 +2,7 @@
test_description='rebase should reread the todo file if an exec modifies it'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh
index f351701fec..59b5d6b6f2 100755
--- a/t/t3430-rebase-merges.sh
+++ b/t/t3430-rebase-merges.sh
@@ -128,14 +128,41 @@ test_expect_success 'generate correct todo list' '
'
test_expect_success '`reset` refuses to overwrite untracked files' '
- git checkout -b refuse-to-reset &&
+ git checkout B &&
test_commit dont-overwrite-untracked &&
- git checkout @{-1} &&
- : >dont-overwrite-untracked.t &&
- echo "reset refs/tags/dont-overwrite-untracked" >script-from-scratch &&
+ cat >script-from-scratch <<-EOF &&
+ exec >dont-overwrite-untracked.t
+ pick $(git rev-parse B) B
+ reset refs/tags/dont-overwrite-untracked
+ pick $(git rev-parse C) C
+ exec cat .git/rebase-merge/done >actual
+ EOF
test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
- test_must_fail git rebase -ir HEAD &&
- git rebase --abort
+ test_must_fail git rebase -ir A &&
+ test_cmp_rev HEAD B &&
+ head -n3 script-from-scratch >expect &&
+ test_cmp expect .git/rebase-merge/done &&
+ rm dont-overwrite-untracked.t &&
+ git rebase --continue &&
+ tail -n3 script-from-scratch >>expect &&
+ test_cmp expect actual
+'
+
+test_expect_success '`reset` rejects trees' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ test_must_fail env GIT_SEQUENCE_EDITOR="echo reset A^{tree} >" \
+ git rebase -i B C >out 2>err &&
+ grep "object .* is a tree" err &&
+ test_must_be_empty out
+'
+
+test_expect_success '`reset` only looks for labels under refs/rewritten/' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git branch refs/rewritten/my-label A &&
+ test_must_fail env GIT_SEQUENCE_EDITOR="echo reset my-label >" \
+ git rebase -i B C >out 2>err &&
+ grep "could not resolve ${SQ}my-label${SQ}" err &&
+ test_must_be_empty out
'
test_expect_success 'failed `merge -C` writes patch (may be rescheduled, too)' '
@@ -148,12 +175,16 @@ test_expect_success 'failed `merge -C` writes patch (may be rescheduled, too)' '
test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
test_tick &&
test_must_fail git rebase -ir HEAD &&
+ test_cmp_rev REBASE_HEAD H^0 &&
grep "^merge -C .* G$" .git/rebase-merge/done &&
grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo &&
- test_path_is_file .git/rebase-merge/patch &&
+ test_path_is_missing .git/rebase-merge/patch &&
+ echo changed >file1 &&
+ git add file1 &&
+ test_must_fail git rebase --continue 2>err &&
+ grep "error: you have staged changes in your working tree" err &&
: fail because of merge conflict &&
- rm G.t .git/rebase-merge/patch &&
git reset --hard conflicting-G &&
test_must_fail git rebase --continue &&
! grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo &&
@@ -233,6 +264,16 @@ test_expect_success 'with a branch tip that was cherry-picked already' '
EOF
'
+test_expect_success '--no-rebase-merges countermands --rebase-merges' '
+ git checkout -b no-rebase-merges E &&
+ git rebase --rebase-merges --no-rebase-merges C &&
+ test_cmp_graph C.. <<-\EOF
+ * B
+ * D
+ o C
+ EOF
+'
+
test_expect_success 'do not rebase cousins unless asked for' '
git checkout -b cousins main &&
before="$(git rev-parse --verify HEAD)" &&
@@ -251,6 +292,40 @@ test_expect_success 'do not rebase cousins unless asked for' '
EOF
'
+test_expect_success 'rebase.rebaseMerges=rebase-cousins is equivalent to --rebase-merges=rebase-cousins' '
+ test_config rebase.rebaseMerges rebase-cousins &&
+ git checkout -b config-rebase-cousins main &&
+ git rebase HEAD^ &&
+ test_cmp_graph HEAD^.. <<-\EOF
+ * Merge the topic branch '\''onebranch'\''
+ |\
+ | * D
+ | * G
+ |/
+ o H
+ EOF
+'
+
+test_expect_success '--no-rebase-merges overrides rebase.rebaseMerges=no-rebase-cousins' '
+ test_config rebase.rebaseMerges no-rebase-cousins &&
+ git checkout -b override-config-no-rebase-cousins E &&
+ git rebase --no-rebase-merges C &&
+ test_cmp_graph C.. <<-\EOF
+ * B
+ * D
+ o C
+ EOF
+'
+
+test_expect_success '--rebase-merges overrides rebase.rebaseMerges=rebase-cousins' '
+ test_config rebase.rebaseMerges rebase-cousins &&
+ git checkout -b override-config-rebase-cousins E &&
+ before="$(git rev-parse --verify HEAD)" &&
+ test_tick &&
+ git rebase --rebase-merges C &&
+ test_cmp_rev HEAD $before
+'
+
test_expect_success 'refs/rewritten/* is worktree-local' '
git worktree add wt &&
cat >wt/script-from-scratch <<-\EOF &&
@@ -517,4 +592,23 @@ test_expect_success '--rebase-merges with message matched with onto label' '
EOF
'
+test_expect_success 'progress shows the correct total' '
+ git checkout -b progress H &&
+ git rebase --rebase-merges --force-rebase --verbose A 2> err &&
+ # Expecting "Rebasing (N/14)" here, no bogus total number
+ grep "^Rebasing.*/14.$" err >progress &&
+ test_line_count = 14 progress
+'
+
+test_expect_success 'truncate label names' '
+ commit=$(git commit-tree -p HEAD^ -p HEAD -m "0123456789 我 123" HEAD^{tree}) &&
+ git merge --ff-only $commit &&
+
+ done="$(git rev-parse --git-path rebase-merge/done)" &&
+ git -c rebase.maxLabelLength=14 rebase --rebase-merges -x "cp \"$done\" out" --root &&
+ grep "label 0123456789-我$" out &&
+ git -c rebase.maxLabelLength=13 rebase --rebase-merges -x "cp \"$done\" out" --root &&
+ grep "label 0123456789-$" out
+'
+
test_done
diff --git a/t/t3431-rebase-fork-point.sh b/t/t3431-rebase-fork-point.sh
index 1d0b15380e..4bfc779bb8 100755
--- a/t/t3431-rebase-fork-point.sh
+++ b/t/t3431-rebase-fork-point.sh
@@ -8,6 +8,7 @@ test_description='git rebase --fork-point test'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# A---B---D---E (main)
@@ -50,7 +51,7 @@ test_rebase () {
test_rebase 'G F E D B A'
test_rebase 'G F D B A' --onto D
-test_rebase 'G F B A' --keep-base
+test_rebase 'G F C B A' --keep-base
test_rebase 'G F C E D B A' --no-fork-point
test_rebase 'G F C D B A' --no-fork-point --onto D
test_rebase 'G F C B A' --no-fork-point --keep-base
diff --git a/t/t3432-rebase-fast-forward.sh b/t/t3432-rebase-fast-forward.sh
index 5086e14c02..7f1a5dd3de 100755
--- a/t/t3432-rebase-fast-forward.sh
+++ b/t/t3432-rebase-fast-forward.sh
@@ -8,6 +8,7 @@ test_description='ensure rebase fast-forwards commits when possible'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3433-rebase-across-mode-change.sh b/t/t3433-rebase-across-mode-change.sh
index 05df964670..c8172b0852 100755
--- a/t/t3433-rebase-across-mode-change.sh
+++ b/t/t3433-rebase-across-mode-change.sh
@@ -2,6 +2,7 @@
test_description='git rebase across mode change'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t3437-rebase-fixup-options.sh b/t/t3437-rebase-fixup-options.sh
index c023fefd68..7929e2e2e3 100755
--- a/t/t3437-rebase-fixup-options.sh
+++ b/t/t3437-rebase-fixup-options.sh
@@ -14,27 +14,13 @@ to the "fixup" command that works with "fixup!", "fixup -C" works with
"amend!" upon --autosquash.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
EMPTY=""
-# test_commit_message <rev> -m <msg>
-# test_commit_message <rev> <path>
-# Verify that the commit message of <rev> matches
-# <msg> or the content of <path>.
-test_commit_message () {
- git show --no-patch --pretty=format:%B "$1" >actual &&
- case "$2" in
- -m)
- echo "$3" >expect &&
- test_cmp expect actual ;;
- *)
- test_cmp "$2" actual ;;
- esac
-}
-
get_author () {
rev="$1" &&
git log -1 --pretty=format:"%an %ae %at" "$rev"
@@ -50,6 +36,7 @@ test_expect_success 'setup' '
body
EOF
+ test_commit initial &&
test_commit A A &&
test_commit B B &&
get_author HEAD >expected-author &&
@@ -208,4 +195,29 @@ test_expect_success 'fixup -C works upon --autosquash with amend!' '
actual-squash-message
'
+test_expect_success 'fixup -[Cc]<commit> works' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ cat >todo <<-\EOF &&
+ pick A
+ fixup -CA1
+ pick B
+ fixup -cA2
+ EOF
+ (
+ set_replace_editor todo &&
+ FAKE_COMMIT_MESSAGE="edited and fixed up" \
+ git rebase -i initial initial
+ ) &&
+ git log --pretty=format:%B initial.. >actual &&
+ cat >expect <<-EOF &&
+ edited and fixed up
+ $EMPTY
+ new subject
+ $EMPTY
+ new
+ body
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3438-rebase-broken-files.sh b/t/t3438-rebase-broken-files.sh
index b92a3ce46b..c614c4f2e4 100755
--- a/t/t3438-rebase-broken-files.sh
+++ b/t/t3438-rebase-broken-files.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='rebase behavior when on-disk files are broken'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'set up conflicting branches' '
diff --git a/t/t3500-cherry.sh b/t/t3500-cherry.sh
index 0458a58b4b..78c3eac54b 100755
--- a/t/t3500-cherry.sh
+++ b/t/t3500-cherry.sh
@@ -16,46 +16,43 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
GIT_AUTHOR_EMAIL=bogus_email_address
export GIT_AUTHOR_EMAIL
-test_expect_success \
- 'prepare repository with topic branch, and check cherry finds the 2 patches from there' \
- 'echo First > A &&
- git update-index --add A &&
- test_tick &&
- git commit -m "Add A." &&
-
- git checkout -b my-topic-branch &&
-
- echo Second > B &&
- git update-index --add B &&
- test_tick &&
- git commit -m "Add B." &&
-
- echo AnotherSecond > C &&
- git update-index --add C &&
- test_tick &&
- git commit -m "Add C." &&
-
- git checkout -f main &&
- rm -f B C &&
-
- echo Third >> A &&
- git update-index A &&
- test_tick &&
- git commit -m "Modify A." &&
-
- expr "$(echo $(git cherry main my-topic-branch) )" : "+ [^ ]* + .*"
+test_expect_success 'prepare repository with topic branch, and check cherry finds the 2 patches from there' '
+ echo First > A &&
+ git update-index --add A &&
+ test_tick &&
+ git commit -m "Add A." &&
+
+ git checkout -b my-topic-branch &&
+
+ echo Second > B &&
+ git update-index --add B &&
+ test_tick &&
+ git commit -m "Add B." &&
+
+ echo AnotherSecond > C &&
+ git update-index --add C &&
+ test_tick &&
+ git commit -m "Add C." &&
+
+ git checkout -f main &&
+ rm -f B C &&
+
+ echo Third >> A &&
+ git update-index A &&
+ test_tick &&
+ git commit -m "Modify A." &&
+
+ expr "$(echo $(git cherry main my-topic-branch) )" : "+ [^ ]* + .*"
'
-test_expect_success \
- 'check that cherry with limit returns only the top patch'\
- 'expr "$(echo $(git cherry main my-topic-branch my-topic-branch^1) )" : "+ [^ ]*"
+test_expect_success 'check that cherry with limit returns only the top patch' '
+ expr "$(echo $(git cherry main my-topic-branch my-topic-branch^1) )" : "+ [^ ]*"
'
-test_expect_success \
- 'cherry-pick one of the 2 patches, and check cherry recognized one and only one as new' \
- 'git cherry-pick my-topic-branch^0 &&
- echo $(git cherry main my-topic-branch) &&
- expr "$(echo $(git cherry main my-topic-branch) )" : "+ [^ ]* - .*"
+test_expect_success 'cherry-pick one of the 2 patches, and check cherry recognized one and only one as new' '
+ git cherry-pick my-topic-branch^0 &&
+ echo $(git cherry main my-topic-branch) &&
+ expr "$(echo $(git cherry main my-topic-branch) )" : "+ [^ ]* - .*"
'
test_expect_success 'cherry ignores whitespace' '
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 1f4cfc3744..4158590322 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -1,18 +1,11 @@
#!/bin/sh
-test_description='test cherry-pick and revert with renames
-
- --
- + rename2: renames oops to opos
- + rename1: renames oops to spoo
- + added: adds extra line to oops
- ++ initial: has lines in oops
-
-'
+test_description='miscellaneous basic tests for cherry-pick and revert'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
@@ -62,6 +55,14 @@ test_expect_success 'revert --nonsense' '
test_i18ngrep "[Uu]sage:" msg
'
+# the following two test cherry-pick and revert with renames
+#
+# --
+# + rename2: renames oops to opos
+# + rename1: renames oops to spoo
+# + added: adds extra line to oops
+# ++ initial: has lines in oops
+
test_expect_success 'cherry-pick after renaming branch' '
git checkout rename2 &&
@@ -175,6 +176,29 @@ test_expect_success 'advice from failed revert' '
test_cmp expected actual
'
+test_expect_subject () {
+ echo "$1" >expect &&
+ git log -1 --pretty=%s >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'titles of fresh reverts' '
+ test_commit --no-tag A file1 &&
+ test_commit --no-tag B file1 &&
+ git revert --no-edit HEAD &&
+ test_expect_subject "Revert \"B\"" &&
+ git revert --no-edit HEAD &&
+ test_expect_subject "Reapply \"B\"" &&
+ git revert --no-edit HEAD &&
+ test_expect_subject "Revert \"Reapply \"B\"\""
+'
+
+test_expect_success 'title of legacy double revert' '
+ test_commit --no-tag "Revert \"Revert \"B\"\"" file1 &&
+ git revert --no-edit HEAD &&
+ test_expect_subject "Revert \"Revert \"Revert \"B\"\"\""
+'
+
test_expect_success 'identification of reverted commit (default)' '
test_commit to-ident &&
test_when_finished "git reset --hard to-ident" &&
diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh
index 5495eacfec..1b2c0d6aca 100755
--- a/t/t3502-cherry-pick-merge.sh
+++ b/t/t3502-cherry-pick-merge.sh
@@ -11,6 +11,7 @@ test_description='cherry picking and reverting a merge
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh
index 95fe4feaee..76d393dc8a 100755
--- a/t/t3503-cherry-pick-root.sh
+++ b/t/t3503-cherry-pick-root.sh
@@ -5,6 +5,7 @@ test_description='test cherry-picking (and reverting) a root commit'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh
index 7e11bd4a4c..b71bad17b8 100755
--- a/t/t3506-cherry-pick-ff.sh
+++ b/t/t3506-cherry-pick-ff.sh
@@ -5,6 +5,7 @@ test_description='test cherry-picking with --ff option'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3511-cherry-pick-x.sh b/t/t3511-cherry-pick-x.sh
index 84a587daf3..dd5d92ef30 100755
--- a/t/t3511-cherry-pick-x.sh
+++ b/t/t3511-cherry-pick-x.sh
@@ -2,6 +2,7 @@
test_description='Test cherry-pick -x and -s'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
pristine_detach () {
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 8689b48589..7623689da2 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -24,17 +24,17 @@ test_mode_in_index () {
esac
}
-test_expect_success \
- 'Test of git add' \
- 'touch foo && git add foo'
+test_expect_success 'Test of git add' '
+ touch foo && git add foo
+'
-test_expect_success \
- 'Post-check that foo is in the index' \
- 'git ls-files foo | grep foo'
+test_expect_success 'Post-check that foo is in the index' '
+ git ls-files foo | grep foo
+'
-test_expect_success \
- 'Test that "git add -- -q" works' \
- 'touch -- -q && git add -- -q'
+test_expect_success 'Test that "git add -- -q" works' '
+ touch -- -q && git add -- -q
+'
BATCH_CONFIGURATION='-c core.fsync=loose-object -c core.fsyncmethod=batch'
@@ -106,24 +106,32 @@ test_expect_success '.gitignore test setup' '
test_expect_success '.gitignore is honored' '
git add . &&
- ! (git ls-files | grep "\\.ig")
+ git ls-files >files &&
+ sed -n "/\\.ig/p" <files >actual &&
+ test_must_be_empty actual
'
test_expect_success 'error out when attempting to add ignored ones without -f' '
test_must_fail git add a.?? &&
- ! (git ls-files | grep "\\.ig")
+ git ls-files >files &&
+ sed -n "/\\.ig/p" <files >actual &&
+ test_must_be_empty actual
'
test_expect_success 'error out when attempting to add ignored ones without -f' '
test_must_fail git add d.?? &&
- ! (git ls-files | grep "\\.ig")
+ git ls-files >files &&
+ sed -n "/\\.ig/p" <files >actual &&
+ test_must_be_empty actual
'
test_expect_success 'error out when attempting to add ignored ones but add others' '
touch a.if &&
test_must_fail git add a.?? &&
- ! (git ls-files | grep "\\.ig") &&
- (git ls-files | grep a.if)
+ git ls-files >files &&
+ sed -n "/\\.ig/p" <files >actual &&
+ test_must_be_empty actual &&
+ grep a.if files
'
test_expect_success 'add ignored ones with -f' '
@@ -276,14 +284,14 @@ test_expect_success POSIXPERM,SANITY 'git add (add.ignore-errors = false)' '
rm -f foo2
test_expect_success POSIXPERM,SANITY '--no-ignore-errors overrides config' '
- git config add.ignore-errors 1 &&
- git reset --hard &&
- date >foo1 &&
- date >foo2 &&
- chmod 0 foo2 &&
- test_must_fail git add --verbose --no-ignore-errors . &&
- ! ( git ls-files foo1 | grep foo1 ) &&
- git config add.ignore-errors 0
+ git config add.ignore-errors 1 &&
+ git reset --hard &&
+ date >foo1 &&
+ date >foo2 &&
+ chmod 0 foo2 &&
+ test_must_fail git add --verbose --no-ignore-errors . &&
+ ! ( git ls-files foo1 | grep foo1 ) &&
+ git config add.ignore-errors 0
'
rm -f foo2
@@ -291,7 +299,7 @@ test_expect_success BSLASHPSPEC "git add 'fo\\[ou\\]bar' ignores foobar" '
git reset --hard &&
touch fo\[ou\]bar foobar &&
git add '\''fo\[ou\]bar'\'' &&
- git ls-files fo\[ou\]bar | fgrep fo\[ou\]bar &&
+ git ls-files fo\[ou\]bar | grep -F fo\[ou\]bar &&
! ( git ls-files foobar | grep foobar )
'
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 5841f280fb..34aabb7f5f 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -7,12 +7,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
-if test_have_prereq !ADD_I_USE_BUILTIN,!PERL
-then
- skip_all='skipping add -i (scripted) tests, perl not available'
- test_done
-fi
-
diff_cmp () {
for x
do
@@ -46,6 +40,21 @@ force_color () {
)
}
+test_expect_success 'warn about add.interactive.useBuiltin' '
+ cat >expect <<-\EOF &&
+ warning: the add.interactive.useBuiltin setting has been removed!
+ See its entry in '\''git help config'\'' for details.
+ No changes.
+ EOF
+
+ for v in = =true =false
+ do
+ git -c "add.interactive.useBuiltin$v" add -p >out 2>actual &&
+ test_must_be_empty out &&
+ test_cmp expect actual || return 1
+ done
+'
+
test_expect_success 'setup (initial)' '
echo content >file &&
git add file &&
@@ -296,9 +305,11 @@ test_expect_success FILEMODE 'stage mode and hunk' '
echo content >>file &&
chmod +x file &&
printf "y\\ny\\n" | git add -p &&
- git diff --cached file | grep "new mode" &&
- git diff --cached file | grep "+content" &&
- test -z "$(git diff file)"
+ git diff --cached file >out &&
+ grep "new mode" out &&
+ grep "+content" out &&
+ git diff file >out &&
+ test_must_be_empty out
'
# end of tests disabled when filemode is not usable
@@ -547,15 +558,7 @@ test_expect_success 'split hunk "add -p (edit)"' '
! grep "^+15" actual
'
-test_expect_success 'setup ADD_I_USE_BUILTIN check' '
- result=success &&
- if ! test_have_prereq ADD_I_USE_BUILTIN
- then
- result=failure
- fi
-'
-
-test_expect_$result 'split hunk "add -p (no, yes, edit)"' '
+test_expect_success 'split hunk "add -p (no, yes, edit)"' '
test_write_lines 5 10 20 21 30 31 40 50 60 >test &&
git reset &&
# test sequence is s(plit), n(o), y(es), e(dit)
@@ -579,7 +582,7 @@ test_expect_success 'split hunk with incomplete line at end' '
test_must_fail git grep --cached before
'
-test_expect_$result 'edit, adding lines to the first hunk' '
+test_expect_success 'edit, adding lines to the first hunk' '
test_write_lines 10 11 20 30 40 50 51 60 >test &&
git reset &&
tr _ " " >patch <<-EOF &&
@@ -731,6 +734,44 @@ test_expect_success 'colors can be overridden' '
test_cmp expect actual
'
+test_expect_success 'brackets appear without color' '
+ git reset --hard &&
+ test_when_finished "git rm -f bracket-test" &&
+ test_write_lines context old more-context >bracket-test &&
+ git add bracket-test &&
+ test_write_lines context new more-context another-one >bracket-test &&
+
+ test_write_lines quit >input &&
+ git add -i >actual <input &&
+
+ sed "s/^|//" >expect <<-\EOF &&
+ | staged unstaged path
+ | 1: +3/-0 +2/-1 bracket-test
+ |
+ |*** Commands ***
+ | 1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked
+ | 5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp
+ |What now> Bye.
+ EOF
+
+ test_cmp expect actual
+'
+
+test_expect_success 'colors can be skipped with color.ui=false' '
+ git reset --hard &&
+ test_when_finished "git rm -f color-test" &&
+ test_write_lines context old more-context >color-test &&
+ git add color-test &&
+ test_write_lines context new more-context another-one >color-test &&
+
+ test_write_lines help quit >input &&
+ force_color git \
+ -c color.ui=false \
+ add -i >actual.raw <input &&
+ test_decode_color <actual.raw >actual &&
+ test_cmp actual.raw actual
+'
+
test_expect_success 'colorized diffs respect diff.wsErrorHighlight' '
git reset --hard &&
@@ -1068,4 +1109,25 @@ test_expect_success 'show help from add--helper' '
test_cmp expect actual
'
+test_expect_success 'reset -p with unmerged files' '
+ test_when_finished "git checkout --force main" &&
+ test_commit one conflict &&
+ git checkout -B side HEAD^ &&
+ test_commit two conflict &&
+ test_must_fail git merge one &&
+
+ # this is a noop with only an unmerged entry
+ git reset -p &&
+
+ # add files that sort before and after unmerged entry
+ echo a >a &&
+ echo z >z &&
+ git add a z &&
+
+ # confirm that we can reset those files
+ printf "%s\n" y y | git reset -p &&
+ git diff-index --cached --diff-filter=u HEAD >staged &&
+ test_must_be_empty staged
+'
+
test_done
diff --git a/t/t3702-add-edit.sh b/t/t3702-add-edit.sh
index a1801a8cbd..82bfb2fd2a 100755
--- a/t/t3702-add-edit.sh
+++ b/t/t3702-add-edit.sh
@@ -100,7 +100,7 @@ EOF
echo "#!$SHELL_PATH" >fake-editor.sh
cat >> fake-editor.sh <<\EOF
-egrep -v '^index' "$1" >orig-patch &&
+grep -E -v '^index' "$1" >orig-patch &&
mv -f patch "$1"
EOF
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index e3cf0ffbe5..d3e428ff46 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -4,6 +4,7 @@
test_description='git mktag: tag object verify test'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
###########################################################
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 376cc8f4ab..0b3dfeaea2 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -1211,19 +1211,19 @@ test_expect_success 'stash with file including $IFS character' '
'
test_expect_success 'stash with pathspec matching multiple paths' '
- echo original >file &&
- echo original >other-file &&
- git commit -m "two" file other-file &&
- echo modified >file &&
- echo modified >other-file &&
- git stash push -- "*file" &&
- echo original >expect &&
- test_cmp expect file &&
- test_cmp expect other-file &&
- git stash pop &&
- echo modified >expect &&
- test_cmp expect file &&
- test_cmp expect other-file
+ echo original >file &&
+ echo original >other-file &&
+ git commit -m "two" file other-file &&
+ echo modified >file &&
+ echo modified >other-file &&
+ git stash push -- "*file" &&
+ echo original >expect &&
+ test_cmp expect file &&
+ test_cmp expect other-file &&
+ git stash pop &&
+ echo modified >expect &&
+ test_cmp expect file &&
+ test_cmp expect other-file
'
test_expect_success 'stash push -p with pathspec shows no changes only once' '
diff --git a/t/t3920-crlf-messages.sh b/t/t3920-crlf-messages.sh
index 4c661d4d54..67fd2345af 100755
--- a/t/t3920-crlf-messages.sh
+++ b/t/t3920-crlf-messages.sh
@@ -12,7 +12,7 @@ create_crlf_ref () {
cat >.crlf-orig-$branch.txt &&
cat .crlf-orig-$branch.txt | append_cr >.crlf-message-$branch.txt &&
grep 'Subject' .crlf-orig-$branch.txt | tr '\n' ' ' | sed 's/[ ]*$//' | tr -d '\n' >.crlf-subject-$branch.txt &&
- grep 'Body' .crlf-message-$branch.txt >.crlf-body-$branch.txt || true &&
+ grep 'Body' .crlf-orig-$branch.txt | append_cr >.crlf-body-$branch.txt &&
LIB_CRLF_BRANCHES="${LIB_CRLF_BRANCHES} ${branch}" &&
test_tick &&
hash=$(git commit-tree HEAD^{tree} -p HEAD -F .crlf-message-${branch}.txt) &&
diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh
index bfcaae390f..8d50331b8c 100755
--- a/t/t4000-diff-format.sh
+++ b/t/t4000-diff-format.sh
@@ -5,6 +5,9 @@
test_description='Test built-in diff output engine.
+We happen to know that all diff plumbing and diff Porcelain share the
+same command line parser, so testing one should be sufficient; pick
+diff-files as a representative.
'
TEST_PASSES_SANITIZE_LEAK=true
@@ -16,9 +19,11 @@ Line 2
line 3'
cat path0 >path1
chmod +x path1
+mkdir path2
+>path2/path3
test_expect_success 'update-index --add two files with and without +x.' '
- git update-index --add path0 path1
+ git update-index --add path0 path1 path2/path3
'
mv path0 path0-
@@ -91,4 +96,31 @@ test_expect_success 'git diff-files --patch --no-patch does not show the patch'
test_must_be_empty err
'
+
+# Smudge path2/path3 so that dirstat has something to show
+date >path2/path3
+
+for format in stat raw numstat shortstat summary \
+ dirstat cumulative dirstat-by-file \
+ patch-with-raw patch-with-stat compact-summary
+do
+ test_expect_success "--no-patch in 'git diff-files --no-patch --$format' is a no-op" '
+ git diff-files --no-patch "--$format" >actual &&
+ git diff-files "--$format" >expect &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "--no-patch clears all previous ones" '
+ git diff-files --$format -s -p >actual &&
+ git diff-files -p >expect &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "--no-patch in 'git diff --no-patch --$format' is a no-op" '
+ git diff --no-patch "--$format" >actual &&
+ git diff "--$format" >expect &&
+ test_cmp expect actual
+ '
+done
+
test_done
diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh
index ea52e5b91b..7afc883ec3 100755
--- a/t/t4002-diff-basic.sh
+++ b/t/t4002-diff-basic.sh
@@ -284,132 +284,131 @@ cmp_diff_files_output () {
test_cmp "$1" .test-tmp
}
-test_expect_success \
- 'diff-tree of known trees.' \
- 'git diff-tree $tree_O $tree_A >.test-a &&
- cmp -s .test-a .test-plain-OA'
-
-test_expect_success \
- 'diff-tree of known trees.' \
- 'git diff-tree -r $tree_O $tree_A >.test-a &&
- cmp -s .test-a .test-recursive-OA'
-
-test_expect_success \
- 'diff-tree of known trees.' \
- 'git diff-tree $tree_O $tree_B >.test-a &&
- cmp -s .test-a .test-plain-OB'
-
-test_expect_success \
- 'diff-tree of known trees.' \
- 'git diff-tree -r $tree_O $tree_B >.test-a &&
- cmp -s .test-a .test-recursive-OB'
-
-test_expect_success \
- 'diff-tree of known trees.' \
- 'git diff-tree $tree_A $tree_B >.test-a &&
- cmp -s .test-a .test-plain-AB'
-
-test_expect_success \
- 'diff-tree of known trees.' \
- 'git diff-tree -r $tree_A $tree_B >.test-a &&
- cmp -s .test-a .test-recursive-AB'
-
-test_expect_success \
- 'diff-tree --stdin of known trees.' \
- 'echo $tree_A $tree_B | git diff-tree --stdin > .test-a &&
- echo $tree_A $tree_B > .test-plain-ABx &&
- cat .test-plain-AB >> .test-plain-ABx &&
- cmp -s .test-a .test-plain-ABx'
-
-test_expect_success \
- 'diff-tree --stdin of known trees.' \
- 'echo $tree_A $tree_B | git diff-tree -r --stdin > .test-a &&
- echo $tree_A $tree_B > .test-recursive-ABx &&
- cat .test-recursive-AB >> .test-recursive-ABx &&
- cmp -s .test-a .test-recursive-ABx'
-
-test_expect_success \
- 'diff-cache O with A in cache' \
- 'git read-tree $tree_A &&
- git diff-index --cached $tree_O >.test-a &&
- cmp -s .test-a .test-recursive-OA'
-
-test_expect_success \
- 'diff-cache O with B in cache' \
- 'git read-tree $tree_B &&
- git diff-index --cached $tree_O >.test-a &&
- cmp -s .test-a .test-recursive-OB'
-
-test_expect_success \
- 'diff-cache A with B in cache' \
- 'git read-tree $tree_B &&
- git diff-index --cached $tree_A >.test-a &&
- cmp -s .test-a .test-recursive-AB'
-
-test_expect_success \
- 'diff-files with O in cache and A checked out' \
- 'rm -fr Z [A-Z][A-Z] &&
- git read-tree $tree_A &&
- git checkout-index -f -a &&
- git read-tree --reset $tree_O &&
- test_must_fail git update-index --refresh -q &&
- git diff-files >.test-a &&
- cmp_diff_files_output .test-a .test-recursive-OA'
-
-test_expect_success \
- 'diff-files with O in cache and B checked out' \
- 'rm -fr Z [A-Z][A-Z] &&
- git read-tree $tree_B &&
- git checkout-index -f -a &&
- git read-tree --reset $tree_O &&
- test_must_fail git update-index --refresh -q &&
- git diff-files >.test-a &&
- cmp_diff_files_output .test-a .test-recursive-OB'
-
-test_expect_success \
- 'diff-files with A in cache and B checked out' \
- 'rm -fr Z [A-Z][A-Z] &&
- git read-tree $tree_B &&
- git checkout-index -f -a &&
- git read-tree --reset $tree_A &&
- test_must_fail git update-index --refresh -q &&
- git diff-files >.test-a &&
- cmp_diff_files_output .test-a .test-recursive-AB'
+test_expect_success 'diff-tree of known trees.' '
+ git diff-tree $tree_O $tree_A >.test-a &&
+ cmp -s .test-a .test-plain-OA
+'
+
+test_expect_success 'diff-tree of known trees.' '
+ git diff-tree -r $tree_O $tree_A >.test-a &&
+ cmp -s .test-a .test-recursive-OA
+'
+
+test_expect_success 'diff-tree of known trees.' '
+ git diff-tree $tree_O $tree_B >.test-a &&
+ cmp -s .test-a .test-plain-OB
+'
+
+test_expect_success 'diff-tree of known trees.' '
+ git diff-tree -r $tree_O $tree_B >.test-a &&
+ cmp -s .test-a .test-recursive-OB
+'
+
+test_expect_success 'diff-tree of known trees.' '
+ git diff-tree $tree_A $tree_B >.test-a &&
+ cmp -s .test-a .test-plain-AB
+'
+
+test_expect_success 'diff-tree of known trees.' '
+ git diff-tree -r $tree_A $tree_B >.test-a &&
+ cmp -s .test-a .test-recursive-AB
+'
+
+test_expect_success 'diff-tree --stdin of known trees.' '
+ echo $tree_A $tree_B | git diff-tree --stdin > .test-a &&
+ echo $tree_A $tree_B > .test-plain-ABx &&
+ cat .test-plain-AB >> .test-plain-ABx &&
+ cmp -s .test-a .test-plain-ABx
+'
+
+test_expect_success 'diff-tree --stdin of known trees.' '
+ echo $tree_A $tree_B | git diff-tree -r --stdin > .test-a &&
+ echo $tree_A $tree_B > .test-recursive-ABx &&
+ cat .test-recursive-AB >> .test-recursive-ABx &&
+ cmp -s .test-a .test-recursive-ABx
+'
+
+test_expect_success 'diff-cache O with A in cache' '
+ git read-tree $tree_A &&
+ git diff-index --cached $tree_O >.test-a &&
+ cmp -s .test-a .test-recursive-OA
+'
+
+test_expect_success 'diff-cache O with B in cache' '
+ git read-tree $tree_B &&
+ git diff-index --cached $tree_O >.test-a &&
+ cmp -s .test-a .test-recursive-OB
+'
+
+test_expect_success 'diff-cache A with B in cache' '
+ git read-tree $tree_B &&
+ git diff-index --cached $tree_A >.test-a &&
+ cmp -s .test-a .test-recursive-AB
+'
+
+test_expect_success 'diff-files with O in cache and A checked out' '
+ rm -fr Z [A-Z][A-Z] &&
+ git read-tree $tree_A &&
+ git checkout-index -f -a &&
+ git read-tree --reset $tree_O &&
+ test_must_fail git update-index --refresh -q &&
+ git diff-files >.test-a &&
+ cmp_diff_files_output .test-a .test-recursive-OA
+'
+
+test_expect_success 'diff-files with O in cache and B checked out' '
+ rm -fr Z [A-Z][A-Z] &&
+ git read-tree $tree_B &&
+ git checkout-index -f -a &&
+ git read-tree --reset $tree_O &&
+ test_must_fail git update-index --refresh -q &&
+ git diff-files >.test-a &&
+ cmp_diff_files_output .test-a .test-recursive-OB
+'
+
+test_expect_success 'diff-files with A in cache and B checked out' '
+ rm -fr Z [A-Z][A-Z] &&
+ git read-tree $tree_B &&
+ git checkout-index -f -a &&
+ git read-tree --reset $tree_A &&
+ test_must_fail git update-index --refresh -q &&
+ git diff-files >.test-a &&
+ cmp_diff_files_output .test-a .test-recursive-AB
+'
################################################################
# Now we have established the baseline, we do not have to
# rely on individual object ID values that much.
-test_expect_success \
- 'diff-tree O A == diff-tree -R A O' \
- 'git diff-tree $tree_O $tree_A >.test-a &&
- git diff-tree -R $tree_A $tree_O >.test-b &&
- cmp -s .test-a .test-b'
-
-test_expect_success \
- 'diff-tree -r O A == diff-tree -r -R A O' \
- 'git diff-tree -r $tree_O $tree_A >.test-a &&
- git diff-tree -r -R $tree_A $tree_O >.test-b &&
- cmp -s .test-a .test-b'
-
-test_expect_success \
- 'diff-tree B A == diff-tree -R A B' \
- 'git diff-tree $tree_B $tree_A >.test-a &&
- git diff-tree -R $tree_A $tree_B >.test-b &&
- cmp -s .test-a .test-b'
-
-test_expect_success \
- 'diff-tree -r B A == diff-tree -r -R A B' \
- 'git diff-tree -r $tree_B $tree_A >.test-a &&
- git diff-tree -r -R $tree_A $tree_B >.test-b &&
- cmp -s .test-a .test-b'
-
-test_expect_success \
- 'diff can read from stdin' \
- 'test_must_fail git diff --no-index -- MN - < NN |
- grep -v "^index" | sed "s#/-#/NN#" >.test-a &&
- test_must_fail git diff --no-index -- MN NN |
- grep -v "^index" >.test-b &&
- test_cmp .test-a .test-b'
+test_expect_success 'diff-tree O A == diff-tree -R A O' '
+ git diff-tree $tree_O $tree_A >.test-a &&
+ git diff-tree -R $tree_A $tree_O >.test-b &&
+ cmp -s .test-a .test-b
+'
+
+test_expect_success 'diff-tree -r O A == diff-tree -r -R A O' '
+ git diff-tree -r $tree_O $tree_A >.test-a &&
+ git diff-tree -r -R $tree_A $tree_O >.test-b &&
+ cmp -s .test-a .test-b
+'
+
+test_expect_success 'diff-tree B A == diff-tree -R A B' '
+ git diff-tree $tree_B $tree_A >.test-a &&
+ git diff-tree -R $tree_A $tree_B >.test-b &&
+ cmp -s .test-a .test-b
+'
+
+test_expect_success 'diff-tree -r B A == diff-tree -r -R A B' '
+ git diff-tree -r $tree_B $tree_A >.test-a &&
+ git diff-tree -r -R $tree_A $tree_B >.test-b &&
+ cmp -s .test-a .test-b'
+
+test_expect_success 'diff can read from stdin' '
+ test_must_fail git diff --no-index -- MN - < NN |
+ grep -v "^index" | sed "s#/-#/NN#" >.test-a &&
+ test_must_fail git diff --no-index -- MN NN |
+ grep -v "^index" >.test-b &&
+ test_cmp .test-a .test-b
+'
test_done
diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh
index 181e9683a7..ebe091828c 100755
--- a/t/t4003-diff-rename-1.sh
+++ b/t/t4003-diff-rename-1.sh
@@ -11,20 +11,20 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash
-test_expect_success \
- 'prepare reference tree' \
- 'COPYING_test_data >COPYING &&
- echo frotz >rezrov &&
- git update-index --add COPYING rezrov &&
- tree=$(git write-tree) &&
- echo $tree'
-
-test_expect_success \
- 'prepare work tree' \
- 'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 &&
- sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 &&
- rm -f COPYING &&
- git update-index --add --remove COPYING COPYING.?'
+test_expect_success 'prepare reference tree' '
+ COPYING_test_data >COPYING &&
+ echo frotz >rezrov &&
+ git update-index --add COPYING rezrov &&
+ tree=$(git write-tree) &&
+ echo $tree
+'
+
+test_expect_success 'prepare work tree' '
+ sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 &&
+ sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 &&
+ rm -f COPYING &&
+ git update-index --add --remove COPYING COPYING.?
+'
# tree has COPYING and rezrov. work tree has COPYING.1 and COPYING.2,
# both are slightly edited, and unchanged rezrov. So we say you
@@ -57,14 +57,14 @@ rename to COPYING.2
+ This file is licensed under the G.P.L v2, or a later version
EOF
-test_expect_success \
- 'validate output from rename/copy detection (#1)' \
- 'compare_diff_patch current expected'
+test_expect_success 'validate output from rename/copy detection (#1)' '
+ compare_diff_patch current expected
+'
-test_expect_success \
- 'prepare work tree again' \
- 'mv COPYING.2 COPYING &&
- git update-index --add --remove COPYING COPYING.1 COPYING.2'
+test_expect_success 'prepare work tree again' '
+ mv COPYING.2 COPYING &&
+ git update-index --add --remove COPYING COPYING.1 COPYING.2
+'
# tree has COPYING and rezrov. work tree has COPYING and COPYING.1,
# both are slightly edited, and unchanged rezrov. So we say you
@@ -95,14 +95,14 @@ copy to COPYING.1
+ However, in order to allow a migration to GPLv3 if that seems like
EOF
-test_expect_success \
- 'validate output from rename/copy detection (#2)' \
- 'compare_diff_patch current expected'
+test_expect_success 'validate output from rename/copy detection (#2)' '
+ compare_diff_patch current expected
+'
-test_expect_success \
- 'prepare work tree once again' \
- 'COPYING_test_data >COPYING &&
- git update-index --add --remove COPYING COPYING.1'
+test_expect_success 'prepare work tree once again' '
+ COPYING_test_data >COPYING &&
+ git update-index --add --remove COPYING COPYING.1
+'
# tree has COPYING and rezrov. work tree has COPYING and COPYING.1,
# but COPYING is not edited. We say you copy-and-edit COPYING.1; this
@@ -123,8 +123,8 @@ copy to COPYING.1
+ However, in order to allow a migration to GPLv3 if that seems like
EOF
-test_expect_success \
- 'validate output from rename/copy detection (#3)' \
- 'compare_diff_patch current expected'
+test_expect_success 'validate output from rename/copy detection (#3)' '
+ compare_diff_patch current expected
+'
test_done
diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh
index 8def4d4aee..1d70d4d221 100755
--- a/t/t4004-diff-rename-symlink.sh
+++ b/t/t4004-diff-rename-symlink.sh
@@ -14,21 +14,21 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff.sh
-test_expect_success SYMLINKS \
- 'prepare reference tree' \
- 'echo xyzzy | tr -d '\\\\'012 >yomin &&
- ln -s xyzzy frotz &&
- git update-index --add frotz yomin &&
- tree=$(git write-tree) &&
- echo $tree'
+test_expect_success SYMLINKS 'prepare reference tree' '
+ echo xyzzy | tr -d '\\\\'012 >yomin &&
+ ln -s xyzzy frotz &&
+ git update-index --add frotz yomin &&
+ tree=$(git write-tree) &&
+ echo $tree
+'
-test_expect_success SYMLINKS \
- 'prepare work tree' \
- 'mv frotz rezrov &&
- rm -f yomin &&
- ln -s xyzzy nitfol &&
- ln -s xzzzy bozbar &&
- git update-index --add --remove frotz rezrov nitfol bozbar yomin'
+test_expect_success SYMLINKS 'prepare work tree' '
+ mv frotz rezrov &&
+ rm -f yomin &&
+ ln -s xyzzy nitfol &&
+ ln -s xzzzy bozbar &&
+ git update-index --add --remove frotz rezrov nitfol bozbar yomin
+'
# tree has frotz pointing at xyzzy, and yomin that contains xyzzy to
# confuse things. work tree has rezrov (xyzzy) nitfol (xyzzy) and
@@ -36,9 +36,9 @@ test_expect_success SYMLINKS \
# rezrov and nitfol are rename/copy of frotz and bozbar should be
# a new creation.
-test_expect_success SYMLINKS 'setup diff output' "
- GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current &&
- cat >expected <<\EOF
+test_expect_success SYMLINKS 'setup diff output' '
+ GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current &&
+ cat >expected <<\EOF
diff --git a/bozbar b/bozbar
new file mode 120000
--- /dev/null
@@ -62,10 +62,10 @@ deleted file mode 100644
-xyzzy
\ No newline at end of file
EOF
-"
+'
-test_expect_success SYMLINKS \
- 'validate diff output' \
- 'compare_diff_patch current expected'
+test_expect_success SYMLINKS 'validate diff output' '
+ compare_diff_patch current expected
+'
test_done
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index c509143c81..c64d9d2f40 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -113,20 +113,20 @@ test_expect_success 'diff --no-index with binary creation' '
'
cat >expect <<EOF
- binfile | Bin 0 -> 1026 bytes
- textfile | 10000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ binfilë | Bin 0 -> 1026 bytes
+ tëxtfilë | 10000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
EOF
test_expect_success 'diff --stat with binary files and big change count' '
- printf "\01\00%1024d" 1 >binfile &&
- git add binfile &&
+ printf "\01\00%1024d" 1 >binfilë &&
+ git add binfilë &&
i=0 &&
while test $i -lt 10000; do
echo $i &&
i=$(($i + 1)) || return 1
- done >textfile &&
- git add textfile &&
- git diff --cached --stat binfile textfile >output &&
+ done >tëxtfilë &&
+ git add tëxtfilë &&
+ git -c core.quotepath=false diff --cached --stat binfilë tëxtfilë >output &&
grep " | " output >actual &&
test_cmp expect actual
'
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index dfcf3a0aaa..5de1d19075 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -616,4 +616,46 @@ test_expect_success 'diff -I<regex>: detect malformed regex' '
test_i18ngrep "invalid regex given to -I: " error
'
+# check_prefix <patch> <src> <dst>
+# check only lines with paths to avoid dependency on exact oid/contents
+check_prefix () {
+ grep -E '^(diff|---|\+\+\+) ' "$1" >actual.paths &&
+ cat >expect <<-EOF &&
+ diff --git $2 $3
+ --- $2
+ +++ $3
+ EOF
+ test_cmp expect actual.paths
+}
+
+test_expect_success 'diff-files does not respect diff.noprefix' '
+ git -c diff.noprefix diff-files -p >actual &&
+ check_prefix actual a/file0 b/file0
+'
+
+test_expect_success 'diff-files respects --no-prefix' '
+ git diff-files -p --no-prefix >actual &&
+ check_prefix actual file0 file0
+'
+
+test_expect_success 'diff respects diff.noprefix' '
+ git -c diff.noprefix diff >actual &&
+ check_prefix actual file0 file0
+'
+
+test_expect_success 'diff --default-prefix overrides diff.noprefix' '
+ git -c diff.noprefix diff --default-prefix >actual &&
+ check_prefix actual a/file0 b/file0
+'
+
+test_expect_success 'diff respects diff.mnemonicprefix' '
+ git -c diff.mnemonicprefix diff >actual &&
+ check_prefix actual i/file0 w/file0
+'
+
+test_expect_success 'diff --default-prefix overrides diff.mnemonicprefix' '
+ git -c diff.mnemonicprefix diff --default-prefix >actual &&
+ check_prefix actual a/file0 b/file0
+'
+
test_done
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index ad5c029279..0a4ab36c3a 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -59,6 +59,10 @@ test_expect_success setup '
test_tick &&
git commit -m "patchid 3" &&
+ git checkout -b empty main &&
+ test_tick &&
+ git commit --allow-empty -m "empty commit" &&
+
git checkout main
'
@@ -128,6 +132,12 @@ test_expect_success 'replay did not screw up the log message' '
grep "^Side .* with .* backslash-n" actual
'
+test_expect_success 'format-patch empty commit' '
+ git format-patch --stdout main..empty >empty &&
+ grep "^From " empty >from &&
+ test_line_count = 1 from
+'
+
test_expect_success 'extra headers' '
git config format.headers "To: R E Cipient <rcipient@example.com>
" &&
@@ -445,13 +455,13 @@ test_expect_success 'no threading' '
cat >expect.thread <<EOF
---
-Message-Id: <0>
+Message-ID: <0>
---
-Message-Id: <1>
+Message-ID: <1>
In-Reply-To: <0>
References: <0>
---
-Message-Id: <2>
+Message-ID: <2>
In-Reply-To: <0>
References: <0>
EOF
@@ -460,17 +470,22 @@ test_expect_success 'thread' '
check_threading expect.thread --thread main
'
+test_expect_success '--thread overrides format.thread=deep' '
+ test_config format.thread deep &&
+ check_threading expect.thread --thread main
+'
+
cat >expect.in-reply-to <<EOF
---
-Message-Id: <0>
+Message-ID: <0>
In-Reply-To: <1>
References: <1>
---
-Message-Id: <2>
+Message-ID: <2>
In-Reply-To: <1>
References: <1>
---
-Message-Id: <3>
+Message-ID: <3>
In-Reply-To: <1>
References: <1>
EOF
@@ -482,17 +497,17 @@ test_expect_success 'thread in-reply-to' '
cat >expect.cover-letter <<EOF
---
-Message-Id: <0>
+Message-ID: <0>
---
-Message-Id: <1>
+Message-ID: <1>
In-Reply-To: <0>
References: <0>
---
-Message-Id: <2>
+Message-ID: <2>
In-Reply-To: <0>
References: <0>
---
-Message-Id: <3>
+Message-ID: <3>
In-Reply-To: <0>
References: <0>
EOF
@@ -503,21 +518,21 @@ test_expect_success 'thread cover-letter' '
cat >expect.cl-irt <<EOF
---
-Message-Id: <0>
+Message-ID: <0>
In-Reply-To: <1>
References: <1>
---
-Message-Id: <2>
+Message-ID: <2>
In-Reply-To: <0>
References: <1>
<0>
---
-Message-Id: <3>
+Message-ID: <3>
In-Reply-To: <0>
References: <1>
<0>
---
-Message-Id: <4>
+Message-ID: <4>
In-Reply-To: <0>
References: <1>
<0>
@@ -535,13 +550,13 @@ test_expect_success 'thread explicit shallow' '
cat >expect.deep <<EOF
---
-Message-Id: <0>
+Message-ID: <0>
---
-Message-Id: <1>
+Message-ID: <1>
In-Reply-To: <0>
References: <0>
---
-Message-Id: <2>
+Message-ID: <2>
In-Reply-To: <1>
References: <0>
<1>
@@ -553,16 +568,16 @@ test_expect_success 'thread deep' '
cat >expect.deep-irt <<EOF
---
-Message-Id: <0>
+Message-ID: <0>
In-Reply-To: <1>
References: <1>
---
-Message-Id: <2>
+Message-ID: <2>
In-Reply-To: <0>
References: <1>
<0>
---
-Message-Id: <3>
+Message-ID: <3>
In-Reply-To: <2>
References: <1>
<0>
@@ -576,18 +591,18 @@ test_expect_success 'thread deep in-reply-to' '
cat >expect.deep-cl <<EOF
---
-Message-Id: <0>
+Message-ID: <0>
---
-Message-Id: <1>
+Message-ID: <1>
In-Reply-To: <0>
References: <0>
---
-Message-Id: <2>
+Message-ID: <2>
In-Reply-To: <1>
References: <0>
<1>
---
-Message-Id: <3>
+Message-ID: <3>
In-Reply-To: <2>
References: <0>
<1>
@@ -600,22 +615,22 @@ test_expect_success 'thread deep cover-letter' '
cat >expect.deep-cl-irt <<EOF
---
-Message-Id: <0>
+Message-ID: <0>
In-Reply-To: <1>
References: <1>
---
-Message-Id: <2>
+Message-ID: <2>
In-Reply-To: <0>
References: <1>
<0>
---
-Message-Id: <3>
+Message-ID: <3>
In-Reply-To: <2>
References: <1>
<0>
<2>
---
-Message-Id: <4>
+Message-ID: <4>
In-Reply-To: <3>
References: <1>
<0>
@@ -1358,7 +1373,27 @@ test_expect_success '--rfc' '
Subject: [RFC PATCH 1/1] header with . in it
EOF
git format-patch -n -1 --stdout --rfc >patch &&
- grep ^Subject: patch >actual &&
+ grep "^Subject:" patch >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--rfc does not overwrite prefix' '
+ cat >expect <<-\EOF &&
+ Subject: [RFC PATCH foobar 1/1] header with . in it
+ EOF
+ git -c format.subjectPrefix="PATCH foobar" \
+ format-patch -n -1 --stdout --rfc >patch &&
+ grep "^Subject:" patch >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--rfc is argument order independent' '
+ cat >expect <<-\EOF &&
+ Subject: [RFC PATCH foobar 1/1] header with . in it
+ EOF
+ git format-patch -n -1 --stdout --rfc \
+ --subject-prefix="PATCH foobar" >patch &&
+ grep "^Subject:" patch >actual &&
test_cmp expect actual
'
@@ -1457,7 +1492,7 @@ append_signoff()
C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
sed -n -e "1,/^---$/p" append_signoff.patch |
- egrep -n "^Subject|Sign|^$"
+ grep -E -n "^Subject|Sign|^$"
}
test_expect_success 'signoff: commit with no body' '
@@ -1976,6 +2011,20 @@ test_expect_success 'cover letter using branch description (6)' '
grep hello actual
'
+test_expect_success 'cover letter with --description-file' '
+ test_when_finished "rm -f description.txt" &&
+ cat >description.txt <<-\EOF &&
+ subject from file
+
+ body from file
+ EOF
+ git checkout rebuild-1 &&
+ git format-patch --stdout --cover-letter --cover-from-description auto \
+ --description-file description.txt main >actual &&
+ grep "^Subject: \[PATCH 0/2\] subject from file$" actual &&
+ grep "^body from file$" actual
+'
+
test_expect_success 'cover letter with nothing' '
git format-patch --stdout --cover-letter >actual &&
test_line_count = 0 actual
@@ -2274,14 +2323,32 @@ test_expect_success 'format-patch --base with --attach' '
test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
test_when_finished "rm -fr patches" &&
git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
- ! egrep "^--+mimemime" patches/0000*.patch &&
- egrep "^--+mimemime$" patches/0001*.patch >output &&
+ ! grep -E "^--+mimemime" patches/0000*.patch &&
+ grep -E "^--+mimemime$" patches/0001*.patch >output &&
test_line_count = 2 output &&
- egrep "^--+mimemime--$" patches/0001*.patch >output &&
+ grep -E "^--+mimemime--$" patches/0001*.patch >output &&
test_line_count = 1 output
'
-test_expect_success 'format-patch --pretty=mboxrd' '
+test_expect_success 'format-patch with format.attach' '
+ test_when_finished "rm -fr patches" &&
+ separator=attachment-separator &&
+ test_config format.attach "$separator" &&
+ filename=$(git format-patch -o patches -1) &&
+ grep "^Content-Type: multipart/.*$separator" "$filename"
+'
+
+test_expect_success 'format-patch with format.attach=disabled' '
+ test_when_finished "rm -fr patches" &&
+ separator=attachment-separator &&
+ test_config_global format.attach "$separator" &&
+ test_config format.attach "" &&
+ filename=$(git format-patch -o patches -1) &&
+ # The output should not even declare content type for text/plain.
+ ! grep "^Content-Type: multipart/" "$filename"
+'
+
+test_expect_success '-c format.mboxrd format-patch' '
sp=" " &&
cat >msg <<-INPUT_END &&
mboxrd should escape the body
@@ -2316,7 +2383,9 @@ test_expect_success 'format-patch --pretty=mboxrd' '
INPUT_END
C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
- git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
+ git -c format.mboxrd format-patch --stdout -1 $C~1..$C >patch &&
+ git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >compat &&
+ test_cmp patch compat &&
git grep -h --no-index -A11 \
"^>From could trip up a loose mbox parser" patch >actual &&
test_cmp expect actual
@@ -2366,4 +2435,20 @@ test_expect_success 'interdiff: solo-patch' '
test_cmp expect actual
'
+test_expect_success 'format-patch does not respect diff.noprefix' '
+ git -c diff.noprefix format-patch -1 --stdout >actual &&
+ grep "^--- a/blorp" actual
+'
+
+test_expect_success 'format-patch respects format.noprefix' '
+ git -c format.noprefix format-patch -1 --stdout >actual &&
+ grep "^--- blorp" actual
+'
+
+test_expect_success 'format-patch --default-prefix overrides format.noprefix' '
+ git -c format.noprefix \
+ format-patch -1 --default-prefix --stdout >actual &&
+ grep "^--- a/blorp" actual
+'
+
test_done
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index f3e20dd5bb..fcd2473e52 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -1,7 +1,7 @@
#!/bin/sh
#
# Copyright (c) 2006 Johannes E. Schindelin
-#
+# Copyright (c) 2023 Google LLC
test_description='Test special whitespace in diff engine.
@@ -11,6 +11,43 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff.sh
+for opt_res in --patch --quiet -s --stat --shortstat --dirstat=lines \
+ --raw! --name-only! --name-status!
+do
+ opts=${opt_res%!} expect_failure=
+ test "$opts" = "$opt_res" ||
+ expect_failure="test_expect_code 1"
+
+ test_expect_success "status with $opts (different)" '
+ echo foo >x &&
+ git add x &&
+ echo bar >x &&
+ test_expect_code 1 git diff -w $opts --exit-code x
+ '
+
+ test_expect_success POSIXPERM "status with $opts (mode differs)" '
+ test_when_finished "git update-index --chmod=-x x" &&
+ echo foo >x &&
+ git add x &&
+ git update-index --chmod=+x x &&
+ test_expect_code 1 git diff -w $opts --exit-code x
+ '
+
+ test_expect_success "status with $opts (removing an empty file)" '
+ : >x &&
+ git add x &&
+ rm x &&
+ test_expect_code 1 git diff -w $opts --exit-code -- x
+ '
+
+ test_expect_success "status with $opts (different but equivalent)" '
+ echo foo >x &&
+ git add x &&
+ echo " foo" >x &&
+ $expect_failure git diff -w $opts --exit-code x
+ '
+done
+
test_expect_success "Ray Lehtiniemi's example" '
cat <<-\EOF >x &&
do {
@@ -1638,7 +1675,7 @@ test_expect_success 'no effect on diff from --color-moved with --word-diff' '
test_cmp expect actual
'
-test_expect_success !SANITIZE_LEAK 'no effect on show from --color-moved with --word-diff' '
+test_expect_success 'no effect on show from --color-moved with --word-diff' '
git show --color-moved --word-diff >actual &&
git show --word-diff >expect &&
test_cmp expect actual
@@ -2024,7 +2061,7 @@ test_expect_success '--color-moved rewinds for MIN_ALNUM_COUNT' '
test_cmp expected actual
'
-test_expect_success !SANITIZE_LEAK 'move detection with submodules' '
+test_expect_success 'move detection with submodules' '
test_create_repo bananas &&
echo ripe >bananas/recipe &&
git -C bananas add recipe &&
diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh
index 5bc28ad9f0..f439f469bd 100755
--- a/t/t4017-diff-retval.sh
+++ b/t/t4017-diff-retval.sh
@@ -138,4 +138,9 @@ test_expect_success 'check honors conflict marker length' '
git reset --hard
'
+test_expect_success 'option errors are not confused by --exit-code' '
+ test_must_fail git diff --exit-code --nonsense 2>err &&
+ grep '^usage:' err
+'
+
test_done
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 42a2b9a13b..c8d555771d 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -63,6 +63,25 @@ do
test_i18ngrep ! fatal msg &&
test_i18ngrep ! error msg
'
+
+ test_expect_success "builtin $p pattern compiles on bare repo with --attr-source" '
+ test_when_finished "rm -rf bare.git" &&
+ git checkout -B master &&
+ git add . &&
+ echo "*.java diff=notexist" >.gitattributes &&
+ git add .gitattributes &&
+ git commit -am "changing gitattributes" &&
+ git checkout -B branchA &&
+ echo "*.java diff=$p" >.gitattributes &&
+ git add .gitattributes &&
+ git commit -am "changing gitattributes" &&
+ git clone --bare --no-local . bare.git &&
+ git -C bare.git symbolic-ref HEAD refs/heads/master &&
+ test_expect_code 1 git -C bare.git --attr-source=branchA \
+ diff --exit-code HEAD:A.java HEAD:B.java 2>msg &&
+ test_i18ngrep ! fatal msg &&
+ test_i18ngrep ! error msg
+ '
done
test_expect_success 'last regexp must not be negated' '
diff --git a/t/t4018/java-class-brace-on-separate-line b/t/t4018/java-class-brace-on-separate-line
new file mode 100644
index 0000000000..8795acd4cf
--- /dev/null
+++ b/t/t4018/java-class-brace-on-separate-line
@@ -0,0 +1,6 @@
+class RIGHT
+{
+ static int ONE;
+ static int TWO;
+ static int ChangeMe;
+}
diff --git a/t/t4018/java-class-space-before-type-parameters b/t/t4018/java-class-space-before-type-parameters
new file mode 100644
index 0000000000..0bdef1dfbe
--- /dev/null
+++ b/t/t4018/java-class-space-before-type-parameters
@@ -0,0 +1,6 @@
+class RIGHT <TYPE, PARAMS, AFTER, SPACE> {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ private A ChangeMe;
+}
diff --git a/t/t4018/java-class-type-parameters b/t/t4018/java-class-type-parameters
new file mode 100644
index 0000000000..579aa7af21
--- /dev/null
+++ b/t/t4018/java-class-type-parameters
@@ -0,0 +1,6 @@
+class RIGHT<A, B> {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ private A ChangeMe;
+}
diff --git a/t/t4018/java-class-type-parameters-implements b/t/t4018/java-class-type-parameters-implements
new file mode 100644
index 0000000000..b8038b1866
--- /dev/null
+++ b/t/t4018/java-class-type-parameters-implements
@@ -0,0 +1,6 @@
+class RIGHT<A, B> implements List<A> {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ private A ChangeMe;
+}
diff --git a/t/t4018/java-interface-type-parameters b/t/t4018/java-interface-type-parameters
new file mode 100644
index 0000000000..a4baa1ae68
--- /dev/null
+++ b/t/t4018/java-interface-type-parameters
@@ -0,0 +1,6 @@
+interface RIGHT<A, B> {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ public B foo(A ChangeMe);
+}
diff --git a/t/t4018/java-interface-type-parameters-extends b/t/t4018/java-interface-type-parameters-extends
new file mode 100644
index 0000000000..31d7fb3244
--- /dev/null
+++ b/t/t4018/java-interface-type-parameters-extends
@@ -0,0 +1,6 @@
+interface RIGHT<A, B> extends Function<A, B> {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ public B foo(A ChangeMe);
+}
diff --git a/t/t4018/java-non-sealed b/t/t4018/java-non-sealed
new file mode 100644
index 0000000000..069087c1c6
--- /dev/null
+++ b/t/t4018/java-non-sealed
@@ -0,0 +1,8 @@
+public abstract sealed class SealedClass {
+ public static non-sealed class RIGHT extends SealedClass {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ private int ChangeMe;
+ }
+}
diff --git a/t/t4018/java-record b/t/t4018/java-record
new file mode 100644
index 0000000000..97aa819dd8
--- /dev/null
+++ b/t/t4018/java-record
@@ -0,0 +1,6 @@
+public record RIGHT(int comp1, double comp2, String comp3) {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ static int ChangeMe;
+}
diff --git a/t/t4018/java-record-space-before-components b/t/t4018/java-record-space-before-components
new file mode 100644
index 0000000000..9827f22583
--- /dev/null
+++ b/t/t4018/java-record-space-before-components
@@ -0,0 +1,6 @@
+public record RIGHT (String components, String after, String space) {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ static int ChangeMe;
+}
diff --git a/t/t4018/java-record-type-parameters b/t/t4018/java-record-type-parameters
new file mode 100644
index 0000000000..f62a035cc8
--- /dev/null
+++ b/t/t4018/java-record-type-parameters
@@ -0,0 +1,6 @@
+public record RIGHT<A, N extends Number>(A comp1, N comp2, int comp3) {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ static int ChangeMe;
+}
diff --git a/t/t4018/java-sealed b/t/t4018/java-sealed
new file mode 100644
index 0000000000..785fbc62bc
--- /dev/null
+++ b/t/t4018/java-sealed
@@ -0,0 +1,7 @@
+public abstract sealed class Sealed { // RIGHT
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ public final class ChangeMe extends Sealed {
+ }
+}
diff --git a/t/t4018/java-sealed-permits b/t/t4018/java-sealed-permits
new file mode 100644
index 0000000000..18dd4894cf
--- /dev/null
+++ b/t/t4018/java-sealed-permits
@@ -0,0 +1,6 @@
+public abstract sealed class RIGHT permits PermittedA, PermittedB {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ private int ChangeMe;
+}
diff --git a/t/t4018/java-sealed-type-parameters b/t/t4018/java-sealed-type-parameters
new file mode 100644
index 0000000000..e6530c47c3
--- /dev/null
+++ b/t/t4018/java-sealed-type-parameters
@@ -0,0 +1,6 @@
+public abstract sealed class RIGHT<A, B> {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ private int ChangeMe;
+}
diff --git a/t/t4018/java-sealed-type-parameters-implements-permits b/t/t4018/java-sealed-type-parameters-implements-permits
new file mode 100644
index 0000000000..bd6e6d3582
--- /dev/null
+++ b/t/t4018/java-sealed-type-parameters-implements-permits
@@ -0,0 +1,6 @@
+public abstract sealed class RIGHT<A, B> implements List<A> permits PermittedA, PermittedB {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ private int ChangeMe;
+}
diff --git a/t/t4018/java-sealed-type-parameters-permits b/t/t4018/java-sealed-type-parameters-permits
new file mode 100644
index 0000000000..25a0da6442
--- /dev/null
+++ b/t/t4018/java-sealed-type-parameters-permits
@@ -0,0 +1,6 @@
+public abstract sealed class RIGHT<A, B> permits PermittedA, PermittedB {
+ static int ONE;
+ static int TWO;
+ static int THREE;
+ private int ChangeMe;
+}
diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh
index 1c89050a97..6fed993ea0 100755
--- a/t/t4022-diff-rewrite.sh
+++ b/t/t4022-diff-rewrite.sh
@@ -24,7 +24,7 @@ test_expect_success setup '
test_expect_success 'detect rewrite' '
actual=$(git diff-files -B --summary test) &&
- verbose expr "$actual" : " rewrite test ([0-9]*%)$"
+ expr "$actual" : " rewrite test ([0-9]*%)$"
'
diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh
index 7cb9909293..787605ce3f 100755
--- a/t/t4023-diff-rename-typechange.sh
+++ b/t/t4023-diff-rename-typechange.sh
@@ -52,8 +52,8 @@ test_expect_success setup '
'
test_expect_success 'cross renames to be detected for regular files' '
-
- git diff-tree five six -r --name-status -B -M | sort >actual &&
+ git diff-tree five six -r --name-status -B -M >out &&
+ sort out >actual &&
{
echo "R100 foo bar" &&
echo "R100 bar foo"
@@ -63,8 +63,8 @@ test_expect_success 'cross renames to be detected for regular files' '
'
test_expect_success 'cross renames to be detected for typechange' '
-
- git diff-tree one two -r --name-status -B -M | sort >actual &&
+ git diff-tree one two -r --name-status -B -M >out &&
+ sort out >actual &&
{
echo "R100 foo bar" &&
echo "R100 bar foo"
@@ -74,8 +74,8 @@ test_expect_success 'cross renames to be detected for typechange' '
'
test_expect_success 'moves and renames' '
-
- git diff-tree three four -r --name-status -B -M | sort >actual &&
+ git diff-tree three four -r --name-status -B -M >out &&
+ sort out >actual &&
{
# see -B -M (#6) in t4008
echo "C100 foo bar" &&
diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh
index 15764ee9ac..74586f3813 100755
--- a/t/t4034-diff-words.sh
+++ b/t/t4034-diff-words.sh
@@ -69,6 +69,10 @@ test_language_driver () {
echo "* diff='"$lang"'" >.gitattributes &&
word_diff --color-words
'
+ test_expect_success "diff driver '$lang' in Islandic" '
+ LANG=is_IS.UTF-8 LANGUAGE=is LC_ALL="$is_IS_locale" \
+ word_diff --color-words
+ '
}
test_expect_success setup '
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index 9a292bac70..2ce26e585c 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -80,11 +80,21 @@ test_expect_success 'check combined output (1)' '
verify_helper sidewithone
'
+test_expect_success 'check combined output (1) with git diff <rev>^!' '
+ git diff sidewithone^! -- >sidewithone &&
+ verify_helper sidewithone
+'
+
test_expect_success 'check combined output (2)' '
git show sidesansone -- >sidesansone &&
verify_helper sidesansone
'
+test_expect_success 'check combined output (2) with git diff <rev>^!' '
+ git diff sidesansone^! -- >sidesansone &&
+ verify_helper sidesansone
+'
+
test_expect_success 'diagnose truncated file' '
>file &&
git add file &&
diff --git a/t/t4040-whitespace-status.sh b/t/t4040-whitespace-status.sh
index e70e020ae9..eec3d73dc2 100755
--- a/t/t4040-whitespace-status.sh
+++ b/t/t4040-whitespace-status.sh
@@ -28,8 +28,7 @@ test_expect_success 'diff-tree --exit-code' '
test_expect_success 'diff-tree -b --exit-code' '
git diff -b --exit-code HEAD^ HEAD &&
- git diff-tree -b -p --exit-code HEAD^ HEAD &&
- git diff-tree -b --exit-code HEAD^ HEAD
+ git diff-tree -b -p --exit-code HEAD^ HEAD
'
test_expect_success 'diff-index --cached --exit-code' '
diff --git a/t/t4044-diff-index-unique-abbrev.sh b/t/t4044-diff-index-unique-abbrev.sh
index 29e49d2290..9f6043daba 100755
--- a/t/t4044-diff-index-unique-abbrev.sh
+++ b/t/t4044-diff-index-unique-abbrev.sh
@@ -34,12 +34,12 @@ test_expect_success 'setup' '
100644 blob $(test_oid hash2) foo
EOF
- echo "$(test_oid val1)" > foo &&
+ test_oid val1 > foo &&
git add foo &&
git commit -m "initial" &&
git cat-file -p HEAD: > actual &&
test_cmp expect_initial actual &&
- echo "$(test_oid val2)" > foo &&
+ test_oid val2 > foo &&
git commit -a -m "update" &&
git cat-file -p HEAD: > actual &&
test_cmp expect_update actual
diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh
index fab351b48a..9b46c4c1be 100755
--- a/t/t4045-diff-relative.sh
+++ b/t/t4045-diff-relative.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='diff --relative tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
@@ -162,6 +164,35 @@ check_diff_relative_option subdir file2 true --no-relative --relative
check_diff_relative_option . file2 false --no-relative --relative=subdir
check_diff_relative_option . file2 true --no-relative --relative=subdir
+test_expect_success 'external diff with --relative' '
+ test_when_finished "git reset --hard" &&
+ echo changed >file1 &&
+ echo changed >subdir/file2 &&
+
+ write_script mydiff <<-\EOF &&
+ # hacky pretend diff; the goal here is just to make sure we got
+ # passed sensible input that we _could_ diff, without relying on
+ # the specific output of a system diff tool.
+ echo "diff a/$1 b/$1" &&
+ echo "--- a/$1" &&
+ echo "+++ b/$1" &&
+ echo "@@ -1 +0,0 @@" &&
+ sed "s/^/-/" "$2" &&
+ sed "s/^/+/" "$5"
+ EOF
+
+ cat >expect <<-\EOF &&
+ diff a/file2 b/file2
+ --- a/file2
+ +++ b/file2
+ @@ -1 +0,0 @@
+ -other content
+ +changed
+ EOF
+ GIT_EXTERNAL_DIFF=./mydiff git diff --relative=subdir >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'setup diff --relative unmerged' '
test_commit zero file0 &&
test_commit base subdir/file0 &&
diff --git a/t/t4046-diff-unmerged.sh b/t/t4046-diff-unmerged.sh
index 0ae0cd3a52..ffaf69335f 100755
--- a/t/t4046-diff-unmerged.sh
+++ b/t/t4046-diff-unmerged.sh
@@ -86,4 +86,14 @@ test_expect_success 'diff-files -3' '
test_cmp diff-files-3.expect diff-files-3.actual
'
+test_expect_success 'diff --stat' '
+ for path in $paths
+ do
+ echo " $path | Unmerged" || return 1
+ done >diff-stat.expect &&
+ echo " 0 files changed" >>diff-stat.expect &&
+ git diff --cached --stat >diff-stat.actual &&
+ test_cmp diff-stat.expect diff-stat.actual
+'
+
test_done
diff --git a/t/t4047-diff-dirstat.sh b/t/t4047-diff-dirstat.sh
index 7fec2cb9cd..70224c3da1 100755
--- a/t/t4047-diff-dirstat.sh
+++ b/t/t4047-diff-dirstat.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='diff --dirstat tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# set up two commits where the second commit has these files
diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh
index b5c281edaa..3ee27e277d 100755
--- a/t/t4052-stat-output.sh
+++ b/t/t4052-stat-output.sh
@@ -8,6 +8,7 @@ test_description='test --stat output of various commands'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
index 3feadf0e35..5f059f65fc 100755
--- a/t/t4053-diff-no-index.sh
+++ b/t/t4053-diff-no-index.sh
@@ -2,6 +2,7 @@
test_description='diff --no-index'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
@@ -204,4 +205,83 @@ test_expect_success POSIXPERM,SYMLINKS 'diff --no-index normalizes: mode not lik
test_cmp expected actual
'
+test_expect_success "diff --no-index treats '-' as stdin" '
+ cat >expect <<-EOF &&
+ diff --git a/- b/a/1
+ index $ZERO_OID..$(git hash-object --stdin <a/1) 100644
+ --- a/-
+ +++ b/a/1
+ @@ -1 +1 @@
+ -x
+ +1
+ EOF
+
+ test_write_lines x | test_expect_code 1 \
+ git -c core.abbrev=no diff --no-index -- - a/1 >actual &&
+ test_cmp expect actual &&
+
+ test_write_lines 1 | git diff --no-index -- a/1 - >actual &&
+ test_must_be_empty actual
+'
+
+test_expect_success "diff --no-index -R treats '-' as stdin" '
+ cat >expect <<-EOF &&
+ diff --git b/a/1 a/-
+ index $(git hash-object --stdin <a/1)..$ZERO_OID 100644
+ --- b/a/1
+ +++ a/-
+ @@ -1 +1 @@
+ -1
+ +x
+ EOF
+
+ test_write_lines x | test_expect_code 1 \
+ git -c core.abbrev=no diff --no-index -R -- - a/1 >actual &&
+ test_cmp expect actual &&
+
+ test_write_lines 1 | git diff --no-index -R -- a/1 - >actual &&
+ test_must_be_empty actual
+'
+
+test_expect_success 'diff --no-index refuses to diff stdin and a directory' '
+ test_must_fail git diff --no-index -- - a </dev/null 2>err &&
+ grep "fatal: cannot compare stdin to a directory" err
+'
+
+test_expect_success PIPE 'diff --no-index refuses to diff a named pipe and a directory' '
+ test_when_finished "rm -f pipe" &&
+ mkfifo pipe &&
+ test_must_fail git diff --no-index -- pipe a 2>err &&
+ grep "fatal: cannot compare a named pipe to a directory" err
+'
+
+test_expect_success PIPE,SYMLINKS 'diff --no-index reads from pipes' '
+ test_when_finished "rm -f old new new-link" &&
+ mkfifo old &&
+ mkfifo new &&
+ ln -s new new-link &&
+ {
+ (test_write_lines a b c >old) &
+ } &&
+ test_when_finished "kill $! || :" &&
+ {
+ (test_write_lines a x c >new) &
+ } &&
+ test_when_finished "kill $! || :" &&
+
+ cat >expect <<-EOF &&
+ diff --git a/old b/new-link
+ --- a/old
+ +++ b/new-link
+ @@ -1,3 +1,3 @@
+ a
+ -b
+ +x
+ c
+ EOF
+
+ test_expect_code 1 git diff --no-index old new-link >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4054-diff-bogus-tree.sh b/t/t4054-diff-bogus-tree.sh
index 294fb55313..05c88f8cdf 100755
--- a/t/t4054-diff-bogus-tree.sh
+++ b/t/t4054-diff-bogus-tree.sh
@@ -10,7 +10,7 @@ test_expect_success 'create bogus tree' '
bogus_tree=$(
printf "100644 fooQ$name" |
q_to_nul |
- git hash-object -w --stdin -t tree
+ git hash-object --literally -w --stdin -t tree
)
'
diff --git a/t/t4058-diff-duplicates.sh b/t/t4058-diff-duplicates.sh
index 54614b814d..2501c89c1c 100755
--- a/t/t4058-diff-duplicates.sh
+++ b/t/t4058-diff-duplicates.sh
@@ -29,7 +29,7 @@ make_tree () {
make_tree_entry "$1" "$2" "$3"
shift; shift; shift
done |
- git hash-object -w -t tree --stdin
+ git hash-object --literally -w -t tree --stdin
}
# this is kind of a convoluted setup, but matches
diff --git a/t/t4062-diff-pickaxe.sh b/t/t4062-diff-pickaxe.sh
index 9aaa068ed9..a90b46b678 100755
--- a/t/t4062-diff-pickaxe.sh
+++ b/t/t4062-diff-pickaxe.sh
@@ -24,7 +24,7 @@ test_expect_success '-G matches' '
test_expect_success '-S --pickaxe-regex' '
git diff --name-only -S0 --pickaxe-regex HEAD^ >out &&
- verbose test 4096-zeroes.txt = "$(cat out)"
+ test 4096-zeroes.txt = "$(cat out)"
'
test_done
diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh
index 28f42a4046..7af3a08862 100755
--- a/t/t4067-diff-partial-clone.sh
+++ b/t/t4067-diff-partial-clone.sh
@@ -2,6 +2,7 @@
test_description='behavior of diff when reading objects in a partial clone'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'git show batches blobs' '
@@ -150,7 +151,7 @@ test_expect_success 'diff does not fetch anything if inexact rename detection is
# Ensure no fetches.
GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD &&
- ! test_path_exists trace
+ test_path_is_missing trace
'
test_expect_success 'diff --break-rewrites fetches only if necessary, and batches blobs if it does' '
@@ -170,7 +171,7 @@ test_expect_success 'diff --break-rewrites fetches only if necessary, and batche
# Ensure no fetches.
GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD &&
- ! test_path_exists trace &&
+ test_path_is_missing trace &&
# But with --break-rewrites, ensure that there is exactly 1 negotiation
# by checking that there is only 1 "done" line sent. ("done" marks the
diff --git a/t/t4111-apply-subdir.sh b/t/t4111-apply-subdir.sh
index 1618a6dbc7..e9a87d761d 100755
--- a/t/t4111-apply-subdir.sh
+++ b/t/t4111-apply-subdir.sh
@@ -2,6 +2,7 @@
test_description='patching from inconvenient places'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
index e95e6d4e7d..a22a90d552 100755
--- a/t/t4115-apply-symlink.sh
+++ b/t/t4115-apply-symlink.sh
@@ -74,7 +74,7 @@ test_expect_success SYMLINKS 'symlink escape when creating new files' '
error: affected file ${SQ}renamed-symlink/create-me${SQ} is beyond a symbolic link
EOF
test_cmp expected_stderr stderr &&
- ! test_path_exists .git/create-me
+ test_path_is_missing .git/create-me
'
test_expect_success SYMLINKS 'symlink escape when modifying file' '
diff --git a/t/t4135-apply-weird-filenames.sh b/t/t4135-apply-weird-filenames.sh
index 6bc3fb97a7..d3502c6fdd 100755
--- a/t/t4135-apply-weird-filenames.sh
+++ b/t/t4135-apply-weird-filenames.sh
@@ -2,6 +2,7 @@
test_description='git apply with weird postimage filenames'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4141-apply-too-large.sh b/t/t4141-apply-too-large.sh
new file mode 100755
index 0000000000..20cc1209f6
--- /dev/null
+++ b/t/t4141-apply-too-large.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+test_description='git apply with too-large patch'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success EXPENSIVE 'git apply rejects patches that are too large' '
+ sz=$((1024 * 1024 * 1023)) &&
+ {
+ cat <<-\EOF &&
+ diff --git a/file b/file
+ new file mode 100644
+ --- /dev/null
+ +++ b/file
+ @@ -0,0 +1 @@
+ EOF
+ test-tool genzeros
+ } | test_copy_bytes $sz | test_must_fail git apply 2>err &&
+ grep "patch too large" err
+'
+
+test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index cdad4b6880..2935fe1b2d 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -103,7 +103,7 @@ test_expect_success setup '
git format-patch --stdout first >patch1 &&
{
- echo "Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" &&
+ echo "Message-ID: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" &&
echo "X-Fake-Field: Line One" &&
echo "X-Fake-Field: Line Two" &&
echo "X-Fake-Field: Line Three" &&
@@ -345,6 +345,21 @@ test_expect_success 'am with failing applypatch-msg hook' '
test_cmp_rev first HEAD
'
+test_expect_success 'am with failing applypatch-msg hook (no verify)' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+ git checkout first &&
+ test_hook applypatch-msg <<-\EOF &&
+ echo hook-message >"$1"
+ exit 1
+ EOF
+ git am --no-verify patch1 &&
+ test_path_is_missing .git/rebase-apply &&
+ git diff --exit-code second &&
+ git log -1 --format=format:%B >actual &&
+ test_cmp msg actual
+'
+
test_expect_success 'am with pre-applypatch hook' '
rm -fr .git/rebase-apply &&
git reset --hard &&
@@ -374,6 +389,23 @@ test_expect_success 'am with failing pre-applypatch hook' '
test_cmp_rev first HEAD
'
+test_expect_success 'am with failing pre-applypatch hook (no verify)' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+ git checkout first &&
+ touch empty-file &&
+ test_hook pre-applypatch <<-\EOF &&
+ rm empty-file
+ exit 1
+ EOF
+ git am --no-verify patch1 &&
+ test_path_is_missing .git/rebase-apply &&
+ test_path_is_file empty-file &&
+ git diff --exit-code second &&
+ git log -1 --format=format:%B >actual &&
+ test_cmp msg actual
+'
+
test_expect_success 'am with post-applypatch hook' '
rm -fr .git/rebase-apply &&
git reset --hard &&
@@ -910,7 +942,7 @@ test_expect_success 'am --message-id really adds the message id' '
git am --message-id patch1.eml &&
test_path_is_missing .git/rebase-apply &&
git cat-file commit HEAD | tail -n1 >actual &&
- grep Message-Id patch1.eml >expected &&
+ grep Message-ID patch1.eml >expected &&
test_cmp expected actual
'
@@ -922,7 +954,7 @@ test_expect_success 'am.messageid really adds the message id' '
git am patch1.eml &&
test_path_is_missing .git/rebase-apply &&
git cat-file commit HEAD | tail -n1 >actual &&
- grep Message-Id patch1.eml >expected &&
+ grep Message-ID patch1.eml >expected &&
test_cmp expected actual
'
@@ -933,7 +965,7 @@ test_expect_success 'am --message-id -s signs off after the message id' '
git am -s --message-id patch1.eml &&
test_path_is_missing .git/rebase-apply &&
git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
- grep Message-Id patch1.eml >expected &&
+ grep Message-ID patch1.eml >expected &&
test_cmp expected actual
'
@@ -1033,7 +1065,7 @@ test_expect_success 'am --patch-format=mboxrd handles mboxrd' '
>From extra escape for reversibility
INPUT_END
git commit -F msg &&
- git format-patch --pretty=mboxrd --stdout -1 >mboxrd1 &&
+ git -c format.mboxrd format-patch --stdout -1 >mboxrd1 &&
grep "^>From could trip up a loose mbox parser" mboxrd1 &&
git checkout -f first &&
git am --patch-format=mboxrd mboxrd1 &&
diff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh
index 4c68245aca..9f2edba1f8 100755
--- a/t/t4152-am-subjects.sh
+++ b/t/t4152-am-subjects.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test subject preservation with format-patch | am'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
make_patches() {
diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh
index 3095b1b2ff..8e4effebdb 100755
--- a/t/t4201-shortlog.sh
+++ b/t/t4201-shortlog.sh
@@ -83,6 +83,13 @@ test_expect_success 'pretty format' '
test_cmp expect log.predictable
'
+test_expect_success 'pretty format (with --date)' '
+ sed "s/SUBJECT/2005-04-07 OBJECT_NAME/" expect.template >expect &&
+ git shortlog --format="%ad %H" --date=short HEAD >log &&
+ fuzz log >log.predictable &&
+ test_cmp expect log.predictable
+'
+
test_expect_success '--abbrev' '
sed s/SUBJECT/OBJID/ expect.template >expect &&
git shortlog --format="%h" --abbrev=35 HEAD >log &&
@@ -237,6 +244,26 @@ test_expect_success 'shortlog --group=trailer:signed-off-by' '
test_cmp expect actual
'
+test_expect_success 'shortlog --group=format' '
+ git shortlog -s --date="format:%Y" --group="format:%cN (%cd)" \
+ HEAD >actual &&
+ cat >expect <<-\EOF &&
+ 4 C O Mitter (2005)
+ 1 Sin Nombre (2005)
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'shortlog --group=<format> DWIM' '
+ git shortlog -s --date="format:%Y" --group="%cN (%cd)" HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'shortlog bogus --group' '
+ test_must_fail git shortlog --group=bogus HEAD 2>err &&
+ grep "unknown group type" err
+'
+
test_expect_success 'trailer idents are split' '
cat >expect <<-\EOF &&
2 C O Mitter
@@ -319,6 +346,18 @@ test_expect_success 'shortlog can match multiple groups' '
test_cmp expect actual
'
+test_expect_success 'shortlog can match multiple format groups' '
+ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME" \
+ git commit --allow-empty -m "identical names" &&
+ test_tick &&
+ cat >expect <<-\EOF &&
+ 2 A U Thor
+ 1 C O Mitter
+ EOF
+ git shortlog -ns --group="%cn" --group="%an" -2 HEAD >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'set up option selection tests' '
git commit --allow-empty -F - <<-\EOF
subject
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index cc15cb4ff6..af4a123cd2 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -187,6 +187,21 @@ test_expect_success 'git config log.follow does not die with no paths' '
git log --
'
+test_expect_success 'git log --follow rejects unsupported pathspec magic' '
+ test_must_fail git log --follow ":(top,glob,icase)ichi" 2>stderr &&
+ # check full error message; we want to be sure we mention both
+ # of the rejected types (glob,icase), but not the allowed one (top)
+ echo "fatal: pathspec magic not supported by --follow: ${SQ}glob${SQ}, ${SQ}icase${SQ}" >expect &&
+ test_cmp expect stderr
+'
+
+test_expect_success 'log.follow disabled with unsupported pathspec magic' '
+ test_config log.follow true &&
+ git log --format=%s ":(glob,icase)ichi" >actual &&
+ echo third >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'git config log.follow is overridden by --no-follow' '
test_config log.follow true &&
git log --no-follow --pretty="format:%s" ichi >actual &&
@@ -249,6 +264,15 @@ test_expect_success 'log --grep' '
test_cmp expect actual
'
+for noop_opt in --invert-grep --all-match
+do
+ test_expect_success "log $noop_opt without --grep is a NOOP" '
+ git log >expect &&
+ git log $noop_opt >actual &&
+ test_cmp expect actual
+ '
+done
+
cat > expect << EOF
second
initial
@@ -826,6 +850,21 @@ test_expect_success 'log.decorate configuration' '
'
+test_expect_success 'parse log.excludeDecoration with no value' '
+ cp .git/config .git/config.orig &&
+ test_when_finished mv .git/config.orig .git/config &&
+
+ cat >>.git/config <<-\EOF &&
+ [log]
+ excludeDecoration
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''log.excludeDecoration'\''
+ EOF
+ git log --decorate=short 2>actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'decorate-refs with glob' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach
@@ -2319,10 +2358,10 @@ test_expect_success 'log --decorate does not include things outside filter' '
'
test_expect_success 'log --end-of-options' '
- git update-ref refs/heads/--source HEAD &&
- git log --end-of-options --source >actual &&
- git log >expect &&
- test_cmp expect actual
+ git update-ref refs/heads/--source HEAD &&
+ git log --end-of-options --source >actual &&
+ git log >expect &&
+ test_cmp expect actual
'
test_expect_success 'set up commits with different authors' '
diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh
index cd1cab3e54..2016132f51 100755
--- a/t/t4203-mailmap.sh
+++ b/t/t4203-mailmap.sh
@@ -466,7 +466,7 @@ test_expect_success 'gitmailmap(5) example output: example #1' '
Author Jane Doe <jane@laptop.(none)> maps to Jane Doe <jane@laptop.(none)>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
- Author Jane D <jane@desktop.(none)> maps to Jane Doe <jane@desktop.(none)>
+ Author Jane D. <jane@desktop.(none)> maps to Jane Doe <jane@desktop.(none)>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
EOF
git -C doc log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual &&
@@ -494,7 +494,7 @@ test_expect_success 'gitmailmap(5) example output: example #2' '
Author Jane Doe <jane@laptop.(none)> maps to Jane Doe <jane@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
- Author Jane D <jane@desktop.(none)> maps to Jane Doe <jane@example.com>
+ Author Jane D. <jane@desktop.(none)> maps to Jane Doe <jane@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
EOF
git -C doc log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual &&
@@ -1022,4 +1022,69 @@ test_expect_success '--mailmap enables mailmap in cat-file for annotated tag obj
test_cmp expect actual
'
+test_expect_success 'git cat-file -s returns correct size with --use-mailmap' '
+ test_when_finished "rm .mailmap" &&
+ cat >.mailmap <<-\EOF &&
+ C O Mitter <committer@example.com> Orig <orig@example.com>
+ EOF
+ git cat-file commit HEAD >commit.out &&
+ echo $(wc -c <commit.out) >expect &&
+ git cat-file --use-mailmap commit HEAD >commit.out &&
+ echo $(wc -c <commit.out) >>expect &&
+ git cat-file -s HEAD >actual &&
+ git cat-file --use-mailmap -s HEAD >>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git cat-file -s returns correct size with --use-mailmap for tag objects' '
+ test_when_finished "rm .mailmap" &&
+ cat >.mailmap <<-\EOF &&
+ Orig <orig@example.com> C O Mitter <committer@example.com>
+ EOF
+ git tag -a -m "annotated tag" v3 &&
+ git cat-file tag v3 >tag.out &&
+ echo $(wc -c <tag.out) >expect &&
+ git cat-file --use-mailmap tag v3 >tag.out &&
+ echo $(wc -c <tag.out) >>expect &&
+ git cat-file -s v3 >actual &&
+ git cat-file --use-mailmap -s v3 >>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git cat-file --batch-check returns correct size with --use-mailmap' '
+ test_when_finished "rm .mailmap" &&
+ cat >.mailmap <<-\EOF &&
+ C O Mitter <committer@example.com> Orig <orig@example.com>
+ EOF
+ git cat-file commit HEAD >commit.out &&
+ commit_size=$(wc -c <commit.out) &&
+ commit_sha=$(git rev-parse HEAD) &&
+ echo $commit_sha commit $commit_size >expect &&
+ git cat-file --use-mailmap commit HEAD >commit.out &&
+ commit_size=$(wc -c <commit.out) &&
+ echo $commit_sha commit $commit_size >>expect &&
+ echo "HEAD" >in &&
+ git cat-file --batch-check <in >actual &&
+ git cat-file --use-mailmap --batch-check <in >>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git cat-file --batch-command returns correct size with --use-mailmap' '
+ test_when_finished "rm .mailmap" &&
+ cat >.mailmap <<-\EOF &&
+ C O Mitter <committer@example.com> Orig <orig@example.com>
+ EOF
+ git cat-file commit HEAD >commit.out &&
+ commit_size=$(wc -c <commit.out) &&
+ commit_sha=$(git rev-parse HEAD) &&
+ echo $commit_sha commit $commit_size >expect &&
+ git cat-file --use-mailmap commit HEAD >commit.out &&
+ commit_size=$(wc -c <commit.out) &&
+ echo $commit_sha commit $commit_size >>expect &&
+ echo "info HEAD" >in &&
+ git cat-file --batch-command <in >actual &&
+ git cat-file --use-mailmap --batch-command <in >>actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh
index a730c0db98..a7fa94ce0a 100755
--- a/t/t4204-patch-id.sh
+++ b/t/t4204-patch-id.sh
@@ -8,13 +8,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
test_expect_success 'setup' '
- as="a a a a a a a a" && # eight a
- test_write_lines $as >foo &&
- test_write_lines $as >bar &&
+ str="ab cd ef gh ij kl mn op" &&
+ test_write_lines $str >foo &&
+ test_write_lines $str >bar &&
git add foo bar &&
git commit -a -m initial &&
- test_write_lines $as b >foo &&
- test_write_lines $as b >bar &&
+ test_write_lines $str b >foo &&
+ test_write_lines $str b >bar &&
git commit -a -m first &&
git checkout -b same main &&
git commit --amend -m same-msg &&
@@ -22,8 +22,23 @@ test_expect_success 'setup' '
echo c >foo &&
echo c >bar &&
git commit --amend -a -m notsame-msg &&
+ git checkout -b with_space main~ &&
+ cat >foo <<-\EOF &&
+ a b
+ c d
+ e f
+ g h
+ i j
+ k l
+ m n
+ op
+ EOF
+ cp foo bar &&
+ git add foo bar &&
+ git commit --amend -m "with spaces" &&
test_write_lines bar foo >bar-then-foo &&
test_write_lines foo bar >foo-then-bar
+
'
test_expect_success 'patch-id output is well-formed' '
@@ -42,7 +57,7 @@ calc_patch_id () {
}
get_top_diff () {
- git log -p -1 "$@" -O bar-then-foo --
+ git log -p -1 "$@" -O bar-then-foo --full-index --
}
get_patch_id () {
@@ -61,6 +76,33 @@ test_expect_success 'patch-id detects inequality' '
get_patch_id notsame &&
! test_cmp patch-id_main patch-id_notsame
'
+test_expect_success 'patch-id detects equality binary' '
+ cat >.gitattributes <<-\EOF &&
+ foo binary
+ bar binary
+ EOF
+ get_patch_id main &&
+ get_patch_id same &&
+ git log -p -1 --binary main >top-diff.output &&
+ calc_patch_id <top-diff.output main_binpatch &&
+ git log -p -1 --binary same >top-diff.output &&
+ calc_patch_id <top-diff.output same_binpatch &&
+ test_cmp patch-id_main patch-id_main_binpatch &&
+ test_cmp patch-id_same patch-id_same_binpatch &&
+ test_cmp patch-id_main patch-id_same &&
+ test_when_finished "rm .gitattributes"
+'
+
+test_expect_success 'patch-id detects inequality binary' '
+ cat >.gitattributes <<-\EOF &&
+ foo binary
+ bar binary
+ EOF
+ get_patch_id main &&
+ get_patch_id notsame &&
+ ! test_cmp patch-id_main patch-id_notsame &&
+ test_when_finished "rm .gitattributes"
+'
test_expect_success 'patch-id supports git-format-patch output' '
get_patch_id main &&
@@ -101,9 +143,21 @@ test_patch_id_file_order () {
git format-patch -1 --stdout -O foo-then-bar >format-patch.output &&
calc_patch_id <format-patch.output "ordered-$name" "$@" &&
cmp_patch_id $relevant "$name" "ordered-$name"
+}
+test_patch_id_whitespace () {
+ relevant="$1"
+ shift
+ name="ws-${1}-$relevant"
+ shift
+ get_top_diff "main~" >top-diff.output &&
+ calc_patch_id <top-diff.output "$name" "$@" &&
+ get_top_diff "with_space" >top-diff.output &&
+ calc_patch_id <top-diff.output "ws-$name" "$@" &&
+ cmp_patch_id $relevant "$name" "ws-$name"
}
+
# combined test for options: add more tests here to make them
# run with all options
test_patch_id () {
@@ -119,6 +173,14 @@ test_expect_success 'file order is relevant with --unstable' '
test_patch_id_file_order relevant --unstable --unstable
'
+test_expect_success 'whitespace is relevant with --verbatim' '
+ test_patch_id_whitespace relevant --verbatim --verbatim
+'
+
+test_expect_success 'whitespace is irrelevant without --verbatim' '
+ test_patch_id_whitespace irrelevant --stable --stable
+'
+
#Now test various option combinations.
test_expect_success 'default is unstable' '
test_patch_id relevant default
@@ -134,6 +196,17 @@ test_expect_success 'patchid.stable = false is unstable' '
test_patch_id relevant patchid.stable=false
'
+test_expect_success 'patchid.verbatim = true is correct and stable' '
+ test_config patchid.verbatim true &&
+ test_patch_id_whitespace relevant patchid.verbatim=true &&
+ test_patch_id irrelevant patchid.verbatim=true
+'
+
+test_expect_success 'patchid.verbatim = false is unstable' '
+ test_config patchid.verbatim false &&
+ test_patch_id relevant patchid.verbatim=false
+'
+
test_expect_success '--unstable overrides patchid.stable = true' '
test_config patchid.stable true &&
test_patch_id relevant patchid.stable=true--unstable --unstable
@@ -144,6 +217,11 @@ test_expect_success '--stable overrides patchid.stable = false' '
test_patch_id irrelevant patchid.stable=false--stable --stable
'
+test_expect_success '--verbatim overrides patchid.stable = false' '
+ test_config patchid.stable false &&
+ test_patch_id_whitespace relevant stable=false--verbatim --verbatim
+'
+
test_expect_success 'patch-id supports git-format-patch MIME output' '
get_patch_id main &&
git checkout same &&
@@ -198,7 +276,10 @@ test_expect_success 'patch-id handles no-nl-at-eof markers' '
EOF
calc_patch_id nonl <nonl &&
calc_patch_id withnl <withnl &&
- test_cmp patch-id_nonl patch-id_withnl
+ test_cmp patch-id_nonl patch-id_withnl &&
+ calc_patch_id nonl-inc-ws --verbatim <nonl &&
+ calc_patch_id withnl-inc-ws --verbatim <withnl &&
+ ! test_cmp patch-id_nonl-inc-ws patch-id_withnl-inc-ws
'
test_expect_success 'patch-id handles diffs with one line of before/after' '
diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
index fedb7ca749..16626e4fe9 100755
--- a/t/t4205-log-pretty-formats.sh
+++ b/t/t4205-log-pretty-formats.sh
@@ -156,7 +156,7 @@ test_expect_success 'NUL termination with --reflog --pretty=oneline' '
for r in $revs
do
git show -s --pretty=oneline "$r" >raw &&
- cat raw | lf_to_nul || exit 1
+ cat raw | lf_to_nul || return 1
done >expect &&
# the trailing NUL is already produced so we do not need to
# output another one
@@ -576,6 +576,38 @@ test_expect_success 'clean log decoration' '
test_cmp expected actual1
'
+test_expect_success 'pretty format %decorate' '
+ git checkout -b foo &&
+ git commit --allow-empty -m "new commit" &&
+ git tag bar &&
+ git branch qux &&
+
+ echo " (HEAD -> foo, tag: bar, qux)" >expect1 &&
+ git log --format="%(decorate)" -1 >actual1 &&
+ test_cmp expect1 actual1 &&
+
+ echo "HEAD -> foo, tag: bar, qux" >expect2 &&
+ git log --format="%(decorate:prefix=,suffix=)" -1 >actual2 &&
+ test_cmp expect2 actual2 &&
+
+ echo "[ HEAD -> foo; tag: bar; qux ]" >expect3 &&
+ git log --format="%(decorate:prefix=[ ,suffix= ],separator=%x3B )" \
+ -1 >actual3 &&
+ test_cmp expect3 actual3 &&
+
+ # Try with a typo (in "separator"), in which case the placeholder should
+ # not be replaced.
+ echo "%(decorate:prefix=[ ,suffix= ],separater=; )" >expect4 &&
+ git log --format="%(decorate:prefix=[ ,suffix= ],separater=%x3B )" \
+ -1 >actual4 &&
+ test_cmp expect4 actual4 &&
+
+ echo "HEAD->foo bar qux" >expect5 &&
+ git log --format="%(decorate:prefix=,suffix=,separator= ,tag=,pointer=->)" \
+ -1 >actual5 &&
+ test_cmp expect5 actual5
+'
+
cat >trailers <<EOF
Signed-off-by: A U Thor <author@example.com>
Acked-by: A U Thor <author@example.com>
@@ -1012,10 +1044,25 @@ test_expect_success '%(describe:tags) vs git describe --tags' '
test_expect_success '%(describe:abbrev=...) vs git describe --abbrev=...' '
test_when_finished "git tag -d tagname" &&
+
+ # Case 1: We have commits between HEAD and the most recent tag
+ # reachable from it
+ test_commit --no-tag file &&
+ git describe --abbrev=15 >expect &&
+ git log -1 --format="%(describe:abbrev=15)" >actual &&
+ test_cmp expect actual &&
+
+ # Make sure the hash used is at least 15 digits long
+ sed -e "s/^.*-g\([0-9a-f]*\)$/\1/" <actual >hexpart &&
+ test 16 -le $(wc -c <hexpart) &&
+
+ # Case 2: We have a tag at HEAD, describe directly gives the
+ # name of the tag
git tag -a -m tagged tagname &&
git describe --abbrev=15 >expect &&
git log -1 --format="%(describe:abbrev=15)" >actual &&
- test_cmp expect actual
+ test_cmp expect actual &&
+ test tagname = $(cat actual)
'
test_expect_success 'log --pretty with space stealing' '
@@ -1094,4 +1141,31 @@ test_expect_success EXPENSIVE,SIZE_T_IS_64BIT 'log --pretty with huge commit mes
test_cmp expect error
'
+# pretty-formats note wide char limitations, and add tests
+test_expect_failure 'wide and decomposed characters column counting' '
+
+# from t/lib-unicode-nfc-nfd.sh hex values converted to octal
+ utf8_nfc=$(printf "\303\251") && # e acute combined.
+ utf8_nfd=$(printf "\145\314\201") && # e with a combining acute (i.e. decomposed)
+ utf8_emoji=$(printf "\360\237\221\250") &&
+
+# replacement character when requesting a wide char fits in a single display colum.
+# "half wide" alternative could be a plain ASCII dot `.`
+ utf8_vert_ell=$(printf "\342\213\256") &&
+
+# use ${xxx} here!
+ nfc10="${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}${utf8_nfc}" &&
+ nfd10="${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}${utf8_nfd}" &&
+ emoji5="${utf8_emoji}${utf8_emoji}${utf8_emoji}${utf8_emoji}${utf8_emoji}" &&
+# emoji5 uses 10 display columns
+
+ test_commit "abcdefghij" &&
+ test_commit --no-tag "${nfc10}" &&
+ test_commit --no-tag "${nfd10}" &&
+ test_commit --no-tag "${emoji5}" &&
+ printf "${utf8_emoji}..${utf8_emoji}${utf8_vert_ell}\n${utf8_nfd}..${utf8_nfd}${utf8_nfd}\n${utf8_nfc}..${utf8_nfc}${utf8_nfc}\na..ij\n" >expected &&
+ git log --format="%<(5,mtrunc)%s" -4 >actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t4206-log-follow-harder-copies.sh b/t/t4206-log-follow-harder-copies.sh
index 33ecf82c7f..9167b0351f 100755
--- a/t/t4206-log-follow-harder-copies.sh
+++ b/t/t4206-log-follow-harder-copies.sh
@@ -16,29 +16,29 @@ Line 2
Line 3
'
-test_expect_success \
- 'add a file path0 and commit.' \
- 'git add path0 &&
- git commit -m "Add path0"'
+test_expect_success 'add a file path0 and commit.' '
+ git add path0 &&
+ git commit -m "Add path0"
+'
echo >path0 'New line 1
New line 2
New line 3
'
-test_expect_success \
- 'Change path0.' \
- 'git add path0 &&
- git commit -m "Change path0"'
+test_expect_success 'Change path0.' '
+ git add path0 &&
+ git commit -m "Change path0"
+'
cat <path0 >path1
-test_expect_success \
- 'copy path0 to path1.' \
- 'git add path1 &&
- git commit -m "Copy path1 from path0"'
+test_expect_success 'copy path0 to path1.' '
+ git add path1 &&
+ git commit -m "Copy path1 from path0"
+'
-test_expect_success \
- 'find the copy path0 -> path1 harder' \
- 'git log --follow --name-status --pretty="format:%s" path1 > current'
+test_expect_success 'find the copy path0 -> path1 harder' '
+ git log --follow --name-status --pretty="format:%s" path1 > current
+'
cat >expected <<\EOF
Copy path1 from path0
@@ -51,8 +51,8 @@ Add path0
A path0
EOF
-test_expect_success \
- 'validate the output.' \
- 'compare_diff_patch current expected'
+test_expect_success 'validate the output.' '
+ compare_diff_patch current expected
+'
test_done
diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh
index ded33a82e2..21986a866d 100755
--- a/t/t4207-log-decoration-colors.sh
+++ b/t/t4207-log-decoration-colors.sh
@@ -53,15 +53,17 @@ cmp_filtered_decorations () {
# to this test since it does not contain any decoration, hence --first-parent
test_expect_success 'commit decorations colored correctly' '
cat >expect <<-EOF &&
- ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \
-${c_reset}${c_branch}main${c_reset}${c_commit}, \
-${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \
-${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B
-${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A1${c_reset}${c_commit}, \
+ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\
+${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \
+${c_reset}${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_commit}, \
+${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_commit})${c_reset} B
+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}A1${c_reset}${c_commit}, \
${c_reset}${c_remoteBranch}other/main${c_reset}${c_commit})${c_reset} A1
- ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_stash}refs/stash${c_reset}${c_commit})${c_reset} \
-On main: Changes to A.t
- ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
+ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
+${c_stash}refs/stash${c_reset}${c_commit})${c_reset} On main: Changes to A.t
+ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A
EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always --all >actual &&
@@ -76,12 +78,14 @@ test_expect_success 'test coloring with replace-objects' '
git replace HEAD~1 HEAD~2 &&
cat >expect <<-EOF &&
- ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \
-${c_reset}${c_branch}main${c_reset}${c_commit}, \
-${c_reset}${c_tag}tag: D${c_reset}${c_commit})${c_reset} D
- ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: C${c_reset}${c_commit}, \
+ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\
+${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \
+${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_commit})${c_reset} D
+ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}C${c_reset}${c_commit}, \
${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B
- ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
+ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A
EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&
@@ -100,13 +104,15 @@ test_expect_success 'test coloring with grafted commit' '
git replace --graft HEAD HEAD~2 &&
cat >expect <<-EOF &&
- ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \
-${c_reset}${c_branch}main${c_reset}${c_commit}, \
-${c_reset}${c_tag}tag: D${c_reset}${c_commit}, \
+ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\
+${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \
+${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_commit}, \
${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D
- ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \
-${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B
- ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
+ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_commit}, \
+${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_commit})${c_reset} B
+ ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A
EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index ac9e4d0928..c6540e822f 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -315,4 +315,26 @@ test_expect_success 'line-log with --before' '
test_cmp expect actual
'
+test_expect_success 'setup tests for zero-width regular expressions' '
+ cat >expect <<-EOF
+ Modify func1() in file.c
+ Add func1() and func2() in file.c
+ EOF
+'
+
+test_expect_success 'zero-width regex $ matches any function name' '
+ git log --format="%s" --no-patch "-L:$:file.c" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'zero-width regex ^ matches any function name' '
+ git log --format="%s" --no-patch "-L:^:file.c" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'zero-width regex .* matches any function name' '
+ git log --format="%s" --no-patch "-L:.*:file.c" >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh
index 30a219894b..85e90acb09 100755
--- a/t/t4212-log-corrupt.sh
+++ b/t/t4212-log-corrupt.sh
@@ -8,9 +8,10 @@ TEST_PASSES_SANITIZE_LEAK=true
test_expect_success 'setup' '
test_commit foo &&
- git cat-file commit HEAD |
- sed "/^author /s/>/>-<>/" >broken_email.commit &&
- git hash-object -w -t commit broken_email.commit >broken_email.hash &&
+ git cat-file commit HEAD >ok.commit &&
+ sed "s/>/>-<>/" <ok.commit >broken_email.commit &&
+
+ git hash-object --literally -w -t commit broken_email.commit >broken_email.hash &&
git update-ref refs/heads/broken_email $(cat broken_email.hash)
'
@@ -43,10 +44,15 @@ test_expect_success 'git log --format with broken author email' '
test_must_be_empty actual.err
'
+test_expect_success '--until handles broken email' '
+ git rev-list --until=1980-01-01 broken_email >actual &&
+ test_must_be_empty actual
+'
+
munge_author_date () {
git cat-file commit "$1" >commit.orig &&
sed "s/^\(author .*>\) [0-9]*/\1 $2/" <commit.orig >commit.munge &&
- git hash-object -w -t commit commit.munge
+ git hash-object --literally -w -t commit commit.munge
}
test_expect_success 'unparsable dates produce sentinel value' '
@@ -86,4 +92,45 @@ test_expect_success 'absurdly far-in-future date' '
git log -1 --format=%ad $commit
'
+test_expect_success 'create commits with whitespace committer dates' '
+ # It is important that this subject line is numeric, since we want to
+ # be sure we are not confused by skipping whitespace and accidentally
+ # parsing the subject as a timestamp.
+ #
+ # Do not use munge_author_date here. Besides not hitting the committer
+ # line, it leaves the timezone intact, and we want nothing but
+ # whitespace.
+ #
+ # We will make two munged commits here. The first, ws_commit, will
+ # be purely spaces. The second contains a vertical tab, which is
+ # considered a space by strtoumax(), but not by our isspace().
+ test_commit 1234567890 &&
+ git cat-file commit HEAD >commit.orig &&
+ sed "s/>.*/> /" <commit.orig >commit.munge &&
+ ws_commit=$(git hash-object --literally -w -t commit commit.munge) &&
+ sed "s/>.*/> $(printf "\013")/" <commit.orig >commit.munge &&
+ vt_commit=$(git hash-object --literally -w -t commit commit.munge)
+'
+
+test_expect_success '--until treats whitespace date as sentinel' '
+ echo $ws_commit >expect &&
+ git rev-list --until=1980-01-01 $ws_commit >actual &&
+ test_cmp expect actual &&
+
+ echo $vt_commit >expect &&
+ git rev-list --until=1980-01-01 $vt_commit >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'pretty-printer handles whitespace date' '
+ # as with the %ad test above, we will show these as the empty string,
+ # not the 1970 epoch date. This is intentional; see 7d9a281941 (t4212:
+ # test bogus timestamps with git-log, 2014-02-24) for more discussion.
+ echo : >expect &&
+ git log -1 --format="%at:%ct" $ws_commit >actual &&
+ test_cmp expect actual &&
+ git log -1 --format="%at:%ct" $vt_commit >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4213-log-tabexpand.sh b/t/t4213-log-tabexpand.sh
index 53a4af3244..590fce95e9 100755
--- a/t/t4213-log-tabexpand.sh
+++ b/t/t4213-log-tabexpand.sh
@@ -2,6 +2,7 @@
test_description='log/show --expand-tabs'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
HT=" "
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
index 54be7da161..45f1d4f95e 100755
--- a/t/t4254-am-corrupt.sh
+++ b/t/t4254-am-corrupt.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git am with corrupt input'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
make_mbox_with_nul () {
diff --git a/t/t4256-am-format-flowed.sh b/t/t4256-am-format-flowed.sh
index 2369c4e17a..1015273bc8 100755
--- a/t/t4256-am-format-flowed.sh
+++ b/t/t4256-am-format-flowed.sh
@@ -2,6 +2,7 @@
test_description='test format=flowed support of git am'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4257-am-interactive.sh b/t/t4257-am-interactive.sh
index aed8f4de3d..f26d7fd2db 100755
--- a/t/t4257-am-interactive.sh
+++ b/t/t4257-am-interactive.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='am --interactive tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'set up patches to apply' '
diff --git a/t/t4258/mbox b/t/t4258/mbox
index c62819f3d2..1ae528ba78 100644
--- a/t/t4258/mbox
+++ b/t/t4258/mbox
@@ -2,7 +2,7 @@ From: A U Thor <mail@example.com>
To: list@example.org
Subject: [PATCH v2] sample
Date: Mon, 3 Aug 2020 22:40:55 +0700
-Message-Id: <msg-id@example.com>
+Message-ID: <msg-id@example.com>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
diff --git a/t/t4300-merge-tree.sh b/t/t4300-merge-tree.sh
index c52c8a21fa..57c4f26e46 100755
--- a/t/t4300-merge-tree.sh
+++ b/t/t4300-merge-tree.sh
@@ -334,4 +334,22 @@ test_expect_success 'turn tree to file' '
test_cmp expect actual
'
+test_expect_success 'merge-tree respects core.useReplaceRefs=false' '
+ test_commit merge-to &&
+ test_commit valid base &&
+ git reset --hard HEAD^ &&
+ test_commit malicious base &&
+
+ test_when_finished "git replace -d $(git rev-parse valid^0)" &&
+ git replace valid^0 malicious^0 &&
+
+ tree=$(git -c core.useReplaceRefs=true merge-tree --write-tree merge-to valid) &&
+ merged=$(git cat-file -p $tree:base) &&
+ test malicious = $merged &&
+
+ tree=$(git -c core.useReplaceRefs=false merge-tree --write-tree merge-to valid) &&
+ merged=$(git cat-file -p $tree:base) &&
+ test valid = $merged
+'
+
test_done
diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh
index 013b77144b..250f721795 100755
--- a/t/t4301-merge-tree-write-tree.sh
+++ b/t/t4301-merge-tree-write-tree.sh
@@ -141,7 +141,7 @@ test_expect_success 'test conflict notices and such' '
# Commit O: foo, olddir/{a,b,c}
# Commit A: modify foo, newdir/{a,b,c}
# Commit B: modify foo differently & rename foo -> olddir/bar
-# Expected: CONFLICT(content) for for newdir/bar (not olddir/bar or foo)
+# Expected: CONFLICT(content) for newdir/bar (not olddir/bar or foo)
test_expect_success 'directory rename + content conflict' '
# Setup
@@ -653,7 +653,7 @@ test_expect_success 'mod6: chains of rename/rename(1to2) and add/add via collidi
# Commit O: foo, olddir/{a,b,c}
# Commit A: delete foo, rename olddir/ -> newdir/, add newdir/bar/file
# Commit B: modify foo & rename foo -> olddir/bar
-# Expected: CONFLICT(content) for for newdir/bar (not olddir/bar or foo)
+# Expected: CONFLICT(content) for newdir/bar (not olddir/bar or foo)
test_expect_success 'directory rename + rename/delete + modify/delete + directory/file conflict' '
# Setup
@@ -819,4 +819,107 @@ test_expect_success SANITY 'merge-ort fails gracefully in a read-only repository
test_must_fail git -C read-only merge-tree side1 side2
'
+test_expect_success '--stdin with both a successful and a conflicted merge' '
+ printf "side1 side3\nside1 side2" | git merge-tree --stdin >actual &&
+
+ git checkout side1^0 &&
+ git merge side3 &&
+
+ printf "1\0" >expect &&
+ git rev-parse HEAD^{tree} | lf_to_nul >>expect &&
+ printf "\0" >>expect &&
+
+ git checkout side1^0 &&
+ test_must_fail git merge side2 &&
+ sed s/HEAD/side1/ greeting >tmp &&
+ mv tmp greeting &&
+ git add -u &&
+ git mv whatever~HEAD whatever~side1 &&
+
+ printf "0\0" >>expect &&
+ git write-tree | lf_to_nul >>expect &&
+
+ cat <<-EOF | q_to_tab | lf_to_nul >>expect &&
+ 100644 $(git rev-parse side1~1:greeting) 1Qgreeting
+ 100644 $(git rev-parse side1:greeting) 2Qgreeting
+ 100644 $(git rev-parse side2:greeting) 3Qgreeting
+ 100644 $(git rev-parse side1~1:whatever) 1Qwhatever~side1
+ 100644 $(git rev-parse side1:whatever) 2Qwhatever~side1
+ EOF
+
+ q_to_nul <<-EOF >>expect &&
+ Q1QgreetingQAuto-mergingQAuto-merging greeting
+ Q1QgreetingQCONFLICT (contents)QCONFLICT (content): Merge conflict in greeting
+ Q1QnumbersQAuto-mergingQAuto-merging numbers
+ Q2Qwhatever~side1QwhateverQCONFLICT (file/directory)QCONFLICT (file/directory): directory in the way of whatever from side1; moving it to whatever~side1 instead.
+ Q1Qwhatever~side1QCONFLICT (modify/delete)QCONFLICT (modify/delete): whatever~side1 deleted in side2 and modified in side1. Version side1 of whatever~side1 left in tree.
+ EOF
+
+ printf "\0\0" >>expect &&
+
+ test_cmp expect actual
+'
+
+
+test_expect_success '--merge-base is incompatible with --stdin' '
+ test_must_fail git merge-tree --merge-base=side1 --stdin 2>expect &&
+
+ grep "^fatal: --merge-base is incompatible with --stdin" expect
+'
+
+# specify merge-base as parent of branch2
+# git merge-tree --write-tree --merge-base=c2 c1 c3
+# Commit c1: add file1
+# Commit c2: add file2 after c1
+# Commit c3: add file3 after c2
+# Expected: add file3, and file2 does NOT appear
+
+test_expect_success 'specify merge-base as parent of branch2' '
+ # Setup
+ test_when_finished "rm -rf base-b2-p" &&
+ git init base-b2-p &&
+ test_commit -C base-b2-p c1 file1 &&
+ test_commit -C base-b2-p c2 file2 &&
+ test_commit -C base-b2-p c3 file3 &&
+
+ # Testing
+ TREE_OID=$(git -C base-b2-p merge-tree --write-tree --merge-base=c2 c1 c3) &&
+
+ q_to_tab <<-EOF >expect &&
+ 100644 blob $(git -C base-b2-p rev-parse c1:file1)Qfile1
+ 100644 blob $(git -C base-b2-p rev-parse c3:file3)Qfile3
+ EOF
+
+ git -C base-b2-p ls-tree $TREE_OID >actual &&
+ test_cmp expect actual
+'
+
+# Since the earlier tests have verified that individual merge-tree calls
+# are doing the right thing, this test case is only used to verify that
+# we can also trigger merges via --stdin, and that when we do we get
+# the same answer as running a bunch of separate merges.
+
+test_expect_success 'check the input format when --stdin is passed' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo c1 &&
+ test_commit -C repo c2 &&
+ test_commit -C repo c3 &&
+ printf "c1 c3\nc2 -- c1 c3\nc2 c3" | git -C repo merge-tree --stdin >actual &&
+
+ printf "1\0" >expect &&
+ git -C repo merge-tree --write-tree -z c1 c3 >>expect &&
+ printf "\0" >>expect &&
+
+ printf "1\0" >>expect &&
+ git -C repo merge-tree --write-tree -z --merge-base=c2 c1 c3 >>expect &&
+ printf "\0" >>expect &&
+
+ printf "1\0" >>expect &&
+ git -C repo merge-tree --write-tree -z c2 c3 >>expect &&
+ printf "\0" >>expect &&
+
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index eaa0b22ece..4b4c3315d8 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -105,6 +105,18 @@ check_added() {
'
}
+check_mtime() {
+ dir=$1
+ path_in_archive=$2
+ mtime=$3
+
+ test_expect_success " validate mtime of $path_in_archive" '
+ test-tool chmtime --get $dir/$path_in_archive >actual.mtime &&
+ echo $mtime >expect.mtime &&
+ test_cmp expect.mtime actual.mtime
+ '
+}
+
test_expect_success 'setup' '
test_oid_cache <<-EOF
obj sha1:19f9c8273ec45a8938e6999cb59b3ff66739902a
@@ -173,6 +185,14 @@ test_expect_success 'git archive' '
'
check_tar b
+check_mtime b a/a 1117231200
+
+test_expect_success 'git archive --mtime' '
+ git archive --mtime=2002-02-02T02:02:02-0200 HEAD >with_mtime.tar
+'
+
+check_tar with_mtime
+check_mtime with_mtime a/a 1012622522
test_expect_success 'git archive --prefix=prefix/' '
git archive --prefix=prefix/ HEAD >with_prefix.tar
@@ -238,14 +258,6 @@ test_expect_success 'git archive --remote with configured remote' '
test_cmp_bin b.tar b5-nick.tar
'
-test_expect_success 'validate file modification time' '
- mkdir extract &&
- "$TAR" xf b.tar -C extract a/a &&
- test-tool chmtime --get extract/a/a >b.mtime &&
- echo "1117231200" >expected.mtime &&
- test_cmp expected.mtime b.mtime
-'
-
test_expect_success 'git get-tar-commit-id' '
git get-tar-commit-id <b.tar >actual &&
git rev-parse HEAD >expect &&
@@ -342,6 +354,13 @@ test_expect_success 'only enabled filters are available remotely' '
test_cmp_bin remote.bar config.bar
'
+test_expect_success 'invalid filter is reported only once' '
+ test_must_fail git -c tar.invalid.command= archive --format=invalid \
+ HEAD >out 2>err &&
+ test_must_be_empty out &&
+ test_line_count = 1 err
+'
+
test_expect_success 'git archive --format=tgz' '
git archive --format=tgz HEAD >j.tgz
'
@@ -395,11 +414,11 @@ test_expect_success GZIP 'extract tgz file (external gzip)' '
test_expect_success 'archive and :(glob)' '
git archive -v HEAD -- ":(glob)**/sh" >/dev/null 2>actual &&
- cat >expect <<EOF &&
-a/
-a/bin/
-a/bin/sh
-EOF
+ cat >expect <<-\EOF &&
+ a/
+ a/bin/
+ a/bin/sh
+ EOF
test_cmp expect actual
'
@@ -407,6 +426,19 @@ test_expect_success 'catch non-matching pathspec' '
test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
'
+test_expect_success 'reject paths outside the current directory' '
+ test_must_fail git -C a/bin archive HEAD .. >/dev/null 2>err &&
+ grep "outside the current directory" err
+'
+
+test_expect_success 'allow pathspecs that resolve to the current directory' '
+ git -C a/bin archive -v HEAD ../bin >/dev/null 2>actual &&
+ cat >expect <<-\EOF &&
+ sh
+ EOF
+ test_cmp expect actual
+'
+
# Pull the size and date of each entry in a tarfile using the system tar.
#
# We'll pull out only the year from the date; that avoids any question of
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 2f6eef5e37..0ff47a239d 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -3,6 +3,7 @@
test_description='git archive attribute tests'
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
SUBSTFORMAT='%H (%h)%n'
@@ -32,6 +33,13 @@ test_expect_success 'setup' '
echo ignored-by-tree.d export-ignore >>.gitattributes &&
git add ignored-by-tree ignored-by-tree.d .gitattributes &&
+ mkdir subdir &&
+ >subdir/included &&
+ >subdir/ignored-by-subtree &&
+ >subdir/ignored-by-tree &&
+ echo ignored-by-subtree export-ignore >subdir/.gitattributes &&
+ git add subdir &&
+
echo ignored by worktree >ignored-by-worktree &&
echo ignored-by-worktree export-ignore >.gitattributes &&
git add ignored-by-worktree &&
@@ -92,6 +100,15 @@ test_expect_exists archive-pathspec-wildcard/ignored-by-worktree
test_expect_missing archive-pathspec-wildcard/excluded-by-pathspec.d
test_expect_missing archive-pathspec-wildcard/excluded-by-pathspec.d/file
+test_expect_success 'git -C subdir archive' '
+ git -C subdir archive HEAD >archive-subdir.tar &&
+ extract_tar_to_dir archive-subdir
+'
+
+test_expect_exists archive-subdir/included
+test_expect_missing archive-subdir/ignored-by-subtree
+test_expect_missing archive-subdir/ignored-by-tree
+
test_expect_success 'git archive with worktree attributes' '
git archive --worktree-attributes HEAD >worktree.tar &&
(mkdir worktree && cd worktree && "$TAR" xf -) <worktree.tar
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index ae508e2162..9f2c6da80e 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test corner cases of git-archive'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# the 10knuls.tar file is used to test for an empty git generated tar
diff --git a/t/t5100/msg0002 b/t/t5100/msg0002
index e2546ec733..1089382425 100644
--- a/t/t5100/msg0002
+++ b/t/t5100/msg0002
@@ -3,7 +3,7 @@ message:
From: Nit Picker <nit.picker@example.net>
Subject: foo is too old
-Message-Id: <nitpicker.12121212@example.net>
+Message-ID: <nitpicker.12121212@example.net>
Hopefully this would fix the problem stated there.
diff --git a/t/t5100/msg0003 b/t/t5100/msg0003
index 1ac68101b1..3402b534a6 100644
--- a/t/t5100/msg0003
+++ b/t/t5100/msg0003
@@ -3,7 +3,7 @@ message:
From: Nit Picker <nit.picker@example.net>
Subject: foo is too old
-Message-Id: <nitpicker.12121212@example.net>
+Message-ID: <nitpicker.12121212@example.net>
Hopefully this would fix the problem stated there.
diff --git a/t/t5100/msg0012--message-id b/t/t5100/msg0012--message-id
index 376e26e9ae..44482958ce 100644
--- a/t/t5100/msg0012--message-id
+++ b/t/t5100/msg0012--message-id
@@ -5,4 +5,4 @@ docutils заменён на python-docutils
python-docutils. В то время как сам rest2web не нужен.
Signed-off-by: Dmitriy Blinov <bda@mnsspb.ru>
-Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>
+Message-ID: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>
diff --git a/t/t5100/quoted-cr.mbox b/t/t5100/quoted-cr.mbox
index 909021bb7a..a529d4de08 100644
--- a/t/t5100/quoted-cr.mbox
+++ b/t/t5100/quoted-cr.mbox
@@ -3,7 +3,7 @@ From: A U Thor <mail@example.com>
To: list@example.org
Subject: [PATCH v2] sample
Date: Mon, 3 Aug 2020 22:40:55 +0700
-Message-Id: <msg-id@example.com>
+Message-ID: <msg-id@example.com>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
@@ -27,7 +27,7 @@ From: A U Thor <mail@example.com>
To: list@example.org
Subject: [PATCH v2] sample
Date: Mon, 3 Aug 2020 22:40:55 +0700
-Message-Id: <msg-id2@example.com>
+Message-ID: <msg-id2@example.com>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
diff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox
index 6d4d0e4474..4a54ee5171 100644
--- a/t/t5100/sample.mbox
+++ b/t/t5100/sample.mbox
@@ -35,7 +35,7 @@ message:
From: Nit Picker <nit.picker@example.net>
Subject: foo is too old
-Message-Id: <nitpicker.12121212@example.net>
+Message-ID: <nitpicker.12121212@example.net>
Hopefully this would fix the problem stated there.
@@ -78,7 +78,7 @@ message:
From: Nit Picker <nit.picker@example.net>
Subject: foo is too old
-Message-Id: <nitpicker.12121212@example.net>
+Message-ID: <nitpicker.12121212@example.net>
Hopefully this would fix the problem stated there.
@@ -508,7 +508,7 @@ From bda@mnsspb.ru Wed Nov 12 17:54:41 2008
From: Dmitriy Blinov <bda@mnsspb.ru>
To: navy-patches@dinar.mns.mnsspb.ru
Date: Wed, 12 Nov 2008 17:54:41 +0300
-Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>
+Message-ID: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>
X-Mailer: git-send-email 1.5.6.5
MIME-Version: 1.0
Content-Type: text/plain;
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index f8a0f309e2..745089479c 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -208,7 +208,7 @@ test_expect_success 'unpack with OFS_DELTA' '
'
test_expect_success 'unpack with OFS_DELTA (core.fsyncmethod=batch)' '
- check_unpack test-3-${packname_3} obj-list "$BATCH_CONFIGURATION"
+ check_unpack test-3-${packname_3} obj-list "$BATCH_CONFIGURATION"
'
test_expect_success 'compare delta flavors' '
@@ -263,97 +263,97 @@ test_expect_success 'survive missing objects/pack directory' '
)
'
-test_expect_success \
- 'verify pack' \
- 'git verify-pack test-1-${packname_1}.idx \
- test-2-${packname_2}.idx \
- test-3-${packname_3}.idx'
-
-test_expect_success \
- 'verify pack -v' \
- 'git verify-pack -v test-1-${packname_1}.idx \
- test-2-${packname_2}.idx \
- test-3-${packname_3}.idx'
-
-test_expect_success \
- 'verify-pack catches mismatched .idx and .pack files' \
- 'cat test-1-${packname_1}.idx >test-3.idx &&
- cat test-2-${packname_2}.pack >test-3.pack &&
- if git verify-pack test-3.idx
- then false
- else :;
- fi'
-
-test_expect_success \
- 'verify-pack catches a corrupted pack signature' \
- 'cat test-1-${packname_1}.pack >test-3.pack &&
- echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=2 &&
- if git verify-pack test-3.idx
- then false
- else :;
- fi'
-
-test_expect_success \
- 'verify-pack catches a corrupted pack version' \
- 'cat test-1-${packname_1}.pack >test-3.pack &&
- echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=7 &&
- if git verify-pack test-3.idx
- then false
- else :;
- fi'
-
-test_expect_success \
- 'verify-pack catches a corrupted type/size of the 1st packed object data' \
- 'cat test-1-${packname_1}.pack >test-3.pack &&
- echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=12 &&
- if git verify-pack test-3.idx
- then false
- else :;
- fi'
-
-test_expect_success \
- 'verify-pack catches a corrupted sum of the index file itself' \
- 'l=$(wc -c <test-3.idx) &&
- l=$(expr $l - 20) &&
- cat test-1-${packname_1}.pack >test-3.pack &&
- printf "%20s" "" | dd of=test-3.idx count=20 bs=1 conv=notrunc seek=$l &&
- if git verify-pack test-3.pack
- then false
- else :;
- fi'
-
-test_expect_success \
- 'build pack index for an existing pack' \
- 'cat test-1-${packname_1}.pack >test-3.pack &&
- git index-pack -o tmp.idx test-3.pack &&
- cmp tmp.idx test-1-${packname_1}.idx &&
-
- git index-pack --promisor=message test-3.pack &&
- cmp test-3.idx test-1-${packname_1}.idx &&
- echo message >expect &&
- test_cmp expect test-3.promisor &&
-
- cat test-2-${packname_2}.pack >test-3.pack &&
- git index-pack -o tmp.idx test-2-${packname_2}.pack &&
- cmp tmp.idx test-2-${packname_2}.idx &&
-
- git index-pack test-3.pack &&
- cmp test-3.idx test-2-${packname_2}.idx &&
-
- cat test-3-${packname_3}.pack >test-3.pack &&
- git index-pack -o tmp.idx test-3-${packname_3}.pack &&
- cmp tmp.idx test-3-${packname_3}.idx &&
-
- git index-pack test-3.pack &&
- cmp test-3.idx test-3-${packname_3}.idx &&
-
- cat test-1-${packname_1}.pack >test-4.pack &&
- rm -f test-4.keep &&
- git index-pack --keep=why test-4.pack &&
- cmp test-1-${packname_1}.idx test-4.idx &&
- test -f test-4.keep &&
-
- :'
+test_expect_success 'verify pack' '
+ git verify-pack test-1-${packname_1}.idx \
+ test-2-${packname_2}.idx \
+ test-3-${packname_3}.idx
+'
+
+test_expect_success 'verify pack -v' '
+ git verify-pack -v test-1-${packname_1}.idx \
+ test-2-${packname_2}.idx \
+ test-3-${packname_3}.idx
+'
+
+test_expect_success 'verify-pack catches mismatched .idx and .pack files' '
+ cat test-1-${packname_1}.idx >test-3.idx &&
+ cat test-2-${packname_2}.pack >test-3.pack &&
+ if git verify-pack test-3.idx
+ then false
+ else :;
+ fi
+'
+
+test_expect_success 'verify-pack catches a corrupted pack signature' '
+ cat test-1-${packname_1}.pack >test-3.pack &&
+ echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=2 &&
+ if git verify-pack test-3.idx
+ then false
+ else :;
+ fi
+'
+
+test_expect_success 'verify-pack catches a corrupted pack version' '
+ cat test-1-${packname_1}.pack >test-3.pack &&
+ echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=7 &&
+ if git verify-pack test-3.idx
+ then false
+ else :;
+ fi
+'
+
+test_expect_success 'verify-pack catches a corrupted type/size of the 1st packed object data' '
+ cat test-1-${packname_1}.pack >test-3.pack &&
+ echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=12 &&
+ if git verify-pack test-3.idx
+ then false
+ else :;
+ fi
+'
+
+test_expect_success 'verify-pack catches a corrupted sum of the index file itself' '
+ l=$(wc -c <test-3.idx) &&
+ l=$(expr $l - 20) &&
+ cat test-1-${packname_1}.pack >test-3.pack &&
+ printf "%20s" "" | dd of=test-3.idx count=20 bs=1 conv=notrunc seek=$l &&
+ if git verify-pack test-3.pack
+ then false
+ else :;
+ fi
+'
+
+test_expect_success 'build pack index for an existing pack' '
+ cat test-1-${packname_1}.pack >test-3.pack &&
+ git index-pack -o tmp.idx test-3.pack &&
+ cmp tmp.idx test-1-${packname_1}.idx &&
+
+ git index-pack --promisor=message test-3.pack &&
+ cmp test-3.idx test-1-${packname_1}.idx &&
+ echo message >expect &&
+ test_cmp expect test-3.promisor &&
+
+ cat test-2-${packname_2}.pack >test-3.pack &&
+ git index-pack -o tmp.idx test-2-${packname_2}.pack &&
+ cmp tmp.idx test-2-${packname_2}.idx &&
+
+ git index-pack test-3.pack &&
+ cmp test-3.idx test-2-${packname_2}.idx &&
+
+ cat test-3-${packname_3}.pack >test-3.pack &&
+ git index-pack -o tmp.idx test-3-${packname_3}.pack &&
+ cmp tmp.idx test-3-${packname_3}.idx &&
+
+ git index-pack test-3.pack &&
+ cmp test-3.idx test-3-${packname_3}.idx &&
+
+ cat test-1-${packname_1}.pack >test-4.pack &&
+ rm -f test-4.keep &&
+ git index-pack --keep=why test-4.pack &&
+ cmp test-1-${packname_1}.idx test-4.idx &&
+ test -f test-4.keep &&
+
+ :
+'
test_expect_success 'unpacking with --strict' '
@@ -589,141 +589,6 @@ test_expect_success 'prefetch objects' '
test_line_count = 1 donelines
'
-test_expect_success 'setup for --stdin-packs tests' '
- git init stdin-packs &&
- (
- cd stdin-packs &&
-
- test_commit A &&
- test_commit B &&
- test_commit C &&
-
- for id in A B C
- do
- git pack-objects .git/objects/pack/pack-$id \
- --incremental --revs <<-EOF || exit 1
- refs/tags/$id
- EOF
- done &&
-
- ls -la .git/objects/pack
- )
-'
-
-test_expect_success '--stdin-packs with excluded packs' '
- (
- cd stdin-packs &&
-
- PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
- PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
- PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
-
- git pack-objects test --stdin-packs <<-EOF &&
- $PACK_A
- ^$PACK_B
- $PACK_C
- EOF
-
- (
- git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-C-*.idx)
- ) >expect.raw &&
- git show-index <$(ls test-*.idx) >actual.raw &&
-
- cut -d" " -f2 <expect.raw | sort >expect &&
- cut -d" " -f2 <actual.raw | sort >actual &&
- test_cmp expect actual
- )
-'
-
-test_expect_success '--stdin-packs is incompatible with --filter' '
- (
- cd stdin-packs &&
- test_must_fail git pack-objects --stdin-packs --stdout \
- --filter=blob:none </dev/null 2>err &&
- test_i18ngrep "cannot use --filter with --stdin-packs" err
- )
-'
-
-test_expect_success '--stdin-packs is incompatible with --revs' '
- (
- cd stdin-packs &&
- test_must_fail git pack-objects --stdin-packs --revs out \
- </dev/null 2>err &&
- test_i18ngrep "cannot use internal rev list with --stdin-packs" err
- )
-'
-
-test_expect_success '--stdin-packs with loose objects' '
- (
- cd stdin-packs &&
-
- PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
- PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
- PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
-
- test_commit D && # loose
-
- git pack-objects test2 --stdin-packs --unpacked <<-EOF &&
- $PACK_A
- ^$PACK_B
- $PACK_C
- EOF
-
- (
- git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
- git rev-list --objects --no-object-names \
- refs/tags/C..refs/tags/D
-
- ) >expect.raw &&
- ls -la . &&
- git show-index <$(ls test2-*.idx) >actual.raw &&
-
- cut -d" " -f2 <expect.raw | sort >expect &&
- cut -d" " -f2 <actual.raw | sort >actual &&
- test_cmp expect actual
- )
-'
-
-test_expect_success '--stdin-packs with broken links' '
- (
- cd stdin-packs &&
-
- # make an unreachable object with a bogus parent
- git cat-file -p HEAD >commit &&
- sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit |
- git hash-object -w -t commit --stdin >in &&
-
- git pack-objects .git/objects/pack/pack-D <in &&
-
- PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
- PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
- PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
- PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" &&
-
- git pack-objects test3 --stdin-packs --unpacked <<-EOF &&
- $PACK_A
- ^$PACK_B
- $PACK_C
- $PACK_D
- EOF
-
- (
- git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-D-*.idx) &&
- git rev-list --objects --no-object-names \
- refs/tags/C..refs/tags/D
- ) >expect.raw &&
- git show-index <$(ls test3-*.idx) >actual.raw &&
-
- cut -d" " -f2 <expect.raw | sort >expect &&
- cut -d" " -f2 <actual.raw | sort >actual &&
- test_cmp expect actual
- )
-'
-
test_expect_success 'negative window clamps to 0' '
git pack-objects --progress --window=-1 neg-window <obj-list 2>stderr &&
check_deltas stderr = 0
diff --git a/t/t5301-sliding-window.sh b/t/t5301-sliding-window.sh
index 3ccaaeb397..226490d60d 100755
--- a/t/t5301-sliding-window.sh
+++ b/t/t5301-sliding-window.sh
@@ -8,55 +8,55 @@ test_description='mmap sliding window tests'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
-test_expect_success \
- 'setup' \
- 'rm -f .git/index* &&
- for i in a b c
- do
- echo $i >$i &&
- test-tool genrandom "$i" 32768 >>$i &&
- git update-index --add $i || return 1
- done &&
- echo d >d && cat c >>d && git update-index --add d &&
- tree=$(git write-tree) &&
- commit1=$(git commit-tree $tree </dev/null) &&
- git update-ref HEAD $commit1 &&
- git repack -a -d &&
- test "$(git count-objects)" = "0 objects, 0 kilobytes" &&
- pack1=$(ls .git/objects/pack/*.pack) &&
- test -f "$pack1"'
-
-test_expect_success \
- 'verify-pack -v, defaults' \
- 'git verify-pack -v "$pack1"'
-
-test_expect_success \
- 'verify-pack -v, packedGitWindowSize == 1 page' \
- 'git config core.packedGitWindowSize 512 &&
- git verify-pack -v "$pack1"'
-
-test_expect_success \
- 'verify-pack -v, packedGit{WindowSize,Limit} == 1 page' \
- 'git config core.packedGitWindowSize 512 &&
- git config core.packedGitLimit 512 &&
- git verify-pack -v "$pack1"'
-
-test_expect_success \
- 'repack -a -d, packedGit{WindowSize,Limit} == 1 page' \
- 'git config core.packedGitWindowSize 512 &&
- git config core.packedGitLimit 512 &&
- commit2=$(git commit-tree $tree -p $commit1 </dev/null) &&
- git update-ref HEAD $commit2 &&
- git repack -a -d &&
- test "$(git count-objects)" = "0 objects, 0 kilobytes" &&
- pack2=$(ls .git/objects/pack/*.pack) &&
- test -f "$pack2" &&
- test "$pack1" \!= "$pack2"'
-
-test_expect_success \
- 'verify-pack -v, defaults' \
- 'git config --unset core.packedGitWindowSize &&
- git config --unset core.packedGitLimit &&
- git verify-pack -v "$pack2"'
+test_expect_success 'setup' '
+ rm -f .git/index* &&
+ for i in a b c
+ do
+ echo $i >$i &&
+ test-tool genrandom "$i" 32768 >>$i &&
+ git update-index --add $i || return 1
+ done &&
+ echo d >d && cat c >>d && git update-index --add d &&
+ tree=$(git write-tree) &&
+ commit1=$(git commit-tree $tree </dev/null) &&
+ git update-ref HEAD $commit1 &&
+ git repack -a -d &&
+ test "$(git count-objects)" = "0 objects, 0 kilobytes" &&
+ pack1=$(ls .git/objects/pack/*.pack) &&
+ test -f "$pack1"
+'
+
+test_expect_success 'verify-pack -v, defaults' '
+ git verify-pack -v "$pack1"
+'
+
+test_expect_success 'verify-pack -v, packedGitWindowSize == 1 page' '
+ git config core.packedGitWindowSize 512 &&
+ git verify-pack -v "$pack1"
+'
+
+test_expect_success 'verify-pack -v, packedGit{WindowSize,Limit} == 1 page' '
+ git config core.packedGitWindowSize 512 &&
+ git config core.packedGitLimit 512 &&
+ git verify-pack -v "$pack1"
+'
+
+test_expect_success 'repack -a -d, packedGit{WindowSize,Limit} == 1 page' '
+ git config core.packedGitWindowSize 512 &&
+ git config core.packedGitLimit 512 &&
+ commit2=$(git commit-tree $tree -p $commit1 </dev/null) &&
+ git update-ref HEAD $commit2 &&
+ git repack -a -d &&
+ test "$(git count-objects)" = "0 objects, 0 kilobytes" &&
+ pack2=$(ls .git/objects/pack/*.pack) &&
+ test -f "$pack2" &&
+ test "$pack1" \!= "$pack2"
+'
+
+test_expect_success 'verify-pack -v, defaults' '
+ git config --unset core.packedGitWindowSize &&
+ git config --unset core.packedGitLimit &&
+ git verify-pack -v "$pack2"
+'
test_done
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index b0095ab41d..f89809be53 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -4,6 +4,8 @@
#
test_description='pack index with 64-bit offsets and object CRC'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
@@ -263,7 +265,7 @@ tag guten tag
This is an invalid tag.
EOF
- tag=$(git hash-object -t tag -w --stdin <wrong-tag) &&
+ tag=$(git hash-object -t tag -w --stdin --literally <wrong-tag) &&
pack1=$(echo $tag $sha | git pack-objects tag-test) &&
echo remove tag object &&
thirtyeight=${tag#??} &&
diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh
index 2926e8dfc4..61469ef4a6 100755
--- a/t/t5303-pack-corruption-resilience.sh
+++ b/t/t5303-pack-corruption-resilience.sh
@@ -59,304 +59,304 @@ do_corrupt_object() {
printf '\0' > zero
-test_expect_success \
- 'initial setup validation' \
- 'create_test_files &&
- create_new_pack &&
- git prune-packed &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- 'create corruption in header of first object' \
- 'do_corrupt_object $blob_1 0 < zero &&
- test_must_fail git cat-file blob $blob_1 > /dev/null &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- test_must_fail git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... but having a loose copy allows for full recovery' \
- 'mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_1 &&
- mv tmp ${pack}.idx &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... and loose copy of first delta allows for partial recovery' \
- 'git prune-packed &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_2 &&
- mv tmp ${pack}.idx &&
- test_must_fail git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- 'create corruption in data of first object' \
- 'create_new_pack &&
- git prune-packed &&
- chmod +w ${pack}.pack &&
- perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack &&
- test_must_fail git cat-file blob $blob_1 > /dev/null &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- test_must_fail git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... but having a loose copy allows for full recovery' \
- 'mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_1 &&
- mv tmp ${pack}.idx &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... and loose copy of second object allows for partial recovery' \
- 'git prune-packed &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_2 &&
- mv tmp ${pack}.idx &&
- test_must_fail git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- 'create corruption in header of first delta' \
- 'create_new_pack &&
- git prune-packed &&
- do_corrupt_object $blob_2 0 < zero &&
- git cat-file blob $blob_1 > /dev/null &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- test_must_fail git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... but having a loose copy allows for full recovery' \
- 'mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_2 &&
- mv tmp ${pack}.idx &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... and then a repack "clears" the corruption' \
- 'do_repack &&
- git prune-packed &&
- git verify-pack ${pack}.pack &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- 'create corruption in data of first delta' \
- 'create_new_pack &&
- git prune-packed &&
- chmod +w ${pack}.pack &&
- perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack &&
- git cat-file blob $blob_1 > /dev/null &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- test_must_fail git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... but having a loose copy allows for full recovery' \
- 'mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_2 &&
- mv tmp ${pack}.idx &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... and then a repack "clears" the corruption' \
- 'do_repack &&
- git prune-packed &&
- git verify-pack ${pack}.pack &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- 'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \
- 'create_new_pack &&
- git prune-packed &&
- do_corrupt_object $blob_2 2 < zero &&
- git cat-file blob $blob_1 > /dev/null &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- test_must_fail git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... but having a loose copy allows for full recovery' \
- 'mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_2 &&
- mv tmp ${pack}.idx &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... and then a repack "clears" the corruption' \
- 'do_repack &&
- git prune-packed &&
- git verify-pack ${pack}.pack &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- 'corruption #0 in delta base reference of first delta (OBJ_OFS_DELTA)' \
- 'create_new_pack --delta-base-offset &&
- git prune-packed &&
- do_corrupt_object $blob_2 2 < zero &&
- git cat-file blob $blob_1 > /dev/null &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- test_must_fail git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... but having a loose copy allows for full recovery' \
- 'mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_2 &&
- mv tmp ${pack}.idx &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... and then a repack "clears" the corruption' \
- 'do_repack --delta-base-offset &&
- git prune-packed &&
- git verify-pack ${pack}.pack &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- 'corruption #1 in delta base reference of first delta (OBJ_OFS_DELTA)' \
- 'create_new_pack --delta-base-offset &&
- git prune-packed &&
- printf "\001" | do_corrupt_object $blob_2 2 &&
- git cat-file blob $blob_1 > /dev/null &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- test_must_fail git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... but having a loose copy allows for full recovery' \
- 'mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_2 &&
- mv tmp ${pack}.idx &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... and then a repack "clears" the corruption' \
- 'do_repack --delta-base-offset &&
- git prune-packed &&
- git verify-pack ${pack}.pack &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... and a redundant pack allows for full recovery too' \
- 'do_corrupt_object $blob_2 2 < zero &&
- git cat-file blob $blob_1 > /dev/null &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- test_must_fail git cat-file blob $blob_3 > /dev/null &&
- mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_1 &&
- git hash-object -t blob -w file_2 &&
- printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack &&
- git prune-packed &&
- mv tmp ${pack}.idx &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- 'corruption of delta base reference pointing to wrong object' \
- 'create_new_pack --delta-base-offset &&
- git prune-packed &&
- printf "\220\033" | do_corrupt_object $blob_3 2 &&
- git cat-file blob $blob_1 >/dev/null &&
- git cat-file blob $blob_2 >/dev/null &&
- test_must_fail git cat-file blob $blob_3 >/dev/null'
-
-test_expect_success \
- '... but having a loose copy allows for full recovery' \
- 'mv ${pack}.idx tmp &&
- git hash-object -t blob -w file_3 &&
- mv tmp ${pack}.idx &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- '... and then a repack "clears" the corruption' \
- 'do_repack --delta-base-offset --no-reuse-delta &&
- git prune-packed &&
- git verify-pack ${pack}.pack &&
- git cat-file blob $blob_1 > /dev/null &&
- git cat-file blob $blob_2 > /dev/null &&
- git cat-file blob $blob_3 > /dev/null'
-
-test_expect_success \
- 'corrupting header to have too small output buffer fails unpack' \
- 'create_new_pack &&
- git prune-packed &&
- printf "\262\001" | do_corrupt_object $blob_1 0 &&
- test_must_fail git cat-file blob $blob_1 > /dev/null &&
- test_must_fail git cat-file blob $blob_2 > /dev/null &&
- test_must_fail git cat-file blob $blob_3 > /dev/null'
+test_expect_success 'initial setup validation' '
+ create_test_files &&
+ create_new_pack &&
+ git prune-packed &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success 'create corruption in header of first object' '
+ do_corrupt_object $blob_1 0 < zero &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... but having a loose copy allows for full recovery' '
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_1 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... and loose copy of first delta allows for partial recovery' '
+ git prune-packed &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success 'create corruption in data of first object' '
+ create_new_pack &&
+ git prune-packed &&
+ chmod +w ${pack}.pack &&
+ perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... but having a loose copy allows for full recovery' '
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_1 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... and loose copy of second object allows for partial recovery' '
+ git prune-packed &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success 'create corruption in header of first delta' '
+ create_new_pack &&
+ git prune-packed &&
+ do_corrupt_object $blob_2 0 < zero &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... but having a loose copy allows for full recovery' '
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... and then a repack "clears" the corruption' '
+ do_repack &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success 'create corruption in data of first delta' '
+ create_new_pack &&
+ git prune-packed &&
+ chmod +w ${pack}.pack &&
+ perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... but having a loose copy allows for full recovery' '
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... and then a repack "clears" the corruption' '
+ do_repack &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success 'corruption in delta base reference of first delta (OBJ_REF_DELTA)' '
+ create_new_pack &&
+ git prune-packed &&
+ do_corrupt_object $blob_2 2 < zero &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... but having a loose copy allows for full recovery' '
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... and then a repack "clears" the corruption' '
+ do_repack &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success 'corruption #0 in delta base reference of first delta (OBJ_OFS_DELTA)' '
+ create_new_pack --delta-base-offset &&
+ git prune-packed &&
+ do_corrupt_object $blob_2 2 < zero &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... but having a loose copy allows for full recovery' '
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... and then a repack "clears" the corruption' '
+ do_repack --delta-base-offset &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success 'corruption #1 in delta base reference of first delta (OBJ_OFS_DELTA)' '
+ create_new_pack --delta-base-offset &&
+ git prune-packed &&
+ printf "\001" | do_corrupt_object $blob_2 2 &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... but having a loose copy allows for full recovery' '
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... and then a repack "clears" the corruption' '
+ do_repack --delta-base-offset &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... and a redundant pack allows for full recovery too' '
+ do_corrupt_object $blob_2 2 < zero &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null &&
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_1 &&
+ git hash-object -t blob -w file_2 &&
+ printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack &&
+ git prune-packed &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success 'corruption of delta base reference pointing to wrong object' '
+ create_new_pack --delta-base-offset &&
+ git prune-packed &&
+ printf "\220\033" | do_corrupt_object $blob_3 2 &&
+ git cat-file blob $blob_1 >/dev/null &&
+ git cat-file blob $blob_2 >/dev/null &&
+ test_must_fail git cat-file blob $blob_3 >/dev/null
+'
+
+test_expect_success '... but having a loose copy allows for full recovery' '
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_3 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success '... and then a repack "clears" the corruption' '
+ do_repack --delta-base-offset --no-reuse-delta &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null
+'
+
+test_expect_success 'corrupting header to have too small output buffer fails unpack' '
+ create_new_pack &&
+ git prune-packed &&
+ printf "\262\001" | do_corrupt_object $blob_1 0 &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null
+'
# \0 - empty base
# \1 - one byte in result
# \1 - one literal byte (X)
-test_expect_success \
- 'apply good minimal delta' \
- 'printf "\0\1\1X" > minimal_delta &&
- test-tool delta -p /dev/null minimal_delta /dev/null'
+test_expect_success 'apply good minimal delta' '
+ printf "\0\1\1X" > minimal_delta &&
+ test-tool delta -p /dev/null minimal_delta /dev/null
+'
# \0 - empty base
# \1 - 1 byte in result
# \2 - two literal bytes (one too many)
-test_expect_success \
- 'apply delta with too many literal bytes' \
- 'printf "\0\1\2XX" > too_big_literal &&
- test_must_fail test-tool delta -p /dev/null too_big_literal /dev/null'
+test_expect_success 'apply delta with too many literal bytes' '
+ printf "\0\1\2XX" > too_big_literal &&
+ test_must_fail test-tool delta -p /dev/null too_big_literal /dev/null
+'
# \4 - four bytes in base
# \1 - one byte in result
# \221 - copy, one byte offset, one byte size
# \0 - copy from offset 0
# \2 - copy two bytes (one too many)
-test_expect_success \
- 'apply delta with too many copied bytes' \
- 'printf "\4\1\221\0\2" > too_big_copy &&
- printf base >base &&
- test_must_fail test-tool delta -p base too_big_copy /dev/null'
+test_expect_success 'apply delta with too many copied bytes' '
+ printf "\4\1\221\0\2" > too_big_copy &&
+ printf base >base &&
+ test_must_fail test-tool delta -p base too_big_copy /dev/null
+'
# \0 - empty base
# \2 - two bytes in result
# \2 - two literal bytes (we are short one)
-test_expect_success \
- 'apply delta with too few literal bytes' \
- 'printf "\0\2\2X" > truncated_delta &&
- test_must_fail test-tool delta -p /dev/null truncated_delta /dev/null'
+test_expect_success 'apply delta with too few literal bytes' '
+ printf "\0\2\2X" > truncated_delta &&
+ test_must_fail test-tool delta -p /dev/null truncated_delta /dev/null
+'
# \0 - empty base
# \1 - one byte in result
# \221 - copy, one byte offset, one byte size
# \0 - copy from offset 0
# \1 - copy one byte (we are short one)
-test_expect_success \
- 'apply delta with too few bytes in base' \
- 'printf "\0\1\221\0\1" > truncated_base &&
- test_must_fail test-tool delta -p /dev/null truncated_base /dev/null'
+test_expect_success 'apply delta with too few bytes in base' '
+ printf "\0\1\221\0\1" > truncated_base &&
+ test_must_fail test-tool delta -p /dev/null truncated_base /dev/null
+'
# \4 - four bytes in base
# \2 - two bytes in result
@@ -366,20 +366,20 @@ test_expect_success \
#
# Note that the literal byte is necessary to get past the uninteresting minimum
# delta size check.
-test_expect_success \
- 'apply delta with truncated copy parameters' \
- 'printf "\4\2\1X\221" > truncated_copy_delta &&
- printf base >base &&
- test_must_fail test-tool delta -p base truncated_copy_delta /dev/null'
+test_expect_success 'apply delta with truncated copy parameters' '
+ printf "\4\2\1X\221" > truncated_copy_delta &&
+ printf base >base &&
+ test_must_fail test-tool delta -p base truncated_copy_delta /dev/null
+'
# \0 - empty base
# \1 - one byte in result
# \1 - one literal byte (X)
# \1 - trailing garbage command
-test_expect_success \
- 'apply delta with trailing garbage literal' \
- 'printf "\0\1\1X\1" > tail_garbage_literal &&
- test_must_fail test-tool delta -p /dev/null tail_garbage_literal /dev/null'
+test_expect_success 'apply delta with trailing garbage literal' '
+ printf "\0\1\1X\1" > tail_garbage_literal &&
+ test_must_fail test-tool delta -p /dev/null tail_garbage_literal /dev/null
+'
# \4 - four bytes in base
# \1 - one byte in result
@@ -387,19 +387,19 @@ test_expect_success \
# \221 - copy, one byte offset, one byte size
# \0 - copy from offset 0
# \1 - copy 1 byte
-test_expect_success \
- 'apply delta with trailing garbage copy' \
- 'printf "\4\1\1X\221\0\1" > tail_garbage_copy &&
- printf base >base &&
- test_must_fail test-tool delta -p /dev/null tail_garbage_copy /dev/null'
+test_expect_success 'apply delta with trailing garbage copy' '
+ printf "\4\1\1X\221\0\1" > tail_garbage_copy &&
+ printf base >base &&
+ test_must_fail test-tool delta -p /dev/null tail_garbage_copy /dev/null
+'
# \0 - empty base
# \1 - one byte in result
# \1 - one literal byte (X)
# \0 - bogus opcode
-test_expect_success \
- 'apply delta with trailing garbage opcode' \
- 'printf "\0\1\1X\0" > tail_garbage_opcode &&
- test_must_fail test-tool delta -p /dev/null tail_garbage_opcode /dev/null'
+test_expect_success 'apply delta with trailing garbage opcode' '
+ printf "\0\1\1X\0" > tail_garbage_opcode &&
+ test_must_fail test-tool delta -p /dev/null tail_garbage_opcode /dev/null
+'
test_done
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index 8ae314af58..b4df545e5a 100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -16,7 +16,7 @@ add_blob() {
before=$(git count-objects | sed "s/ .*//") &&
BLOB=$(echo aleph_0 | git hash-object -w --stdin) &&
BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
- verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+ test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
test-tool chmtime =+0 $BLOB_FILE
}
@@ -29,6 +29,14 @@ test_expect_success setup '
git gc
'
+test_expect_success 'bare repo prune is quiet without $GIT_DIR/objects/pack' '
+ git clone -q --shared --template= --bare . bare.git &&
+ rmdir bare.git/objects/pack &&
+ git --git-dir=bare.git prune --no-progress 2>prune.err &&
+ test_must_be_empty prune.err &&
+ rm -r bare.git prune.err
+'
+
test_expect_success 'prune stale packs' '
orig_pack=$(echo .git/objects/pack/*.pack) &&
>.git/objects/tmp_1.pack &&
@@ -43,34 +51,42 @@ test_expect_success 'prune stale packs' '
test_expect_success 'prune --expire' '
add_blob &&
git prune --expire=1.hour.ago &&
- verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+ test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
test-tool chmtime =-86500 $BLOB_FILE &&
git prune --expire 1.day &&
- verbose test $before = $(git count-objects | sed "s/ .*//") &&
+ test $before = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc: implicit prune --expire' '
add_blob &&
test-tool chmtime =-$((2*$week-30)) $BLOB_FILE &&
- git gc &&
- verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+ git gc --no-cruft &&
+ test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
test-tool chmtime =-$((2*$week+1)) $BLOB_FILE &&
- git gc &&
- verbose test $before = $(git count-objects | sed "s/ .*//") &&
+ git gc --no-cruft &&
+ test $before = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc: refuse to start with invalid gc.pruneExpire' '
- git config gc.pruneExpire invalid &&
- test_must_fail git gc
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ >repo/.git/config &&
+ git -C repo config gc.pruneExpire invalid &&
+ cat >expect <<-\EOF &&
+ error: Invalid gc.pruneexpire: '\''invalid'\''
+ fatal: bad config variable '\''gc.pruneexpire'\'' in file '\''.git/config'\'' at line 2
+ EOF
+ test_must_fail git -C repo gc 2>actual &&
+ test_cmp expect actual
'
test_expect_success 'gc: start with ok gc.pruneExpire' '
git config gc.pruneExpire 2.days.ago &&
- git gc
+ git gc --no-cruft
'
test_expect_success 'prune: prune nonsense parameters' '
@@ -121,44 +137,44 @@ test_expect_success 'gc --no-prune' '
add_blob &&
test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
git config gc.pruneExpire 2.days.ago &&
- git gc --no-prune &&
- verbose test 1 = $(git count-objects | sed "s/ .*//") &&
+ git gc --no-prune --no-cruft &&
+ test 1 = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE
'
test_expect_success 'gc respects gc.pruneExpire' '
git config gc.pruneExpire 5002.days.ago &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_file $BLOB_FILE &&
git config gc.pruneExpire 5000.days.ago &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc --prune=<date>' '
add_blob &&
test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
- git gc --prune=5002.days.ago &&
+ git gc --prune=5002.days.ago --no-cruft &&
test_path_is_file $BLOB_FILE &&
- git gc --prune=5000.days.ago &&
+ git gc --prune=5000.days.ago --no-cruft &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc --prune=never' '
add_blob &&
- git gc --prune=never &&
+ git gc --prune=never --no-cruft &&
test_path_is_file $BLOB_FILE &&
- git gc --prune=now &&
+ git gc --prune=now --no-cruft &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc respects gc.pruneExpire=never' '
git config gc.pruneExpire never &&
add_blob &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_file $BLOB_FILE &&
git config gc.pruneExpire now &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_missing $BLOB_FILE
'
@@ -176,10 +192,10 @@ test_expect_success 'gc: prune old objects after local clone' '
git clone --no-hardlinks . aclone &&
(
cd aclone &&
- verbose test 1 = $(git count-objects | sed "s/ .*//") &&
+ test 1 = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
- git gc --prune &&
- verbose test 0 = $(git count-objects | sed "s/ .*//") &&
+ git gc --prune --no-cruft &&
+ test 0 = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
)
'
@@ -221,7 +237,7 @@ test_expect_success 'clean pack garbage with gc' '
>.git/objects/pack/fake2.keep &&
>.git/objects/pack/fake2.idx &&
>.git/objects/pack/fake3.keep &&
- git gc &&
+ git gc --no-cruft &&
git count-objects -v 2>stderr &&
grep "^warning:" stderr | sort >actual &&
cat >expected <<\EOF &&
@@ -334,4 +350,18 @@ test_expect_success 'old reachable-from-recent retained with bitmaps' '
test_must_fail git cat-file -e $to_drop
'
+test_expect_success 'gc.recentObjectsHook' '
+ add_blob &&
+ test-tool chmtime =-86500 $BLOB_FILE &&
+
+ write_script precious-objects <<-EOF &&
+ echo $BLOB
+ EOF
+ test_config gc.recentObjectsHook ./precious-objects &&
+
+ git prune --expire=now &&
+
+ git cat-file -p $BLOB
+'
+
test_done
diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh
index 51973f4a51..0d50c6b4bc 100755
--- a/t/t5306-pack-nobase.sh
+++ b/t/t5306-pack-nobase.sh
@@ -6,22 +6,23 @@
test_description='git-pack-object with missing base
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Create A-B chain
#
-test_expect_success \
- 'setup base' \
- 'test_write_lines a b c d e f g h i >text &&
- echo side >side &&
- git update-index --add text side &&
- A=$(echo A | git commit-tree $(git write-tree)) &&
+test_expect_success 'setup base' '
+ test_write_lines a b c d e f g h i >text &&
+ echo side >side &&
+ git update-index --add text side &&
+ A=$(echo A | git commit-tree $(git write-tree)) &&
- echo m >>text &&
- git update-index text &&
- B=$(echo B | git commit-tree $(git write-tree) -p $A) &&
- git update-ref HEAD $B
- '
+ echo m >>text &&
+ git update-index text &&
+ B=$(echo B | git commit-tree $(git write-tree) -p $A) &&
+ git update-ref HEAD $B
+'
# Create repository with C whose parent is B.
# Repository contains C, C^{tree}, C:text, B, B^{tree}.
@@ -29,52 +30,49 @@ test_expect_success \
# Repository is missing A (parent of B).
# Repository is missing A:side.
#
-test_expect_success \
- 'setup patch_clone' \
- 'base_objects=$(pwd)/.git/objects &&
- (mkdir patch_clone &&
- cd patch_clone &&
- git init &&
- echo "$base_objects" >.git/objects/info/alternates &&
- echo q >>text &&
- git read-tree $B &&
- git update-index text &&
- git update-ref HEAD $(echo C | git commit-tree $(git write-tree) -p $B) &&
- rm .git/objects/info/alternates &&
+test_expect_success 'setup patch_clone' '
+ base_objects=$(pwd)/.git/objects &&
+ (mkdir patch_clone &&
+ cd patch_clone &&
+ git init &&
+ echo "$base_objects" >.git/objects/info/alternates &&
+ echo q >>text &&
+ git read-tree $B &&
+ git update-index text &&
+ git update-ref HEAD $(echo C | git commit-tree $(git write-tree) -p $B) &&
+ rm .git/objects/info/alternates &&
- git --git-dir=../.git cat-file commit $B |
- git hash-object -t commit -w --stdin &&
+ git --git-dir=../.git cat-file commit $B |
+ git hash-object -t commit -w --stdin &&
- git --git-dir=../.git cat-file tree "$B^{tree}" |
- git hash-object -t tree -w --stdin
- ) &&
- C=$(git --git-dir=patch_clone/.git rev-parse HEAD)
- '
+ git --git-dir=../.git cat-file tree "$B^{tree}" |
+ git hash-object -t tree -w --stdin
+ ) &&
+ C=$(git --git-dir=patch_clone/.git rev-parse HEAD)
+'
# Clone patch_clone indirectly by cloning base and fetching.
#
-test_expect_success \
- 'indirectly clone patch_clone' \
- '(mkdir user_clone &&
- cd user_clone &&
- git init &&
- git pull ../.git &&
- test $(git rev-parse HEAD) = $B &&
+test_expect_success 'indirectly clone patch_clone' '
+ (mkdir user_clone &&
+ cd user_clone &&
+ git init &&
+ git pull ../.git &&
+ test $(git rev-parse HEAD) = $B &&
- git pull ../patch_clone/.git &&
- test $(git rev-parse HEAD) = $C
- )
- '
+ git pull ../patch_clone/.git &&
+ test $(git rev-parse HEAD) = $C
+ )
+'
# Cloning the patch_clone directly should fail.
#
-test_expect_success \
- 'clone of patch_clone is incomplete' \
- '(mkdir user_direct &&
- cd user_direct &&
- git init &&
- test_must_fail git fetch ../patch_clone/.git
- )
- '
+test_expect_success 'clone of patch_clone is incomplete' '
+ (mkdir user_direct &&
+ cd user_direct &&
+ git init &&
+ test_must_fail git fetch ../patch_clone/.git
+ )
+'
test_done
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index 6d693eef82..78c1c6c923 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -9,6 +9,10 @@ test_description='exercise basic bitmap functionality'
# their place.
GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
+# Likewise, allow individual tests to control whether or not they use
+# the boundary-based traversal.
+sane_unset GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL
+
objpath () {
echo ".git/objects/$(echo "$1" | sed -e 's|\(..\)|\1/|')"
}
@@ -404,6 +408,26 @@ test_bitmap_cases () {
)
'
+ test_expect_success 'pack.preferBitmapTips' '
+ git init repo &&
+ test_when_finished "rm -rf repo" &&
+ (
+ cd repo &&
+ git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
+ test_commit_bulk --message="%s" 103 &&
+
+ cat >>.git/config <<-\EOF &&
+ [pack]
+ preferBitmapTips
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''pack.preferbitmaptips'\''
+ EOF
+ git repack -adb 2>actual &&
+ test_cmp expect actual
+ )
+ '
+
test_expect_success 'complains about multiple pack bitmaps' '
rm -fr repo &&
git init repo &&
@@ -428,14 +452,22 @@ test_bitmap_cases () {
test_line_count = 2 packs &&
test_line_count = 2 bitmaps &&
- git rev-list --use-bitmap-index HEAD 2>err &&
- grep "ignoring extra bitmap file" err
+ GIT_TRACE2_EVENT=$(pwd)/trace2.txt git rev-list --use-bitmap-index HEAD &&
+ grep "opened bitmap" trace2.txt &&
+ grep "ignoring extra bitmap" trace2.txt
)
'
}
test_bitmap_cases
+GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL=1
+export GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL
+
+test_bitmap_cases
+
+sane_unset GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL
+
test_expect_success 'incremental repack fails when bitmaps are requested' '
test_commit more-1 &&
test_must_fail git repack -d 2>err &&
@@ -447,6 +479,33 @@ test_expect_success 'incremental repack can disable bitmaps' '
git repack -d --no-write-bitmap-index
'
+test_expect_success 'boundary-based traversal is used when requested' '
+ git repack -a -d --write-bitmap-index &&
+
+ for argv in \
+ "git -c pack.useBitmapBoundaryTraversal=true" \
+ "git -c feature.experimental=true" \
+ "GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL=1 git"
+ do
+ eval "GIT_TRACE2_EVENT=1 $argv rev-list --objects \
+ --use-bitmap-index second..other 2>perf" &&
+ grep "\"region_enter\".*\"label\":\"haves/boundary\"" perf ||
+ return 1
+ done &&
+
+ for argv in \
+ "git -c pack.useBitmapBoundaryTraversal=false" \
+ "git -c feature.experimental=true -c pack.useBitmapBoundaryTraversal=false" \
+ "GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL=0 git -c pack.useBitmapBoundaryTraversal=true" \
+ "GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL=0 git -c feature.experimental=true"
+ do
+ eval "GIT_TRACE2_EVENT=1 $argv rev-list --objects \
+ --use-bitmap-index second..other 2>perf" &&
+ grep "\"region_enter\".*\"label\":\"haves/classic\"" perf ||
+ return 1
+ done
+'
+
test_bitmap_cases "pack.writeBitmapLookupTable"
test_expect_success 'verify writing bitmap lookup table when enabled' '
diff --git a/t/t5312-prune-corruption.sh b/t/t5312-prune-corruption.sh
index 9d8e249ae8..230cb38712 100755
--- a/t/t5312-prune-corruption.sh
+++ b/t/t5312-prune-corruption.sh
@@ -14,6 +14,7 @@ what currently happens. If that changes, these tests should be revisited.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'disable reflogs' '
diff --git a/t/t5313-pack-bounds-checks.sh b/t/t5313-pack-bounds-checks.sh
index cc4cfaa9d3..ceaa6700a2 100755
--- a/t/t5313-pack-bounds-checks.sh
+++ b/t/t5313-pack-bounds-checks.sh
@@ -59,7 +59,7 @@ test_expect_success 'setup' '
test_expect_success 'set up base packfile and variables' '
# the hash of this content starts with ff, which
# makes some later computations much simpler
- echo $(test_oid oidfff) >file &&
+ test_oid oidfff >file &&
git add file &&
git commit -m base &&
git repack -ad &&
diff --git a/t/t5314-pack-cycle-detection.sh b/t/t5314-pack-cycle-detection.sh
index 73a241743a..82734b9a3c 100755
--- a/t/t5314-pack-cycle-detection.sh
+++ b/t/t5314-pack-cycle-detection.sh
@@ -63,13 +63,16 @@ TEST_PASSES_SANITIZE_LEAK=true
# Note that the two variants of "file" must be similar enough to convince git
# to create the delta.
make_pack () {
- {
- printf '%s\n' "-$(git rev-parse $2)"
- printf '%s dummy\n' "$(git rev-parse $1:dummy)"
- printf '%s file\n' "$(git rev-parse $1:file)"
- } |
- git pack-objects --stdout |
- git index-pack --stdin --fix-thin
+ ln1=$(git rev-parse "$2") &&
+ ln2=$(git rev-parse "$1:dummy") &&
+ ln3=$(git rev-parse "$1:file") &&
+ cat >list <<-EOF
+ -$ln1
+ $ln2 dummy
+ $ln3 file
+ EOF
+ git pack-objects --stdout <list >pack &&
+ git index-pack --stdin --fix-thin <pack
}
test_expect_success 'setup' '
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index bb633c9b09..b26d476c64 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -5,6 +5,7 @@ test_description='git pack-objects using object filtering'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Test blob:none filter.
@@ -24,8 +25,9 @@ parse_verify_pack_blob_oid () {
}
test_expect_success 'verify blob count in normal packfile' '
- git -C r1 ls-files -s file.1 file.2 file.3 file.4 file.5 |
- test_parse_ls_files_stage_oids |
+ git -C r1 ls-files -s file.1 file.2 file.3 file.4 file.5 \
+ >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
git -C r1 pack-objects --revs --stdout >all.pack <<-EOF &&
@@ -123,8 +125,8 @@ test_expect_success 'setup r2' '
'
test_expect_success 'verify blob count in normal packfile' '
- git -C r2 ls-files -s large.1000 large.10000 |
- test_parse_ls_files_stage_oids |
+ git -C r2 ls-files -s large.1000 large.10000 >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
git -C r2 pack-objects --revs --stdout >all.pack <<-EOF &&
@@ -161,8 +163,8 @@ test_expect_success 'verify blob:limit=1000' '
'
test_expect_success 'verify blob:limit=1001' '
- git -C r2 ls-files -s large.1000 |
- test_parse_ls_files_stage_oids |
+ git -C r2 ls-files -s large.1000 >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
git -C r2 pack-objects --revs --stdout --filter=blob:limit=1001 >filter.pack <<-EOF &&
@@ -179,8 +181,8 @@ test_expect_success 'verify blob:limit=1001' '
'
test_expect_success 'verify blob:limit=10001' '
- git -C r2 ls-files -s large.1000 large.10000 |
- test_parse_ls_files_stage_oids |
+ git -C r2 ls-files -s large.1000 large.10000 >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
git -C r2 pack-objects --revs --stdout --filter=blob:limit=10001 >filter.pack <<-EOF &&
@@ -197,8 +199,8 @@ test_expect_success 'verify blob:limit=10001' '
'
test_expect_success 'verify blob:limit=1k' '
- git -C r2 ls-files -s large.1000 |
- test_parse_ls_files_stage_oids |
+ git -C r2 ls-files -s large.1000 >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
git -C r2 pack-objects --revs --stdout --filter=blob:limit=1k >filter.pack <<-EOF &&
@@ -215,8 +217,8 @@ test_expect_success 'verify blob:limit=1k' '
'
test_expect_success 'verify explicitly specifying oversized blob in input' '
- git -C r2 ls-files -s large.1000 large.10000 |
- test_parse_ls_files_stage_oids |
+ git -C r2 ls-files -s large.1000 large.10000 >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
echo HEAD >objects &&
@@ -233,8 +235,8 @@ test_expect_success 'verify explicitly specifying oversized blob in input' '
'
test_expect_success 'verify blob:limit=1m' '
- git -C r2 ls-files -s large.1000 large.10000 |
- test_parse_ls_files_stage_oids |
+ git -C r2 ls-files -s large.1000 large.10000 >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
git -C r2 pack-objects --revs --stdout --filter=blob:limit=1m >filter.pack <<-EOF &&
@@ -264,6 +266,44 @@ test_expect_success 'verify normal and blob:limit packfiles have same commits/tr
test_cmp expected observed
'
+test_expect_success 'verify small limit and big limit results in small limit' '
+ git -C r2 ls-files -s large.1000 >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
+ sort >expected &&
+
+ git -C r2 pack-objects --revs --stdout --filter=blob:limit=1001 \
+ --filter=blob:limit=10001 >filter.pack <<-EOF &&
+ HEAD
+ EOF
+ git -C r2 index-pack ../filter.pack &&
+
+ git -C r2 verify-pack -v ../filter.pack >verify_result &&
+ grep blob verify_result |
+ parse_verify_pack_blob_oid |
+ sort >observed &&
+
+ test_cmp expected observed
+'
+
+test_expect_success 'verify big limit and small limit results in small limit' '
+ git -C r2 ls-files -s large.1000 >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
+ sort >expected &&
+
+ git -C r2 pack-objects --revs --stdout --filter=blob:limit=10001 \
+ --filter=blob:limit=1001 >filter.pack <<-EOF &&
+ HEAD
+ EOF
+ git -C r2 index-pack ../filter.pack &&
+
+ git -C r2 verify-pack -v ../filter.pack >verify_result &&
+ grep blob verify_result |
+ parse_verify_pack_blob_oid |
+ sort >observed &&
+
+ test_cmp expected observed
+'
+
# Test sparse:path=<path> filter.
# !!!!
# NOTE: sparse:path filter support has been dropped for security reasons,
@@ -289,8 +329,9 @@ test_expect_success 'setup r3' '
'
test_expect_success 'verify blob count in normal packfile' '
- git -C r3 ls-files -s sparse1 sparse2 dir1/sparse1 dir1/sparse2 |
- test_parse_ls_files_stage_oids |
+ git -C r3 ls-files -s sparse1 sparse2 dir1/sparse1 dir1/sparse2 \
+ >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
git -C r3 pack-objects --revs --stdout >all.pack <<-EOF &&
@@ -341,8 +382,9 @@ test_expect_success 'setup r4' '
'
test_expect_success 'verify blob count in normal packfile' '
- git -C r4 ls-files -s pattern sparse1 sparse2 dir1/sparse1 dir1/sparse2 |
- test_parse_ls_files_stage_oids |
+ git -C r4 ls-files -s pattern sparse1 sparse2 dir1/sparse1 dir1/sparse2 \
+ >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
git -C r4 pack-objects --revs --stdout >all.pack <<-EOF &&
@@ -359,8 +401,8 @@ test_expect_success 'verify blob count in normal packfile' '
'
test_expect_success 'verify sparse:oid=OID' '
- git -C r4 ls-files -s dir1/sparse1 dir1/sparse2 |
- test_parse_ls_files_stage_oids |
+ git -C r4 ls-files -s dir1/sparse1 dir1/sparse2 >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
git -C r4 ls-files -s pattern >staged &&
@@ -379,8 +421,8 @@ test_expect_success 'verify sparse:oid=OID' '
'
test_expect_success 'verify sparse:oid=oid-ish' '
- git -C r4 ls-files -s dir1/sparse1 dir1/sparse2 |
- test_parse_ls_files_stage_oids |
+ git -C r4 ls-files -s dir1/sparse1 dir1/sparse2 >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
git -C r4 pack-objects --revs --stdout --filter=sparse:oid=main:pattern >filter.pack <<-EOF &&
@@ -400,8 +442,9 @@ test_expect_success 'verify sparse:oid=oid-ish' '
# This models previously omitted objects that we did not receive.
test_expect_success 'setup r1 - delete loose blobs' '
- git -C r1 ls-files -s file.1 file.2 file.3 file.4 file.5 |
- test_parse_ls_files_stage_oids |
+ git -C r1 ls-files -s file.1 file.2 file.3 file.4 file.5 \
+ >ls_files_result &&
+ test_parse_ls_files_stage_oids <ls_files_result |
sort >expected &&
for id in `cat expected | sed "s|..|&/|"`
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index 049c5fc8ea..ba65f17dd9 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -24,12 +24,10 @@ test_expect_success 'usage shown with an error on unknown sub-command' '
test_cmp expect actual
'
+objdir=".git/objects"
+
test_expect_success 'setup full repo' '
- mkdir full &&
- cd "$TRASH_DIRECTORY/full" &&
- git init &&
- git config core.commitGraph true &&
- objdir=".git/objects"
+ git init full
'
test_expect_success POSIXPERM 'tweak umask for modebit tests' '
@@ -37,31 +35,28 @@ test_expect_success POSIXPERM 'tweak umask for modebit tests' '
'
test_expect_success 'verify graph with no graph file' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph verify
+ git -C full commit-graph verify
'
test_expect_success 'write graph with no packs' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph write --object-dir $objdir &&
- test_path_is_missing $objdir/info/commit-graph
+ git -C full commit-graph write --object-dir $objdir &&
+ test_path_is_missing full/$objdir/info/commit-graph
'
test_expect_success 'exit with correct error on bad input to --stdin-packs' '
- cd "$TRASH_DIRECTORY/full" &&
echo doesnotexist >in &&
- test_expect_code 1 git commit-graph write --stdin-packs <in 2>stderr &&
+ test_expect_code 1 git -C full commit-graph write --stdin-packs \
+ <in 2>stderr &&
test_i18ngrep "error adding pack" stderr
'
test_expect_success 'create commits and repack' '
- cd "$TRASH_DIRECTORY/full" &&
for i in $(test_seq 3)
do
- test_commit $i &&
- git branch commits/$i || return 1
+ test_commit -C full $i &&
+ git -C full branch commits/$i || return 1
done &&
- git repack
+ git -C full repack
'
. "$TEST_DIRECTORY"/lib-commit-graph.sh
@@ -69,117 +64,106 @@ test_expect_success 'create commits and repack' '
graph_git_behavior 'no graph' full commits/3 commits/1
test_expect_success 'exit with correct error on bad input to --stdin-commits' '
- cd "$TRASH_DIRECTORY/full" &&
# invalid, non-hex OID
- echo HEAD >in &&
- test_expect_code 1 git commit-graph write --stdin-commits <in 2>stderr &&
+ echo HEAD | test_expect_code 1 git -C full commit-graph write \
+ --stdin-commits 2>stderr &&
test_i18ngrep "unexpected non-hex object ID: HEAD" stderr &&
# non-existent OID
- echo $ZERO_OID >in &&
- test_expect_code 1 git commit-graph write --stdin-commits <in 2>stderr &&
+ echo $ZERO_OID | test_expect_code 1 git -C full commit-graph write \
+ --stdin-commits 2>stderr &&
test_i18ngrep "invalid object" stderr &&
# valid commit and tree OID
- git rev-parse HEAD HEAD^{tree} >in &&
- git commit-graph write --stdin-commits <in &&
- graph_read_expect 3 generation_data
+ git -C full rev-parse HEAD HEAD^{tree} >in &&
+ git -C full commit-graph write --stdin-commits <in &&
+ graph_read_expect -C full 3 generation_data
'
test_expect_success 'write graph' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph write &&
- test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "3" generation_data
+ git -C full commit-graph write &&
+ test_path_is_file full/$objdir/info/commit-graph &&
+ graph_read_expect -C full 3 generation_data
'
test_expect_success POSIXPERM 'write graph has correct permissions' '
- test_path_is_file $objdir/info/commit-graph &&
+ test_path_is_file full/$objdir/info/commit-graph &&
echo "-r--r--r--" >expect &&
- test_modebits $objdir/info/commit-graph >actual &&
+ test_modebits full/$objdir/info/commit-graph >actual &&
test_cmp expect actual
'
graph_git_behavior 'graph exists' full commits/3 commits/1
test_expect_success 'Add more commits' '
- cd "$TRASH_DIRECTORY/full" &&
- git reset --hard commits/1 &&
+ git -C full reset --hard commits/1 &&
for i in $(test_seq 4 5)
do
- test_commit $i &&
- git branch commits/$i || return 1
+ test_commit -C full $i &&
+ git -C full branch commits/$i || return 1
done &&
- git reset --hard commits/2 &&
+ git -C full reset --hard commits/2 &&
for i in $(test_seq 6 7)
do
- test_commit $i &&
- git branch commits/$i || return 1
+ test_commit -C full $i &&
+ git -C full branch commits/$i || return 1
done &&
- git reset --hard commits/2 &&
- git merge commits/4 &&
- git branch merge/1 &&
- git reset --hard commits/4 &&
- git merge commits/6 &&
- git branch merge/2 &&
- git reset --hard commits/3 &&
- git merge commits/5 commits/7 &&
- git branch merge/3 &&
- git repack
+ git -C full reset --hard commits/2 &&
+ git -C full merge commits/4 &&
+ git -C full branch merge/1 &&
+ git -C full reset --hard commits/4 &&
+ git -C full merge commits/6 &&
+ git -C full branch merge/2 &&
+ git -C full reset --hard commits/3 &&
+ git -C full merge commits/5 commits/7 &&
+ git -C full branch merge/3 &&
+ git -C full repack
'
test_expect_success 'commit-graph write progress off for redirected stderr' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph write 2>err &&
+ git -C full commit-graph write 2>err &&
test_must_be_empty err
'
test_expect_success 'commit-graph write force progress on for stderr' '
- cd "$TRASH_DIRECTORY/full" &&
- GIT_PROGRESS_DELAY=0 git commit-graph write --progress 2>err &&
+ GIT_PROGRESS_DELAY=0 git -C full commit-graph write --progress 2>err &&
test_file_not_empty err
'
test_expect_success 'commit-graph write with the --no-progress option' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph write --no-progress 2>err &&
+ git -C full commit-graph write --no-progress 2>err &&
test_must_be_empty err
'
test_expect_success 'commit-graph write --stdin-commits progress off for redirected stderr' '
- cd "$TRASH_DIRECTORY/full" &&
- git rev-parse commits/5 >in &&
- git commit-graph write --stdin-commits <in 2>err &&
+ git -C full rev-parse commits/5 >in &&
+ git -C full commit-graph write --stdin-commits <in 2>err &&
test_must_be_empty err
'
test_expect_success 'commit-graph write --stdin-commits force progress on for stderr' '
- cd "$TRASH_DIRECTORY/full" &&
- git rev-parse commits/5 >in &&
- GIT_PROGRESS_DELAY=0 git commit-graph write --stdin-commits --progress <in 2>err &&
+ git -C full rev-parse commits/5 >in &&
+ GIT_PROGRESS_DELAY=0 git -C full commit-graph write --stdin-commits \
+ --progress <in 2>err &&
test_i18ngrep "Collecting commits from input" err
'
test_expect_success 'commit-graph write --stdin-commits with the --no-progress option' '
- cd "$TRASH_DIRECTORY/full" &&
- git rev-parse commits/5 >in &&
- git commit-graph write --stdin-commits --no-progress <in 2>err &&
+ git -C full rev-parse commits/5 >in &&
+ git -C full commit-graph write --stdin-commits --no-progress <in 2>err &&
test_must_be_empty err
'
test_expect_success 'commit-graph verify progress off for redirected stderr' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph verify 2>err &&
+ git -C full commit-graph verify 2>err &&
test_must_be_empty err
'
test_expect_success 'commit-graph verify force progress on for stderr' '
- cd "$TRASH_DIRECTORY/full" &&
- GIT_PROGRESS_DELAY=0 git commit-graph verify --progress 2>err &&
+ GIT_PROGRESS_DELAY=0 git -C full commit-graph verify --progress 2>err &&
test_file_not_empty err
'
test_expect_success 'commit-graph verify with the --no-progress option' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph verify --no-progress 2>err &&
+ git -C full commit-graph verify --no-progress 2>err &&
test_must_be_empty err
'
@@ -194,10 +178,9 @@ test_expect_success 'commit-graph verify with the --no-progress option' '
# 1
test_expect_success 'write graph with merges' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph write &&
- test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "10" "generation_data extra_edges"
+ git -C full commit-graph write &&
+ test_path_is_file full/$objdir/info/commit-graph &&
+ graph_read_expect -C full 10 "generation_data extra_edges"
'
graph_git_behavior 'merge 1 vs 2' full merge/1 merge/2
@@ -205,12 +188,11 @@ graph_git_behavior 'merge 1 vs 3' full merge/1 merge/3
graph_git_behavior 'merge 2 vs 3' full merge/2 merge/3
test_expect_success 'Add one more commit' '
- cd "$TRASH_DIRECTORY/full" &&
- test_commit 8 &&
- git branch commits/8 &&
- ls $objdir/pack | grep idx >existing-idx &&
- git repack &&
- ls $objdir/pack| grep idx | grep -v -f existing-idx >new-idx
+ test_commit -C full 8 &&
+ git -C full branch commits/8 &&
+ ls full/$objdir/pack | grep idx >existing-idx &&
+ git -C full repack &&
+ ls full/$objdir/pack| grep idx | grep -v -f existing-idx >new-idx
'
# Current graph structure:
@@ -229,114 +211,101 @@ graph_git_behavior 'mixed mode, commit 8 vs merge 1' full commits/8 merge/1
graph_git_behavior 'mixed mode, commit 8 vs merge 2' full commits/8 merge/2
test_expect_success 'write graph with new commit' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph write &&
- test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "11" "generation_data extra_edges"
+ git -C full commit-graph write &&
+ test_path_is_file full/$objdir/info/commit-graph &&
+ graph_read_expect -C full 11 "generation_data extra_edges"
'
graph_git_behavior 'full graph, commit 8 vs merge 1' full commits/8 merge/1
graph_git_behavior 'full graph, commit 8 vs merge 2' full commits/8 merge/2
test_expect_success 'write graph with nothing new' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph write &&
- test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "11" "generation_data extra_edges"
+ git -C full commit-graph write &&
+ test_path_is_file full/$objdir/info/commit-graph &&
+ graph_read_expect -C full 11 "generation_data extra_edges"
'
graph_git_behavior 'cleared graph, commit 8 vs merge 1' full commits/8 merge/1
graph_git_behavior 'cleared graph, commit 8 vs merge 2' full commits/8 merge/2
test_expect_success 'build graph from latest pack with closure' '
- cd "$TRASH_DIRECTORY/full" &&
- cat new-idx | git commit-graph write --stdin-packs &&
- test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "9" "generation_data extra_edges"
+ git -C full commit-graph write --stdin-packs <new-idx &&
+ test_path_is_file full/$objdir/info/commit-graph &&
+ graph_read_expect -C full 9 "generation_data extra_edges"
'
graph_git_behavior 'graph from pack, commit 8 vs merge 1' full commits/8 merge/1
graph_git_behavior 'graph from pack, commit 8 vs merge 2' full commits/8 merge/2
test_expect_success 'build graph from commits with closure' '
- cd "$TRASH_DIRECTORY/full" &&
- git tag -a -m "merge" tag/merge merge/2 &&
- git rev-parse tag/merge >commits-in &&
- git rev-parse merge/1 >>commits-in &&
- cat commits-in | git commit-graph write --stdin-commits &&
- test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "6" "generation_data"
+ git -C full tag -a -m "merge" tag/merge merge/2 &&
+ git -C full rev-parse tag/merge >commits-in &&
+ git -C full rev-parse merge/1 >>commits-in &&
+ git -C full commit-graph write --stdin-commits <commits-in &&
+ test_path_is_file full/$objdir/info/commit-graph &&
+ graph_read_expect -C full 6 "generation_data"
'
graph_git_behavior 'graph from commits, commit 8 vs merge 1' full commits/8 merge/1
graph_git_behavior 'graph from commits, commit 8 vs merge 2' full commits/8 merge/2
test_expect_success 'build graph from commits with append' '
- cd "$TRASH_DIRECTORY/full" &&
- git rev-parse merge/3 | git commit-graph write --stdin-commits --append &&
- test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "10" "generation_data extra_edges"
+ git -C full rev-parse merge/3 >in &&
+ git -C full commit-graph write --stdin-commits --append <in &&
+ test_path_is_file full/$objdir/info/commit-graph &&
+ graph_read_expect -C full 10 "generation_data extra_edges"
'
graph_git_behavior 'append graph, commit 8 vs merge 1' full commits/8 merge/1
graph_git_behavior 'append graph, commit 8 vs merge 2' full commits/8 merge/2
test_expect_success 'build graph using --reachable' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit-graph write --reachable &&
- test_path_is_file $objdir/info/commit-graph &&
- graph_read_expect "11" "generation_data extra_edges"
+ git -C full commit-graph write --reachable &&
+ test_path_is_file full/$objdir/info/commit-graph &&
+ graph_read_expect -C full 11 "generation_data extra_edges"
'
graph_git_behavior 'append graph, commit 8 vs merge 1' full commits/8 merge/1
graph_git_behavior 'append graph, commit 8 vs merge 2' full commits/8 merge/2
test_expect_success 'setup bare repo' '
- cd "$TRASH_DIRECTORY" &&
- git clone --bare --no-local full bare &&
- cd bare &&
- git config core.commitGraph true &&
- baredir="./objects"
+ git clone --bare --no-local full bare
'
graph_git_behavior 'bare repo, commit 8 vs merge 1' bare commits/8 merge/1
graph_git_behavior 'bare repo, commit 8 vs merge 2' bare commits/8 merge/2
test_expect_success 'write graph in bare repo' '
- cd "$TRASH_DIRECTORY/bare" &&
- git commit-graph write &&
- test_path_is_file $baredir/info/commit-graph &&
- graph_read_expect "11" "generation_data extra_edges"
+ git -C bare commit-graph write &&
+ test_path_is_file bare/objects/info/commit-graph &&
+ graph_read_expect -C bare 11 "generation_data extra_edges"
'
graph_git_behavior 'bare repo with graph, commit 8 vs merge 1' bare commits/8 merge/1
graph_git_behavior 'bare repo with graph, commit 8 vs merge 2' bare commits/8 merge/2
test_expect_success 'perform fast-forward merge in full repo' '
- cd "$TRASH_DIRECTORY/full" &&
- git checkout -b merge-5-to-8 commits/5 &&
- git merge commits/8 &&
- git show-ref -s merge-5-to-8 >output &&
- git show-ref -s commits/8 >expect &&
+ git -C full checkout -b merge-5-to-8 commits/5 &&
+ git -C full merge commits/8 &&
+ git -C full show-ref -s merge-5-to-8 >output &&
+ git -C full show-ref -s commits/8 >expect &&
test_cmp expect output
'
test_expect_success 'check that gc computes commit-graph' '
- cd "$TRASH_DIRECTORY/full" &&
- git commit --allow-empty -m "blank" &&
- git commit-graph write --reachable &&
- cp $objdir/info/commit-graph commit-graph-before-gc &&
- git reset --hard HEAD~1 &&
- git config gc.writeCommitGraph true &&
- git gc &&
- cp $objdir/info/commit-graph commit-graph-after-gc &&
+ test_commit -C full --no-tag blank &&
+ git -C full commit-graph write --reachable &&
+ cp full/$objdir/info/commit-graph commit-graph-before-gc &&
+ git -C full reset --hard HEAD~1 &&
+ test_config -C full gc.writeCommitGraph true &&
+ git -C full gc &&
+ cp full/$objdir/info/commit-graph commit-graph-after-gc &&
! test_cmp_bin commit-graph-before-gc commit-graph-after-gc &&
- git commit-graph write --reachable &&
- test_cmp_bin commit-graph-after-gc $objdir/info/commit-graph
+ git -C full commit-graph write --reachable &&
+ test_cmp_bin commit-graph-after-gc full/$objdir/info/commit-graph
'
test_expect_success 'replace-objects invalidates commit-graph' '
- cd "$TRASH_DIRECTORY" &&
test_when_finished rm -rf replace &&
git clone full replace &&
(
@@ -359,7 +328,6 @@ test_expect_success 'replace-objects invalidates commit-graph' '
'
test_expect_success 'commit grafts invalidate commit-graph' '
- cd "$TRASH_DIRECTORY" &&
test_when_finished rm -rf graft &&
git clone --template= full graft &&
(
@@ -384,7 +352,6 @@ test_expect_success 'commit grafts invalidate commit-graph' '
'
test_expect_success 'replace-objects invalidates commit-graph' '
- cd "$TRASH_DIRECTORY" &&
test_when_finished rm -rf shallow &&
git clone --depth 2 "file://$TRASH_DIRECTORY/full" shallow &&
(
@@ -427,24 +394,25 @@ test_expect_success 'warn on improper hash version' '
'
test_expect_success TIME_IS_64BIT,TIME_T_IS_64BIT 'lower layers have overflow chunk' '
- cd "$TRASH_DIRECTORY/full" &&
UNIX_EPOCH_ZERO="@0 +0000" &&
FUTURE_DATE="@4147483646 +0000" &&
- rm -f .git/objects/info/commit-graph &&
- test_commit --date "$FUTURE_DATE" future-1 &&
- test_commit --date "$UNIX_EPOCH_ZERO" old-1 &&
- git commit-graph write --reachable &&
- test_commit --date "$FUTURE_DATE" future-2 &&
- test_commit --date "$UNIX_EPOCH_ZERO" old-2 &&
- git commit-graph write --reachable --split=no-merge &&
- test_commit extra &&
- git commit-graph write --reachable --split=no-merge &&
- git commit-graph write --reachable &&
- graph_read_expect 16 "generation_data generation_data_overflow extra_edges" &&
- mv .git/objects/info/commit-graph commit-graph-upgraded &&
- git commit-graph write --reachable &&
- graph_read_expect 16 "generation_data generation_data_overflow extra_edges" &&
- test_cmp .git/objects/info/commit-graph commit-graph-upgraded
+ rm -f full/.git/objects/info/commit-graph &&
+ test_commit -C full --date "$FUTURE_DATE" future-1 &&
+ test_commit -C full --date "$UNIX_EPOCH_ZERO" old-1 &&
+ git -C full commit-graph write --reachable &&
+ test_commit -C full --date "$FUTURE_DATE" future-2 &&
+ test_commit -C full --date "$UNIX_EPOCH_ZERO" old-2 &&
+ git -C full commit-graph write --reachable --split=no-merge &&
+ test_commit -C full extra &&
+ git -C full commit-graph write --reachable --split=no-merge &&
+ git -C full commit-graph write --reachable &&
+ graph_read_expect -C full 16 \
+ "generation_data generation_data_overflow extra_edges" &&
+ mv full/.git/objects/info/commit-graph commit-graph-upgraded &&
+ git -C full commit-graph write --reachable &&
+ graph_read_expect -C full 16 \
+ "generation_data generation_data_overflow extra_edges" &&
+ test_cmp full/.git/objects/info/commit-graph commit-graph-upgraded
'
# the verify tests below expect the commit-graph to contain
@@ -454,10 +422,11 @@ test_expect_success TIME_IS_64BIT,TIME_T_IS_64BIT 'lower layers have overflow ch
# and the tests will likely break.
test_expect_success 'git commit-graph verify' '
- cd "$TRASH_DIRECTORY/full" &&
- git rev-parse commits/8 | git -c commitGraph.generationVersion=1 commit-graph write --stdin-commits &&
- git commit-graph verify >output &&
- graph_read_expect 9 extra_edges 1
+ git -C full rev-parse commits/8 >in &&
+ git -C full -c commitGraph.generationVersion=1 commit-graph write \
+ --stdin-commits <in &&
+ git -C full commit-graph verify >output &&
+ graph_read_expect -C full 9 extra_edges 1
'
NUM_COMMITS=9
@@ -481,39 +450,39 @@ GRAPH_BYTE_FANOUT2=$(($GRAPH_FANOUT_OFFSET + 4 * 255))
GRAPH_OID_LOOKUP_OFFSET=$(($GRAPH_FANOUT_OFFSET + 4 * 256))
GRAPH_BYTE_OID_LOOKUP_ORDER=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * 8))
GRAPH_BYTE_OID_LOOKUP_MISSING=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * 4 + 10))
+GRAPH_COMMIT_DATA_WIDTH=$(($HASH_LEN + 16))
GRAPH_COMMIT_DATA_OFFSET=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * $NUM_COMMITS))
GRAPH_BYTE_COMMIT_TREE=$GRAPH_COMMIT_DATA_OFFSET
GRAPH_BYTE_COMMIT_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN))
GRAPH_BYTE_COMMIT_EXTRA_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 4))
GRAPH_BYTE_COMMIT_WRONG_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 3))
GRAPH_BYTE_COMMIT_GENERATION=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 11))
+GRAPH_BYTE_COMMIT_GENERATION_LAST=$(($GRAPH_BYTE_COMMIT_GENERATION + $(($NUM_COMMITS - 1)) * $GRAPH_COMMIT_DATA_WIDTH))
GRAPH_BYTE_COMMIT_DATE=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 12))
-GRAPH_COMMIT_DATA_WIDTH=$(($HASH_LEN + 16))
GRAPH_OCTOPUS_DATA_OFFSET=$(($GRAPH_COMMIT_DATA_OFFSET + \
$GRAPH_COMMIT_DATA_WIDTH * $NUM_COMMITS))
GRAPH_BYTE_OCTOPUS=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4))
GRAPH_BYTE_FOOTER=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4 * $NUM_OCTOPUS_EDGES))
corrupt_graph_setup() {
- cd "$TRASH_DIRECTORY/full" &&
- test_when_finished mv commit-graph-backup $objdir/info/commit-graph &&
- cp $objdir/info/commit-graph commit-graph-backup &&
- chmod u+w $objdir/info/commit-graph
+ test_when_finished mv commit-graph-backup full/$objdir/info/commit-graph &&
+ cp full/$objdir/info/commit-graph commit-graph-backup &&
+ chmod u+w full/$objdir/info/commit-graph
}
corrupt_graph_verify() {
grepstr=$1
- test_must_fail git commit-graph verify 2>test_err &&
+ test_must_fail git -C full commit-graph verify 2>test_err &&
grep -v "^+" test_err >err &&
test_i18ngrep "$grepstr" err &&
if test "$2" != "no-copy"
then
- cp $objdir/info/commit-graph commit-graph-pre-write-test
+ cp full/$objdir/info/commit-graph commit-graph-pre-write-test
fi &&
- git status --short &&
- GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE=true git commit-graph write &&
- chmod u+w $objdir/info/commit-graph &&
- git commit-graph verify
+ git -C full status --short &&
+ GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE=true git -C full commit-graph write &&
+ chmod u+w full/$objdir/info/commit-graph &&
+ git -C full commit-graph verify
}
# usage: corrupt_graph_and_verify <position> <data> <string> [<zero_pos>]
@@ -527,24 +496,24 @@ corrupt_graph_and_verify() {
data="${2:-\0}"
grepstr=$3
corrupt_graph_setup &&
- orig_size=$(wc -c < $objdir/info/commit-graph) &&
+ orig_size=$(wc -c <full/$objdir/info/commit-graph) &&
zero_pos=${4:-${orig_size}} &&
- printf "$data" | dd of="$objdir/info/commit-graph" bs=1 seek="$pos" conv=notrunc &&
- dd of="$objdir/info/commit-graph" bs=1 seek="$zero_pos" if=/dev/null &&
- test-tool genzeros $(($orig_size - $zero_pos)) >>"$objdir/info/commit-graph" &&
+ printf "$data" | dd of="full/$objdir/info/commit-graph" bs=1 seek="$pos" conv=notrunc &&
+ dd of="full/$objdir/info/commit-graph" bs=1 seek="$zero_pos" if=/dev/null &&
+ test-tool genzeros $(($orig_size - $zero_pos)) >>"full/$objdir/info/commit-graph" &&
corrupt_graph_verify "$grepstr"
}
test_expect_success POSIXPERM,SANITY 'detect permission problem' '
corrupt_graph_setup &&
- chmod 000 $objdir/info/commit-graph &&
+ chmod 000 full/$objdir/info/commit-graph &&
corrupt_graph_verify "Could not open" "no-copy"
'
test_expect_success 'detect too small' '
corrupt_graph_setup &&
- echo "a small graph" >$objdir/info/commit-graph &&
+ echo "a small graph" >full/$objdir/info/commit-graph &&
corrupt_graph_verify "too small"
'
@@ -628,11 +597,6 @@ test_expect_success 'detect incorrect generation number' '
"generation for commit"
'
-test_expect_success 'detect incorrect generation number' '
- corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\01" \
- "non-zero generation number"
-'
-
test_expect_success 'detect incorrect commit date' '
corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_DATE "\01" \
"commit date"
@@ -654,34 +618,51 @@ test_expect_success 'detect incorrect chunk count' '
$GRAPH_CHUNK_LOOKUP_OFFSET
'
+test_expect_success 'detect mixed generation numbers (non-zero to zero)' '
+ corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION_LAST "\0\0\0\0" \
+ "both zero and non-zero generations"
+'
+
+test_expect_success 'detect mixed generation numbers (zero to non-zero)' '
+ corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\0\0\0\0" \
+ "both zero and non-zero generations"
+'
+
test_expect_success 'git fsck (checks commit-graph when config set to true)' '
- cd "$TRASH_DIRECTORY/full" &&
- git fsck &&
+ git -C full fsck &&
corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
"incorrect checksum" &&
- cp commit-graph-pre-write-test $objdir/info/commit-graph &&
- test_must_fail git -c core.commitGraph=true fsck
+ cp commit-graph-pre-write-test full/$objdir/info/commit-graph &&
+ test_must_fail git -C full -c core.commitGraph=true fsck
'
test_expect_success 'git fsck (ignores commit-graph when config set to false)' '
- cd "$TRASH_DIRECTORY/full" &&
- git fsck &&
+ git -C full fsck &&
corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
"incorrect checksum" &&
- cp commit-graph-pre-write-test $objdir/info/commit-graph &&
- git -c core.commitGraph=false fsck
+ cp commit-graph-pre-write-test full/$objdir/info/commit-graph &&
+ git -C full -c core.commitGraph=false fsck
'
test_expect_success 'git fsck (checks commit-graph when config unset)' '
- cd "$TRASH_DIRECTORY/full" &&
- test_when_finished "git config core.commitGraph true" &&
+ test_when_finished "git -C full config core.commitGraph true" &&
- git fsck &&
+ git -C full fsck &&
corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
"incorrect checksum" &&
- test_unconfig core.commitGraph &&
- cp commit-graph-pre-write-test $objdir/info/commit-graph &&
- test_must_fail git fsck
+ test_unconfig -C full core.commitGraph &&
+ cp commit-graph-pre-write-test full/$objdir/info/commit-graph &&
+ test_must_fail git -C full fsck
+'
+
+test_expect_success 'git fsck shows commit-graph output with --progress' '
+ git -C "$TRASH_DIRECTORY/full" fsck --progress 2>err &&
+ grep "Verifying commits in commit graph" err
+'
+
+test_expect_success 'git fsck suppresses commit-graph output with --no-progress' '
+ git -C "$TRASH_DIRECTORY/full" fsck --no-progress 2>err &&
+ ! grep "Verifying commits in commit graph" err
'
test_expect_success 'setup non-the_repository tests' '
@@ -782,32 +763,33 @@ test_expect_success 'corrupt commit-graph write (missing tree)' '
#
test_expect_success 'set up and verify repo with generation data overflow chunk' '
- objdir=".git/objects" &&
UNIX_EPOCH_ZERO="@0 +0000" &&
FUTURE_DATE="@2147483646 +0000" &&
- cd "$TRASH_DIRECTORY" &&
- mkdir repo &&
- cd repo &&
- git init &&
- test_commit --date "$UNIX_EPOCH_ZERO" 1 &&
- test_commit 2 &&
- test_commit --date "$UNIX_EPOCH_ZERO" 3 &&
- git commit-graph write --reachable &&
- graph_read_expect 3 generation_data &&
- test_commit --date "$FUTURE_DATE" 4 &&
- test_commit 5 &&
- test_commit --date "$UNIX_EPOCH_ZERO" 6 &&
- git branch left &&
- git reset --hard 3 &&
- test_commit 7 &&
- test_commit --date "$FUTURE_DATE" 8 &&
- test_commit 9 &&
- git branch right &&
- git reset --hard 3 &&
- test_merge M left right &&
- git commit-graph write --reachable &&
- graph_read_expect 10 "generation_data generation_data_overflow" &&
- git commit-graph verify
+
+ git init repo &&
+ (
+ cd repo &&
+
+ test_commit --date "$UNIX_EPOCH_ZERO" 1 &&
+ test_commit 2 &&
+ test_commit --date "$UNIX_EPOCH_ZERO" 3 &&
+ git commit-graph write --reachable &&
+ graph_read_expect 3 generation_data &&
+ test_commit --date "$FUTURE_DATE" 4 &&
+ test_commit 5 &&
+ test_commit --date "$UNIX_EPOCH_ZERO" 6 &&
+ git branch left &&
+ git reset --hard 3 &&
+ test_commit 7 &&
+ test_commit --date "$FUTURE_DATE" 8 &&
+ test_commit 9 &&
+ git branch right &&
+ git reset --hard 3 &&
+ test_merge M left right &&
+ git commit-graph write --reachable &&
+ graph_read_expect 10 "generation_data generation_data_overflow" &&
+ git commit-graph verify
+ )
'
graph_git_behavior 'generation data overflow chunk repo' repo left right
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index b5f9b10922..1bcc02004d 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -183,6 +183,18 @@ test_expect_success 'write midx with --stdin-packs' '
compare_results_with_midx "mixed mode (one pack + extra)"
+test_expect_success 'write with no objects and preferred pack' '
+ test_when_finished "rm -rf empty" &&
+ git init empty &&
+ test_must_fail git -C empty multi-pack-index write \
+ --stdin-packs --preferred-pack=does-not-exist </dev/null 2>err &&
+ cat >expect <<-EOF &&
+ warning: unknown preferred pack: ${SQ}does-not-exist${SQ}
+ error: no pack files to index.
+ EOF
+ test_cmp expect err
+'
+
test_expect_success 'write progress off for redirected stderr' '
git multi-pack-index --object-dir=$objdir write 2>err &&
test_line_count = 0 err
@@ -473,6 +485,18 @@ test_expect_success 'git-fsck incorrect offset' '
git -c core.multiPackIndex=false fsck
'
+test_expect_success 'git fsck shows MIDX output with --progress' '
+ git fsck --progress 2>err &&
+ grep "Verifying OID order in multi-pack-index" err &&
+ grep "Verifying object offsets" err
+'
+
+test_expect_success 'git fsck suppresses MIDX output with --no-progress' '
+ git fsck --no-progress 2>err &&
+ ! grep "Verifying OID order in multi-pack-index" err &&
+ ! grep "Verifying object offsets" err
+'
+
test_expect_success 'corrupt MIDX is not reused' '
corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\377" $objdir \
"incorrect object offset" &&
@@ -1015,4 +1039,20 @@ test_expect_success 'complains when run outside of a repository' '
grep "not a git repository" err
'
+test_expect_success 'repack with delta islands' '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit first &&
+ git repack &&
+ test_commit second &&
+ git repack &&
+
+ git multi-pack-index write &&
+ git -c repack.useDeltaIslands=true multi-pack-index repack
+ )
+'
+
test_done
diff --git a/t/t5320-delta-islands.sh b/t/t5320-delta-islands.sh
index 124d47603d..406363381f 100755
--- a/t/t5320-delta-islands.sh
+++ b/t/t5320-delta-islands.sh
@@ -134,7 +134,7 @@ test_expect_success 'island core places core objects first' '
repack -adfi &&
git verify-pack -v .git/objects/pack/*.pack |
cut -d" " -f1 |
- egrep "$root|$two" >actual &&
+ grep -E "$root|$two" >actual &&
test_cmp expect actual
'
diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh
index 669ddc645f..36c4141e67 100755
--- a/t/t5324-split-commit-graph.sh
+++ b/t/t5324-split-commit-graph.sh
@@ -351,7 +351,8 @@ test_expect_success 'add octopus merge' '
git branch merge/octopus &&
git commit-graph write --reachable --split &&
git commit-graph verify --progress 2>err &&
- test_line_count = 3 err &&
+ test_line_count = 1 err &&
+ grep "Verifying commits in commit graph: 100% (18/18)" err &&
test_i18ngrep ! warning err &&
test_line_count = 3 $graphdir/commit-graph-chain
'
diff --git a/t/t5325-reverse-index.sh b/t/t5325-reverse-index.sh
index d042d26f2b..431a603ca0 100755
--- a/t/t5325-reverse-index.sh
+++ b/t/t5325-reverse-index.sh
@@ -1,17 +1,20 @@
#!/bin/sh
test_description='on-disk reverse index'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# The below tests want control over the 'pack.writeReverseIndex' setting
# themselves to assert various combinations of it with other options.
-sane_unset GIT_TEST_WRITE_REV_INDEX
+sane_unset GIT_TEST_NO_WRITE_REV_INDEX
packdir=.git/objects/pack
test_expect_success 'setup' '
test_commit base &&
+ test_config pack.writeReverseIndex false &&
pack=$(git pack-objects --all $packdir/pack) &&
rev=$packdir/pack-$pack.rev &&
@@ -94,6 +97,17 @@ test_expect_success 'reverse index is not generated when available on disk' '
--batch-check="%(objectsize:disk)" <tip
'
+test_expect_success 'reverse index is ignored when pack.readReverseIndex is false' '
+ test_index_pack true &&
+ test_path_is_file $rev &&
+
+ test_config pack.readReverseIndex false &&
+
+ git rev-parse HEAD >tip &&
+ GIT_TEST_REV_INDEX_DIE_ON_DISK=1 git cat-file \
+ --batch-check="%(objectsize:disk)" <tip
+'
+
test_expect_success 'revindex in-memory vs on-disk' '
git init repo &&
test_when_finished "rm -fr repo" &&
@@ -117,4 +131,78 @@ test_expect_success 'revindex in-memory vs on-disk' '
test_cmp on-disk in-core
)
'
+
+test_expect_success 'fsck succeeds on good rev-index' '
+ test_when_finished rm -fr repo &&
+ git init repo &&
+ (
+ cd repo &&
+
+ test_commit commit &&
+ git -c pack.writeReverseIndex=true repack -ad &&
+ git fsck 2>err &&
+ test_must_be_empty err
+ )
+'
+
+test_expect_success 'set up rev-index corruption tests' '
+ git init corrupt &&
+ (
+ cd corrupt &&
+
+ test_commit commit &&
+ git -c pack.writeReverseIndex=true repack -ad &&
+
+ revfile=$(ls .git/objects/pack/pack-*.rev) &&
+ chmod a+w $revfile &&
+ cp $revfile $revfile.bak
+ )
+'
+
+corrupt_rev_and_verify () {
+ (
+ pos="$1" &&
+ value="$2" &&
+ error="$3" &&
+
+ cd corrupt &&
+ revfile=$(ls .git/objects/pack/pack-*.rev) &&
+
+ # Reset to original rev-file.
+ cp $revfile.bak $revfile &&
+
+ printf "$value" | dd of=$revfile bs=1 seek="$pos" conv=notrunc &&
+ test_must_fail git fsck 2>err &&
+ grep "$error" err
+ )
+}
+
+test_expect_success 'fsck catches invalid checksum' '
+ revfile=$(ls corrupt/.git/objects/pack/pack-*.rev) &&
+ orig_size=$(wc -c <$revfile) &&
+ hashpos=$((orig_size - 10)) &&
+ corrupt_rev_and_verify $hashpos bogus \
+ "invalid checksum"
+'
+
+test_expect_success 'fsck catches invalid row position' '
+ corrupt_rev_and_verify 14 "\07" \
+ "invalid rev-index position"
+'
+
+test_expect_success 'fsck catches invalid header: magic number' '
+ corrupt_rev_and_verify 1 "\07" \
+ "reverse-index file .* has unknown signature"
+'
+
+test_expect_success 'fsck catches invalid header: version' '
+ corrupt_rev_and_verify 7 "\02" \
+ "reverse-index file .* has unsupported version"
+'
+
+test_expect_success 'fsck catches invalid header: hash function' '
+ corrupt_rev_and_verify 11 "\03" \
+ "reverse-index file .* has unsupported hash id"
+'
+
test_done
diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh
index ad6eea5fa0..70d1b58709 100755
--- a/t/t5326-multi-pack-bitmaps.sh
+++ b/t/t5326-multi-pack-bitmaps.sh
@@ -410,4 +410,107 @@ test_expect_success 'preferred pack change with existing MIDX bitmap' '
)
'
+test_expect_success 'tagged commits are selected for bitmapping' '
+ rm -fr repo &&
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit --annotate base &&
+ git repack -d &&
+
+ # Remove refs/heads/main which points at the commit directly,
+ # leaving only a reference to the annotated tag.
+ git branch -M main &&
+ git checkout base &&
+ git branch -d main &&
+
+ git multi-pack-index write --bitmap &&
+
+ git rev-parse HEAD >want &&
+ test-tool bitmap list-commits >actual &&
+ grep $(cat want) actual
+ )
+'
+
+corrupt_file () {
+ chmod a+w "$1" &&
+ printf "bogus" | dd of="$1" bs=1 seek="12" conv=notrunc
+}
+
+test_expect_success 'git fsck correctly identifies good and bad bitmaps' '
+ git init valid &&
+ test_when_finished rm -rf valid &&
+
+ test_commit_bulk 20 &&
+ git repack -adbf &&
+
+ # Move pack-bitmap aside so it is not deleted
+ # in next repack.
+ packbitmap=$(ls .git/objects/pack/pack-*.bitmap) &&
+ mv "$packbitmap" "$packbitmap.bak" &&
+
+ test_commit_bulk 10 &&
+ git repack -b --write-midx &&
+ midxbitmap=$(ls .git/objects/pack/multi-pack-index-*.bitmap) &&
+
+ # Copy MIDX bitmap to backup. Copy pack bitmap from backup.
+ cp "$midxbitmap" "$midxbitmap.bak" &&
+ cp "$packbitmap.bak" "$packbitmap" &&
+
+ # fsck works at first
+ git fsck 2>err &&
+ test_must_be_empty err &&
+
+ corrupt_file "$packbitmap" &&
+ test_must_fail git fsck 2>err &&
+ grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err &&
+
+ cp "$packbitmap.bak" "$packbitmap" &&
+ corrupt_file "$midxbitmap" &&
+ test_must_fail git fsck 2>err &&
+ grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err &&
+
+ corrupt_file "$packbitmap" &&
+ test_must_fail git fsck 2>err &&
+ grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err &&
+ grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err
+'
+
+test_expect_success 'corrupt MIDX with bitmap causes fallback' '
+ git init corrupt-midx-bitmap &&
+ (
+ cd corrupt-midx-bitmap &&
+
+ test_commit first &&
+ git repack -d &&
+ test_commit second &&
+ git repack -d &&
+
+ git multi-pack-index write --bitmap &&
+ checksum=$(midx_checksum $objdir) &&
+ for f in $midx $midx-$checksum.bitmap
+ do
+ mv $f $f.bak || return 1
+ done &&
+
+ # pack everything together, invalidating the MIDX
+ git repack -ad &&
+ # then restore the now-stale MIDX
+ for f in $midx $midx-$checksum.bitmap
+ do
+ mv $f.bak $f || return 1
+ done &&
+
+ git rev-list --count --objects --use-bitmap-index HEAD >out 2>err &&
+ # should attempt opening the broken pack twice (once
+ # from the attempt to load it via the stale bitmap, and
+ # again when attempting to load it from the stale MIDX)
+ # before falling back to the non-MIDX case
+ test 2 -eq $(grep -c "could not open pack" err) &&
+ test 6 -eq $(cat out)
+ )
+'
+
test_done
diff --git a/t/t5328-commit-graph-64bit-time.sh b/t/t5328-commit-graph-64bit-time.sh
index 093f0c067a..e9c521c061 100755
--- a/t/t5328-commit-graph-64bit-time.sh
+++ b/t/t5328-commit-graph-64bit-time.sh
@@ -37,30 +37,39 @@ test_expect_success 'lower layers have overflow chunk' '
graph_git_behavior 'overflow' '' HEAD~2 HEAD
test_expect_success 'set up and verify repo with generation data overflow chunk' '
- mkdir repo &&
- cd repo &&
- git init &&
- test_commit --date "$UNIX_EPOCH_ZERO" 1 &&
- test_commit 2 &&
- test_commit --date "$UNIX_EPOCH_ZERO" 3 &&
- git commit-graph write --reachable &&
- graph_read_expect 3 generation_data &&
- test_commit --date "$FUTURE_DATE" 4 &&
- test_commit 5 &&
- test_commit --date "$UNIX_EPOCH_ZERO" 6 &&
- git branch left &&
- git reset --hard 3 &&
- test_commit 7 &&
- test_commit --date "$FUTURE_DATE" 8 &&
- test_commit 9 &&
- git branch right &&
- git reset --hard 3 &&
- test_merge M left right &&
- git commit-graph write --reachable &&
- graph_read_expect 10 "generation_data generation_data_overflow" &&
- git commit-graph verify
+ git init repo &&
+ (
+ cd repo &&
+ test_commit --date "$UNIX_EPOCH_ZERO" 1 &&
+ test_commit 2 &&
+ test_commit --date "$UNIX_EPOCH_ZERO" 3 &&
+ git commit-graph write --reachable &&
+ graph_read_expect 3 generation_data &&
+ test_commit --date "$FUTURE_DATE" 4 &&
+ test_commit 5 &&
+ test_commit --date "$UNIX_EPOCH_ZERO" 6 &&
+ git branch left &&
+ git reset --hard 3 &&
+ test_commit 7 &&
+ test_commit --date "$FUTURE_DATE" 8 &&
+ test_commit 9 &&
+ git branch right &&
+ git reset --hard 3 &&
+ test_merge M left right &&
+ git commit-graph write --reachable &&
+ graph_read_expect 10 "generation_data generation_data_overflow" &&
+ git commit-graph verify
+ )
'
graph_git_behavior 'overflow 2' repo left right
+test_expect_success 'single commit with generation data exceeding UINT32_MAX' '
+ git init repo-uint32-max &&
+ test_commit -C repo-uint32-max --date "@4294967297 +0000" 1 &&
+ git -C repo-uint32-max commit-graph write --reachable &&
+ graph_read_expect -C repo-uint32-max 1 "generation_data" &&
+ git -C repo-uint32-max commit-graph verify
+'
+
test_done
diff --git a/t/t5329-pack-objects-cruft.sh b/t/t5329-pack-objects-cruft.sh
index 303f7a5d84..fc5fedbe9b 100755
--- a/t/t5329-pack-objects-cruft.sh
+++ b/t/t5329-pack-objects-cruft.sh
@@ -573,23 +573,54 @@ test_expect_success 'cruft repack with no reachable objects' '
)
'
-test_expect_success 'cruft repack ignores --max-pack-size' '
+write_blob () {
+ test-tool genrandom "$@" >in &&
+ git hash-object -w -t blob in
+}
+
+find_pack () {
+ for idx in $(ls $packdir/pack-*.idx)
+ do
+ git show-index <$idx >out &&
+ if grep -q "$1" out
+ then
+ echo $idx
+ fi || return 1
+ done
+}
+
+test_expect_success 'cruft repack with --max-pack-size' '
git init max-pack-size &&
(
cd max-pack-size &&
test_commit base &&
+
# two cruft objects which exceed the maximum pack size
- test-tool genrandom foo 1048576 | git hash-object --stdin -w &&
- test-tool genrandom bar 1048576 | git hash-object --stdin -w &&
+ foo=$(write_blob foo 1048576) &&
+ bar=$(write_blob bar 1048576) &&
+ test-tool chmtime --get -1000 \
+ "$objdir/$(test_oid_to_path $foo)" >foo.mtime &&
+ test-tool chmtime --get -2000 \
+ "$objdir/$(test_oid_to_path $bar)" >bar.mtime &&
git repack --cruft --max-pack-size=1M &&
find $packdir -name "*.mtimes" >cruft &&
- test_line_count = 1 cruft &&
- test-tool pack-mtimes "$(basename "$(cat cruft)")" >objects &&
- test_line_count = 2 objects
+ test_line_count = 2 cruft &&
+
+ foo_mtimes="$(basename $(find_pack $foo) .idx).mtimes" &&
+ bar_mtimes="$(basename $(find_pack $bar) .idx).mtimes" &&
+ test-tool pack-mtimes $foo_mtimes >foo.actual &&
+ test-tool pack-mtimes $bar_mtimes >bar.actual &&
+
+ echo "$foo $(cat foo.mtime)" >foo.expect &&
+ echo "$bar $(cat bar.mtime)" >bar.expect &&
+
+ test_cmp foo.expect foo.actual &&
+ test_cmp bar.expect bar.actual &&
+ test "$foo_mtimes" != "$bar_mtimes"
)
'
-test_expect_success 'cruft repack ignores pack.packSizeLimit' '
+test_expect_success 'cruft repack with pack.packSizeLimit' '
(
cd max-pack-size &&
# repack everything back together to remove the existing cruft
@@ -599,9 +630,12 @@ test_expect_success 'cruft repack ignores pack.packSizeLimit' '
# ensure the same post condition is met when --max-pack-size
# would otherwise be inferred from the configuration
find $packdir -name "*.mtimes" >cruft &&
- test_line_count = 1 cruft &&
- test-tool pack-mtimes "$(basename "$(cat cruft)")" >objects &&
- test_line_count = 2 objects
+ test_line_count = 2 cruft &&
+ for pack in $(cat cruft)
+ do
+ test-tool pack-mtimes "$(basename $pack)" >objects &&
+ test_line_count = 1 objects || return 1
+ done
)
'
@@ -739,4 +773,175 @@ test_expect_success 'cruft objects are freshend via loose' '
)
'
+test_expect_success 'gc.recentObjectsHook' '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ # Create a handful of objects.
+ #
+ # - one reachable commit, "base", designated for the reachable
+ # pack
+ # - one unreachable commit, "cruft.discard", which is marked
+ # for deletion
+ # - one unreachable commit, "cruft.old", which would be marked
+ # for deletion, but is rescued as an extra cruft tip
+ # - one unreachable commit, "cruft.new", which is not marked
+ # for deletion
+ test_commit base &&
+ git branch -M main &&
+
+ git checkout --orphan discard &&
+ git rm -fr . &&
+ test_commit --no-tag cruft.discard &&
+
+ git checkout --orphan old &&
+ git rm -fr . &&
+ test_commit --no-tag cruft.old &&
+ cruft_old="$(git rev-parse HEAD)" &&
+
+ git checkout --orphan new &&
+ git rm -fr . &&
+ test_commit --no-tag cruft.new &&
+ cruft_new="$(git rev-parse HEAD)" &&
+
+ git checkout main &&
+ git branch -D discard old new &&
+ git reflog expire --all --expire=all &&
+
+ # mark cruft.old with an mtime that is many minutes
+ # older than the expiration period, and mark cruft.new
+ # with an mtime that is in the future (and thus not
+ # eligible for pruning).
+ test-tool chmtime -2000 "$objdir/$(test_oid_to_path $cruft_old)" &&
+ test-tool chmtime +1000 "$objdir/$(test_oid_to_path $cruft_new)" &&
+
+ # Write the list of cruft objects we expect to
+ # accumulate, which is comprised of everything reachable
+ # from cruft.old and cruft.new, but not cruft.discard.
+ git rev-list --objects --no-object-names \
+ $cruft_old $cruft_new >cruft.raw &&
+ sort cruft.raw >cruft.expect &&
+
+ # Write the script to list extra tips, which are limited
+ # to cruft.old, in this case.
+ write_script extra-tips <<-EOF &&
+ echo $cruft_old
+ EOF
+ git config gc.recentObjectsHook ./extra-tips &&
+
+ git repack --cruft --cruft-expiration=now -d &&
+
+ mtimes="$(ls .git/objects/pack/pack-*.mtimes)" &&
+ git show-index <${mtimes%.mtimes}.idx >cruft &&
+ cut -d" " -f2 cruft | sort >cruft.actual &&
+ test_cmp cruft.expect cruft.actual &&
+
+ # Ensure that the "old" objects are removed after
+ # dropping the gc.recentObjectsHook hook.
+ git config --unset gc.recentObjectsHook &&
+ git repack --cruft --cruft-expiration=now -d &&
+
+ mtimes="$(ls .git/objects/pack/pack-*.mtimes)" &&
+ git show-index <${mtimes%.mtimes}.idx >cruft &&
+ cut -d" " -f2 cruft | sort >cruft.actual &&
+
+ git rev-list --objects --no-object-names $cruft_new >cruft.raw &&
+ cp cruft.expect cruft.old &&
+ sort cruft.raw >cruft.expect &&
+ test_cmp cruft.expect cruft.actual &&
+
+ # ensure objects which are no longer in the cruft pack were
+ # removed from the repository
+ for object in $(comm -13 cruft.expect cruft.old)
+ do
+ test_must_fail git cat-file -t $object || return 1
+ done
+ )
+'
+
+test_expect_success 'multi-valued gc.recentObjectsHook' '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit base &&
+ git branch -M main &&
+
+ git checkout --orphan cruft.a &&
+ git rm -fr . &&
+ test_commit --no-tag cruft.a &&
+ cruft_a="$(git rev-parse HEAD)" &&
+
+ git checkout --orphan cruft.b &&
+ git rm -fr . &&
+ test_commit --no-tag cruft.b &&
+ cruft_b="$(git rev-parse HEAD)" &&
+
+ git checkout main &&
+ git branch -D cruft.a cruft.b &&
+ git reflog expire --all --expire=all &&
+
+ echo "echo $cruft_a" | write_script extra-tips.a &&
+ echo "echo $cruft_b" | write_script extra-tips.b &&
+ echo "false" | write_script extra-tips.c &&
+
+ git rev-list --objects --no-object-names $cruft_a $cruft_b \
+ >cruft.raw &&
+ sort cruft.raw >cruft.expect &&
+
+ # ensure that each extra cruft tip is saved by its
+ # respective hook
+ git config --add gc.recentObjectsHook ./extra-tips.a &&
+ git config --add gc.recentObjectsHook ./extra-tips.b &&
+ git repack --cruft --cruft-expiration=now -d &&
+
+ mtimes="$(ls .git/objects/pack/pack-*.mtimes)" &&
+ git show-index <${mtimes%.mtimes}.idx >cruft &&
+ cut -d" " -f2 cruft | sort >cruft.actual &&
+ test_cmp cruft.expect cruft.actual &&
+
+ # ensure that a dirty exit halts cruft pack generation
+ git config --add gc.recentObjectsHook ./extra-tips.c &&
+ test_must_fail git repack --cruft --cruft-expiration=now -d 2>err &&
+ grep "unable to enumerate additional recent objects" err &&
+
+ # and that the existing cruft pack is left alone
+ test_path_is_file "$mtimes"
+ )
+'
+
+test_expect_success 'additional cruft blobs via gc.recentObjectsHook' '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit base &&
+
+ blob=$(echo "unreachable" | git hash-object -w --stdin) &&
+
+ # mark the unreachable blob we wrote above as having
+ # aged out of the retention period
+ test-tool chmtime -2000 "$objdir/$(test_oid_to_path $blob)" &&
+
+ # Write the script to list extra tips, which is just the
+ # extra blob as above.
+ write_script extra-tips <<-EOF &&
+ echo $blob
+ EOF
+ git config gc.recentObjectsHook ./extra-tips &&
+
+ git repack --cruft --cruft-expiration=now -d &&
+
+ mtimes="$(ls .git/objects/pack/pack-*.mtimes)" &&
+ git show-index <${mtimes%.mtimes}.idx >cruft &&
+ cut -d" " -f2 cruft >actual &&
+ echo $blob >expect &&
+ test_cmp expect actual
+ )
+'
+
test_done
diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh
index 2cc7fd7a47..5eb28f0512 100755
--- a/t/t5330-no-lazy-fetch-with-commit-graph.sh
+++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh
@@ -2,6 +2,7 @@
test_description='test for no lazy fetch with the commit-graph'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup: prepare a repository with a commit' '
diff --git a/t/t5331-pack-objects-stdin.sh b/t/t5331-pack-objects-stdin.sh
new file mode 100755
index 0000000000..acab31667a
--- /dev/null
+++ b/t/t5331-pack-objects-stdin.sh
@@ -0,0 +1,240 @@
+#!/bin/sh
+
+test_description='pack-objects --stdin'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+packed_objects () {
+ git show-index <"$1" >tmp-object-list &&
+ cut -d' ' -f2 tmp-object-list | sort &&
+ rm tmp-object-list
+ }
+
+test_expect_success 'setup for --stdin-packs tests' '
+ git init stdin-packs &&
+ (
+ cd stdin-packs &&
+
+ test_commit A &&
+ test_commit B &&
+ test_commit C &&
+
+ for id in A B C
+ do
+ git pack-objects .git/objects/pack/pack-$id \
+ --incremental --revs <<-EOF || exit 1
+ refs/tags/$id
+ EOF
+ done &&
+
+ ls -la .git/objects/pack
+ )
+'
+
+test_expect_success '--stdin-packs with excluded packs' '
+ (
+ cd stdin-packs &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+
+ git pack-objects test --stdin-packs <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx)
+ ) >expect.raw &&
+ git show-index <$(ls test-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success '--stdin-packs is incompatible with --filter' '
+ (
+ cd stdin-packs &&
+ test_must_fail git pack-objects --stdin-packs --stdout \
+ --filter=blob:none </dev/null 2>err &&
+ test_i18ngrep "cannot use --filter with --stdin-packs" err
+ )
+'
+
+test_expect_success '--stdin-packs is incompatible with --revs' '
+ (
+ cd stdin-packs &&
+ test_must_fail git pack-objects --stdin-packs --revs out \
+ </dev/null 2>err &&
+ test_i18ngrep "cannot use internal rev list with --stdin-packs" err
+ )
+'
+
+test_expect_success '--stdin-packs with loose objects' '
+ (
+ cd stdin-packs &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+
+ test_commit D && # loose
+
+ git pack-objects test2 --stdin-packs --unpacked <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
+ git rev-list --objects --no-object-names \
+ refs/tags/C..refs/tags/D
+
+ ) >expect.raw &&
+ ls -la . &&
+ git show-index <$(ls test2-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success '--stdin-packs with broken links' '
+ (
+ cd stdin-packs &&
+
+ # make an unreachable object with a bogus parent
+ git cat-file -p HEAD >commit &&
+ sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit |
+ git hash-object -w -t commit --stdin >in &&
+
+ git pack-objects .git/objects/pack/pack-D <in &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+ PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" &&
+
+ git pack-objects test3 --stdin-packs --unpacked <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ $PACK_D
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-D-*.idx) &&
+ git rev-list --objects --no-object-names \
+ refs/tags/C..refs/tags/D
+ ) >expect.raw &&
+ git show-index <$(ls test3-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'pack-objects --stdin with duplicate packfile' '
+ test_when_finished "rm -fr repo" &&
+
+ git init repo &&
+ (
+ cd repo &&
+ test_commit "commit" &&
+ git repack -ad &&
+
+ {
+ basename .git/objects/pack/pack-*.pack &&
+ basename .git/objects/pack/pack-*.pack
+ } >packfiles &&
+
+ git pack-objects --stdin-packs generated-pack <packfiles &&
+ packed_objects .git/objects/pack/pack-*.idx >expect &&
+ packed_objects generated-pack-*.idx >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'pack-objects --stdin with same packfile excluded and included' '
+ test_when_finished "rm -fr repo" &&
+
+ git init repo &&
+ (
+ cd repo &&
+ test_commit "commit" &&
+ git repack -ad &&
+
+ {
+ basename .git/objects/pack/pack-*.pack &&
+ printf "^%s\n" "$(basename .git/objects/pack/pack-*.pack)"
+ } >packfiles &&
+
+ git pack-objects --stdin-packs generated-pack <packfiles &&
+ packed_objects generated-pack-*.idx >packed-objects &&
+ test_must_be_empty packed-objects
+ )
+'
+
+test_expect_success 'pack-objects --stdin with packfiles from alternate object database' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Set up a shared repository with a single packfile.
+ git init shared &&
+ test_commit -C shared "shared-objects" &&
+ git -C shared repack -ad &&
+ basename shared/.git/objects/pack/pack-*.pack >packfile &&
+
+ # Set up a repository that is connected to the shared repository. This
+ # repository has no objects on its own, but we still expect to be able
+ # to pack objects from its alternate.
+ git clone --shared shared member &&
+ git -C member pack-objects --stdin-packs generated-pack <packfile &&
+ test_cmp shared/.git/objects/pack/pack-*.pack member/generated-pack-*.pack
+'
+
+test_expect_success 'pack-objects --stdin with packfiles from main and alternate object database' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Set up a shared repository with a single packfile.
+ git init shared &&
+ test_commit -C shared "shared-commit" &&
+ git -C shared repack -ad &&
+
+ # Set up a repository that is connected to the shared repository. This
+ # repository has a second packfile so that we can verify that it is
+ # possible to write packs that include packfiles from different object
+ # databases.
+ git clone --shared shared member &&
+ test_commit -C member "local-commit" &&
+ git -C member repack -dl &&
+
+ {
+ basename shared/.git/objects/pack/pack-*.pack &&
+ basename member/.git/objects/pack/pack-*.pack
+ } >packfiles &&
+
+ {
+ packed_objects shared/.git/objects/pack/pack-*.idx &&
+ packed_objects member/.git/objects/pack/pack-*.idx
+ } | sort >expected-objects &&
+
+ git -C member pack-objects --stdin-packs generated-pack <packfiles &&
+ packed_objects member/generated-pack-*.idx >actual-objects &&
+ test_cmp expected-objects actual-objects
+'
+
+test_done
diff --git a/t/t5351-unpack-large-objects.sh b/t/t5351-unpack-large-objects.sh
index 8c8af99b84..43cbcd5d49 100755
--- a/t/t5351-unpack-large-objects.sh
+++ b/t/t5351-unpack-large-objects.sh
@@ -55,7 +55,7 @@ check_fsync_events () {
cat >expect &&
sed -n \
- -e '/^{"event":"data",.*"category":"fsync",/ {
+ -e '/^{"event":"counter",.*"category":"fsync",/ {
s/.*"category":"fsync",//;
s/}$//;
p;
@@ -78,8 +78,8 @@ test_expect_success 'unpack big object in stream (core.fsyncmethod=batch)' '
flush_count=1
fi &&
check_fsync_events trace2.txt <<-EOF &&
- "key":"fsync/writeout-only","value":"6"
- "key":"fsync/hardware-flush","value":"$flush_count"
+ "name":"writeout-only","count":6
+ "name":"hardware-flush","count":$flush_count
EOF
test_dir_is_empty dest.git/objects/pack &&
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 978f240cda..cfaae54739 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,6 +7,7 @@ test_description='Test the post-checkout hook.'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5404-tracking-branches.sh b/t/t5404-tracking-branches.sh
index cc07889667..51737eeafe 100755
--- a/t/t5404-tracking-branches.sh
+++ b/t/t5404-tracking-branches.sh
@@ -5,6 +5,7 @@ test_description='tracking branch update checks for git push'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index 11f03239a0..1686ac13aa 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -5,6 +5,7 @@ test_description='forced push to replace commit we do not have'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh
index dcbeb42082..d6a9946633 100755
--- a/t/t5406-remote-rejects.sh
+++ b/t/t5406-remote-rejects.sh
@@ -2,6 +2,7 @@
test_description='remote push rejects are reported by client'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t5407-post-rewrite-hook.sh b/t/t5407-post-rewrite-hook.sh
index 5f3ff051ca..ad7f8c6f00 100755
--- a/t/t5407-post-rewrite-hook.sh
+++ b/t/t5407-post-rewrite-hook.sh
@@ -17,6 +17,12 @@ test_expect_success 'setup' '
git checkout A^0 &&
test_commit E bar E &&
test_commit F foo F &&
+ git checkout B &&
+ git merge E &&
+ git tag merge-E &&
+ test_commit G G &&
+ test_commit H H &&
+ test_commit I I &&
git checkout main &&
test_hook --setup post-rewrite <<-EOF
@@ -173,6 +179,48 @@ test_fail_interactive_rebase () {
)
}
+test_expect_success 'git rebase with failed pick' '
+ clear_hook_input &&
+ cat >todo <<-\EOF &&
+ exec >bar
+ merge -C merge-E E
+ exec >G
+ pick G
+ exec >H 2>I
+ pick H
+ fixup I
+ EOF
+
+ (
+ set_replace_editor todo &&
+ test_must_fail git rebase -i D D 2>err
+ ) &&
+ grep "would be overwritten" err &&
+ rm bar &&
+
+ test_must_fail git rebase --continue 2>err &&
+ grep "would be overwritten" err &&
+ rm G &&
+
+ test_must_fail git rebase --continue 2>err &&
+ grep "would be overwritten" err &&
+ rm H &&
+
+ test_must_fail git rebase --continue 2>err &&
+ grep "would be overwritten" err &&
+ rm I &&
+
+ git rebase --continue &&
+ echo rebase >expected.args &&
+ cat >expected.data <<-EOF &&
+ $(git rev-parse merge-E) $(git rev-parse HEAD~2)
+ $(git rev-parse G) $(git rev-parse HEAD~1)
+ $(git rev-parse H) $(git rev-parse HEAD)
+ $(git rev-parse I) $(git rev-parse HEAD)
+ EOF
+ verify_hook_input
+'
+
test_expect_success 'git rebase -i (unchanged)' '
git reset --hard D &&
clear_hook_input &&
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index b160f8b7fb..7b3ff21b98 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -5,6 +5,7 @@ test_description='test quickfetch from local'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
index ac4099ca89..0b8ab4afdb 100755
--- a/t/t5504-fetch-receive-strict.sh
+++ b/t/t5504-fetch-receive-strict.sh
@@ -4,6 +4,7 @@ test_description='fetch/receive strict mode'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup and inject "corrupt or missing" object' '
@@ -138,7 +139,7 @@ This commit object intentionally broken
EOF
test_expect_success 'setup bogus commit' '
- commit="$(git hash-object -t commit -w --stdin <bogus-commit)"
+ commit="$(git hash-object --literally -t commit -w --stdin <bogus-commit)"
'
test_expect_success 'fsck with no skipList input' '
diff --git a/t/t5506-remote-groups.sh b/t/t5506-remote-groups.sh
index 5bac03ede8..0e176175a3 100755
--- a/t/t5506-remote-groups.sh
+++ b/t/t5506-remote-groups.sh
@@ -99,4 +99,13 @@ test_expect_success 'updating remote name updates that remote' '
! repo_fetched two
'
+test_expect_success 'updating group in parallel with a duplicate remote does not fail (fetch)' '
+ mark fetch-group-duplicate &&
+ update_repo one &&
+ git config --add remotes.duplicate one &&
+ git config --add remotes.duplicate one &&
+ git -c fetch.parallel=2 remote update duplicate &&
+ repo_fetched one
+'
+
test_done
diff --git a/t/t5507-remote-environment.sh b/t/t5507-remote-environment.sh
index e6149295b1..c6a6957c50 100755
--- a/t/t5507-remote-environment.sh
+++ b/t/t5507-remote-environment.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='check environment showed to remote side of transports'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'set up "remote" push situation' '
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index c0b745e33b..19c36b57f4 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -806,6 +806,14 @@ test_expect_success 'fetch.writeCommitGraph with submodules' '
)
'
+# fetches from first configured url
+test_expect_success 'fetch from multiple configured URLs in single remote' '
+ git init url1 &&
+ git remote add multipleurls url1 &&
+ git remote set-url --add multipleurls url2 &&
+ git fetch multipleurls
+'
+
# configured prune tests
set_config_tristate () {
@@ -1110,58 +1118,60 @@ test_expect_success 'fetching with auto-gc does not lock up' '
)
'
-test_expect_success 'fetch aligned output' '
- git clone . full-output &&
- test_commit looooooooooooong-tag &&
- (
- cd full-output &&
- git -c fetch.output=full fetch origin >actual 2>&1 &&
- grep -e "->" actual | cut -c 22- >../actual
- ) &&
- cat >expect <<-\EOF &&
- main -> origin/main
- looooooooooooong-tag -> looooooooooooong-tag
- EOF
- test_cmp expect actual
-'
+for section in fetch transfer
+do
+ test_expect_success "$section.hideRefs affects connectivity check" '
+ GIT_TRACE="$PWD"/trace git -c $section.hideRefs=refs -c \
+ $section.hideRefs="!refs/tags/" fetch &&
+ grep "git rev-list .*--exclude-hidden=fetch" trace
+ '
+done
+
+test_expect_success 'prepare source branch' '
+ echo one >onebranch &&
+ git checkout --orphan onebranch &&
+ git rm --cached -r . &&
+ git add onebranch &&
+ git commit -m onebranch &&
+ git rev-list --objects onebranch -- >actual &&
+ # 3 objects should be created, at least ...
+ test 3 -le $(wc -l <actual)
+'
+
+validate_store_type () {
+ git -C dest count-objects -v >actual &&
+ case "$store_type" in
+ packed)
+ grep "^count: 0$" actual ;;
+ loose)
+ grep "^packs: 0$" actual ;;
+ esac || {
+ echo "store_type is $store_type"
+ cat actual
+ false
+ }
+}
-test_expect_success 'fetch compact output' '
- git clone . compact &&
- test_commit extraaa &&
- (
- cd compact &&
- git -c fetch.output=compact fetch origin >actual 2>&1 &&
- grep -e "->" actual | cut -c 22- >../actual
- ) &&
- cat >expect <<-\EOF &&
- main -> origin/*
- extraaa -> *
- EOF
- test_cmp expect actual
-'
+test_unpack_limit () {
+ store_type=$1
-test_expect_success '--no-show-forced-updates' '
- mkdir forced-updates &&
- (
- cd forced-updates &&
- git init &&
- test_commit 1 &&
- test_commit 2
- ) &&
- git clone forced-updates forced-update-clone &&
- git clone forced-updates no-forced-update-clone &&
- git -C forced-updates reset --hard HEAD~1 &&
- (
- cd forced-update-clone &&
- git fetch --show-forced-updates origin 2>output &&
- test_i18ngrep "(forced update)" output
- ) &&
- (
- cd no-forced-update-clone &&
- git fetch --no-show-forced-updates origin 2>output &&
- test_i18ngrep ! "(forced update)" output
- )
-'
+ case "$store_type" in
+ packed) fetch_limit=1 transfer_limit=10000 ;;
+ loose) fetch_limit=10000 transfer_limit=1 ;;
+ esac
+
+ test_expect_success "fetch trumps transfer limit" '
+ rm -fr dest &&
+ git --bare init dest &&
+ git -C dest config fetch.unpacklimit $fetch_limit &&
+ git -C dest config transfer.unpacklimit $transfer_limit &&
+ git -C dest fetch .. onebranch &&
+ validate_store_type
+ '
+}
+
+test_unpack_limit packed
+test_unpack_limit loose
setup_negotiation_tip () {
SERVER="$1"
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 20d063fb9a..151c76eb09 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -15,6 +15,19 @@ generate_references () {
done
}
+test_expect_success 'set up fake upload-pack' '
+ # This can be used to simulate an upload-pack that just shows the
+ # contents of the "input" file (prepared with the test-tool pkt-line
+ # helper), and does not do any negotiation (since ls-remote does not
+ # need it).
+ write_script cat-input <<-\EOF
+ # send our initial advertisement/response
+ cat input
+ # soak up the flush packet from the client
+ cat
+ EOF
+'
+
test_expect_success 'dies when no remote found' '
test_must_fail git ls-remote
'
@@ -231,22 +244,25 @@ test_expect_success 'protocol v2 supports hiderefs' '
test_expect_success 'ls-remote --symref' '
git fetch origin &&
- echo "ref: refs/heads/main HEAD" >expect &&
+ echo "ref: refs/heads/main HEAD" >expect.v2 &&
generate_references \
HEAD \
- refs/heads/main >>expect &&
+ refs/heads/main >>expect.v2 &&
+ echo "ref: refs/remotes/origin/main refs/remotes/origin/HEAD" >>expect.v2 &&
oid=$(git rev-parse HEAD) &&
- echo "$oid refs/remotes/origin/HEAD" >>expect &&
+ echo "$oid refs/remotes/origin/HEAD" >>expect.v2 &&
generate_references \
refs/remotes/origin/main \
refs/tags/mark \
refs/tags/mark1.1 \
refs/tags/mark1.10 \
- refs/tags/mark1.2 >>expect &&
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref >actual &&
- test_cmp expect actual
+ refs/tags/mark1.2 >>expect.v2 &&
+ # v0 does not show non-HEAD symrefs
+ grep -v "ref: refs/remotes" <expect.v2 >expect.v0 &&
+ git -c protocol.version=0 ls-remote --symref >actual.v0 &&
+ test_cmp expect.v0 actual.v0 &&
+ git -c protocol.version=2 ls-remote --symref >actual.v2 &&
+ test_cmp expect.v2 actual.v2
'
test_expect_success 'ls-remote with filtered symref (refname)' '
@@ -255,76 +271,41 @@ test_expect_success 'ls-remote with filtered symref (refname)' '
ref: refs/heads/main HEAD
$rev HEAD
EOF
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . HEAD >actual &&
+ git ls-remote --symref . HEAD >actual &&
test_cmp expect actual
'
-test_expect_failure 'ls-remote with filtered symref (--heads)' '
+test_expect_success 'ls-remote with filtered symref (--heads)' '
git symbolic-ref refs/heads/foo refs/tags/mark &&
- cat >expect <<-EOF &&
+ cat >expect.v2 <<-EOF &&
ref: refs/tags/mark refs/heads/foo
$rev refs/heads/foo
$rev refs/heads/main
EOF
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual &&
- test_cmp expect actual
+ grep -v "^ref: refs/tags/" <expect.v2 >expect.v0 &&
+ git -c protocol.version=0 ls-remote --symref --heads . >actual.v0 &&
+ test_cmp expect.v0 actual.v0 &&
+ git -c protocol.version=2 ls-remote --symref --heads . >actual.v2 &&
+ test_cmp expect.v2 actual.v2
'
-test_expect_success 'ls-remote --symref omits filtered-out matches' '
- cat >expect <<-EOF &&
- $rev refs/heads/foo
- $rev refs/heads/main
+test_expect_success 'indicate no refs in v0 standards-compliant empty remote' '
+ # Git does not produce an output like this, but it does match the
+ # standard and is produced by other implementations like JGit. So
+ # hard-code the case we care about.
+ #
+ # The actual capabilities do not matter; there are none that would
+ # change how ls-remote behaves.
+ oid=0000000000000000000000000000000000000000 &&
+ test-tool pkt-line pack >input.q <<-EOF &&
+ $oid capabilities^{}Qcaps-go-here
+ 0000
EOF
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual &&
- test_cmp expect actual &&
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . "refs/heads/*" >actual &&
- test_cmp expect actual
-'
-
-test_lazy_prereq GIT_DAEMON '
- test_bool_env GIT_TEST_GIT_DAEMON true
-'
+ q_to_nul <input.q >input &&
-# This test spawns a daemon, so run it only if the user would be OK with
-# testing with git-daemon.
-test_expect_success PIPE,JGIT,GIT_DAEMON 'indicate no refs in standards-compliant empty remote' '
- test_set_port JGIT_DAEMON_PORT &&
- JGIT_DAEMON_PID= &&
- git init --bare empty.git &&
- >empty.git/git-daemon-export-ok &&
- mkfifo jgit_daemon_output &&
- {
- jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
- JGIT_DAEMON_PID=$!
- } &&
- test_when_finished kill "$JGIT_DAEMON_PID" &&
- {
- read line &&
- case $line in
- Exporting*)
- ;;
- *)
- echo "Expected: Exporting" &&
- false;;
- esac &&
- read line &&
- case $line in
- "Listening on"*)
- ;;
- *)
- echo "Expected: Listening on" &&
- false;;
- esac
- } <jgit_daemon_output &&
# --exit-code asks the command to exit with 2 when no
# matching refs are found.
- test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
+ test_expect_code 2 git ls-remote --exit-code --upload-pack=./cat-input .
'
test_expect_success 'ls-remote works outside repository' '
@@ -345,8 +326,8 @@ test_expect_success 'ls-remote --sort fails gracefully outside repository' '
test_expect_success 'ls-remote patterns work with all protocol versions' '
git for-each-ref --format="%(objectname) %(refname)" \
refs/heads/main refs/remotes/origin/main >expect &&
- git -c protocol.version=1 ls-remote . main >actual.v1 &&
- test_cmp expect actual.v1 &&
+ git -c protocol.version=0 ls-remote . main >actual.v0 &&
+ test_cmp expect actual.v0 &&
git -c protocol.version=2 ls-remote . main >actual.v2 &&
test_cmp expect actual.v2
'
@@ -354,10 +335,49 @@ test_expect_success 'ls-remote patterns work with all protocol versions' '
test_expect_success 'ls-remote prefixes work with all protocol versions' '
git for-each-ref --format="%(objectname) %(refname)" \
refs/heads/ refs/tags/ >expect &&
- git -c protocol.version=1 ls-remote --heads --tags . >actual.v1 &&
- test_cmp expect actual.v1 &&
+ git -c protocol.version=0 ls-remote --heads --tags . >actual.v0 &&
+ test_cmp expect actual.v0 &&
git -c protocol.version=2 ls-remote --heads --tags . >actual.v2 &&
test_cmp expect actual.v2
'
+test_expect_success 'v0 clients can handle multiple symrefs' '
+ # Modern versions of Git will not return multiple symref capabilities
+ # for v0, so we have to hard-code the response. Note that we will
+ # always use both v0 and object-format=sha1 here, as the hard-coded
+ # response reflects a server that only supports those.
+ oid=1234567890123456789012345678901234567890 &&
+ symrefs="symref=refs/remotes/origin/HEAD:refs/remotes/origin/main" &&
+ symrefs="$symrefs symref=HEAD:refs/heads/main" &&
+
+ # Likewise we want to make sure our parser is not fooled by the string
+ # "symref" appearing as part of an earlier cap. But there is no way to
+ # do that via upload-pack, as arbitrary strings can appear only in a
+ # "symref" value itself (where we skip past the values as a whole)
+ # and "agent" (which always appears after "symref", so putting our
+ # parser in a confused state is less interesting).
+ caps="some other caps including a-fake-symref-cap" &&
+
+ test-tool pkt-line pack >input.q <<-EOF &&
+ $oid HEADQ$caps $symrefs
+ $oid refs/heads/main
+ $oid refs/remotes/origin/HEAD
+ $oid refs/remotes/origin/main
+ 0000
+ EOF
+ q_to_nul <input.q >input &&
+
+ cat >expect <<-EOF &&
+ ref: refs/heads/main HEAD
+ $oid HEAD
+ $oid refs/heads/main
+ ref: refs/remotes/origin/main refs/remotes/origin/HEAD
+ $oid refs/remotes/origin/HEAD
+ $oid refs/remotes/origin/main
+ EOF
+
+ git ls-remote --symref --upload-pack=./cat-input . >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh
index 511ba3bd45..98f034aa77 100755
--- a/t/t5514-fetch-multiple.sh
+++ b/t/t5514-fetch-multiple.sh
@@ -58,6 +58,13 @@ test_expect_success 'git fetch --all' '
test_cmp expect output)
'
+test_expect_success 'git fetch --all --no-write-fetch-head' '
+ (cd test &&
+ rm -f .git/FETCH_HEAD &&
+ git fetch --all --no-write-fetch-head &&
+ test_path_is_missing .git/FETCH_HEAD)
+'
+
test_expect_success 'git fetch --all should continue if a remote has errors' '
(git clone one test2 &&
cd test2 &&
@@ -197,4 +204,9 @@ test_expect_success 'parallel' '
test_i18ngrep "could not fetch .two.*128" err
'
+test_expect_success 'git fetch --multiple --jobs=0 picks a default' '
+ (cd test &&
+ git fetch --multiple --jobs=0)
+'
+
test_done
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 79dc470c01..87163d7745 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -120,6 +120,17 @@ test_expect_success setup '
'
+for cmd in push fetch
+do
+ for opt in ipv4 ipv6
+ do
+ test_expect_success "reject 'git $cmd --no-$opt'" '
+ test_must_fail git $cmd --no-$opt 2>err &&
+ grep "unknown option .no-$opt" err
+ '
+ done
+done
+
test_expect_success 'fetch without wildcard' '
mk_empty testrepo &&
(
@@ -401,6 +412,11 @@ test_expect_success 'push with ambiguity' '
'
+test_expect_success 'push with onelevel ref' '
+ mk_test testrepo heads/main &&
+ test_must_fail git push testrepo HEAD:refs/onelevel
+'
+
test_expect_success 'push with colon-less refspec (1)' '
mk_test testrepo heads/frotz tags/frotz &&
@@ -898,6 +914,13 @@ test_expect_success 'push --delete refuses empty string' '
test_must_fail git push testrepo --delete ""
'
+test_expect_success 'push --delete onelevel refspecs' '
+ mk_test testrepo heads/main &&
+ git -C testrepo update-ref refs/onelevel refs/heads/main &&
+ git push testrepo --delete refs/onelevel &&
+ test_must_fail git -C testrepo rev-parse --verify refs/onelevel
+'
+
test_expect_success 'warn on push to HEAD of non-bare repository' '
mk_test testrepo heads/main &&
(
@@ -1853,55 +1876,24 @@ test_expect_success 'refuse to push a hidden ref, and make sure do not pollute t
test_dir_is_empty testrepo/.git/objects/pack
'
-test_expect_success LIBCURL 'fetch warns or fails when using username:password' '
- message="URL '\''https://username:<redacted>@localhost/'\'' uses plaintext credentials" &&
- test_must_fail git -c transfer.credentialsInUrl=allow fetch https://username:password@localhost 2>err &&
- ! grep "$message" err &&
-
- test_must_fail git -c transfer.credentialsInUrl=warn fetch https://username:password@localhost 2>err &&
- grep "warning: $message" err >warnings &&
- test_line_count = 3 warnings &&
-
- test_must_fail git -c transfer.credentialsInUrl=die fetch https://username:password@localhost 2>err &&
- grep "fatal: $message" err >warnings &&
- test_line_count = 1 warnings &&
-
- test_must_fail git -c transfer.credentialsInUrl=die fetch https://username:@localhost 2>err &&
- grep "fatal: $message" err >warnings &&
- test_line_count = 1 warnings
-'
-
-
-test_expect_success LIBCURL 'push warns or fails when using username:password' '
- message="URL '\''https://username:<redacted>@localhost/'\'' uses plaintext credentials" &&
- test_must_fail git -c transfer.credentialsInUrl=allow push https://username:password@localhost 2>err &&
- ! grep "$message" err &&
-
- test_must_fail git -c transfer.credentialsInUrl=warn push https://username:password@localhost 2>err &&
- grep "warning: $message" err >warnings &&
- test_must_fail git -c transfer.credentialsInUrl=die push https://username:password@localhost 2>err &&
- grep "fatal: $message" err >warnings &&
- test_line_count = 1 warnings
-'
-
test_expect_success 'push with config push.useBitmaps' '
mk_test testrepo heads/main &&
git checkout main &&
test_unconfig push.useBitmaps &&
GIT_TRACE2_EVENT="$PWD/default" \
- git push testrepo main:test &&
+ git push --quiet testrepo main:test &&
test_subcommand git pack-objects --all-progress-implied --revs --stdout \
--thin --delta-base-offset -q <default &&
test_config push.useBitmaps true &&
GIT_TRACE2_EVENT="$PWD/true" \
- git push testrepo main:test2 &&
+ git push --quiet testrepo main:test2 &&
test_subcommand git pack-objects --all-progress-implied --revs --stdout \
--thin --delta-base-offset -q <true &&
test_config push.useBitmaps false &&
GIT_TRACE2_EVENT="$PWD/false" \
- git push testrepo main:test3 &&
+ git push --quiet testrepo main:test3 &&
test_subcommand git pack-objects --all-progress-implied --revs --stdout \
--thin --delta-base-offset -q --no-use-bitmap-index <false
'
diff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh
index a448e169bd..6d4944a728 100755
--- a/t/t5517-push-mirror.sh
+++ b/t/t5517-push-mirror.sh
@@ -5,6 +5,7 @@ test_description='pushing to a mirror repository'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
D=$(pwd)
diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh
index bcff460d0a..cc5496e28f 100755
--- a/t/t5522-pull-symlink.sh
+++ b/t/t5522-pull-symlink.sh
@@ -2,6 +2,7 @@
test_description='pulling from symlinked subdir'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# The scenario we are building:
@@ -78,7 +79,9 @@ test_expect_success SYMLINKS 'pushing from symlinked subdir' '
git commit -m push ./file &&
git push
) &&
- test push = $(git show HEAD:subdir/file)
+ echo push >expect &&
+ git show HEAD:subdir/file >actual &&
+ test_cmp expect actual
'
test_done
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index fdb4292056..1b8d609879 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -4,6 +4,7 @@ test_description='push with --set-upstream'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
@@ -60,12 +61,20 @@ test_expect_success 'push -u :topic_2' '
check_config topic_2 upstream refs/heads/other2
'
-test_expect_success 'push -u --all' '
+test_expect_success 'push -u --all(the same behavior with--branches)' '
git branch all1 &&
git branch all2 &&
git push -u --all &&
check_config all1 upstream refs/heads/all1 &&
- check_config all2 upstream refs/heads/all2
+ check_config all2 upstream refs/heads/all2 &&
+ git config --get-regexp branch.all* > expect &&
+ git config --remove-section branch.all1 &&
+ git config --remove-section branch.all2 &&
+ git push -u --branches &&
+ check_config all1 upstream refs/heads/all1 &&
+ check_config all2 upstream refs/heads/all2 &&
+ git config --get-regexp branch.all* > actual &&
+ test_cmp expect actual
'
test_expect_success 'push -u HEAD' '
diff --git a/t/t5525-fetch-tagopt.sh b/t/t5525-fetch-tagopt.sh
index 45815f7378..3a28f1ded5 100755
--- a/t/t5525-fetch-tagopt.sh
+++ b/t/t5525-fetch-tagopt.sh
@@ -2,6 +2,7 @@
test_description='tagopt variable affects "git fetch" and is overridden by commandline.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
setup_clone () {
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index 3c44f19612..26e933f93a 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -167,6 +167,19 @@ test_expect_success "fetch --recurse-submodules recurses into submodules" '
verify_fetch_result actual.err
'
+test_expect_success "fetch --recurse-submodules honors --no-write-fetch-head" '
+ (
+ cd downstream &&
+ git submodule foreach --recursive \
+ sh -c "cd \"\$(git rev-parse --git-dir)\" && rm -f FETCH_HEAD" &&
+
+ git fetch --recurse-submodules --no-write-fetch-head &&
+
+ git submodule foreach --recursive \
+ sh -c "cd \"\$(git rev-parse --git-dir)\" && ! test -f FETCH_HEAD"
+ )
+'
+
test_expect_success "submodule.recurse option triggers recursive fetch" '
add_submodule_commits &&
(
@@ -178,6 +191,7 @@ test_expect_success "submodule.recurse option triggers recursive fetch" '
'
test_expect_success "fetch --recurse-submodules -j2 has the same output behaviour" '
+ test_when_finished "rm -f trace.out" &&
add_submodule_commits &&
(
cd downstream &&
@@ -705,17 +719,30 @@ test_expect_success "'fetch.recurseSubmodules=on-demand' works also without .git
test_expect_success 'fetching submodules respects parallel settings' '
git config fetch.recurseSubmodules true &&
+ test_when_finished "rm -f downstream/trace.out" &&
(
cd downstream &&
GIT_TRACE=$(pwd)/trace.out git fetch &&
grep "1 tasks" trace.out &&
+ >trace.out &&
+
GIT_TRACE=$(pwd)/trace.out git fetch --jobs 7 &&
grep "7 tasks" trace.out &&
+ >trace.out &&
+
git config submodule.fetchJobs 8 &&
GIT_TRACE=$(pwd)/trace.out git fetch &&
grep "8 tasks" trace.out &&
+ >trace.out &&
+
GIT_TRACE=$(pwd)/trace.out git fetch --jobs 9 &&
- grep "9 tasks" trace.out
+ grep "9 tasks" trace.out &&
+ >trace.out &&
+
+ GIT_TRACE=$(pwd)/trace.out git -c submodule.fetchJobs=0 fetch &&
+ grep "preparing to run up to [0-9]* tasks" trace.out &&
+ ! grep "up to 0 tasks" trace.out &&
+ >trace.out
)
'
@@ -1153,4 +1180,17 @@ test_expect_success 'fetch --all with --recurse-submodules with multiple' '
test_line_count = 2 fetch-subs
'
+test_expect_success "fetch --all with --no-recurse-submodules only fetches superproject" '
+ test_when_finished "rm -rf src_clone" &&
+
+ git clone --recurse-submodules src src_clone &&
+ (
+ cd src_clone &&
+ git remote add secondary ../src &&
+ git config submodule.recurse true &&
+ git fetch --all --no-recurse-submodules 2>../fetch-log
+ ) &&
+ ! grep "Fetching submodule" fetch-log
+'
+
test_done
diff --git a/t/t5527-fetch-odd-refs.sh b/t/t5527-fetch-odd-refs.sh
index e2770e4541..98ece27c6a 100755
--- a/t/t5527-fetch-odd-refs.sh
+++ b/t/t5527-fetch-odd-refs.sh
@@ -4,6 +4,7 @@ test_description='test fetching of oddly-named refs'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# afterwards we will have:
diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
index ce85fd30ad..0247137cb3 100755
--- a/t/t5529-push-errors.sh
+++ b/t/t5529-push-errors.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='detect some push errors early (before contacting remote)'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup commits' '
diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh
index 3f58b515ce..302e4cbdba 100755
--- a/t/t5531-deep-submodule-push.sh
+++ b/t/t5531-deep-submodule-push.sh
@@ -512,6 +512,56 @@ test_expect_success 'push only unpushed submodules recursively' '
test_cmp expected_pub actual_pub
'
+setup_subsub () {
+ git init upstream &&
+ git init upstream/sub &&
+ git init upstream/sub/deepsub &&
+ test_commit -C upstream/sub/deepsub innermost &&
+ git -C upstream/sub submodule add ./deepsub deepsub &&
+ git -C upstream/sub commit -m middle &&
+ git -C upstream submodule add ./sub sub &&
+ git -C upstream commit -m outermost &&
+
+ git -c protocol.file.allow=always clone --recurse-submodules upstream downstream &&
+ git -C downstream/sub/deepsub checkout -b downstream-branch &&
+ git -C downstream/sub checkout -b downstream-branch &&
+ git -C downstream checkout -b downstream-branch
+}
+
+new_downstream_commits () {
+ test_commit -C downstream/sub/deepsub new-innermost &&
+ git -C downstream/sub add deepsub &&
+ git -C downstream/sub commit -m new-middle &&
+ git -C downstream add sub &&
+ git -C downstream commit -m new-outermost
+}
+
+test_expect_success 'push with push.recurseSubmodules=only on superproject' '
+ test_when_finished rm -rf upstream downstream &&
+ setup_subsub &&
+ new_downstream_commits &&
+ git -C downstream config push.recurseSubmodules only &&
+ git -C downstream push origin downstream-branch &&
+
+ test_must_fail git -C upstream rev-parse refs/heads/downstream-branch &&
+ git -C upstream/sub rev-parse refs/heads/downstream-branch &&
+ test_must_fail git -C upstream/sub/deepsub rev-parse refs/heads/downstream-branch
+'
+
+test_expect_success 'push with push.recurseSubmodules=only on superproject and top-level submodule' '
+ test_when_finished rm -rf upstream downstream &&
+ setup_subsub &&
+ new_downstream_commits &&
+ git -C downstream config push.recurseSubmodules only &&
+ git -C downstream/sub config push.recurseSubmodules only &&
+ git -C downstream push origin downstream-branch 2> err &&
+
+ test_must_fail git -C upstream rev-parse refs/heads/downstream-branch &&
+ git -C upstream/sub rev-parse refs/heads/downstream-branch &&
+ git -C upstream/sub/deepsub rev-parse refs/heads/downstream-branch &&
+ grep "recursing into submodule with push.recurseSubmodules=only; using on-demand instead" err
+'
+
test_expect_success 'push propagating the remotes name to a submodule' '
git -C work remote add origin ../pub.git &&
git -C work remote add pub ../pub.git &&
diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
index fbad2d5ff5..d0211cd8be 100755
--- a/t/t5541-http-push-smart.sh
+++ b/t/t5541-http-push-smart.sh
@@ -36,28 +36,6 @@ test_expect_success 'setup remote repository' '
setup_askpass_helper
-cat >exp <<EOF
-GET /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
-EOF
-test_expect_success 'no empty path components' '
- # Clear the log, so that it does not affect the "used receive-pack
- # service" test which reads the log too.
- test_when_finished ">\"\$HTTPD_ROOT_PATH\"/access.log" &&
-
- # In the URL, add a trailing slash, and see if git appends yet another
- # slash.
- cd "$ROOT_PATH" &&
- git clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone &&
-
- # NEEDSWORK: If the overspecification of the expected result is reduced, we
- # might be able to run this test in all protocol versions.
- if test "$GIT_TEST_PROTOCOL_VERSION" = 0
- then
- check_access_log exp
- fi
-'
-
test_expect_success 'clone remote repository' '
rm -rf test_repo_clone &&
git clone $HTTPD_URL/smart/test_repo.git test_repo_clone &&
@@ -67,6 +45,10 @@ test_expect_success 'clone remote repository' '
'
test_expect_success 'push to remote repository (standard)' '
+ # Clear the log, so that the "used receive-pack service" test below
+ # sees just what we did here.
+ >"$HTTPD_ROOT_PATH"/access.log &&
+
cd "$ROOT_PATH"/test_repo_clone &&
: >path2 &&
git add path2 &&
@@ -80,6 +62,15 @@ test_expect_success 'push to remote repository (standard)' '
test $HEAD = $(git rev-parse --verify HEAD))
'
+test_expect_success 'used receive-pack service' '
+ cat >exp <<-\EOF &&
+ GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+ POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
+ EOF
+
+ check_access_log exp
+'
+
test_expect_success 'push to remote repository (standard) with sending Accept-Language' '
cat >exp <<-\EOF &&
=> Send header: Accept-Language: ko-KR, *;q=0.9
@@ -141,28 +132,6 @@ test_expect_success 'rejected update prints status' '
'
rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
-cat >exp <<EOF
-GET /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
-GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
-GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
-GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
-GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
-GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
-EOF
-test_expect_success 'used receive-pack service' '
- # NEEDSWORK: If the overspecification of the expected result is reduced, we
- # might be able to run this test in all protocol versions.
- if test "$GIT_TEST_PROTOCOL_VERSION" = 0
- then
- check_access_log exp
- fi
-'
-
test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
"$ROOT_PATH"/test_repo_clone main success
diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh
index 70431122a4..04b47ad84a 100755
--- a/t/t5543-atomic-push.sh
+++ b/t/t5543-atomic-push.sh
@@ -117,7 +117,10 @@ test_expect_success 'atomic push fails if one branch fails' '
test_commit five &&
git checkout main &&
test_commit six &&
- test_must_fail git push --atomic --all up
+ test_must_fail git push --atomic --all up >output-all 2>&1 &&
+ # --all and --branches have the same behavior when be combined with --atomic
+ test_must_fail git push --atomic --branches up >output-branches 2>&1 &&
+ test_cmp output-all output-branches
) &&
test_refs main HEAD@{7} &&
test_refs second HEAD@{4}
diff --git a/t/t5544-pack-objects-hook.sh b/t/t5544-pack-objects-hook.sh
index 54f54f8d2e..1a9e14bbcc 100755
--- a/t/t5544-pack-objects-hook.sh
+++ b/t/t5544-pack-objects-hook.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test custom script in place of pack-objects'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create some history to fetch' '
diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
index 0b0e987fdb..9fc9ba552f 100755
--- a/t/t5546-receive-limits.sh
+++ b/t/t5546-receive-limits.sh
@@ -1,16 +1,34 @@
#!/bin/sh
test_description='check receive input limits'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Let's run tests with different unpack limits: 1 and 10000
# When the limit is 1, `git receive-pack` will call `git index-pack`.
# When the limit is 10000, `git receive-pack` will call `git unpack-objects`.
+validate_store_type () {
+ git -C dest count-objects -v >actual &&
+ case "$store_type" in
+ index)
+ grep "^count: 0$" actual ;;
+ unpack)
+ grep "^packs: 0$" actual ;;
+ esac || {
+ echo "store_type is $store_type"
+ cat actual
+ false;
+ }
+}
+
test_pack_input_limit () {
- case "$1" in
- index) unpack_limit=1 ;;
- unpack) unpack_limit=10000 ;;
+ store_type=$1
+
+ case "$store_type" in
+ index) unpack_limit=1 other_limit=10000 ;;
+ unpack) unpack_limit=10000 other_limit=1 ;;
esac
test_expect_success 'prepare destination repository' '
@@ -41,6 +59,19 @@ test_pack_input_limit () {
git --git-dir=dest config receive.maxInputSize 0 &&
git push dest HEAD
'
+
+ test_expect_success 'prepare destination repository (once more)' '
+ rm -fr dest &&
+ git --bare init dest
+ '
+
+ test_expect_success 'receive trumps transfer' '
+ git --git-dir=dest config receive.unpacklimit "$unpack_limit" &&
+ git --git-dir=dest config transfer.unpacklimit "$other_limit" &&
+ git push dest HEAD &&
+ validate_store_type
+ '
+
}
test_expect_success "create known-size (1024 bytes) commit" '
diff --git a/t/t5547-push-quarantine.sh b/t/t5547-push-quarantine.sh
index 1876fb34e5..9f899b8c7d 100755
--- a/t/t5547-push-quarantine.sh
+++ b/t/t5547-push-quarantine.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='check quarantine of objects during push'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create picky dest repo' '
diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
index d7cf85ffea..8f182a3cbf 100755
--- a/t/t5550-http-fetch-dumb.sh
+++ b/t/t5550-http-fetch-dumb.sh
@@ -234,7 +234,7 @@ test_expect_success 'http-fetch --packfile' '
--index-pack-arg=--keep \
"$HTTPD_URL"/dumb/repo_pack.git/$p >out &&
- grep "^keep.[0-9a-f]\{16,\}$" out &&
+ grep -E "^keep.[0-9a-f]{16,}$" out &&
cut -c6- out >packhash &&
# Ensure that the expected files are generated
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 6a38294a47..21b7767cbd 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -1,13 +1,19 @@
#!/bin/sh
-test_description='test smart fetching over http via http-backend'
+: ${HTTP_PROTO:=HTTP/1.1}
+test_description="test smart fetching over http via http-backend ($HTTP_PROTO)"
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh
+test "$HTTP_PROTO" = "HTTP/2" && enable_http2
start_httpd
+test_expect_success HTTP2 'enable client-side http/2' '
+ git config --global http.version HTTP/2
+'
+
test_expect_success 'setup repository' '
git config push.default matching &&
echo content >file &&
@@ -27,35 +33,71 @@ test_expect_success 'create http-accessible bare repository' '
setup_askpass_helper
test_expect_success 'clone http repository' '
- cat >exp <<-\EOF &&
- > GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1
- > Accept: */*
- > Accept-Encoding: ENCODINGS
- > Accept-Language: ko-KR, *;q=0.9
- > Pragma: no-cache
- < HTTP/1.1 200 OK
- < Pragma: no-cache
- < Cache-Control: no-cache, max-age=0, must-revalidate
- < Content-Type: application/x-git-upload-pack-advertisement
- > POST /smart/repo.git/git-upload-pack HTTP/1.1
- > Accept-Encoding: ENCODINGS
- > Content-Type: application/x-git-upload-pack-request
- > Accept: application/x-git-upload-pack-result
- > Accept-Language: ko-KR, *;q=0.9
- > Content-Length: xxx
- < HTTP/1.1 200 OK
- < Pragma: no-cache
- < Cache-Control: no-cache, max-age=0, must-revalidate
- < Content-Type: application/x-git-upload-pack-result
+ if test_have_prereq HTTP2 && test "$HTTPD_PROTO" = "https"
+ then
+ # ALPN lets us immediately use HTTP/2; likewise, POSTs with
+ # bodies can use it because they do not need to upgrade
+ INITIAL_PROTO=HTTP/2
+ else
+ # either we are not using HTTP/2, or the initial
+ # request is sent via HTTP/1.1 and asks for upgrade
+ INITIAL_PROTO=HTTP/1.1
+ fi &&
+
+ cat >exp.raw <<-EOF &&
+ > GET /smart/repo.git/info/refs?service=git-upload-pack $INITIAL_PROTO
+ > accept: */*
+ > accept-encoding: ENCODINGS
+ > accept-language: ko-KR, *;q=0.9
+ > pragma: no-cache
+ {V2} > git-protocol: version=2
+ < $HTTP_PROTO 200 OK
+ < pragma: no-cache
+ < cache-control: no-cache, max-age=0, must-revalidate
+ < content-type: application/x-git-upload-pack-advertisement
+ > POST /smart/repo.git/git-upload-pack $INITIAL_PROTO
+ > accept-encoding: ENCODINGS
+ > content-type: application/x-git-upload-pack-request
+ > accept: application/x-git-upload-pack-result
+ > accept-language: ko-KR, *;q=0.9
+ {V2} > git-protocol: version=2
+ > content-length: xxx
+ < $INITIAL_PROTO 200 OK
+ < pragma: no-cache
+ < cache-control: no-cache, max-age=0, must-revalidate
+ < content-type: application/x-git-upload-pack-result
+ {V2} > POST /smart/repo.git/git-upload-pack $INITIAL_PROTO
+ {V2} > accept-encoding: ENCODINGS
+ {V2} > content-type: application/x-git-upload-pack-request
+ {V2} > accept: application/x-git-upload-pack-result
+ {V2} > accept-language: ko-KR, *;q=0.9
+ {V2} > git-protocol: version=2
+ {V2} > content-length: xxx
+ {V2} < $INITIAL_PROTO 200 OK
+ {V2} < pragma: no-cache
+ {V2} < cache-control: no-cache, max-age=0, must-revalidate
+ {V2} < content-type: application/x-git-upload-pack-result
EOF
- GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION=0 LANGUAGE="ko_KR.UTF-8" \
+ if test "$GIT_TEST_PROTOCOL_VERSION" = 0
+ then
+ sed "/^{V2}/d" <exp.raw >exp
+ else
+ sed "s/^{V2} //" <exp.raw >exp
+ fi &&
+
+ GIT_TRACE_CURL=true LANGUAGE="ko_KR.UTF-8" \
git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
test_cmp file clone/file &&
tr '\''\015'\'' Q <err |
+ perl -pe '\''
+ s/(Send|Recv) header: ([A-Za-z0-9-]+):/
+ "$1 header: " . lc($2) . ":"
+ /e;
+ '\'' |
sed -e "
s/Q\$//
- /^[*] /d
+ /^[^<=]/d
/^== Info:/d
/^=> Send header, /d
/^=> Send header:$/d
@@ -65,6 +107,8 @@ test_expect_success 'clone http repository' '
s/= Recv header://
/^<= Recv data/d
/^=> Send data/d
+ /^<= Recv SSL data/d
+ /^=> Send SSL data/d
/^$/d
/^< $/d
@@ -72,36 +116,35 @@ test_expect_success 'clone http repository' '
s/^/> /
}
- /^> User-Agent: /d
- /^> Host: /d
+ /^< HTTP/ {
+ s/200$/200 OK/
+ }
+ /^< HTTP\\/1.1 101/d
+ /^[><] connection: /d
+ /^[><] upgrade: /d
+ /^> http2-settings: /d
+
+ /^> user-agent: /d
+ /^> host: /d
/^> POST /,$ {
/^> Accept: [*]\\/[*]/d
}
- s/^> Content-Length: .*/> Content-Length: xxx/
+ s/^> content-length: .*/> content-length: xxx/
/^> 00..want /d
/^> 00.*done/d
- /^< Server: /d
- /^< Expires: /d
- /^< Date: /d
- /^< Content-Length: /d
- /^< Transfer-Encoding: /d
+ /^< server: /d
+ /^< expires: /d
+ /^< date: /d
+ /^< content-length: /d
+ /^< transfer-encoding: /d
" >actual &&
- # NEEDSWORK: If the overspecification of the expected result is reduced, we
- # might be able to run this test in all protocol versions.
- if test "$GIT_TEST_PROTOCOL_VERSION" = 0
- then
- sed -e "s/^> Accept-Encoding: .*/> Accept-Encoding: ENCODINGS/" \
- actual >actual.smudged &&
- test_cmp exp actual.smudged &&
-
- grep "Accept-Encoding:.*gzip" actual >actual.gzip &&
- test_line_count = 2 actual.gzip &&
+ sed -e "s/^> accept-encoding: .*/> accept-encoding: ENCODINGS/" \
+ actual >actual.smudged &&
+ test_cmp exp actual.smudged &&
- grep "Accept-Language: ko-KR, *" actual >actual.language &&
- test_line_count = 2 actual.language
- fi
+ grep "accept-encoding:.*gzip" actual >actual.gzip
'
test_expect_success 'fetch changes via http' '
@@ -113,19 +156,9 @@ test_expect_success 'fetch changes via http' '
'
test_expect_success 'used upload-pack service' '
- cat >exp <<-\EOF &&
- GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
- POST /smart/repo.git/git-upload-pack HTTP/1.1 200
- GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
- POST /smart/repo.git/git-upload-pack HTTP/1.1 200
- EOF
-
- # NEEDSWORK: If the overspecification of the expected result is reduced, we
- # might be able to run this test in all protocol versions.
- if test "$GIT_TEST_PROTOCOL_VERSION" = 0
- then
- check_access_log exp
- fi
+ strip_access_log >log &&
+ grep "GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/[0-9.]* 200" log &&
+ grep "POST /smart/repo.git/git-upload-pack HTTP/[0-9.]* 200" log
'
test_expect_success 'follow redirects (301)' '
@@ -274,21 +307,23 @@ test_expect_success 'cookies stored in http.cookiefile when http.savecookies set
127.0.0.1 FALSE /smart_cookies/ FALSE 0 othername othervalue
EOF
sort >expect_cookies.txt <<-\EOF &&
-
127.0.0.1 FALSE /smart_cookies/ FALSE 0 othername othervalue
+ 127.0.0.1 FALSE /smart_cookies/repo.git/ FALSE 0 name value
127.0.0.1 FALSE /smart_cookies/repo.git/info/ FALSE 0 name value
EOF
git config http.cookiefile cookies.txt &&
git config http.savecookies true &&
- git ls-remote $HTTPD_URL/smart_cookies/repo.git main &&
- # NEEDSWORK: If the overspecification of the expected result is reduced, we
- # might be able to run this test in all protocol versions.
- if test "$GIT_TEST_PROTOCOL_VERSION" = 0
- then
- tail -3 cookies.txt | sort >cookies_tail.txt &&
- test_cmp expect_cookies.txt cookies_tail.txt
- fi
+ test_when_finished "
+ git --git-dir=\"\$HTTPD_DOCUMENT_ROOT_PATH/repo.git\" \
+ tag -d cookie-tag
+ " &&
+ git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
+ tag -m "foo" cookie-tag &&
+ git fetch $HTTPD_URL/smart_cookies/repo.git cookie-tag &&
+
+ grep "^[^#]" cookies.txt | sort >cookies_stripped.txt &&
+ test_cmp expect_cookies.txt cookies_stripped.txt
'
test_expect_success 'transfer.hiderefs works over smart-http' '
@@ -347,7 +382,10 @@ test_expect_success CMDLINE_LIMIT \
test_expect_success 'large fetch-pack requests can be sent using chunked encoding' '
GIT_TRACE_CURL=true git -c http.postbuffer=65536 \
clone --bare "$HTTPD_URL/smart/repo.git" split.git 2>err &&
- grep "^=> Send header: Transfer-Encoding: chunked" err
+ {
+ test_have_prereq HTTP2 ||
+ grep "^=> Send header: Transfer-Encoding: chunked" err
+ }
'
test_expect_success 'test allowreachablesha1inwant' '
@@ -573,6 +611,33 @@ test_expect_success 'client falls back from v2 to v0 to match server' '
grep symref=HEAD:refs/heads/ trace
'
+test_expect_success 'create empty http-accessible SHA-256 repository' '
+ mkdir "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
+ git --bare init --object-format=sha256
+ )
+'
+
+test_expect_success 'clone empty SHA-256 repository with protocol v2' '
+ rm -fr sha256 &&
+ echo sha256 >expected &&
+ git -c protocol.version=2 clone "$HTTPD_URL/smart/sha256.git" &&
+ git -C sha256 rev-parse --show-object-format >actual &&
+ test_cmp actual expected &&
+ git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
+ test_must_be_empty actual
+'
+
+test_expect_success 'clone empty SHA-256 repository with protocol v0' '
+ rm -fr sha256 &&
+ echo sha256 >expected &&
+ GIT_TRACE=1 GIT_TRACE_PACKET=1 git -c protocol.version=0 clone "$HTTPD_URL/smart/sha256.git" &&
+ git -C sha256 rev-parse --show-object-format >actual &&
+ test_cmp actual expected &&
+ git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
+ test_must_be_empty actual
+'
+
test_expect_success 'passing hostname resolution information works' '
BOGUS_HOST=gitbogusexamplehost.invalid &&
BOGUS_HTTPD_URL=$HTTPD_PROTO://$BOGUS_HOST:$LIB_HTTPD_PORT &&
@@ -580,4 +645,90 @@ test_expect_success 'passing hostname resolution information works' '
git -c "http.curloptResolve=$BOGUS_HOST:$LIB_HTTPD_PORT:127.0.0.1" ls-remote "$BOGUS_HTTPD_URL/smart/repo.git" >/dev/null
'
+# here user%40host is the URL-encoded version of user@host,
+# which is our intentionally-odd username to catch parsing errors
+url_user=$HTTPD_URL_USER/auth/smart/repo.git
+url_userpass=$HTTPD_URL_USER_PASS/auth/smart/repo.git
+url_userblank=$HTTPD_PROTO://user%40host:@$HTTPD_DEST/auth/smart/repo.git
+message="URL .*:<redacted>@.* uses plaintext credentials"
+
+test_expect_success 'clone warns or fails when using username:password' '
+ test_when_finished "rm -rf attempt*" &&
+
+ git -c transfer.credentialsInUrl=allow \
+ clone $url_userpass attempt1 2>err &&
+ ! grep "$message" err &&
+
+ git -c transfer.credentialsInUrl=warn \
+ clone $url_userpass attempt2 2>err &&
+ grep "warning: $message" err >warnings &&
+ test_line_count -ge 1 warnings &&
+
+ test_must_fail git -c transfer.credentialsInUrl=die \
+ clone $url_userpass attempt3 2>err &&
+ grep "fatal: $message" err >warnings &&
+ test_line_count -ge 1 warnings &&
+
+ test_must_fail git -c transfer.credentialsInUrl=die \
+ clone $url_userblank attempt4 2>err &&
+ grep "fatal: $message" err >warnings &&
+ test_line_count -ge 1 warnings
+'
+
+test_expect_success 'clone does not detect username:password when it is https://username@domain:port/' '
+ test_when_finished "rm -rf attempt1" &&
+
+ # we are relying on lib-httpd for url construction, so document our
+ # assumptions
+ case "$HTTPD_URL_USER" in
+ *:[0-9]*) : ok ;;
+ *) BUG "httpd url does not have port: $HTTPD_URL_USER"
+ esac &&
+
+ git -c transfer.credentialsInUrl=warn clone $url_user attempt1 2>err &&
+ ! grep "uses plaintext credentials" err
+'
+
+test_expect_success 'fetch warns or fails when using username:password' '
+ git -c transfer.credentialsInUrl=allow fetch $url_userpass 2>err &&
+ ! grep "$message" err &&
+
+ git -c transfer.credentialsInUrl=warn fetch $url_userpass 2>err &&
+ grep "warning: $message" err >warnings &&
+ test_line_count -ge 1 warnings &&
+
+ test_must_fail git -c transfer.credentialsInUrl=die \
+ fetch $url_userpass 2>err &&
+ grep "fatal: $message" err >warnings &&
+ test_line_count -ge 1 warnings &&
+
+ test_must_fail git -c transfer.credentialsInUrl=die \
+ fetch $url_userblank 2>err &&
+ grep "fatal: $message" err >warnings &&
+ test_line_count -ge 1 warnings
+'
+
+
+test_expect_success 'push warns or fails when using username:password' '
+ git -c transfer.credentialsInUrl=allow push $url_userpass 2>err &&
+ ! grep "$message" err &&
+
+ git -c transfer.credentialsInUrl=warn push $url_userpass 2>err &&
+ grep "warning: $message" err >warnings &&
+
+ test_must_fail git -c transfer.credentialsInUrl=die \
+ push $url_userpass 2>err &&
+ grep "fatal: $message" err >warnings &&
+ test_line_count -ge 1 warnings
+'
+
+test_expect_success 'no empty path components' '
+ # In the URL, add a trailing slash, and see if git appends yet another
+ # slash.
+ git clone $HTTPD_URL/smart/repo.git/ clone-with-slash &&
+
+ strip_access_log >log &&
+ ! grep "//" log
+'
+
test_done
diff --git a/t/t5552-skipping-fetch-negotiator.sh b/t/t5552-skipping-fetch-negotiator.sh
index 165427d57e..b55a9f65e6 100755
--- a/t/t5552-skipping-fetch-negotiator.sh
+++ b/t/t5552-skipping-fetch-negotiator.sh
@@ -3,6 +3,22 @@
test_description='test skipping fetch negotiator'
. ./test-lib.sh
+test_expect_success 'fetch.negotiationalgorithm config' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ cat >repo/.git/config <<-\EOF &&
+ [fetch]
+ negotiationAlgorithm
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''fetch.negotiationalgorithm'\''
+ fatal: bad config variable '\''fetch.negotiationalgorithm'\'' in file '\''.git/config'\'' at line 2
+ EOF
+ test_expect_code 128 git -C repo fetch >out 2>actual &&
+ test_must_be_empty out &&
+ test_cmp expect actual
+'
+
have_sent () {
while test "$#" -ne 0
do
diff --git a/t/t5554-noop-fetch-negotiator.sh b/t/t5554-noop-fetch-negotiator.sh
index 2ac7b5859e..06991e8e8a 100755
--- a/t/t5554-noop-fetch-negotiator.sh
+++ b/t/t5554-noop-fetch-negotiator.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test noop fetch negotiator'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'noop negotiator does not emit any "have"' '
diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh
index ad666a2d28..996a08e90c 100755
--- a/t/t5558-clone-bundle-uri.sh
+++ b/t/t5558-clone-bundle-uri.sh
@@ -41,6 +41,215 @@ test_expect_success 'clone with file:// bundle' '
test_cmp expect actual
'
+# To get interesting tests for bundle lists, we need to construct a
+# somewhat-interesting commit history.
+#
+# ---------------- bundle-4
+#
+# 4
+# / \
+# ----|---|------- bundle-3
+# | |
+# | 3
+# | |
+# ----|---|------- bundle-2
+# | |
+# 2 |
+# | |
+# ----|---|------- bundle-1
+# \ /
+# 1
+# |
+# (previous commits)
+test_expect_success 'construct incremental bundle list' '
+ (
+ cd clone-from &&
+ git checkout -b base &&
+ test_commit 1 &&
+ git checkout -b left &&
+ test_commit 2 &&
+ git checkout -b right base &&
+ test_commit 3 &&
+ git checkout -b merge left &&
+ git merge right -m "4" &&
+
+ git bundle create bundle-1.bundle base &&
+ git bundle create bundle-2.bundle base..left &&
+ git bundle create bundle-3.bundle base..right &&
+ git bundle create bundle-4.bundle merge --not left right
+ )
+'
+
+test_expect_success 'clone bundle list (file, no heuristic)' '
+ cat >bundle-list <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+
+ [bundle "bundle-1"]
+ uri = file://$(pwd)/clone-from/bundle-1.bundle
+
+ [bundle "bundle-2"]
+ uri = file://$(pwd)/clone-from/bundle-2.bundle
+
+ [bundle "bundle-3"]
+ uri = file://$(pwd)/clone-from/bundle-3.bundle
+
+ [bundle "bundle-4"]
+ uri = file://$(pwd)/clone-from/bundle-4.bundle
+ EOF
+
+ git clone --bundle-uri="file://$(pwd)/bundle-list" \
+ clone-from clone-list-file 2>err &&
+ ! grep "Repository lacks these prerequisite commits" err &&
+
+ git -C clone-from for-each-ref --format="%(objectname)" >oids &&
+ git -C clone-list-file cat-file --batch-check <oids &&
+
+ git -C clone-list-file for-each-ref --format="%(refname)" >refs &&
+ grep "refs/bundles/" refs >actual &&
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ refs/bundles/merge
+ refs/bundles/right
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'clone bundle list (file, all mode, some failures)' '
+ cat >bundle-list <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+
+ # Does not exist. Should be skipped.
+ [bundle "bundle-0"]
+ uri = file://$(pwd)/clone-from/bundle-0.bundle
+
+ [bundle "bundle-1"]
+ uri = file://$(pwd)/clone-from/bundle-1.bundle
+
+ [bundle "bundle-2"]
+ uri = file://$(pwd)/clone-from/bundle-2.bundle
+
+ # No bundle-3 means bundle-4 will not apply.
+
+ [bundle "bundle-4"]
+ uri = file://$(pwd)/clone-from/bundle-4.bundle
+
+ # Does not exist. Should be skipped.
+ [bundle "bundle-5"]
+ uri = file://$(pwd)/clone-from/bundle-5.bundle
+ EOF
+
+ GIT_TRACE2_PERF=1 \
+ git clone --bundle-uri="file://$(pwd)/bundle-list" \
+ clone-from clone-all-some 2>err &&
+ ! grep "Repository lacks these prerequisite commits" err &&
+ ! grep "fatal" err &&
+ grep "warning: failed to download bundle from URI" err &&
+
+ git -C clone-from for-each-ref --format="%(objectname)" >oids &&
+ git -C clone-all-some cat-file --batch-check <oids &&
+
+ git -C clone-all-some for-each-ref --format="%(refname)" >refs &&
+ grep "refs/bundles/" refs >actual &&
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'clone bundle list (file, all mode, all failures)' '
+ cat >bundle-list <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+
+ # Does not exist. Should be skipped.
+ [bundle "bundle-0"]
+ uri = file://$(pwd)/clone-from/bundle-0.bundle
+
+ # Does not exist. Should be skipped.
+ [bundle "bundle-5"]
+ uri = file://$(pwd)/clone-from/bundle-5.bundle
+ EOF
+
+ git clone --bundle-uri="file://$(pwd)/bundle-list" \
+ clone-from clone-all-fail 2>err &&
+ ! grep "Repository lacks these prerequisite commits" err &&
+ ! grep "fatal" err &&
+ grep "warning: failed to download bundle from URI" err &&
+
+ git -C clone-from for-each-ref --format="%(objectname)" >oids &&
+ git -C clone-all-fail cat-file --batch-check <oids &&
+
+ git -C clone-all-fail for-each-ref --format="%(refname)" >refs &&
+ ! grep "refs/bundles/" refs
+'
+
+test_expect_success 'clone bundle list (file, any mode)' '
+ cat >bundle-list <<-EOF &&
+ [bundle]
+ version = 1
+ mode = any
+
+ # Does not exist. Should be skipped.
+ [bundle "bundle-0"]
+ uri = file://$(pwd)/clone-from/bundle-0.bundle
+
+ [bundle "bundle-1"]
+ uri = file://$(pwd)/clone-from/bundle-1.bundle
+
+ # Does not exist. Should be skipped.
+ [bundle "bundle-5"]
+ uri = file://$(pwd)/clone-from/bundle-5.bundle
+ EOF
+
+ git clone --bundle-uri="file://$(pwd)/bundle-list" \
+ clone-from clone-any-file 2>err &&
+ ! grep "Repository lacks these prerequisite commits" err &&
+
+ git -C clone-from for-each-ref --format="%(objectname)" >oids &&
+ git -C clone-any-file cat-file --batch-check <oids &&
+
+ git -C clone-any-file for-each-ref --format="%(refname)" >refs &&
+ grep "refs/bundles/" refs >actual &&
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'clone bundle list (file, any mode, all failures)' '
+ cat >bundle-list <<-EOF &&
+ [bundle]
+ version = 1
+ mode = any
+
+ # Does not exist. Should be skipped.
+ [bundle "bundle-0"]
+ uri = $HTTPD_URL/bundle-0.bundle
+
+ # Does not exist. Should be skipped.
+ [bundle "bundle-5"]
+ uri = $HTTPD_URL/bundle-5.bundle
+ EOF
+
+ git clone --bundle-uri="file://$(pwd)/bundle-list" \
+ clone-from clone-any-fail 2>err &&
+ ! grep "fatal" err &&
+ grep "warning: failed to download bundle from URI" err &&
+
+ git -C clone-from for-each-ref --format="%(objectname)" >oids &&
+ git -C clone-any-fail cat-file --batch-check <oids &&
+
+ git -C clone-any-fail for-each-ref --format="%(refname)" >refs &&
+ ! grep "refs/bundles/" refs
+'
+
#########################################################################
# HTTP tests begin here
@@ -75,6 +284,774 @@ test_expect_success 'clone HTTP bundle' '
test_config -C clone-http log.excludedecoration refs/bundle/
'
+test_expect_success 'clone bundle list (HTTP, no heuristic)' '
+ test_when_finished rm -f trace*.txt &&
+
+ cp clone-from/bundle-*.bundle "$HTTPD_DOCUMENT_ROOT_PATH/" &&
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+
+ [bundle "bundle-1"]
+ uri = $HTTPD_URL/bundle-1.bundle
+
+ [bundle "bundle-2"]
+ uri = $HTTPD_URL/bundle-2.bundle
+
+ [bundle "bundle-3"]
+ uri = $HTTPD_URL/bundle-3.bundle
+
+ [bundle "bundle-4"]
+ uri = $HTTPD_URL/bundle-4.bundle
+ EOF
+
+ GIT_TRACE2_EVENT="$(pwd)/trace-clone.txt" \
+ git clone --bundle-uri="$HTTPD_URL/bundle-list" \
+ clone-from clone-list-http 2>err &&
+ ! grep "Repository lacks these prerequisite commits" err &&
+
+ git -C clone-from for-each-ref --format="%(objectname)" >oids &&
+ git -C clone-list-http cat-file --batch-check <oids &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-1.bundle
+ $HTTPD_URL/bundle-2.bundle
+ $HTTPD_URL/bundle-3.bundle
+ $HTTPD_URL/bundle-4.bundle
+ $HTTPD_URL/bundle-list
+ EOF
+
+ # Sort the list, since the order is not well-defined
+ # without a heuristic.
+ test_remote_https_urls <trace-clone.txt | sort >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'clone bundle list (HTTP, any mode)' '
+ cp clone-from/bundle-*.bundle "$HTTPD_DOCUMENT_ROOT_PATH/" &&
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = any
+
+ # Does not exist. Should be skipped.
+ [bundle "bundle-0"]
+ uri = $HTTPD_URL/bundle-0.bundle
+
+ [bundle "bundle-1"]
+ uri = $HTTPD_URL/bundle-1.bundle
+
+ # Does not exist. Should be skipped.
+ [bundle "bundle-5"]
+ uri = $HTTPD_URL/bundle-5.bundle
+ EOF
+
+ git clone --bundle-uri="$HTTPD_URL/bundle-list" \
+ clone-from clone-any-http 2>err &&
+ ! grep "fatal" err &&
+ grep "warning: failed to download bundle from URI" err &&
+
+ git -C clone-from for-each-ref --format="%(objectname)" >oids &&
+ git -C clone-any-http cat-file --batch-check <oids &&
+
+ git -C clone-list-file for-each-ref --format="%(refname)" >refs &&
+ grep "refs/bundles/" refs >actual &&
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ refs/bundles/merge
+ refs/bundles/right
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'clone bundle list (http, creationToken)' '
+ test_when_finished rm -f trace*.txt &&
+
+ cp clone-from/bundle-*.bundle "$HTTPD_DOCUMENT_ROOT_PATH/" &&
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = bundle-1.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = bundle-2.bundle
+ creationToken = 2
+
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+
+ [bundle "bundle-4"]
+ uri = bundle-4.bundle
+ creationToken = 4
+ EOF
+
+ GIT_TRACE2_EVENT="$(pwd)/trace-clone.txt" git \
+ clone --bundle-uri="$HTTPD_URL/bundle-list" \
+ "$HTTPD_URL/smart/fetch.git" clone-list-http-2 &&
+
+ git -C clone-from for-each-ref --format="%(objectname)" >oids &&
+ git -C clone-list-http-2 cat-file --batch-check <oids &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/bundle-4.bundle
+ $HTTPD_URL/bundle-3.bundle
+ $HTTPD_URL/bundle-2.bundle
+ $HTTPD_URL/bundle-1.bundle
+ EOF
+
+ test_remote_https_urls <trace-clone.txt >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'clone incomplete bundle list (http, creationToken)' '
+ test_when_finished rm -f trace*.txt &&
+
+ cp clone-from/bundle-*.bundle "$HTTPD_DOCUMENT_ROOT_PATH/" &&
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = bundle-1.bundle
+ creationToken = 1
+ EOF
+
+ GIT_TRACE2_EVENT=$(pwd)/trace-clone.txt \
+ git clone --bundle-uri="$HTTPD_URL/bundle-list" \
+ --single-branch --branch=base --no-tags \
+ "$HTTPD_URL/smart/fetch.git" clone-token-http &&
+
+ test_cmp_config -C clone-token-http "$HTTPD_URL/bundle-list" fetch.bundleuri &&
+ test_cmp_config -C clone-token-http 1 fetch.bundlecreationtoken &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/bundle-1.bundle
+ EOF
+
+ test_remote_https_urls <trace-clone.txt >actual &&
+ test_cmp expect actual &&
+
+ # We now have only one bundle ref.
+ git -C clone-token-http for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ EOF
+ test_cmp expect refs &&
+
+ # Add remaining bundles, exercising the "deepening" strategy
+ # for downloading via the creationToken heurisitc.
+ cat >>"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle "bundle-2"]
+ uri = bundle-2.bundle
+ creationToken = 2
+
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+
+ [bundle "bundle-4"]
+ uri = bundle-4.bundle
+ creationToken = 4
+ EOF
+
+ GIT_TRACE2_EVENT="$(pwd)/trace1.txt" \
+ git -C clone-token-http fetch origin --no-tags \
+ refs/heads/merge:refs/heads/merge &&
+ test_cmp_config -C clone-token-http 4 fetch.bundlecreationtoken &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/bundle-4.bundle
+ $HTTPD_URL/bundle-3.bundle
+ $HTTPD_URL/bundle-2.bundle
+ EOF
+
+ test_remote_https_urls <trace1.txt >actual &&
+ test_cmp expect actual &&
+
+ # We now have all bundle refs.
+ git -C clone-token-http for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ refs/bundles/merge
+ refs/bundles/right
+ EOF
+ test_cmp expect refs
+'
+
+test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '
+ test_when_finished rm -rf fetch-http-4 trace*.txt &&
+
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = bundle-1.bundle
+ creationToken = 1
+ EOF
+
+ GIT_TRACE2_EVENT="$(pwd)/trace-clone.txt" \
+ git clone --single-branch --branch=base \
+ --bundle-uri="$HTTPD_URL/bundle-list" \
+ "$HTTPD_URL/smart/fetch.git" fetch-http-4 &&
+
+ test_cmp_config -C fetch-http-4 "$HTTPD_URL/bundle-list" fetch.bundleuri &&
+ test_cmp_config -C fetch-http-4 1 fetch.bundlecreationtoken &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/bundle-1.bundle
+ EOF
+
+ test_remote_https_urls <trace-clone.txt >actual &&
+ test_cmp expect actual &&
+
+ # only received base ref from bundle-1
+ git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ EOF
+ test_cmp expect refs &&
+
+ cat >>"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle "bundle-2"]
+ uri = bundle-2.bundle
+ creationToken = 2
+ EOF
+
+ # Fetch the objects for bundle-2 _and_ bundle-3.
+ GIT_TRACE2_EVENT="$(pwd)/trace1.txt" \
+ git -C fetch-http-4 fetch origin --no-tags \
+ refs/heads/left:refs/heads/left \
+ refs/heads/right:refs/heads/right &&
+ test_cmp_config -C fetch-http-4 2 fetch.bundlecreationtoken &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/bundle-2.bundle
+ EOF
+
+ test_remote_https_urls <trace1.txt >actual &&
+ test_cmp expect actual &&
+
+ # received left from bundle-2
+ git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ EOF
+ test_cmp expect refs &&
+
+ # No-op fetch
+ GIT_TRACE2_EVENT="$(pwd)/trace1b.txt" \
+ git -C fetch-http-4 fetch origin --no-tags \
+ refs/heads/left:refs/heads/left \
+ refs/heads/right:refs/heads/right &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ EOF
+ test_remote_https_urls <trace1b.txt >actual &&
+ test_cmp expect actual &&
+
+ cat >>"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+
+ [bundle "bundle-4"]
+ uri = bundle-4.bundle
+ creationToken = 4
+ EOF
+
+ # This fetch should skip bundle-3.bundle, since its objects are
+ # already local (we have the requisite commits for bundle-4.bundle).
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C fetch-http-4 fetch origin --no-tags \
+ refs/heads/merge:refs/heads/merge &&
+ test_cmp_config -C fetch-http-4 4 fetch.bundlecreationtoken &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/bundle-4.bundle
+ EOF
+
+ test_remote_https_urls <trace2.txt >actual &&
+ test_cmp expect actual &&
+
+ # received merge ref from bundle-4, but right is missing
+ # because we did not download bundle-3.
+ git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ refs/bundles/merge
+ EOF
+ test_cmp expect refs &&
+
+ # No-op fetch
+ GIT_TRACE2_EVENT="$(pwd)/trace2b.txt" \
+ git -C fetch-http-4 fetch origin &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ EOF
+ test_remote_https_urls <trace2b.txt >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'creationToken heuristic with failed downloads (clone)' '
+ test_when_finished rm -rf download-* trace*.txt &&
+
+ # Case 1: base bundle does not exist, nothing can unbundle
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = fake.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = bundle-2.bundle
+ creationToken = 2
+
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+
+ [bundle "bundle-4"]
+ uri = bundle-4.bundle
+ creationToken = 4
+ EOF
+
+ GIT_TRACE2_EVENT="$(pwd)/trace-clone-1.txt" \
+ git clone --single-branch --branch=base \
+ --bundle-uri="$HTTPD_URL/bundle-list" \
+ "$HTTPD_URL/smart/fetch.git" download-1 &&
+
+ # Bundle failure does not set these configs.
+ test_must_fail git -C download-1 config fetch.bundleuri &&
+ test_must_fail git -C download-1 config fetch.bundlecreationtoken &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/bundle-4.bundle
+ $HTTPD_URL/bundle-3.bundle
+ $HTTPD_URL/bundle-2.bundle
+ $HTTPD_URL/fake.bundle
+ EOF
+ test_remote_https_urls <trace-clone-1.txt >actual &&
+ test_cmp expect actual &&
+
+ # All bundles failed to unbundle
+ git -C download-1 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+ test_must_be_empty refs &&
+
+ # Case 2: middle bundle does not exist, only two bundles can unbundle
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = bundle-1.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = fake.bundle
+ creationToken = 2
+
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+
+ [bundle "bundle-4"]
+ uri = bundle-4.bundle
+ creationToken = 4
+ EOF
+
+ GIT_TRACE2_EVENT="$(pwd)/trace-clone-2.txt" \
+ git clone --single-branch --branch=base \
+ --bundle-uri="$HTTPD_URL/bundle-list" \
+ "$HTTPD_URL/smart/fetch.git" download-2 &&
+
+ # Bundle failure does not set these configs.
+ test_must_fail git -C download-2 config fetch.bundleuri &&
+ test_must_fail git -C download-2 config fetch.bundlecreationtoken &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/bundle-4.bundle
+ $HTTPD_URL/bundle-3.bundle
+ $HTTPD_URL/fake.bundle
+ $HTTPD_URL/bundle-1.bundle
+ EOF
+ test_remote_https_urls <trace-clone-2.txt >actual &&
+ test_cmp expect actual &&
+
+ # bundle-1 and bundle-3 could unbundle, but bundle-4 could not
+ git -C download-2 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+ cat >expect <<-EOF &&
+ refs/bundles/base
+ refs/bundles/right
+ EOF
+ test_cmp expect refs &&
+
+ # Case 3: top bundle does not exist, rest unbundle fine.
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = bundle-1.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = bundle-2.bundle
+ creationToken = 2
+
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+
+ [bundle "bundle-4"]
+ uri = fake.bundle
+ creationToken = 4
+ EOF
+
+ GIT_TRACE2_EVENT="$(pwd)/trace-clone-3.txt" \
+ git clone --single-branch --branch=base \
+ --bundle-uri="$HTTPD_URL/bundle-list" \
+ "$HTTPD_URL/smart/fetch.git" download-3 &&
+
+ # As long as we have continguous successful downloads,
+ # we _do_ set these configs.
+ test_cmp_config -C download-3 "$HTTPD_URL/bundle-list" fetch.bundleuri &&
+ test_cmp_config -C download-3 3 fetch.bundlecreationtoken &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/fake.bundle
+ $HTTPD_URL/bundle-3.bundle
+ $HTTPD_URL/bundle-2.bundle
+ $HTTPD_URL/bundle-1.bundle
+ EOF
+ test_remote_https_urls <trace-clone-3.txt >actual &&
+ test_cmp expect actual &&
+
+ # fake.bundle did not unbundle, but the others did.
+ git -C download-3 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+ cat >expect <<-EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ refs/bundles/right
+ EOF
+ test_cmp expect refs
+'
+
+# Expand the bundle list to include other interesting shapes, specifically
+# interesting for use when fetching from a previous state.
+#
+# ---------------- bundle-7
+# 7
+# _/|\_
+# ---/--|--\------ bundle-6
+# 5 | 6
+# --|---|---|----- bundle-4
+# | 4 |
+# | / \ /
+# --|-|---|/------ bundle-3 (the client will be caught up to this point.)
+# \ | 3
+# ---\|---|------- bundle-2
+# 2 |
+# ----|---|------- bundle-1
+# \ /
+# 1
+# |
+# (previous commits)
+test_expect_success 'expand incremental bundle list' '
+ (
+ cd clone-from &&
+ git checkout -b lefter left &&
+ test_commit 5 &&
+ git checkout -b righter right &&
+ test_commit 6 &&
+ git checkout -b top lefter &&
+ git merge -m "7" merge righter &&
+
+ git bundle create bundle-6.bundle lefter righter --not left right &&
+ git bundle create bundle-7.bundle top --not lefter merge righter &&
+
+ cp bundle-*.bundle "$HTTPD_DOCUMENT_ROOT_PATH/"
+ ) &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/fetch.git" fetch origin +refs/heads/*:refs/heads/*
+'
+
+test_expect_success 'creationToken heuristic with failed downloads (fetch)' '
+ test_when_finished rm -rf download-* trace*.txt &&
+
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = bundle-1.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = bundle-2.bundle
+ creationToken = 2
+
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+ EOF
+
+ git clone --single-branch --branch=left \
+ --bundle-uri="$HTTPD_URL/bundle-list" \
+ "$HTTPD_URL/smart/fetch.git" fetch-base &&
+ test_cmp_config -C fetch-base "$HTTPD_URL/bundle-list" fetch.bundleURI &&
+ test_cmp_config -C fetch-base 3 fetch.bundleCreationToken &&
+
+ # Case 1: all bundles exist: successful unbundling of all bundles
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = bundle-1.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = bundle-2.bundle
+ creationToken = 2
+
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+
+ [bundle "bundle-4"]
+ uri = bundle-4.bundle
+ creationToken = 4
+
+ [bundle "bundle-6"]
+ uri = bundle-6.bundle
+ creationToken = 6
+
+ [bundle "bundle-7"]
+ uri = bundle-7.bundle
+ creationToken = 7
+ EOF
+
+ cp -r fetch-base fetch-1 &&
+ GIT_TRACE2_EVENT="$(pwd)/trace-fetch-1.txt" \
+ git -C fetch-1 fetch origin &&
+ test_cmp_config -C fetch-1 7 fetch.bundlecreationtoken &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/bundle-7.bundle
+ $HTTPD_URL/bundle-6.bundle
+ $HTTPD_URL/bundle-4.bundle
+ EOF
+ test_remote_https_urls <trace-fetch-1.txt >actual &&
+ test_cmp expect actual &&
+
+ # Check which bundles have unbundled by refs
+ git -C fetch-1 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+ cat >expect <<-EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ refs/bundles/lefter
+ refs/bundles/merge
+ refs/bundles/right
+ refs/bundles/righter
+ refs/bundles/top
+ EOF
+ test_cmp expect refs &&
+
+ # Case 2: middle bundle does not exist, only bundle-4 can unbundle
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = bundle-1.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = bundle-2.bundle
+ creationToken = 2
+
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+
+ [bundle "bundle-4"]
+ uri = bundle-4.bundle
+ creationToken = 4
+
+ [bundle "bundle-6"]
+ uri = fake.bundle
+ creationToken = 6
+
+ [bundle "bundle-7"]
+ uri = bundle-7.bundle
+ creationToken = 7
+ EOF
+
+ cp -r fetch-base fetch-2 &&
+ GIT_TRACE2_EVENT="$(pwd)/trace-fetch-2.txt" \
+ git -C fetch-2 fetch origin &&
+
+ # Since bundle-7 fails to unbundle, do not update creation token.
+ test_cmp_config -C fetch-2 3 fetch.bundlecreationtoken &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/bundle-7.bundle
+ $HTTPD_URL/fake.bundle
+ $HTTPD_URL/bundle-4.bundle
+ EOF
+ test_remote_https_urls <trace-fetch-2.txt >actual &&
+ test_cmp expect actual &&
+
+ # Check which bundles have unbundled by refs
+ git -C fetch-2 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+ cat >expect <<-EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ refs/bundles/merge
+ refs/bundles/right
+ EOF
+ test_cmp expect refs &&
+
+ # Case 3: top bundle does not exist, rest unbundle fine.
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = bundle-1.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = bundle-2.bundle
+ creationToken = 2
+
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+
+ [bundle "bundle-4"]
+ uri = bundle-4.bundle
+ creationToken = 4
+
+ [bundle "bundle-6"]
+ uri = bundle-6.bundle
+ creationToken = 6
+
+ [bundle "bundle-7"]
+ uri = fake.bundle
+ creationToken = 7
+ EOF
+
+ cp -r fetch-base fetch-3 &&
+ GIT_TRACE2_EVENT="$(pwd)/trace-fetch-3.txt" \
+ git -C fetch-3 fetch origin &&
+
+ # As long as we have continguous successful downloads,
+ # we _do_ set the maximum creation token.
+ test_cmp_config -C fetch-3 6 fetch.bundlecreationtoken &&
+
+ # NOTE: the fetch skips bundle-4 since bundle-6 successfully
+ # unbundles itself and bundle-7 failed to download.
+ cat >expect <<-EOF &&
+ $HTTPD_URL/bundle-list
+ $HTTPD_URL/fake.bundle
+ $HTTPD_URL/bundle-6.bundle
+ EOF
+ test_remote_https_urls <trace-fetch-3.txt >actual &&
+ test_cmp expect actual &&
+
+ # Check which bundles have unbundled by refs
+ git -C fetch-3 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
+ cat >expect <<-EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ refs/bundles/lefter
+ refs/bundles/right
+ refs/bundles/righter
+ EOF
+ test_cmp expect refs
+'
+
+test_expect_success 'bundles are downloaded once during fetch --all' '
+ test_when_finished rm -rf download-* trace*.txt fetch-mult &&
+
+ cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = bundle-1.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = bundle-2.bundle
+ creationToken = 2
+
+ [bundle "bundle-3"]
+ uri = bundle-3.bundle
+ creationToken = 3
+ EOF
+
+ git clone --single-branch --branch=left \
+ --bundle-uri="$HTTPD_URL/bundle-list" \
+ "$HTTPD_URL/smart/fetch.git" fetch-mult &&
+ git -C fetch-mult remote add dup1 "$HTTPD_URL/smart/fetch.git" &&
+ git -C fetch-mult remote add dup2 "$HTTPD_URL/smart/fetch.git" &&
+
+ GIT_TRACE2_EVENT="$(pwd)/trace-mult.txt" \
+ git -C fetch-mult fetch --all &&
+ grep "\"child_start\".*\"git-remote-https\",\"$HTTPD_URL/bundle-list\"" \
+ trace-mult.txt >bundle-fetches &&
+ test_line_count = 1 bundle-fetches
+'
# Do not add tests here unless they use the HTTP server, as they will
# not run unless the HTTP dependencies exist.
diff --git a/t/t5559-http-fetch-smart-http2.sh b/t/t5559-http-fetch-smart-http2.sh
new file mode 100755
index 0000000000..54aa9d3bff
--- /dev/null
+++ b/t/t5559-http-fetch-smart-http2.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+HTTP_PROTO=HTTP/2
+LIB_HTTPD_SSL=1
+. ./t5551-http-fetch-smart.sh
diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh
index d30cf4f5b8..f75068de64 100755
--- a/t/t5560-http-backend-noserver.sh
+++ b/t/t5560-http-backend-noserver.sh
@@ -4,6 +4,7 @@ test_description='test git-http-backend-noserver'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY"
diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh
index 9c57d84315..e1d3b8caed 100755
--- a/t/t5561-http-backend.sh
+++ b/t/t5561-http-backend.sh
@@ -4,6 +4,7 @@ test_description='test git-http-backend'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh
diff --git a/t/t5562-http-backend-content-length.sh b/t/t5562-http-backend-content-length.sh
index b68ec22d3f..7ee9858a78 100755
--- a/t/t5562-http-backend-content-length.sh
+++ b/t/t5562-http-backend-content-length.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test git-http-backend respects CONTENT_LENGTH'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_lazy_prereq GZIP 'gzip --version'
diff --git a/t/t5563-simple-http-auth.sh b/t/t5563-simple-http-auth.sh
new file mode 100755
index 0000000000..ab8a721ccc
--- /dev/null
+++ b/t/t5563-simple-http-auth.sh
@@ -0,0 +1,329 @@
+#!/bin/sh
+
+test_description='test http auth header and credential helper interop'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-httpd.sh
+
+enable_cgipassauth
+if ! test_have_prereq CGIPASSAUTH
+then
+ skip_all="no CGIPassAuth support"
+ test_done
+fi
+start_httpd
+
+test_expect_success 'setup_credential_helper' '
+ mkdir "$TRASH_DIRECTORY/bin" &&
+ PATH=$PATH:"$TRASH_DIRECTORY/bin" &&
+ export PATH &&
+
+ CREDENTIAL_HELPER="$TRASH_DIRECTORY/bin/git-credential-test-helper" &&
+ write_script "$CREDENTIAL_HELPER" <<-\EOF
+ cmd=$1
+ teefile=$cmd-query.cred
+ catfile=$cmd-reply.cred
+ sed -n -e "/^$/q" -e "p" >>$teefile
+ if test "$cmd" = "get"
+ then
+ cat $catfile
+ fi
+ EOF
+'
+
+set_credential_reply () {
+ cat >"$TRASH_DIRECTORY/$1-reply.cred"
+}
+
+expect_credential_query () {
+ cat >"$TRASH_DIRECTORY/$1-expect.cred" &&
+ test_cmp "$TRASH_DIRECTORY/$1-expect.cred" \
+ "$TRASH_DIRECTORY/$1-query.cred"
+}
+
+per_test_cleanup () {
+ rm -f *.cred &&
+ rm -f "$HTTPD_ROOT_PATH"/custom-auth.valid \
+ "$HTTPD_ROOT_PATH"/custom-auth.challenge
+}
+
+test_expect_success 'setup repository' '
+ test_commit foo &&
+ git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git push --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git"
+'
+
+test_expect_success 'access using basic auth' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=alice
+ password=secret-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ WWW-Authenticate: Basic realm="example.com"
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=Basic realm="example.com"
+ EOF
+
+ expect_credential_query store <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=alice
+ password=secret-passwd
+ EOF
+'
+
+test_expect_success 'access using basic auth invalid credentials' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=baduser
+ password=wrong-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ WWW-Authenticate: Basic realm="example.com"
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ test_must_fail git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=Basic realm="example.com"
+ EOF
+
+ expect_credential_query erase <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=baduser
+ password=wrong-passwd
+ wwwauth[]=Basic realm="example.com"
+ EOF
+'
+
+test_expect_success 'access using basic auth with extra challenges' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=alice
+ password=secret-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ WWW-Authenticate: FooBar param1="value1" param2="value2"
+ WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
+ WWW-Authenticate: Basic realm="example.com"
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=FooBar param1="value1" param2="value2"
+ wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+ wwwauth[]=Basic realm="example.com"
+ EOF
+
+ expect_credential_query store <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=alice
+ password=secret-passwd
+ EOF
+'
+
+test_expect_success 'access using basic auth mixed-case wwwauth header name' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=alice
+ password=secret-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ www-authenticate: foobar param1="value1" param2="value2"
+ WWW-AUTHENTICATE: BEARER authorize_uri="id.example.com" p=1 q=0
+ WwW-aUtHeNtIcAtE: baSiC realm="example.com"
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=foobar param1="value1" param2="value2"
+ wwwauth[]=BEARER authorize_uri="id.example.com" p=1 q=0
+ wwwauth[]=baSiC realm="example.com"
+ EOF
+
+ expect_credential_query store <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=alice
+ password=secret-passwd
+ EOF
+'
+
+test_expect_success 'access using basic auth with wwwauth header continuations' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=alice
+ password=secret-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ # Note that leading and trailing whitespace is important to correctly
+ # simulate a continuation/folded header.
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ WWW-Authenticate: FooBar param1="value1"
+ param2="value2"
+ WWW-Authenticate: Bearer authorize_uri="id.example.com"
+ p=1
+ q=0
+ WWW-Authenticate: Basic realm="example.com"
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=FooBar param1="value1" param2="value2"
+ wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+ wwwauth[]=Basic realm="example.com"
+ EOF
+
+ expect_credential_query store <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=alice
+ password=secret-passwd
+ EOF
+'
+
+test_expect_success 'access using basic auth with wwwauth header empty continuations' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=alice
+ password=secret-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
+
+ # Note that leading and trailing whitespace is important to correctly
+ # simulate a continuation/folded header.
+ printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >"$CHALLENGE" &&
+ printf " \r\n" >>"$CHALLENGE" &&
+ printf " param2=\"value2\"\r\n" >>"$CHALLENGE" &&
+ printf "WWW-Authenticate: Bearer authorize_uri=\"id.example.com\"\r\n" >>"$CHALLENGE" &&
+ printf " p=1\r\n" >>"$CHALLENGE" &&
+ printf " \r\n" >>"$CHALLENGE" &&
+ printf " q=0\r\n" >>"$CHALLENGE" &&
+ printf "WWW-Authenticate: Basic realm=\"example.com\"\r\n" >>"$CHALLENGE" &&
+
+ test_config_global credential.helper test-helper &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=FooBar param1="value1" param2="value2"
+ wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+ wwwauth[]=Basic realm="example.com"
+ EOF
+
+ expect_credential_query store <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=alice
+ password=secret-passwd
+ EOF
+'
+
+test_expect_success 'access using basic auth with wwwauth header mixed line-endings' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=alice
+ password=secret-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
+
+ # Note that leading and trailing whitespace is important to correctly
+ # simulate a continuation/folded header.
+ printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >"$CHALLENGE" &&
+ printf " \r\n" >>"$CHALLENGE" &&
+ printf "\tparam2=\"value2\"\r\n" >>"$CHALLENGE" &&
+ printf "WWW-Authenticate: Basic realm=\"example.com\"" >>"$CHALLENGE" &&
+
+ test_config_global credential.helper test-helper &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=FooBar param1="value1" param2="value2"
+ wwwauth[]=Basic realm="example.com"
+ EOF
+
+ expect_credential_query store <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=alice
+ password=secret-passwd
+ EOF
+'
+
+test_done
diff --git a/t/t5564-http-proxy.sh b/t/t5564-http-proxy.sh
new file mode 100755
index 0000000000..9da5134614
--- /dev/null
+++ b/t/t5564-http-proxy.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+test_description="test fetching through http proxy"
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-httpd.sh
+
+LIB_HTTPD_PROXY=1
+start_httpd
+
+test_expect_success 'setup repository' '
+ test_commit foo &&
+ git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git push --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git"
+'
+
+setup_askpass_helper
+
+# sanity check that our test setup is correctly using proxy
+test_expect_success 'proxy requires password' '
+ test_config_global http.proxy $HTTPD_DEST &&
+ test_must_fail git clone $HTTPD_URL/smart/repo.git 2>err &&
+ grep "error.*407" err
+'
+
+test_expect_success 'clone through proxy with auth' '
+ test_when_finished "rm -rf clone" &&
+ test_config_global http.proxy http://proxuser:proxpass@$HTTPD_DEST &&
+ GIT_TRACE_CURL=$PWD/trace git clone $HTTPD_URL/smart/repo.git clone &&
+ grep -i "Proxy-Authorization: Basic <redacted>" trace
+'
+
+test_expect_success 'clone can prompt for proxy password' '
+ test_when_finished "rm -rf clone" &&
+ test_config_global http.proxy http://proxuser@$HTTPD_DEST &&
+ set_askpass nobody proxpass &&
+ GIT_TRACE_CURL=$PWD/trace git clone $HTTPD_URL/smart/repo.git clone &&
+ expect_askpass pass proxuser
+'
+
+test_done
diff --git a/t/t5571-pre-push-hook.sh b/t/t5571-pre-push-hook.sh
index a11b20e378..448134c4bf 100755
--- a/t/t5571-pre-push-hook.sh
+++ b/t/t5571-pre-push-hook.sh
@@ -4,6 +4,7 @@ test_description='check pre-push hooks'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh
index 09097eff3f..4e917bf87d 100755
--- a/t/t5572-pull-submodule.sh
+++ b/t/t5572-pull-submodule.sh
@@ -121,7 +121,7 @@ test_expect_success "fetch.recurseSubmodules option triggers recursive fetch (bu
sub_oid=$(git -C child rev-parse HEAD) &&
git -C super/sub cat-file -e $sub_oid &&
# Check that the submodule worktree did not update
- ! test_path_is_file super/sub/merge_strategy_5.t
+ test_path_is_missing super/sub/merge_strategy_5.t
'
test_expect_success "fetch.recurseSubmodules takes precedence over submodule.recurse" '
@@ -134,7 +134,7 @@ test_expect_success "fetch.recurseSubmodules takes precedence over submodule.rec
sub_oid=$(git -C child rev-parse HEAD) &&
git -C super/sub cat-file -e $sub_oid &&
# Check that the submodule worktree did not update
- ! test_path_is_file super/sub/merge_strategy_6.t
+ test_path_is_missing super/sub/merge_strategy_6.t
'
test_expect_success 'pull --rebase --recurse-submodules (remote superproject submodule changes, local submodule changes)' '
diff --git a/t/t5573-pull-verify-signatures.sh b/t/t5573-pull-verify-signatures.sh
index a53dd8550d..1221ac0597 100755
--- a/t/t5573-pull-verify-signatures.sh
+++ b/t/t5573-pull-verify-signatures.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='pull signature verification tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t5574-fetch-output.sh b/t/t5574-fetch-output.sh
new file mode 100755
index 0000000000..90e6dcb9a7
--- /dev/null
+++ b/t/t5574-fetch-output.sh
@@ -0,0 +1,293 @@
+#!/bin/sh
+
+test_description='git fetch output format'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+test_expect_success 'fetch with invalid output format configuration' '
+ test_when_finished "rm -rf clone" &&
+ git clone . clone &&
+
+ test_must_fail git -C clone -c fetch.output fetch origin 2>actual.err &&
+ cat >expect <<-EOF &&
+ error: missing value for ${SQ}fetch.output${SQ}
+ fatal: unable to parse ${SQ}fetch.output${SQ} from command-line config
+ EOF
+ test_cmp expect actual.err &&
+
+ test_must_fail git -C clone -c fetch.output= fetch origin 2>actual.err &&
+ cat >expect <<-EOF &&
+ fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}${SQ}
+ EOF
+ test_cmp expect actual.err &&
+
+ test_must_fail git -C clone -c fetch.output=garbage fetch origin 2>actual.err &&
+ cat >expect <<-EOF &&
+ fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}garbage${SQ}
+ EOF
+ test_cmp expect actual.err
+'
+
+test_expect_success 'fetch aligned output' '
+ git clone . full-output &&
+ test_commit looooooooooooong-tag &&
+ (
+ cd full-output &&
+ git -c fetch.output=full fetch origin >actual 2>&1 &&
+ grep -e "->" actual | cut -c 22- >../actual
+ ) &&
+ cat >expect <<-\EOF &&
+ main -> origin/main
+ looooooooooooong-tag -> looooooooooooong-tag
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'fetch compact output' '
+ git clone . compact &&
+ test_commit extraaa &&
+ (
+ cd compact &&
+ git -c fetch.output=compact fetch origin >actual 2>&1 &&
+ grep -e "->" actual | cut -c 22- >../actual
+ ) &&
+ cat >expect <<-\EOF &&
+ main -> origin/*
+ extraaa -> *
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'fetch porcelain output' '
+ test_when_finished "rm -rf porcelain" &&
+
+ # Set up a bunch of references that we can use to demonstrate different
+ # kinds of flag symbols in the output format.
+ MAIN_OLD=$(git rev-parse HEAD) &&
+ git branch "fast-forward" &&
+ git branch "deleted-branch" &&
+ git checkout -b force-updated &&
+ test_commit --no-tag force-update-old &&
+ FORCE_UPDATED_OLD=$(git rev-parse HEAD) &&
+ git checkout main &&
+
+ # Clone and pre-seed the repositories. We fetch references into two
+ # namespaces so that we can test that rejected and force-updated
+ # references are reported properly.
+ refspecs="refs/heads/*:refs/unforced/* +refs/heads/*:refs/forced/*" &&
+ git clone . porcelain &&
+ git -C porcelain fetch origin $refspecs &&
+
+ # Now that we have set up the client repositories we can change our
+ # local references.
+ git branch new-branch &&
+ git branch -d deleted-branch &&
+ git checkout fast-forward &&
+ test_commit --no-tag fast-forward-new &&
+ FAST_FORWARD_NEW=$(git rev-parse HEAD) &&
+ git checkout force-updated &&
+ git reset --hard HEAD~ &&
+ test_commit --no-tag force-update-new &&
+ FORCE_UPDATED_NEW=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ - $MAIN_OLD $ZERO_OID refs/forced/deleted-branch
+ - $MAIN_OLD $ZERO_OID refs/unforced/deleted-branch
+ $MAIN_OLD $FAST_FORWARD_NEW refs/unforced/fast-forward
+ ! $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/unforced/force-updated
+ * $ZERO_OID $MAIN_OLD refs/unforced/new-branch
+ $MAIN_OLD $FAST_FORWARD_NEW refs/forced/fast-forward
+ + $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/forced/force-updated
+ * $ZERO_OID $MAIN_OLD refs/forced/new-branch
+ $MAIN_OLD $FAST_FORWARD_NEW refs/remotes/origin/fast-forward
+ + $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/remotes/origin/force-updated
+ * $ZERO_OID $MAIN_OLD refs/remotes/origin/new-branch
+ EOF
+
+ # Execute a dry-run fetch first. We do this to assert that the dry-run
+ # and non-dry-run fetches produces the same output. Execution of the
+ # fetch is expected to fail as we have a rejected reference update.
+ test_must_fail git -C porcelain fetch \
+ --porcelain --dry-run --prune origin $refspecs >actual &&
+ test_cmp expect actual &&
+
+ # And now we perform a non-dry-run fetch.
+ test_must_fail git -C porcelain fetch \
+ --porcelain --prune origin $refspecs >actual 2>stderr &&
+ test_cmp expect actual &&
+ test_must_be_empty stderr
+'
+
+test_expect_success 'fetch porcelain with multiple remotes' '
+ test_when_finished "rm -rf porcelain" &&
+
+ git switch --create multiple-remotes &&
+ git clone . porcelain &&
+ git -C porcelain remote add second-remote "$PWD" &&
+ git -C porcelain fetch second-remote &&
+
+ test_commit --no-tag multi-commit &&
+ old_commit=$(git rev-parse HEAD~) &&
+ new_commit=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ $old_commit $new_commit refs/remotes/origin/multiple-remotes
+ $old_commit $new_commit refs/remotes/second-remote/multiple-remotes
+ EOF
+
+ git -C porcelain fetch --porcelain --all >actual 2>stderr &&
+ test_cmp expect actual &&
+ test_must_be_empty stderr
+'
+
+test_expect_success 'fetch porcelain refuses to work with submodules' '
+ test_when_finished "rm -rf porcelain" &&
+
+ cat >expect <<-EOF &&
+ fatal: options ${SQ}--porcelain${SQ} and ${SQ}--recurse-submodules${SQ} cannot be used together
+ EOF
+
+ git init porcelain &&
+ test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=yes 2>stderr &&
+ test_cmp expect stderr &&
+
+ test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=on-demand 2>stderr &&
+ test_cmp expect stderr
+'
+
+test_expect_success 'fetch porcelain overrides fetch.output config' '
+ test_when_finished "rm -rf porcelain" &&
+
+ git switch --create config-override &&
+ git clone . porcelain &&
+ test_commit new-commit &&
+ old_commit=$(git rev-parse HEAD~) &&
+ new_commit=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ $old_commit $new_commit refs/remotes/origin/config-override
+ * $ZERO_OID $new_commit refs/tags/new-commit
+ EOF
+
+ git -C porcelain -c fetch.output=compact fetch --porcelain >stdout 2>stderr &&
+ test_must_be_empty stderr &&
+ test_cmp expect stdout
+'
+
+test_expect_success 'fetch --no-porcelain overrides previous --porcelain' '
+ test_when_finished "rm -rf no-porcelain" &&
+
+ git switch --create no-porcelain &&
+ git clone . no-porcelain &&
+ test_commit --no-tag no-porcelain &&
+ old_commit=$(git rev-parse --short HEAD~) &&
+ new_commit=$(git rev-parse --short HEAD) &&
+
+ cat >expect <<-EOF &&
+ From $(test-tool path-utils real_path .)/.
+ $old_commit..$new_commit no-porcelain -> origin/no-porcelain
+ EOF
+
+ git -C no-porcelain fetch --porcelain --no-porcelain >stdout 2>stderr &&
+ test_cmp expect stderr &&
+ test_must_be_empty stdout
+'
+
+test_expect_success 'fetch output with HEAD' '
+ test_when_finished "rm -rf head" &&
+ git clone . head &&
+
+ git -C head fetch --dry-run origin HEAD >actual.out 2>actual.err &&
+ cat >expect <<-EOF &&
+ From $(test-tool path-utils real_path .)/.
+ * branch HEAD -> FETCH_HEAD
+ EOF
+ test_must_be_empty actual.out &&
+ test_cmp expect actual.err &&
+
+ git -C head fetch origin HEAD >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_cmp expect actual.err &&
+
+ git -C head fetch --dry-run origin HEAD:foo >actual.out 2>actual.err &&
+ cat >expect <<-EOF &&
+ From $(test-tool path-utils real_path .)/.
+ * [new ref] HEAD -> foo
+ EOF
+ test_must_be_empty actual.out &&
+ test_cmp expect actual.err &&
+
+ git -C head fetch origin HEAD:foo >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_cmp expect actual.err
+'
+
+test_expect_success 'fetch porcelain output with HEAD' '
+ test_when_finished "rm -rf head" &&
+ git clone . head &&
+ COMMIT_ID=$(git rev-parse HEAD) &&
+
+ git -C head fetch --porcelain --dry-run origin HEAD >actual &&
+ cat >expect <<-EOF &&
+ * $ZERO_OID $COMMIT_ID FETCH_HEAD
+ EOF
+ test_cmp expect actual &&
+
+ git -C head fetch --porcelain origin HEAD >actual &&
+ test_cmp expect actual &&
+
+ git -C head fetch --porcelain --dry-run origin HEAD:foo >actual &&
+ cat >expect <<-EOF &&
+ * $ZERO_OID $COMMIT_ID refs/heads/foo
+ EOF
+ test_cmp expect actual &&
+
+ git -C head fetch --porcelain origin HEAD:foo >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'fetch output with object ID' '
+ test_when_finished "rm -rf object-id" &&
+ git clone . object-id &&
+ commit=$(git rev-parse HEAD) &&
+
+ git -C object-id fetch --dry-run origin $commit:object-id >actual.out 2>actual.err &&
+ cat >expect <<-EOF &&
+ From $(test-tool path-utils real_path .)/.
+ * [new ref] $commit -> object-id
+ EOF
+ test_must_be_empty actual.out &&
+ test_cmp expect actual.err &&
+
+ git -C object-id fetch origin $commit:object-id >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_cmp expect actual.err
+'
+
+test_expect_success '--no-show-forced-updates' '
+ mkdir forced-updates &&
+ (
+ cd forced-updates &&
+ git init &&
+ test_commit 1 &&
+ test_commit 2
+ ) &&
+ git clone forced-updates forced-update-clone &&
+ git clone forced-updates no-forced-update-clone &&
+ git -C forced-updates reset --hard HEAD~1 &&
+ (
+ cd forced-update-clone &&
+ git fetch --show-forced-updates origin 2>output &&
+ test_i18ngrep "(forced update)" output
+ ) &&
+ (
+ cd no-forced-update-clone &&
+ git fetch --no-show-forced-updates origin 2>output &&
+ test_i18ngrep ! "(forced update)" output
+ )
+'
+
+test_done
diff --git a/t/t5583-push-branches.sh b/t/t5583-push-branches.sh
new file mode 100755
index 0000000000..320f49c753
--- /dev/null
+++ b/t/t5583-push-branches.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+test_description='check the consisitency of behavior of --all and --branches'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+delete_refs() {
+ dir=$1
+ shift
+ rm -rf deletes
+ for arg in $*
+ do
+ echo "delete ${arg}" >>deletes
+ done
+ git -C $dir update-ref --stdin < deletes
+}
+
+test_expect_success 'setup bare remote' '
+ git init --bare remote-1 &&
+ git -C remote-1 config gc.auto 0 &&
+ test_commit one &&
+ git push remote-1 HEAD
+'
+
+test_expect_success 'setup different types of references' '
+ cat >refs <<-EOF &&
+ update refs/heads/branch-1 HEAD
+ update refs/heads/branch-2 HEAD
+ EOF
+
+ git tag -a -m "annotated" annotated-1 HEAD &&
+ git tag -a -m "annotated" annotated-2 HEAD &&
+ git update-ref --stdin < refs
+'
+
+test_expect_success '--all and --branches have the same behavior' '
+ test_when_finished "delete_refs remote-1 \
+ refs/heads/branch-1 \
+ refs/heads/branch-2" &&
+ git push remote-1 --all &&
+ commit=$(git rev-parse HEAD) &&
+ cat >expect <<-EOF &&
+ $commit refs/heads/branch-1
+ $commit refs/heads/branch-2
+ $commit refs/heads/main
+ EOF
+
+ git -C remote-1 show-ref --heads >actual.all &&
+ delete_refs remote-1 refs/heads/branch-1 refs/heads/branch-2 &&
+ git push remote-1 --branches &&
+ git -C remote-1 show-ref --heads >actual.branches &&
+ test_cmp actual.all actual.branches &&
+ test_cmp expect actual.all
+'
+
+test_expect_success '--all or --branches can not be combined with refspecs' '
+ test_must_fail git push remote-1 --all main >actual.all 2>&1 &&
+ test_must_fail git push remote-1 --branches main >actual.branches 2>&1 &&
+ test_cmp actual.all actual.branches &&
+ grep "be combined with refspecs" actual.all
+'
+
+test_expect_success '--all or --branches can not be combined with --mirror' '
+ test_must_fail git push remote-1 --all --mirror >actual.all 2>&1 &&
+ test_must_fail git push remote-1 --branches --mirror >actual.branches 2>&1 &&
+ test_cmp actual.all actual.branches &&
+ grep "cannot be used together" actual.all
+'
+
+test_expect_success '--all or --branches can not be combined with --tags' '
+ test_must_fail git push remote-1 --all --tags >actual.all 2>&1 &&
+ test_must_fail git push remote-1 --branches --tags >actual.branches 2>&1 &&
+ test_cmp actual.all actual.branches &&
+ grep "cannot be used together" actual.all
+'
+
+
+test_expect_success '--all or --branches can not be combined with --delete' '
+ test_must_fail git push remote-1 --all --delete >actual.all 2>&1 &&
+ test_must_fail git push remote-1 --branches --delete >actual.branches 2>&1 &&
+ test_cmp actual.all actual.branches &&
+ grep "cannot be used together" actual.all
+'
+
+test_expect_success '--all or --branches combines with --follow-tags have same behavior' '
+ test_when_finished "delete_refs remote-1 \
+ refs/heads/branch-1 \
+ refs/heads/branch-2 \
+ refs/tags/annotated-1 \
+ refs/tags/annotated-2" &&
+ git push remote-1 --all --follow-tags &&
+ git -C remote-1 show-ref > actual.all &&
+ cat >expect <<-EOF &&
+ $commit refs/heads/branch-1
+ $commit refs/heads/branch-2
+ $commit refs/heads/main
+ $(git rev-parse annotated-1) refs/tags/annotated-1
+ $(git rev-parse annotated-2) refs/tags/annotated-2
+ EOF
+
+ delete_refs remote-1 \
+ refs/heads/branch-1 \
+ refs/heads/branch-2 \
+ refs/tags/annotated-1 \
+ refs/tags/annotated-2 &&
+ git push remote-1 --branches --follow-tags &&
+ git -C remote-1 show-ref >actual.branches &&
+ test_cmp actual.all actual.branches &&
+ test_cmp expect actual.all
+'
+
+test_done
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 45f0803ed4..b7d5551262 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -71,29 +71,6 @@ test_expect_success 'clone respects GIT_WORK_TREE' '
'
-test_expect_success LIBCURL 'clone warns or fails when using username:password' '
- message="URL '\''https://username:<redacted>@localhost/'\'' uses plaintext credentials" &&
- test_must_fail git -c transfer.credentialsInUrl=allow clone https://username:password@localhost attempt1 2>err &&
- ! grep "$message" err &&
-
- test_must_fail git -c transfer.credentialsInUrl=warn clone https://username:password@localhost attempt2 2>err &&
- grep "warning: $message" err >warnings &&
- test_line_count = 2 warnings &&
-
- test_must_fail git -c transfer.credentialsInUrl=die clone https://username:password@localhost attempt3 2>err &&
- grep "fatal: $message" err >warnings &&
- test_line_count = 1 warnings &&
-
- test_must_fail git -c transfer.credentialsInUrl=die clone https://username:@localhost attempt3 2>err &&
- grep "fatal: $message" err >warnings &&
- test_line_count = 1 warnings
-'
-
-test_expect_success LIBCURL 'clone does not detect username:password when it is https://username@domain:port/' '
- test_must_fail git -c transfer.credentialsInUrl=warn clone https://username@localhost:8080 attempt3 2>err &&
- ! grep "uses plaintext credentials" err
-'
-
test_expect_success 'clone from hooks' '
test_create_repo r0 &&
@@ -795,6 +772,111 @@ test_expect_success 'reject cloning shallow repository using HTTP' '
git clone --no-reject-shallow $HTTPD_URL/smart/repo.git repo
'
+test_expect_success 'auto-discover bundle URI from HTTP clone' '
+ test_when_finished rm -rf trace.txt repo2 "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" &&
+ git -C src bundle create "$HTTPD_DOCUMENT_ROOT_PATH/everything.bundle" --all &&
+ git clone --bare --no-local src "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" &&
+
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" config \
+ uploadpack.advertiseBundleURIs true &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" config \
+ bundle.version 1 &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" config \
+ bundle.mode all &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" config \
+ bundle.everything.uri "$HTTPD_URL/everything.bundle" &&
+
+ GIT_TRACE2_EVENT="$(pwd)/trace.txt" \
+ git -c protocol.version=2 \
+ -c transfer.bundleURI=true clone \
+ $HTTPD_URL/smart/repo2.git repo2 &&
+ cat >pattern <<-EOF &&
+ "event":"child_start".*"argv":\["git-remote-https","$HTTPD_URL/everything.bundle"\]
+ EOF
+ grep -f pattern trace.txt
+'
+
+test_expect_success 'auto-discover multiple bundles from HTTP clone' '
+ test_when_finished rm -rf trace.txt repo3 "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" &&
+
+ test_commit -C src new &&
+ git -C src bundle create "$HTTPD_DOCUMENT_ROOT_PATH/new.bundle" HEAD~1..HEAD &&
+ git clone --bare --no-local src "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" &&
+
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" config \
+ uploadpack.advertiseBundleURIs true &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" config \
+ bundle.version 1 &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" config \
+ bundle.mode all &&
+
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" config \
+ bundle.everything.uri "$HTTPD_URL/everything.bundle" &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" config \
+ bundle.new.uri "$HTTPD_URL/new.bundle" &&
+
+ GIT_TRACE2_EVENT="$(pwd)/trace.txt" \
+ git -c protocol.version=2 \
+ -c transfer.bundleURI=true clone \
+ $HTTPD_URL/smart/repo3.git repo3 &&
+
+ # We should fetch _both_ bundles
+ cat >pattern <<-EOF &&
+ "event":"child_start".*"argv":\["git-remote-https","$HTTPD_URL/everything.bundle"\]
+ EOF
+ grep -f pattern trace.txt &&
+ cat >pattern <<-EOF &&
+ "event":"child_start".*"argv":\["git-remote-https","$HTTPD_URL/new.bundle"\]
+ EOF
+ grep -f pattern trace.txt
+'
+
+test_expect_success 'auto-discover multiple bundles from HTTP clone: creationToken heuristic' '
+ test_when_finished rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/repo4.git" &&
+ test_when_finished rm -rf clone-heuristic trace*.txt &&
+
+ test_commit -C src newest &&
+ git -C src bundle create "$HTTPD_DOCUMENT_ROOT_PATH/newest.bundle" HEAD~1..HEAD &&
+ git clone --bare --no-local src "$HTTPD_DOCUMENT_ROOT_PATH/repo4.git" &&
+
+ cat >>"$HTTPD_DOCUMENT_ROOT_PATH/repo4.git/config" <<-EOF &&
+ [uploadPack]
+ advertiseBundleURIs = true
+
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "everything"]
+ uri = $HTTPD_URL/everything.bundle
+ creationtoken = 1
+
+ [bundle "new"]
+ uri = $HTTPD_URL/new.bundle
+ creationtoken = 2
+
+ [bundle "newest"]
+ uri = $HTTPD_URL/newest.bundle
+ creationtoken = 3
+ EOF
+
+ GIT_TRACE2_EVENT="$(pwd)/trace-clone.txt" \
+ git -c protocol.version=2 \
+ -c transfer.bundleURI=true clone \
+ "$HTTPD_URL/smart/repo4.git" clone-heuristic &&
+
+ cat >expect <<-EOF &&
+ $HTTPD_URL/newest.bundle
+ $HTTPD_URL/new.bundle
+ $HTTPD_URL/everything.bundle
+ EOF
+
+ # We should fetch all bundles in the expected order.
+ test_remote_https_urls <trace-clone.txt >actual &&
+ test_cmp expect actual
+'
+
# DO NOT add non-httpd-specific tests here, because the last part of this
# test script is only executed when httpd is available and enabled.
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 7ccebb40c3..9845fc04d5 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -7,6 +7,7 @@ test_description='test clone --reference'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
base_dir=$(pwd)
@@ -357,7 +358,7 @@ test_expect_success SYMLINKS 'clone repo with symlinked objects directory' '
test_must_fail git clone --local malicious clone 2>err &&
test_path_is_missing clone &&
- grep "failed to start iterator over" err
+ grep "is a symlink, refusing to clone with --local" err
'
test_done
diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh
index 38b850c10e..1d7b1abda1 100755
--- a/t/t5605-clone-local.sh
+++ b/t/t5605-clone-local.sh
@@ -15,8 +15,12 @@ test_expect_success 'preparing origin repository' '
: >file && git add . && git commit -m1 &&
git clone --bare . a.git &&
git clone --bare . x &&
- test "$(cd a.git && git config --bool core.bare)" = true &&
- test "$(cd x && git config --bool core.bare)" = true &&
+ echo true >expect &&
+ git -C a.git config --bool core.bare >actual &&
+ test_cmp expect actual &&
+ echo true >expect &&
+ git -C x config --bool core.bare >actual &&
+ test_cmp expect actual &&
git bundle create b1.bundle --all &&
git bundle create b2.bundle main &&
mkdir dir &&
@@ -29,7 +33,9 @@ test_expect_success 'preparing origin repository' '
test_expect_success 'local clone without .git suffix' '
git clone -l -s a b &&
(cd b &&
- test "$(git config --bool core.bare)" = false &&
+ echo false >expect &&
+ git config --bool core.bare >actual &&
+ test_cmp expect actual &&
git fetch)
'
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index cf221e92c4..5890319b97 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -4,6 +4,7 @@ test_description='basic clone options'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
@@ -119,6 +120,16 @@ test_expect_success 'prefers -c config over --template config' '
'
+test_expect_failure 'prefers --template config even for core.bare' '
+
+ template="$TRASH_DIRECTORY/template-with-bare-config" &&
+ mkdir "$template" &&
+ git config --file "$template/config" core.bare true &&
+ git clone "--template=$template" parent clone-bare-config &&
+ test "$(git -C clone-bare-config config --local core.bare)" = "true" &&
+ test_path_is_file clone-bare-config/HEAD
+'
+
test_expect_success 'prefers config "clone.defaultRemoteName" over default' '
test_config_global clone.defaultRemoteName from_config &&
diff --git a/t/t5610-clone-detached.sh b/t/t5610-clone-detached.sh
index a7ec21eda5..022ed3d87c 100755
--- a/t/t5610-clone-detached.sh
+++ b/t/t5610-clone-detached.sh
@@ -4,6 +4,7 @@ test_description='test cloning a repository with detached HEAD'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
head_is_detached() {
diff --git a/t/t5611-clone-config.sh b/t/t5611-clone-config.sh
index 4b3877216e..727caff443 100755
--- a/t/t5611-clone-config.sh
+++ b/t/t5611-clone-config.sh
@@ -4,6 +4,7 @@ test_description='tests for git clone -c key=value'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'clone -c sets config in cloned repo' '
diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh
index 895f46bb91..7708cbafa9 100755
--- a/t/t5613-info-alternate.sh
+++ b/t/t5613-info-alternate.sh
@@ -4,6 +4,8 @@
#
test_description='test transitive info/alternate entries'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'preparing first repository' '
diff --git a/t/t5614-clone-submodules-shallow.sh b/t/t5614-clone-submodules-shallow.sh
index 0c85ef834a..c2a2bb453e 100755
--- a/t/t5614-clone-submodules-shallow.sh
+++ b/t/t5614-clone-submodules-shallow.sh
@@ -2,6 +2,7 @@
test_description='Test shallow cloning of repos with submodules'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
pwd=$(pwd)
diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh
index 037941b95d..8759fc2853 100755
--- a/t/t5616-partial-clone.sh
+++ b/t/t5616-partial-clone.sh
@@ -257,8 +257,8 @@ test_expect_success 'partial clone with transfer.fsckobjects=1 works with submod
test_commit -C submodule mycommit &&
test_create_repo src_with_sub &&
- test_config -C src_with_sub uploadpack.allowfilter 1 &&
- test_config -C src_with_sub uploadpack.allowanysha1inwant 1 &&
+ git -C src_with_sub config uploadpack.allowfilter 1 &&
+ git -C src_with_sub config uploadpack.allowanysha1inwant 1 &&
test_config_global protocol.file.allow always &&
@@ -270,6 +270,12 @@ test_expect_success 'partial clone with transfer.fsckobjects=1 works with submod
test_when_finished rm -rf dst
'
+test_expect_success 'lazily fetched .gitmodules works' '
+ git clone --filter="blob:none" --no-checkout "file://$(pwd)/src_with_sub" dst &&
+ git -C dst fetch &&
+ test_when_finished rm -rf dst
+'
+
test_expect_success 'partial clone with transfer.fsckobjects=1 uses index-pack --fsck-objects' '
git init src &&
test_commit -C src x &&
@@ -644,6 +650,49 @@ test_expect_success 'repack does not loosen promisor objects' '
grep "loosen_unused_packed_objects/loosened:0" trace
'
+test_expect_success 'lazy-fetch in submodule succeeds' '
+ # setup
+ test_config_global protocol.file.allow always &&
+
+ test_when_finished "rm -rf src-sub" &&
+ git init src-sub &&
+ git -C src-sub config uploadpack.allowfilter 1 &&
+ git -C src-sub config uploadpack.allowanysha1inwant 1 &&
+
+ # This blob must be missing in the subsequent commit.
+ echo foo >src-sub/file &&
+ git -C src-sub add file &&
+ git -C src-sub commit -m "submodule one" &&
+ SUB_ONE=$(git -C src-sub rev-parse HEAD) &&
+
+ echo bar >src-sub/file &&
+ git -C src-sub add file &&
+ git -C src-sub commit -m "submodule two" &&
+ SUB_TWO=$(git -C src-sub rev-parse HEAD) &&
+
+ test_when_finished "rm -rf src-super" &&
+ git init src-super &&
+ git -C src-super config uploadpack.allowfilter 1 &&
+ git -C src-super config uploadpack.allowanysha1inwant 1 &&
+ git -C src-super submodule add ../src-sub src-sub &&
+
+ git -C src-super/src-sub checkout $SUB_ONE &&
+ git -C src-super add src-sub &&
+ git -C src-super commit -m "superproject one" &&
+
+ git -C src-super/src-sub checkout $SUB_TWO &&
+ git -C src-super add src-sub &&
+ git -C src-super commit -m "superproject two" &&
+
+ # the fetch
+ test_when_finished "rm -rf client" &&
+ git clone --filter=blob:none --also-filter-submodules \
+ --recurse-submodules "file://$(pwd)/src-super" client &&
+
+ # Trigger lazy-fetch from the superproject
+ git -C client restore --recurse-submodules --source=HEAD^ :/
+'
+
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
diff --git a/t/t5617-clone-submodules-remote.sh b/t/t5617-clone-submodules-remote.sh
index 6884338249..5a4d7936a7 100755
--- a/t/t5617-clone-submodules-remote.sh
+++ b/t/t5617-clone-submodules-remote.sh
@@ -5,6 +5,7 @@ test_description='Test cloning repos with submodules using remote-tracking branc
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
pwd=$(pwd)
diff --git a/t/t5618-alternate-refs.sh b/t/t5618-alternate-refs.sh
index 3353216f09..f905db0a3f 100755
--- a/t/t5618-alternate-refs.sh
+++ b/t/t5618-alternate-refs.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test handling of --alternate-refs traversal'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Avoid test_commit because we want a specific and known set of refs:
diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh
index 6c8d4c6cf1..a73b4d4ff6 100755
--- a/t/t5700-protocol-v1.sh
+++ b/t/t5700-protocol-v1.sh
@@ -244,15 +244,28 @@ test_expect_success 'push with ssh:// using protocol v1' '
grep "push< version 1" log
'
+test_expect_success 'clone propagates object-format from empty repo' '
+ test_when_finished "rm -fr src256 dst256" &&
+
+ echo sha256 >expect &&
+ git init --object-format=sha256 src256 &&
+ git clone --no-local src256 dst256 &&
+ git -C dst256 rev-parse --show-object-format >actual &&
+
+ test_cmp expect actual
+'
+
# Test protocol v1 with 'http://' transport
#
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
-test_expect_success 'create repo to be served by http:// transport' '
+test_expect_success 'create repos to be served by http:// transport' '
git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" config http.receivepack true &&
- test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one
+ test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one &&
+ git init --object-format=sha256 "$HTTPD_DOCUMENT_ROOT_PATH/sha256" &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/sha256" config http.receivepack true
'
test_expect_success 'clone with http:// using protocol v1' '
@@ -269,6 +282,20 @@ test_expect_success 'clone with http:// using protocol v1' '
grep "git< version 1" log
'
+test_expect_success 'clone with http:// using protocol v1 with empty SHA-256 repo' '
+ GIT_TRACE_PACKET=1 GIT_TRACE_CURL=1 git -c protocol.version=1 \
+ clone "$HTTPD_URL/smart/sha256" sha256 2>log &&
+
+ echo sha256 >expect &&
+ git -C sha256 rev-parse --show-object-format >actual &&
+ test_cmp expect actual &&
+
+ # Client requested to use protocol v1
+ grep "Git-Protocol: version=1" log &&
+ # Server responded using protocol v1
+ grep "git< version 1" log
+'
+
test_expect_success 'fetch with http:// using protocol v1' '
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two &&
diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh
index 1896f671cb..f21e5e9d33 100755
--- a/t/t5701-git-serve.sh
+++ b/t/t5701-git-serve.sh
@@ -13,7 +13,7 @@ test_expect_success 'test capability advertisement' '
wrong_algo sha1:sha256
wrong_algo sha256:sha1
EOF
- cat >expect <<-EOF &&
+ cat >expect.base <<-EOF &&
version 2
agent=git/$(git version | cut -d" " -f3)
ls-refs=unborn
@@ -21,8 +21,11 @@ test_expect_success 'test capability advertisement' '
server-option
object-format=$(test_oid algo)
object-info
+ EOF
+ cat >expect.trailer <<-EOF &&
0000
EOF
+ cat expect.base expect.trailer >expect &&
GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \
--advertise-capabilities >out &&
@@ -342,4 +345,39 @@ test_expect_success 'basics of object-info' '
test_cmp expect actual
'
+test_expect_success 'test capability advertisement with uploadpack.advertiseBundleURIs' '
+ test_config uploadpack.advertiseBundleURIs true &&
+
+ cat >expect.extra <<-EOF &&
+ bundle-uri
+ EOF
+ cat expect.base \
+ expect.extra \
+ expect.trailer >expect &&
+
+ GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \
+ --advertise-capabilities >out &&
+ test-tool pkt-line unpack <out >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'basics of bundle-uri: dies if not enabled' '
+ test-tool pkt-line pack >in <<-EOF &&
+ command=bundle-uri
+ 0000
+ EOF
+
+ cat >err.expect <<-\EOF &&
+ fatal: invalid command '"'"'bundle-uri'"'"'
+ EOF
+
+ cat >expect <<-\EOF &&
+ ERR serve: invalid command '"'"'bundle-uri'"'"'
+ EOF
+
+ test_must_fail test-tool serve-v2 --stateless-rpc <in >out 2>err.actual &&
+ test_cmp err.expect err.actual &&
+ test_must_be_empty out
+'
+
test_done
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 5d42a355a8..6af5c2062f 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -269,6 +269,17 @@ test_expect_success 'clone propagates unborn HEAD from non-empty repo' '
grep "warning: remote HEAD refers to nonexistent ref" stderr
'
+test_expect_success 'clone propagates object-format from empty repo' '
+ test_when_finished "rm -fr src256 dst256" &&
+
+ echo sha256 >expect &&
+ git init --object-format=sha256 src256 &&
+ git clone src256 dst256 &&
+ git -C dst256 rev-parse --show-object-format >actual &&
+
+ test_cmp expect actual
+'
+
test_expect_success 'bare clone propagates unborn HEAD from non-empty repo' '
test_when_finished "rm -rf file_unborn_parent file_unborn_child.git" &&
@@ -728,6 +739,33 @@ test_expect_success 'file:// --negotiate-only with protocol v0' '
test_i18ngrep "negotiate-only requires protocol v2" err
'
+test_expect_success 'push with custom path does not request v2' '
+ rm -f env.trace &&
+ git -C client push \
+ --receive-pack="env >../env.trace; git-receive-pack" \
+ origin HEAD:refs/heads/custom-push-test &&
+ test_path_is_file env.trace &&
+ ! grep ^GIT_PROTOCOL env.trace
+'
+
+test_expect_success 'fetch with custom path does request v2' '
+ rm -f env.trace &&
+ git -C client fetch \
+ --upload-pack="env >../env.trace; git-upload-pack" \
+ origin HEAD &&
+ grep ^GIT_PROTOCOL=version=2 env.trace
+'
+
+test_expect_success 'archive with custom path does not request v2' '
+ rm -f env.trace &&
+ git -C client archive \
+ --exec="env >../env.trace; git-upload-archive" \
+ --remote=origin \
+ HEAD >/dev/null &&
+ test_path_is_file env.trace &&
+ ! grep ^GIT_PROTOCOL env.trace
+'
+
# Test protocol v2 with 'http://' transport
#
. "$TEST_DIRECTORY"/lib-httpd.sh
@@ -1001,7 +1039,7 @@ test_expect_success 'part of packfile response provided as URI' '
do
git verify-pack --object-format=$(test_oid algo) --verbose $idx >out &&
{
- grep "^[0-9a-f]\{16,\} " out || :
+ grep -E "^[0-9a-f]{16,} " out || :
} >out.objectlist &&
if test_line_count = 1 out.objectlist
then
@@ -1114,7 +1152,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object'
This commit object intentionally broken
EOF
- BOGUS=$(git -C "$P" hash-object -t commit -w --stdin <bogus-commit) &&
+ BOGUS=$(git -C "$P" hash-object -t commit -w --stdin --literally <bogus-commit) &&
git -C "$P" branch bogus-branch "$BOGUS" &&
echo my-blob >"$P/my-blob" &&
diff --git a/t/t5705-session-id-in-capabilities.sh b/t/t5705-session-id-in-capabilities.sh
index ed38c76c29..b8a722ec27 100755
--- a/t/t5705-session-id-in-capabilities.sh
+++ b/t/t5705-session-id-in-capabilities.sh
@@ -2,6 +2,7 @@
test_description='session ID in capabilities'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
REPO="$(pwd)/repo"
diff --git a/t/t5730-protocol-v2-bundle-uri-file.sh b/t/t5730-protocol-v2-bundle-uri-file.sh
new file mode 100755
index 0000000000..37bdb725bc
--- /dev/null
+++ b/t/t5730-protocol-v2-bundle-uri-file.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+test_description="Test bundle-uri with protocol v2 and 'file://' transport"
+
+TEST_NO_CREATE_REPO=1
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+# Test protocol v2 with 'file://' transport
+#
+BUNDLE_URI_PROTOCOL=file
+. "$TEST_DIRECTORY"/lib-bundle-uri-protocol.sh
+
+test_done
diff --git a/t/t5731-protocol-v2-bundle-uri-git.sh b/t/t5731-protocol-v2-bundle-uri-git.sh
new file mode 100755
index 0000000000..8add1b37ab
--- /dev/null
+++ b/t/t5731-protocol-v2-bundle-uri-git.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+test_description="Test bundle-uri with protocol v2 and 'git://' transport"
+
+TEST_NO_CREATE_REPO=1
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+# Test protocol v2 with 'git://' transport
+#
+BUNDLE_URI_PROTOCOL=git
+. "$TEST_DIRECTORY"/lib-bundle-uri-protocol.sh
+
+test_done
diff --git a/t/t5732-protocol-v2-bundle-uri-http.sh b/t/t5732-protocol-v2-bundle-uri-http.sh
new file mode 100755
index 0000000000..129daa0226
--- /dev/null
+++ b/t/t5732-protocol-v2-bundle-uri-http.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+test_description="Test bundle-uri with protocol v2 and 'http://' transport"
+
+TEST_NO_CREATE_REPO=1
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+# Test protocol v2 with 'http://' transport
+#
+BUNDLE_URI_PROTOCOL=http
+. "$TEST_DIRECTORY"/lib-bundle-uri-protocol.sh
+
+test_done
diff --git a/t/t5750-bundle-uri-parse.sh b/t/t5750-bundle-uri-parse.sh
new file mode 100755
index 0000000000..81bdf58b94
--- /dev/null
+++ b/t/t5750-bundle-uri-parse.sh
@@ -0,0 +1,290 @@
+#!/bin/sh
+
+test_description="Test bundle-uri bundle_uri_parse_line()"
+
+TEST_NO_CREATE_REPO=1
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success 'bundle_uri_parse_line() just URIs' '
+ cat >in <<-\EOF &&
+ bundle.one.uri=http://example.com/bundle.bdl
+ bundle.two.uri=https://example.com/bundle.bdl
+ bundle.three.uri=file:///usr/share/git/bundle.bdl
+ EOF
+
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = http://example.com/bundle.bdl
+ [bundle "two"]
+ uri = https://example.com/bundle.bdl
+ [bundle "three"]
+ uri = file:///usr/share/git/bundle.bdl
+ EOF
+
+ test-tool bundle-uri parse-key-values in >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success 'bundle_uri_parse_line(): relative URIs' '
+ cat >in <<-\EOF &&
+ bundle.one.uri=bundle.bdl
+ bundle.two.uri=../bundle.bdl
+ bundle.three.uri=sub/dir/bundle.bdl
+ EOF
+
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = <uri>/bundle.bdl
+ [bundle "two"]
+ uri = bundle.bdl
+ [bundle "three"]
+ uri = <uri>/sub/dir/bundle.bdl
+ EOF
+
+ test-tool bundle-uri parse-key-values in >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success 'bundle_uri_parse_line(): relative URIs and parent paths' '
+ cat >in <<-\EOF &&
+ bundle.one.uri=bundle.bdl
+ bundle.two.uri=../bundle.bdl
+ bundle.three.uri=../../bundle.bdl
+ EOF
+
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = <uri>/bundle.bdl
+ [bundle "two"]
+ uri = bundle.bdl
+ [bundle "three"]
+ uri = <uri>/../bundle.bdl
+ EOF
+
+ # TODO: We would prefer if parsing a bundle list would not cause
+ # a die() and instead would give a warning and allow the rest of
+ # a Git command to continue. This test_must_fail is necessary for
+ # now until the interface for relative_url() allows for reporting
+ # an error instead of die()ing.
+ test_must_fail test-tool bundle-uri parse-key-values in >actual 2>err &&
+ grep "fatal: cannot strip one component off url" err
+'
+
+test_expect_success 'bundle_uri_parse_line() parsing edge cases: empty key or value' '
+ cat >in <<-\EOF &&
+ =bogus-value
+ bogus-key=
+ EOF
+
+ cat >err.expect <<-EOF &&
+ error: bundle-uri: line has empty key or value
+ error: bad line: '\''=bogus-value'\''
+ error: bundle-uri: line has empty key or value
+ error: bad line: '\''bogus-key='\''
+ EOF
+
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ EOF
+
+ test_must_fail test-tool bundle-uri parse-key-values in >actual 2>err &&
+ test_cmp err.expect err &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success 'bundle_uri_parse_line() parsing edge cases: empty lines' '
+ cat >in <<-\EOF &&
+ bundle.one.uri=http://example.com/bundle.bdl
+
+ bundle.two.uri=https://example.com/bundle.bdl
+
+ bundle.three.uri=file:///usr/share/git/bundle.bdl
+ EOF
+
+ cat >err.expect <<-\EOF &&
+ error: bundle-uri: got an empty line
+ error: bad line: '\'''\''
+ error: bundle-uri: got an empty line
+ error: bad line: '\'''\''
+ EOF
+
+ # We fail, but try to continue parsing regardless
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = http://example.com/bundle.bdl
+ [bundle "two"]
+ uri = https://example.com/bundle.bdl
+ [bundle "three"]
+ uri = file:///usr/share/git/bundle.bdl
+ EOF
+
+ test_must_fail test-tool bundle-uri parse-key-values in >actual 2>err &&
+ test_cmp err.expect err &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success 'bundle_uri_parse_line() parsing edge cases: duplicate lines' '
+ cat >in <<-\EOF &&
+ bundle.one.uri=http://example.com/bundle.bdl
+ bundle.two.uri=https://example.com/bundle.bdl
+ bundle.one.uri=https://example.com/bundle-2.bdl
+ bundle.three.uri=file:///usr/share/git/bundle.bdl
+ EOF
+
+ cat >err.expect <<-\EOF &&
+ error: bad line: '\''bundle.one.uri=https://example.com/bundle-2.bdl'\''
+ EOF
+
+ # We fail, but try to continue parsing regardless
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = http://example.com/bundle.bdl
+ [bundle "two"]
+ uri = https://example.com/bundle.bdl
+ [bundle "three"]
+ uri = file:///usr/share/git/bundle.bdl
+ EOF
+
+ test_must_fail test-tool bundle-uri parse-key-values in >actual 2>err &&
+ test_cmp err.expect err &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success 'parse config format: just URIs' '
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = http://example.com/bundle.bdl
+ [bundle "two"]
+ uri = https://example.com/bundle.bdl
+ [bundle "three"]
+ uri = file:///usr/share/git/bundle.bdl
+ EOF
+
+ test-tool bundle-uri parse-config expect >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success 'parse config format: relative URIs' '
+ cat >in <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = bundle.bdl
+ [bundle "two"]
+ uri = ../bundle.bdl
+ [bundle "three"]
+ uri = sub/dir/bundle.bdl
+ EOF
+
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = <uri>/bundle.bdl
+ [bundle "two"]
+ uri = bundle.bdl
+ [bundle "three"]
+ uri = <uri>/sub/dir/bundle.bdl
+ EOF
+
+ test-tool bundle-uri parse-config in >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success 'parse config format edge cases: empty key or value' '
+ cat >in1 <<-\EOF &&
+ = bogus-value
+ EOF
+
+ cat >err1 <<-EOF &&
+ error: bad config line 1 in file in1
+ EOF
+
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ EOF
+
+ test_must_fail test-tool bundle-uri parse-config in1 >actual 2>err &&
+ test_cmp err1 err &&
+ test_cmp_config_output expect actual &&
+
+ cat >in2 <<-\EOF &&
+ bogus-key =
+ EOF
+
+ cat >err2 <<-EOF &&
+ error: bad config line 1 in file in2
+ EOF
+
+ test_must_fail test-tool bundle-uri parse-config in2 >actual 2>err &&
+ test_cmp err2 err &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success 'parse config format: creationToken heuristic' '
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+ [bundle "one"]
+ uri = http://example.com/bundle.bdl
+ creationToken = 123456
+ [bundle "two"]
+ uri = https://example.com/bundle.bdl
+ creationToken = 12345678901234567890
+ [bundle "three"]
+ uri = file:///usr/share/git/bundle.bdl
+ creationToken = 1
+ EOF
+
+ test-tool bundle-uri parse-config expect >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp_config_output expect actual
+'
+
+test_expect_success 'parse config format edge cases: creationToken heuristic' '
+ cat >expect <<-\EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+ [bundle "one"]
+ uri = http://example.com/bundle.bdl
+ creationToken = bogus
+ EOF
+
+ test-tool bundle-uri parse-config expect >actual 2>err &&
+ grep "could not parse bundle list key creationToken with value '\''bogus'\''" err
+'
+
+test_done
diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh
index c1ef99b85c..862610256f 100755
--- a/t/t5810-proto-disable-local.sh
+++ b/t/t5810-proto-disable-local.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test disabling of local paths in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-proto-disable.sh"
diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh
index 3f084ee306..2e975dc70e 100755
--- a/t/t5813-proto-disable-ssh.sh
+++ b/t/t5813-proto-disable-ssh.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test disabling of git-over-ssh in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-proto-disable.sh"
diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh
index 1f7d7dd20c..5cf2cee74d 100755
--- a/t/t6003-rev-list-topo-order.sh
+++ b/t/t6003-rev-list-topo-order.sh
@@ -326,19 +326,16 @@ a2
c3
EOF
-#
-# this test fails on --topo-order - a fix is required
-#
-#test_output_expect_success '--max-age=c3, --topo-order' "git rev-list --topo-order --max-age=$(commit_date c3) l5" <<EOF
-#l5
-#l4
-#l3
-#a4
-#c3
-#b4
-#a3
-#a2
-#EOF
+test_output_expect_success '--max-age=c3, --topo-order' "git rev-list --topo-order --max-age=$(commit_date c3) l5" <<EOF
+l5
+l4
+l3
+a4
+c3
+b4
+a3
+a2
+EOF
test_output_expect_success 'one specified head reachable from another a4, c3, --topo-order' "list_duplicates git rev-list --topo-order a4 c3" <<EOF
EOF
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 41d0ca00b1..573eb97a0f 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -493,7 +493,7 @@ test_expect_success 'empty email' '
test_tick &&
C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) &&
A=$(git show --pretty=format:%an,%ae,%ad%n -s $C) &&
- verbose test "$A" = "$GIT_AUTHOR_NAME,,Thu Apr 7 15:14:13 2005 -0700"
+ test "$A" = "$GIT_AUTHOR_NAME,,Thu Apr 7 15:14:13 2005 -0700"
'
test_expect_success 'del LF before empty (1)' '
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
index bad02cf5b8..b2e422cf0f 100755
--- a/t/t6011-rev-list-with-bad-commit.sh
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -2,6 +2,7 @@
test_description='git rev-list should notice bad commits'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Note:
diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh
index c9bedd29cb..16b8bd1d09 100755
--- a/t/t6014-rev-list-all.sh
+++ b/t/t6014-rev-list-all.sh
@@ -2,6 +2,7 @@
test_description='--all includes detached HEADs'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
diff --git a/t/t6017-rev-list-stdin.sh b/t/t6017-rev-list-stdin.sh
index 05162512a0..a57f1ae2ba 100755
--- a/t/t6017-rev-list-stdin.sh
+++ b/t/t6017-rev-list-stdin.sh
@@ -48,7 +48,9 @@ test_expect_success setup '
git add file-$i &&
test_tick &&
git commit -m side-$i || exit
- done
+ done &&
+
+ git update-ref refs/heads/-dashed-branch HEAD
)
'
@@ -60,6 +62,12 @@ check side-1 ^side-7 -- file-2
check side-3 ^side-4 -- file-3
check side-3 ^side-2
check side-3 ^side-2 -- file-1
+check --all
+check --all --not --branches
+check --glob=refs/heads
+check --glob=refs/heads --
+check --glob=refs/heads -- file-1
+check --end-of-options -dashed-branch
test_expect_success 'not only --stdin' '
cat >expect <<-EOF &&
@@ -78,4 +86,45 @@ test_expect_success 'not only --stdin' '
test_cmp expect actual
'
+test_expect_success 'pseudo-opt with missing value' '
+ cat >input <<-EOF &&
+ --glob
+ refs/heads
+ EOF
+
+ cat >expect <<-EOF &&
+ fatal: Option ${SQ}--glob${SQ} requires a value
+ EOF
+
+ test_must_fail git rev-list --stdin <input 2>error &&
+ test_cmp expect error
+'
+
+test_expect_success 'pseudo-opt with invalid value' '
+ cat >input <<-EOF &&
+ --no-walk=garbage
+ EOF
+
+ cat >expect <<-EOF &&
+ error: invalid argument to --no-walk
+ fatal: invalid option ${SQ}--no-walk=garbage${SQ} in --stdin mode
+ EOF
+
+ test_must_fail git rev-list --stdin <input 2>error &&
+ test_cmp expect error
+'
+
+test_expect_success 'unknown option without --end-of-options' '
+ cat >input <<-EOF &&
+ -dashed-branch
+ EOF
+
+ cat >expect <<-EOF &&
+ fatal: invalid option ${SQ}-dashed-branch${SQ} in --stdin mode
+ EOF
+
+ test_must_fail git rev-list --stdin <input 2>error &&
+ test_cmp expect error
+'
+
test_done
diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh
index e1abc5c2b3..67d523d405 100755
--- a/t/t6018-rev-list-glob.sh
+++ b/t/t6018-rev-list-glob.sh
@@ -187,6 +187,46 @@ test_expect_success 'rev-parse --exclude=ref with --remotes=glob' '
compare rev-parse "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two"
'
+for section in fetch receive uploadpack
+do
+ test_expect_success "rev-parse --exclude-hidden=$section with --all" '
+ compare "-c transfer.hideRefs=refs/remotes/ rev-parse" "--branches --tags" "--exclude-hidden=$section --all"
+ '
+
+ test_expect_success "rev-parse --exclude-hidden=$section with --all" '
+ compare "-c transfer.hideRefs=refs/heads/subspace/ rev-parse" "--exclude=refs/heads/subspace/* --all" "--exclude-hidden=$section --all"
+ '
+
+ test_expect_success "rev-parse --exclude-hidden=$section with --glob" '
+ compare "-c transfer.hideRefs=refs/heads/subspace/ rev-parse" "--exclude=refs/heads/subspace/* --glob=refs/heads/*" "--exclude-hidden=$section --glob=refs/heads/*"
+ '
+
+ test_expect_success "rev-parse --exclude-hidden=$section can be passed once per pseudo-ref" '
+ compare "-c transfer.hideRefs=refs/remotes/ rev-parse" "--branches --tags --branches --tags" "--exclude-hidden=$section --all --exclude-hidden=$section --all"
+ '
+
+ test_expect_success "rev-parse --exclude-hidden=$section can only be passed once per pseudo-ref" '
+ echo "fatal: --exclude-hidden= passed more than once" >expected &&
+ test_must_fail git rev-parse --exclude-hidden=$section --exclude-hidden=$section 2>err &&
+ test_cmp expected err
+ '
+
+ for pseudoopt in branches tags remotes
+ do
+ test_expect_success "rev-parse --exclude-hidden=$section fails with --$pseudoopt" '
+ echo "error: --exclude-hidden cannot be used together with --$pseudoopt" >expected &&
+ test_must_fail git rev-parse --exclude-hidden=$section --$pseudoopt 2>err &&
+ test_cmp expected err
+ '
+
+ test_expect_success "rev-parse --exclude-hidden=$section fails with --$pseudoopt=pattern" '
+ echo "error: --exclude-hidden cannot be used together with --$pseudoopt" >expected &&
+ test_must_fail git rev-parse --exclude-hidden=$section --$pseudoopt=pattern 2>err &&
+ test_cmp expected err
+ '
+ done
+done
+
test_expect_success 'rev-list --exclude=glob with --branches=glob' '
compare rev-list "--exclude=subspace-* --branches=sub*" "subspace/one subspace/two"
'
diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
index 833205125a..3e6bcbf30c 100755
--- a/t/t6020-bundle-misc.sh
+++ b/t/t6020-bundle-misc.sh
@@ -10,6 +10,14 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-bundle.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
+
+for cmd in create verify list-heads unbundle
+do
+ test_expect_success "usage: git bundle $cmd needs an argument" '
+ test_expect_code 129 git bundle $cmd
+ '
+done
# Create a commit or tag and set the variable with the object ID.
test_commit_setvar () {
@@ -559,4 +567,88 @@ test_expect_success 'cloning from filtered bundle has useful error' '
grep "cannot clone from filtered bundle" err
'
+test_expect_success 'verify catches unreachable, broken prerequisites' '
+ test_when_finished rm -rf clone-from clone-to &&
+ git init clone-from &&
+ (
+ cd clone-from &&
+ git checkout -b base &&
+ test_commit A &&
+ git checkout -b tip &&
+ git commit --allow-empty -m "will drop by shallow" &&
+ git commit --allow-empty -m "will keep by shallow" &&
+ git commit --allow-empty -m "for bundle, not clone" &&
+ git bundle create tip.bundle tip~1..tip &&
+ git reset --hard HEAD~1 &&
+ git checkout base
+ ) &&
+ BAD_OID=$(git -C clone-from rev-parse tip~1) &&
+ TIP_OID=$(git -C clone-from rev-parse tip) &&
+ git clone --depth=1 --no-single-branch \
+ "file://$(pwd)/clone-from" clone-to &&
+ (
+ cd clone-to &&
+
+ # Set up broken history by removing shallow markers
+ git update-ref -d refs/remotes/origin/tip &&
+ rm .git/shallow &&
+
+ # Verify should fail
+ test_must_fail git bundle verify \
+ ../clone-from/tip.bundle 2>err &&
+ grep "some prerequisite commits .* are not connected" err &&
+ test_line_count = 1 err &&
+
+ # Unbundling should fail
+ test_must_fail git bundle unbundle \
+ ../clone-from/tip.bundle 2>err &&
+ grep "some prerequisite commits .* are not connected" err &&
+ test_line_count = 1 err
+ )
+'
+
+test_expect_success 'bundle progress includes write phase' '
+ GIT_PROGRESS_DELAY=0 \
+ git bundle create --progress out.bundle --all 2>err &&
+ grep 'Writing' err
+'
+
+test_expect_success TTY 'create --quiet disables all bundle progress' '
+ test_terminal env GIT_PROGRESS_DELAY=0 \
+ git bundle create --quiet out.bundle --all 2>err &&
+ test_must_be_empty err
+'
+
+test_expect_success 'bundle progress with --no-quiet' '
+ GIT_PROGRESS_DELAY=0 \
+ git bundle create --no-quiet out.bundle --all 2>err &&
+ grep "%" err
+'
+
+test_expect_success 'read bundle over stdin' '
+ git bundle create some.bundle HEAD &&
+
+ git bundle verify - <some.bundle 2>err &&
+ grep "<stdin> is okay" err &&
+
+ git bundle list-heads some.bundle >expect &&
+ git bundle list-heads - <some.bundle >actual &&
+ test_cmp expect actual &&
+
+ git bundle unbundle some.bundle >expect &&
+ git bundle unbundle - <some.bundle >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'send a bundle to standard output' '
+ git bundle create - --all HEAD >bundle-one &&
+ mkdir -p down &&
+ git -C down bundle create - --all HEAD >bundle-two &&
+ git bundle verify bundle-one &&
+ git bundle verify bundle-two &&
+ git ls-remote bundle-one >expect &&
+ git ls-remote bundle-two >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
new file mode 100755
index 0000000000..1a9d37e638
--- /dev/null
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -0,0 +1,164 @@
+#!/bin/sh
+
+test_description='git rev-list --exclude-hidden test'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit_bulk --id=commit --ref=refs/heads/branch 1 &&
+ COMMIT=$(git rev-parse refs/heads/branch) &&
+ test_commit_bulk --id=tag --ref=refs/tags/lightweight 1 &&
+ TAG=$(git rev-parse refs/tags/lightweight) &&
+ test_commit_bulk --id=hidden --ref=refs/hidden/commit 1 &&
+ HIDDEN=$(git rev-parse refs/hidden/commit) &&
+ test_commit_bulk --id=namespace --ref=refs/namespaces/namespace/refs/namespaced/commit 1 &&
+ NAMESPACE=$(git rev-parse refs/namespaces/namespace/refs/namespaced/commit)
+'
+
+test_expect_success 'invalid section' '
+ echo "fatal: unsupported section for hidden refs: unsupported" >expected &&
+ test_must_fail git rev-list --exclude-hidden=unsupported 2>err &&
+ test_cmp expected err
+'
+
+for section in fetch receive uploadpack
+do
+ test_expect_success "$section: passed multiple times" '
+ echo "fatal: --exclude-hidden= passed more than once" >expected &&
+ test_must_fail git rev-list --exclude-hidden=$section --exclude-hidden=$section 2>err &&
+ test_cmp expected err
+ '
+
+ test_expect_success "$section: without hiddenRefs" '
+ git rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $HIDDEN
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: hidden via transfer.hideRefs" '
+ git -c transfer.hideRefs=refs/hidden/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: hidden via $section.hideRefs" '
+ git -c $section.hideRefs=refs/hidden/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: respects both transfer.hideRefs and $section.hideRefs" '
+ git -c transfer.hideRefs=refs/tags/ -c $section.hideRefs=refs/hidden/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: negation without hidden refs marks everything as uninteresting" '
+ git rev-list --all --exclude-hidden=$section --not --all >out &&
+ test_must_be_empty out
+ '
+
+ test_expect_success "$section: negation with hidden refs marks them as interesting" '
+ git -c transfer.hideRefs=refs/hidden/ rev-list --all --exclude-hidden=$section --not --all >out &&
+ cat >expected <<-EOF &&
+ $HIDDEN
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: hidden refs and excludes work together" '
+ git -c transfer.hideRefs=refs/hidden/ rev-list --exclude=refs/tags/* --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: excluded hidden refs get reset" '
+ git -c transfer.hideRefs=refs/ rev-list --exclude-hidden=$section --all --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $HIDDEN
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: excluded hidden refs can be used with multiple pseudo-refs" '
+ git -c transfer.hideRefs=refs/ rev-list --exclude-hidden=$section --all --exclude-hidden=$section --all >out &&
+ test_must_be_empty out
+ '
+
+ test_expect_success "$section: works with --glob" '
+ git -c transfer.hideRefs=refs/hidden/ rev-list --exclude-hidden=$section --glob=refs/h* >out &&
+ cat >expected <<-EOF &&
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: operates on stripped refs by default" '
+ GIT_NAMESPACE=namespace git -c transfer.hideRefs=refs/namespaced/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $HIDDEN
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: does not hide namespace by default" '
+ GIT_NAMESPACE=namespace git -c transfer.hideRefs=refs/namespaces/namespace/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $NAMESPACE
+ $HIDDEN
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ test_expect_success "$section: can operate on unstripped refs" '
+ GIT_NAMESPACE=namespace git -c transfer.hideRefs=^refs/namespaces/namespace/ rev-list --exclude-hidden=$section --all >out &&
+ cat >expected <<-EOF &&
+ $HIDDEN
+ $TAG
+ $COMMIT
+ EOF
+ test_cmp expected out
+ '
+
+ for pseudoopt in remotes branches tags
+ do
+ test_expect_success "$section: fails with --$pseudoopt" '
+ test_must_fail git rev-list --exclude-hidden=$section --$pseudoopt 2>err &&
+ test_i18ngrep "error: --exclude-hidden cannot be used together with --$pseudoopt" err
+ '
+
+ test_expect_success "$section: fails with --$pseudoopt=pattern" '
+ test_must_fail git rev-list --exclude-hidden=$section --$pseudoopt=pattern 2>err &&
+ test_i18ngrep "error: --exclude-hidden cannot be used together with --$pseudoopt" err
+ '
+ done
+done
+
+test_done
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 83931d482f..fb01bd6abc 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -34,6 +34,36 @@ HASH2=
HASH3=
HASH4=
+test_bisect_usage () {
+ local code="$1" &&
+ shift &&
+ cat >expect &&
+ test_expect_code $code "$@" >out 2>actual &&
+ test_must_be_empty out &&
+ test_cmp expect actual
+}
+
+test_expect_success 'bisect usage' "
+ test_bisect_usage 1 git bisect reset extra1 extra2 <<-\EOF &&
+ error: 'git bisect reset' requires either no argument or a commit
+ EOF
+ test_bisect_usage 1 git bisect terms extra1 extra2 <<-\EOF &&
+ error: 'git bisect terms' requires 0 or 1 argument
+ EOF
+ test_bisect_usage 1 git bisect next extra1 <<-\EOF &&
+ error: 'git bisect next' requires 0 arguments
+ EOF
+ test_bisect_usage 1 git bisect log extra1 <<-\EOF &&
+ error: We are not bisecting.
+ EOF
+ test_bisect_usage 1 git bisect replay <<-\EOF &&
+ error: no logfile given
+ EOF
+ test_bisect_usage 1 git bisect run <<-\EOF
+ error: 'git bisect run' failed: no command provided.
+ EOF
+"
+
test_expect_success 'set up basic repo with 1 file (hello) and 4 commits' '
add_line_into_file "1: Hello World" hello &&
HASH1=$(git rev-parse --verify HEAD) &&
@@ -92,6 +122,29 @@ test_expect_success 'bisect start without -- takes unknown arg as pathspec' '
grep bar ".git/BISECT_NAMES"
'
+test_expect_success 'bisect reset: back in a branch checked out also elsewhere' '
+ echo "shared" > branch.expect &&
+ test_bisect_reset() {
+ git -C $1 bisect start &&
+ git -C $1 bisect good $HASH1 &&
+ git -C $1 bisect bad $HASH3 &&
+ git -C $1 bisect reset &&
+ git -C $1 branch --show-current > branch.output &&
+ cmp branch.expect branch.output
+ } &&
+ test_when_finished "
+ git worktree remove wt1 &&
+ git worktree remove wt2 &&
+ git branch -d shared
+ " &&
+ git worktree add wt1 -b shared &&
+ git worktree add wt2 -f shared &&
+ # we test in both worktrees to ensure that works
+ # as expected with "first" and "next" worktrees
+ test_bisect_reset wt1 &&
+ test_bisect_reset wt2
+'
+
test_expect_success 'bisect reset: back in the main branch' '
git bisect reset &&
echo "* main" > branch.expect &&
@@ -252,6 +305,124 @@ test_expect_success 'bisect skip: with commit both bad and skipped' '
grep $HASH4 my_bisect_log.txt
'
+test_bisect_run_args () {
+ test_when_finished "rm -f run.sh actual" &&
+ >actual &&
+ cat >expect.args &&
+ cat <&6 >expect.out &&
+ cat <&7 >expect.err &&
+ write_script run.sh <<-\EOF &&
+ while test $# != 0
+ do
+ echo "<$1>" &&
+ shift
+ done >actual.args
+ EOF
+
+ test_when_finished "git bisect reset" &&
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ git bisect run ./run.sh $@ >actual.out.raw 2>actual.err &&
+ # Prune just the log output
+ sed -n \
+ -e '/^Author:/d' \
+ -e '/^Date:/d' \
+ -e '/^$/d' \
+ -e '/^commit /d' \
+ -e '/^ /d' \
+ -e 'p' \
+ <actual.out.raw >actual.out &&
+ test_cmp expect.out actual.out &&
+ test_cmp expect.err actual.err &&
+ test_cmp expect.args actual.args
+}
+
+test_expect_success 'git bisect run: args, stdout and stderr with no arguments' "
+ test_bisect_run_args <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
+ EOF_ARGS
+ running './run.sh'
+ $HASH4 is the first bad commit
+ bisect found first bad commit
+ EOF_OUT
+ EOF_ERR
+"
+
+test_expect_success 'git bisect run: args, stdout and stderr: "--" argument' "
+ test_bisect_run_args -- <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
+ <-->
+ EOF_ARGS
+ running './run.sh' '--'
+ $HASH4 is the first bad commit
+ bisect found first bad commit
+ EOF_OUT
+ EOF_ERR
+"
+
+test_expect_success 'git bisect run: args, stdout and stderr: "--log foo --no-log bar" arguments' "
+ test_bisect_run_args --log foo --no-log bar <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
+ <--log>
+ <foo>
+ <--no-log>
+ <bar>
+ EOF_ARGS
+ running './run.sh' '--log' 'foo' '--no-log' 'bar'
+ $HASH4 is the first bad commit
+ bisect found first bad commit
+ EOF_OUT
+ EOF_ERR
+"
+
+test_expect_success 'git bisect run: args, stdout and stderr: "--bisect-start" argument' "
+ test_bisect_run_args --bisect-start <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
+ <--bisect-start>
+ EOF_ARGS
+ running './run.sh' '--bisect-start'
+ $HASH4 is the first bad commit
+ bisect found first bad commit
+ EOF_OUT
+ EOF_ERR
+"
+
+test_expect_success 'git bisect run: negative exit code' "
+ write_script fail.sh <<-'EOF' &&
+ exit 255
+ EOF
+ cat <<-'EOF' >expect &&
+ bisect run failed: exit code -1 from './fail.sh' is < 0 or >= 128
+ EOF
+ test_when_finished 'git bisect reset' &&
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ ! git bisect run ./fail.sh 2>err &&
+ sed -En 's/.*(bisect.*code) (-?[0-9]+) (from.*)/\1 -1 \3/p' err >actual &&
+ test_cmp expect actual
+"
+
+test_expect_success 'git bisect run: unable to verify on good' "
+ write_script fail.sh <<-'EOF' &&
+ head=\$(git rev-parse --verify HEAD)
+ good=\$(git rev-parse --verify $HASH1)
+ if test "\$head" = "\$good"
+ then
+ exit 255
+ else
+ exit 127
+ fi
+ EOF
+ cat <<-'EOF' >expect &&
+ unable to verify './fail.sh' on good revision
+ EOF
+ test_when_finished 'git bisect reset' &&
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ ! git bisect run ./fail.sh 2>err &&
+ sed -n 's/.*\(unable to verify.*\)/\1/p' err >actual &&
+ test_cmp expect actual
+"
+
# We want to automatically find the commit that
# added "Another" into hello.
test_expect_success '"git bisect run" simple case' '
@@ -266,6 +437,16 @@ test_expect_success '"git bisect run" simple case' '
git bisect reset
'
+# We want to make sure no arguments has been eaten
+test_expect_success '"git bisect run" simple case' '
+ git bisect start &&
+ git bisect good $HASH1 &&
+ git bisect bad $HASH4 &&
+ git bisect run printf "%s %s\n" reset --bisect-skip >my_bisect_log.txt &&
+ grep -e "reset --bisect-skip" my_bisect_log.txt &&
+ git bisect reset
+'
+
# We want to automatically find the commit that
# added "Ciao" into hello.
test_expect_success '"git bisect run" with more complex "git bisect start"' '
@@ -900,6 +1081,16 @@ test_expect_success 'bisect start with one term1 and term2' '
git bisect reset
'
+test_expect_success 'bogus command does not start bisect' '
+ git bisect reset &&
+ test_must_fail git bisect --bisect-terms 1 2 2>out &&
+ ! grep "You need to start" out &&
+ test_must_fail git bisect --bisect-terms 2>out &&
+ ! grep "You need to start" out &&
+ grep "git bisect.*visualize" out &&
+ git bisect reset
+'
+
test_expect_success 'bisect replay with term1 and term2' '
git bisect replay log_to_replay.txt >bisect_result &&
grep "$HASH2 is the first term1 commit" bisect_result &&
@@ -990,7 +1181,6 @@ test_expect_success 'git bisect reset cleans bisection state properly' '
test_path_is_missing ".git/BISECT_LOG" &&
test_path_is_missing ".git/BISECT_RUN" &&
test_path_is_missing ".git/BISECT_TERMS" &&
- test_path_is_missing ".git/head-name" &&
test_path_is_missing ".git/BISECT_HEAD" &&
test_path_is_missing ".git/BISECT_START"
'
@@ -1053,4 +1243,14 @@ test_expect_success 'bisect state output with bad commit' '
grep -F "waiting for good commit(s), bad commit known" output
'
+test_expect_success 'verify correct error message' '
+ git bisect reset &&
+ git bisect start $HASH4 $HASH1 &&
+ write_script test_script.sh <<-\EOF &&
+ rm .git/BISECT*
+ EOF
+ test_must_fail git bisect run ./test_script.sh 2>error &&
+ grep "git bisect good.*exited with error code" error
+'
+
test_done
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
index a313849406..7ddbd96e58 100755
--- a/t/t6040-tracking-info.sh
+++ b/t/t6040-tracking-info.sh
@@ -5,6 +5,7 @@ test_description='remote tracking stats'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
advance () {
diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh
index 2500acc2ef..c9925edf20 100755
--- a/t/t6050-replace.sh
+++ b/t/t6050-replace.sh
@@ -62,59 +62,59 @@ HASH6=
HASH7=
test_expect_success 'set up buggy branch' '
- echo "line 1" >>hello &&
- echo "line 2" >>hello &&
- echo "line 3" >>hello &&
- echo "line 4" >>hello &&
- add_and_commit_file hello "4 lines" &&
- HASH1=$(git rev-parse --verify HEAD) &&
- echo "line BUG" >>hello &&
- echo "line 6" >>hello &&
- echo "line 7" >>hello &&
- echo "line 8" >>hello &&
- add_and_commit_file hello "4 more lines with a BUG" &&
- HASH2=$(git rev-parse --verify HEAD) &&
- echo "line 9" >>hello &&
- echo "line 10" >>hello &&
- add_and_commit_file hello "2 more lines" &&
- HASH3=$(git rev-parse --verify HEAD) &&
- echo "line 11" >>hello &&
- add_and_commit_file hello "1 more line" &&
- HASH4=$(git rev-parse --verify HEAD) &&
- sed -e "s/BUG/5/" hello >hello.new &&
- mv hello.new hello &&
- add_and_commit_file hello "BUG fixed" &&
- HASH5=$(git rev-parse --verify HEAD) &&
- echo "line 12" >>hello &&
- echo "line 13" >>hello &&
- add_and_commit_file hello "2 more lines" &&
- HASH6=$(git rev-parse --verify HEAD) &&
- echo "line 14" >>hello &&
- echo "line 15" >>hello &&
- echo "line 16" >>hello &&
- add_and_commit_file hello "again 3 more lines" &&
- HASH7=$(git rev-parse --verify HEAD)
+ echo "line 1" >>hello &&
+ echo "line 2" >>hello &&
+ echo "line 3" >>hello &&
+ echo "line 4" >>hello &&
+ add_and_commit_file hello "4 lines" &&
+ HASH1=$(git rev-parse --verify HEAD) &&
+ echo "line BUG" >>hello &&
+ echo "line 6" >>hello &&
+ echo "line 7" >>hello &&
+ echo "line 8" >>hello &&
+ add_and_commit_file hello "4 more lines with a BUG" &&
+ HASH2=$(git rev-parse --verify HEAD) &&
+ echo "line 9" >>hello &&
+ echo "line 10" >>hello &&
+ add_and_commit_file hello "2 more lines" &&
+ HASH3=$(git rev-parse --verify HEAD) &&
+ echo "line 11" >>hello &&
+ add_and_commit_file hello "1 more line" &&
+ HASH4=$(git rev-parse --verify HEAD) &&
+ sed -e "s/BUG/5/" hello >hello.new &&
+ mv hello.new hello &&
+ add_and_commit_file hello "BUG fixed" &&
+ HASH5=$(git rev-parse --verify HEAD) &&
+ echo "line 12" >>hello &&
+ echo "line 13" >>hello &&
+ add_and_commit_file hello "2 more lines" &&
+ HASH6=$(git rev-parse --verify HEAD) &&
+ echo "line 14" >>hello &&
+ echo "line 15" >>hello &&
+ echo "line 16" >>hello &&
+ add_and_commit_file hello "again 3 more lines" &&
+ HASH7=$(git rev-parse --verify HEAD)
'
test_expect_success 'replace the author' '
- git cat-file commit $HASH2 | grep "author A U Thor" &&
- R=$(git cat-file commit $HASH2 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) &&
- git cat-file commit $R | grep "author O Thor" &&
- git update-ref refs/replace/$HASH2 $R &&
- git show HEAD~5 | grep "O Thor" &&
- git show $HASH2 | grep "O Thor"
+ git cat-file commit $HASH2 | grep "author A U Thor" &&
+ R=$(git cat-file commit $HASH2 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) &&
+ git cat-file commit $R | grep "author O Thor" &&
+ git update-ref refs/replace/$HASH2 $R &&
+ git show HEAD~5 | grep "O Thor" &&
+ git show $HASH2 | grep "O Thor"
'
test_expect_success 'test --no-replace-objects option' '
- git cat-file commit $HASH2 | grep "author O Thor" &&
- git --no-replace-objects cat-file commit $HASH2 | grep "author A U Thor" &&
- git show $HASH2 | grep "O Thor" &&
- git --no-replace-objects show $HASH2 | grep "A U Thor"
+ git cat-file commit $HASH2 | grep "author O Thor" &&
+ git --no-replace-objects cat-file commit $HASH2 | grep "author A U Thor" &&
+ git show $HASH2 | grep "O Thor" &&
+ git --no-replace-objects show $HASH2 | grep "A U Thor"
'
test_expect_success 'test GIT_NO_REPLACE_OBJECTS env variable' '
- GIT_NO_REPLACE_OBJECTS=1 git cat-file commit $HASH2 | grep "author A U Thor" &&
- GIT_NO_REPLACE_OBJECTS=1 git show $HASH2 | grep "A U Thor"
+ GIT_NO_REPLACE_OBJECTS=1 git cat-file commit $HASH2 | grep "author A U Thor" &&
+ GIT_NO_REPLACE_OBJECTS=1 git show $HASH2 | grep "A U Thor"
'
test_expect_success 'test core.usereplacerefs config option' '
@@ -132,64 +132,64 @@ tagger T A Gger <> 0 +0000
EOF
test_expect_success 'tag replaced commit' '
- git update-ref refs/tags/mytag $(git mktag <tag.sig)
+ git update-ref refs/tags/mytag $(git mktag <tag.sig)
'
test_expect_success '"git fsck" works' '
- git fsck main >fsck_main.out &&
- test_i18ngrep "dangling commit $R" fsck_main.out &&
- test_i18ngrep "dangling tag $(git show-ref -s refs/tags/mytag)" fsck_main.out &&
- test -z "$(git fsck)"
+ git fsck main >fsck_main.out &&
+ test_i18ngrep "dangling commit $R" fsck_main.out &&
+ test_i18ngrep "dangling tag $(git show-ref -s refs/tags/mytag)" fsck_main.out &&
+ test -z "$(git fsck)"
'
test_expect_success 'repack, clone and fetch work' '
- git repack -a -d &&
- git clone --no-hardlinks . clone_dir &&
- (
- cd clone_dir &&
- git show HEAD~5 | grep "A U Thor" &&
- git show $HASH2 | grep "A U Thor" &&
- git cat-file commit $R &&
- git repack -a -d &&
- test_must_fail git cat-file commit $R &&
- git fetch ../ "refs/replace/*:refs/replace/*" &&
- git show HEAD~5 | grep "O Thor" &&
- git show $HASH2 | grep "O Thor" &&
- git cat-file commit $R
- )
+ git repack -a -d &&
+ git clone --no-hardlinks . clone_dir &&
+ (
+ cd clone_dir &&
+ git show HEAD~5 | grep "A U Thor" &&
+ git show $HASH2 | grep "A U Thor" &&
+ git cat-file commit $R &&
+ git repack -a -d &&
+ test_must_fail git cat-file commit $R &&
+ git fetch ../ "refs/replace/*:refs/replace/*" &&
+ git show HEAD~5 | grep "O Thor" &&
+ git show $HASH2 | grep "O Thor" &&
+ git cat-file commit $R
+ )
'
test_expect_success '"git replace" listing and deleting' '
- test "$HASH2" = "$(git replace -l)" &&
- test "$HASH2" = "$(git replace)" &&
- aa=${HASH2%??????????????????????????????????????} &&
- test "$HASH2" = "$(git replace --list "$aa*")" &&
- test_must_fail git replace -d $R &&
- test_must_fail git replace --delete &&
- test_must_fail git replace -l -d $HASH2 &&
- git replace -d $HASH2 &&
- git show $HASH2 | grep "A U Thor" &&
- test -z "$(git replace -l)"
+ test "$HASH2" = "$(git replace -l)" &&
+ test "$HASH2" = "$(git replace)" &&
+ aa=${HASH2%??????????????????????????????????????} &&
+ test "$HASH2" = "$(git replace --list "$aa*")" &&
+ test_must_fail git replace -d $R &&
+ test_must_fail git replace --delete &&
+ test_must_fail git replace -l -d $HASH2 &&
+ git replace -d $HASH2 &&
+ git show $HASH2 | grep "A U Thor" &&
+ test -z "$(git replace -l)"
'
test_expect_success '"git replace" replacing' '
- git replace $HASH2 $R &&
- git show $HASH2 | grep "O Thor" &&
- test_must_fail git replace $HASH2 $R &&
- git replace -f $HASH2 $R &&
- test_must_fail git replace -f &&
- test "$HASH2" = "$(git replace)"
+ git replace $HASH2 $R &&
+ git show $HASH2 | grep "O Thor" &&
+ test_must_fail git replace $HASH2 $R &&
+ git replace -f $HASH2 $R &&
+ test_must_fail git replace -f &&
+ test "$HASH2" = "$(git replace)"
'
test_expect_success '"git replace" resolves sha1' '
- SHORTHASH2=$(git rev-parse --short=8 $HASH2) &&
- git replace -d $SHORTHASH2 &&
- git replace $SHORTHASH2 $R &&
- git show $HASH2 | grep "O Thor" &&
- test_must_fail git replace $HASH2 $R &&
- git replace -f $HASH2 $R &&
- test_must_fail git replace --force &&
- test "$HASH2" = "$(git replace)"
+ SHORTHASH2=$(git rev-parse --short=8 $HASH2) &&
+ git replace -d $SHORTHASH2 &&
+ git replace $SHORTHASH2 $R &&
+ git show $HASH2 | grep "O Thor" &&
+ test_must_fail git replace $HASH2 $R &&
+ git replace -f $HASH2 $R &&
+ test_must_fail git replace --force &&
+ test "$HASH2" = "$(git replace)"
'
# This creates a side branch where the bug in H2
@@ -207,79 +207,79 @@ test_expect_success '"git replace" resolves sha1' '
# Then we replace H6 with P6.
#
test_expect_success 'create parallel branch without the bug' '
- git replace -d $HASH2 &&
- git show $HASH2 | grep "A U Thor" &&
- git checkout $HASH1 &&
- git cherry-pick $HASH2 &&
- git show $HASH5 | git apply &&
- git commit --amend -m "hello: 4 more lines WITHOUT the bug" hello &&
- PARA2=$(git rev-parse --verify HEAD) &&
- git cherry-pick $HASH3 &&
- PARA3=$(git rev-parse --verify HEAD) &&
- git cherry-pick $HASH4 &&
- PARA4=$(git rev-parse --verify HEAD) &&
- git cherry-pick $HASH6 &&
- PARA6=$(git rev-parse --verify HEAD) &&
- git replace $HASH6 $PARA6 &&
- git checkout main &&
- cur=$(git rev-parse --verify HEAD) &&
- test "$cur" = "$HASH7" &&
- git log --pretty=oneline | grep $PARA2 &&
- git remote add cloned ./clone_dir
+ git replace -d $HASH2 &&
+ git show $HASH2 | grep "A U Thor" &&
+ git checkout $HASH1 &&
+ git cherry-pick $HASH2 &&
+ git show $HASH5 | git apply &&
+ git commit --amend -m "hello: 4 more lines WITHOUT the bug" hello &&
+ PARA2=$(git rev-parse --verify HEAD) &&
+ git cherry-pick $HASH3 &&
+ PARA3=$(git rev-parse --verify HEAD) &&
+ git cherry-pick $HASH4 &&
+ PARA4=$(git rev-parse --verify HEAD) &&
+ git cherry-pick $HASH6 &&
+ PARA6=$(git rev-parse --verify HEAD) &&
+ git replace $HASH6 $PARA6 &&
+ git checkout main &&
+ cur=$(git rev-parse --verify HEAD) &&
+ test "$cur" = "$HASH7" &&
+ git log --pretty=oneline | grep $PARA2 &&
+ git remote add cloned ./clone_dir
'
test_expect_success 'push to cloned repo' '
- git push cloned $HASH6^:refs/heads/parallel &&
- (
- cd clone_dir &&
- git checkout parallel &&
- git log --pretty=oneline | grep $PARA2
- )
+ git push cloned $HASH6^:refs/heads/parallel &&
+ (
+ cd clone_dir &&
+ git checkout parallel &&
+ git log --pretty=oneline | grep $PARA2
+ )
'
test_expect_success 'push branch with replacement' '
- git cat-file commit $PARA3 | grep "author A U Thor" &&
- S=$(git cat-file commit $PARA3 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) &&
- git cat-file commit $S | grep "author O Thor" &&
- git replace $PARA3 $S &&
- git show $HASH6~2 | grep "O Thor" &&
- git show $PARA3 | grep "O Thor" &&
- git push cloned $HASH6^:refs/heads/parallel2 &&
- (
- cd clone_dir &&
- git checkout parallel2 &&
- git log --pretty=oneline | grep $PARA3 &&
- git show $PARA3 | grep "A U Thor"
- )
+ git cat-file commit $PARA3 | grep "author A U Thor" &&
+ S=$(git cat-file commit $PARA3 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) &&
+ git cat-file commit $S | grep "author O Thor" &&
+ git replace $PARA3 $S &&
+ git show $HASH6~2 | grep "O Thor" &&
+ git show $PARA3 | grep "O Thor" &&
+ git push cloned $HASH6^:refs/heads/parallel2 &&
+ (
+ cd clone_dir &&
+ git checkout parallel2 &&
+ git log --pretty=oneline | grep $PARA3 &&
+ git show $PARA3 | grep "A U Thor"
+ )
'
test_expect_success 'fetch branch with replacement' '
- git branch tofetch $HASH6 &&
- (
- cd clone_dir &&
- git fetch origin refs/heads/tofetch:refs/heads/parallel3 &&
- git log --pretty=oneline parallel3 >output.txt &&
- ! grep $PARA3 output.txt &&
- git show $PARA3 >para3.txt &&
- grep "A U Thor" para3.txt &&
- git fetch origin "refs/replace/*:refs/replace/*" &&
- git log --pretty=oneline parallel3 >output.txt &&
- grep $PARA3 output.txt &&
- git show $PARA3 >para3.txt &&
- grep "O Thor" para3.txt
- )
+ git branch tofetch $HASH6 &&
+ (
+ cd clone_dir &&
+ git fetch origin refs/heads/tofetch:refs/heads/parallel3 &&
+ git log --pretty=oneline parallel3 >output.txt &&
+ ! grep $PARA3 output.txt &&
+ git show $PARA3 >para3.txt &&
+ grep "A U Thor" para3.txt &&
+ git fetch origin "refs/replace/*:refs/replace/*" &&
+ git log --pretty=oneline parallel3 >output.txt &&
+ grep $PARA3 output.txt &&
+ git show $PARA3 >para3.txt &&
+ grep "O Thor" para3.txt
+ )
'
test_expect_success 'bisect and replacements' '
- git bisect start $HASH7 $HASH1 &&
- test "$PARA3" = "$(git rev-parse --verify HEAD)" &&
- git bisect reset &&
- GIT_NO_REPLACE_OBJECTS=1 git bisect start $HASH7 $HASH1 &&
- test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
- git bisect reset &&
- git --no-replace-objects bisect start $HASH7 $HASH1 &&
- test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
- git bisect reset
+ git bisect start $HASH7 $HASH1 &&
+ test "$PARA3" = "$(git rev-parse --verify HEAD)" &&
+ git bisect reset &&
+ GIT_NO_REPLACE_OBJECTS=1 git bisect start $HASH7 $HASH1 &&
+ test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
+ git bisect reset &&
+ git --no-replace-objects bisect start $HASH7 $HASH1 &&
+ test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
+ git bisect reset
'
test_expect_success 'index-pack and replacements' '
diff --git a/t/t6060-merge-index.sh b/t/t6060-merge-index.sh
index ed449abe55..1a8b64cce1 100755
--- a/t/t6060-merge-index.sh
+++ b/t/t6060-merge-index.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='basic git merge-index / git-merge-one-file tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup diverging branches' '
diff --git a/t/t6102-rev-list-unexpected-objects.sh b/t/t6102-rev-list-unexpected-objects.sh
index 4a9a4436e2..9350b5fd2c 100755
--- a/t/t6102-rev-list-unexpected-objects.sh
+++ b/t/t6102-rev-list-unexpected-objects.sh
@@ -121,8 +121,8 @@ test_expect_success 'setup unexpected non-blob tag' '
tag=$(git hash-object -w --literally -t tag broken-tag)
'
-test_expect_success 'TODO (should fail!): traverse unexpected non-blob tag (lone)' '
- git rev-list --objects $tag
+test_expect_success 'traverse unexpected non-blob tag (lone)' '
+ test_must_fail git rev-list --objects $tag
'
test_expect_success 'traverse unexpected non-blob tag (seen)' '
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 9a35e783a7..0a5c487540 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -85,6 +85,7 @@ check_describe e-1-gHASH --tags HEAD^^
check_describe c-2-gHASH --tags HEAD^^2
check_describe B --tags HEAD^^2^
check_describe e --tags HEAD^^^
+check_describe e --tags --exact-match HEAD^^^
check_describe heads/main --all HEAD
check_describe tags/c-6-gHASH --all HEAD^
@@ -96,6 +97,13 @@ check_describe A-3-gHASH --long HEAD^^2
check_describe c-7-gHASH --tags
check_describe e-3-gHASH --first-parent --tags
+check_describe c-7-gHASH --tags --no-exact-match HEAD
+check_describe e-3-gHASH --first-parent --tags --no-exact-match HEAD
+
+test_expect_success '--exact-match failure' '
+ test_must_fail git describe --exact-match HEAD 2>err
+'
+
test_expect_success 'describe --contains defaults to HEAD without commit-ish' '
echo "A^0" >expect &&
git checkout A &&
@@ -657,4 +665,10 @@ test_expect_success 'setup: describe commits with disjoint bases 2' '
check_describe -C disjoint2 "B-3-gHASH" HEAD
+test_expect_success 'setup misleading taggerdates' '
+ GIT_COMMITTER_DATE="2006-12-12 12:31" git tag -a -m "another tag" newer-tag-older-commit unique-file~1
+'
+
+check_describe newer-tag-older-commit~1 --contains unique-file~2
+
test_done
diff --git a/t/t6132-pathspec-exclude.sh b/t/t6132-pathspec-exclude.sh
index cada952f9a..9fdafeb1e9 100755
--- a/t/t6132-pathspec-exclude.sh
+++ b/t/t6132-pathspec-exclude.sh
@@ -293,11 +293,7 @@ test_expect_success 'add with all negative' '
test_cmp expect actual
'
-test_lazy_prereq ADD_I_USE_BUILTIN_OR_PERL '
- test_have_prereq ADD_I_USE_BUILTIN || test_have_prereq PERL
-'
-
-test_expect_success ADD_I_USE_BUILTIN_OR_PERL 'add -p with all negative' '
+test_expect_success 'add -p with all negative' '
H=$(git rev-parse HEAD) &&
git reset --hard $H &&
git clean -f &&
diff --git a/t/t6135-pathspec-with-attrs.sh b/t/t6135-pathspec-with-attrs.sh
index 457cc167c7..f70c395e75 100755
--- a/t/t6135-pathspec-with-attrs.sh
+++ b/t/t6135-pathspec-with-attrs.sh
@@ -65,7 +65,8 @@ test_expect_success 'setup .gitattributes' '
fileValue label=foo
fileWrongLabel label☺
EOF
- git add .gitattributes &&
+ echo fileSetLabel label1 >sub/.gitattributes &&
+ git add .gitattributes sub/.gitattributes &&
git commit -m "add attributes"
'
@@ -78,7 +79,17 @@ test_expect_success 'check specific set attr' '
test_cmp expect actual
'
-test_expect_success 'check specific set attr (2)' '
+test_expect_success 'check set attr with pathspec pattern' '
+ echo sub/fileSetLabel >expect &&
+
+ git ls-files ":(attr:label)sub" >actual &&
+ test_cmp expect actual &&
+
+ git ls-files ":(attr:label)sub/" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check specific set attr in tree-ish' '
cat <<-\EOF >expect &&
HEAD:fileSetLabel
HEAD:sub/fileSetLabel
@@ -87,6 +98,16 @@ test_expect_success 'check specific set attr (2)' '
test_cmp expect actual
'
+test_expect_success 'check specific set attr with pathspec pattern in tree-ish' '
+ echo HEAD:sub/fileSetLabel >expect &&
+
+ git grep -l content HEAD ":(attr:label)sub" >actual &&
+ test_cmp expect actual &&
+
+ git grep -l content HEAD ":(attr:label)sub/" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'check specific unset attr' '
cat <<-\EOF >expect &&
fileUnsetLabel
@@ -137,6 +158,7 @@ test_expect_success 'check unspecified attr' '
fileC
fileNoLabel
fileWrongLabel
+ sub/.gitattributes
sub/fileA
sub/fileAB
sub/fileAC
@@ -161,6 +183,7 @@ test_expect_success 'check unspecified attr (2)' '
HEAD:fileC
HEAD:fileNoLabel
HEAD:fileWrongLabel
+ HEAD:sub/.gitattributes
HEAD:sub/fileA
HEAD:sub/fileAB
HEAD:sub/fileAC
@@ -180,6 +203,7 @@ test_expect_success 'check multiple unspecified attr' '
fileC
fileNoLabel
fileWrongLabel
+ sub/.gitattributes
sub/fileC
sub/fileNoLabel
sub/fileWrongLabel
@@ -253,4 +277,22 @@ test_expect_success 'backslash cannot be used as a value' '
test_i18ngrep "for value matching" actual
'
+test_expect_success 'reading from .gitattributes in a subdirectory (1)' '
+ git ls-files ":(attr:label1)" >actual &&
+ test_write_lines "sub/fileSetLabel" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'reading from .gitattributes in a subdirectory (2)' '
+ git ls-files ":(attr:label1)sub" >actual &&
+ test_write_lines "sub/fileSetLabel" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'reading from .gitattributes in a subdirectory (3)' '
+ git ls-files ":(attr:label1)sub/" >actual &&
+ test_write_lines "sub/fileSetLabel" >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index dcaab7265f..7b943fd34c 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -6,6 +6,7 @@
test_description='for-each-ref test'
. ./test-lib.sh
+GNUPGHOME_NOT_USED=$GNUPGHOME
. "$TEST_DIRECTORY"/lib-gpg.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
@@ -448,6 +449,41 @@ test_expect_success 'exercise glob patterns with prefixes' '
'
cat >expected <<\EOF
+refs/tags/bar
+refs/tags/baz
+refs/tags/testtag
+EOF
+
+test_expect_success 'exercise patterns with prefix exclusions' '
+ for tag in foo/one foo/two foo/three bar baz
+ do
+ git tag "$tag" || return 1
+ done &&
+ test_when_finished "git tag -d foo/one foo/two foo/three bar baz" &&
+ git for-each-ref --format="%(refname)" \
+ refs/tags/ --exclude=refs/tags/foo >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+refs/tags/bar
+refs/tags/baz
+refs/tags/foo/one
+refs/tags/testtag
+EOF
+
+test_expect_success 'exercise patterns with pattern exclusions' '
+ for tag in foo/one foo/two foo/three bar baz
+ do
+ git tag "$tag" || return 1
+ done &&
+ test_when_finished "git tag -d foo/one foo/two foo/three bar baz" &&
+ git for-each-ref --format="%(refname)" \
+ refs/tags/ --exclude="refs/tags/foo/t*" >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
'refs/heads/main'
'refs/remotes/origin/main'
'refs/tags/testtag'
@@ -561,6 +597,144 @@ test_expect_success 'color.ui=always does not override tty check' '
test_cmp expected.bare actual
'
+test_expect_success 'setup for describe atom tests' '
+ git init -b master describe-repo &&
+ (
+ cd describe-repo &&
+
+ test_commit --no-tag one &&
+ git tag tagone &&
+
+ test_commit --no-tag two &&
+ git tag -a -m "tag two" tagtwo
+ )
+'
+
+test_expect_success 'describe atom vs git describe' '
+ (
+ cd describe-repo &&
+
+ git for-each-ref --format="%(objectname)" \
+ refs/tags/ >obj &&
+ while read hash
+ do
+ if desc=$(git describe $hash)
+ then
+ : >expect-contains-good
+ else
+ : >expect-contains-bad
+ fi &&
+ echo "$hash $desc" || return 1
+ done <obj >expect &&
+ test_path_exists expect-contains-good &&
+ test_path_exists expect-contains-bad &&
+
+ git for-each-ref --format="%(objectname) %(describe)" \
+ refs/tags/ >actual 2>err &&
+ test_cmp expect actual &&
+ test_must_be_empty err
+ )
+'
+
+test_expect_success 'describe:tags vs describe --tags' '
+ (
+ cd describe-repo &&
+ git describe --tags >expect &&
+ git for-each-ref --format="%(describe:tags)" \
+ refs/heads/master >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'describe:abbrev=... vs describe --abbrev=...' '
+ (
+ cd describe-repo &&
+
+ # Case 1: We have commits between HEAD and the most
+ # recent tag reachable from it
+ test_commit --no-tag file &&
+ git describe --abbrev=14 >expect &&
+ git for-each-ref --format="%(describe:abbrev=14)" \
+ refs/heads/master >actual &&
+ test_cmp expect actual &&
+
+ # Make sure the hash used is atleast 14 digits long
+ sed -e "s/^.*-g\([0-9a-f]*\)$/\1/" <actual >hexpart &&
+ test 15 -le $(wc -c <hexpart) &&
+
+ # Case 2: We have a tag at HEAD, describe directly gives
+ # the name of the tag
+ git tag -a -m tagged tagname &&
+ git describe --abbrev=14 >expect &&
+ git for-each-ref --format="%(describe:abbrev=14)" \
+ refs/heads/master >actual &&
+ test_cmp expect actual &&
+ test tagname = $(cat actual)
+ )
+'
+
+test_expect_success 'describe:match=... vs describe --match ...' '
+ (
+ cd describe-repo &&
+ git tag -a -m "tag foo" tag-foo &&
+ git describe --match "*-foo" >expect &&
+ git for-each-ref --format="%(describe:match="*-foo")" \
+ refs/heads/master >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'describe:exclude:... vs describe --exclude ...' '
+ (
+ cd describe-repo &&
+ git tag -a -m "tag bar" tag-bar &&
+ git describe --exclude "*-bar" >expect &&
+ git for-each-ref --format="%(describe:exclude="*-bar")" \
+ refs/heads/master >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'deref with describe atom' '
+ (
+ cd describe-repo &&
+ cat >expect <<-\EOF &&
+
+ tagname
+ tagname
+ tagname
+
+ tagtwo
+ EOF
+ git for-each-ref --format="%(*describe)" >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'err on bad describe atom arg' '
+ (
+ cd describe-repo &&
+
+ # The bad arg is the only arg passed to describe atom
+ cat >expect <<-\EOF &&
+ fatal: unrecognized %(describe) argument: baz
+ EOF
+ test_must_fail git for-each-ref --format="%(describe:baz)" \
+ refs/heads/master 2>actual &&
+ test_cmp expect actual &&
+
+ # The bad arg is in the middle of the option string
+ # passed to the describe atom
+ cat >expect <<-\EOF &&
+ fatal: unrecognized %(describe) argument: qux=1,abbrev=14
+ EOF
+ test_must_fail git for-each-ref \
+ --format="%(describe:tags,qux=1,abbrev=14)" \
+ ref/heads/master 2>actual &&
+ test_cmp expect actual
+ )
+'
+
cat >expected <<\EOF
heads/main
tags/main
@@ -606,7 +780,7 @@ test_expect_success 'create tag without tagger' '
git tag -a -m "Broken tag" taggerless &&
git tag -f taggerless $(git cat-file tag taggerless |
sed -e "/^tagger /d" |
- git hash-object --stdin -w -t tag)
+ git hash-object --literally --stdin -w -t tag)
'
test_atom refs/tags/taggerless type 'commit'
@@ -843,16 +1017,16 @@ test_expect_success 'Verify sorts with raw' '
test_expect_success 'Verify sorts with raw:size' '
cat >expected <<-EOF &&
refs/myblobs/blob8
- refs/myblobs/first
refs/myblobs/blob7
- refs/heads/main
refs/myblobs/blob4
refs/myblobs/blob1
refs/myblobs/blob2
refs/myblobs/blob3
refs/myblobs/blob5
refs/myblobs/blob6
+ refs/myblobs/first
refs/mytrees/first
+ refs/heads/main
EOF
git for-each-ref --format="%(refname)" --sort=raw:size \
refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
@@ -964,6 +1138,17 @@ test_expect_success 'for-each-ref --format compare with cat-file --batch' '
test_cmp expected actual
'
+test_expect_success 'verify sorts with contents:size' '
+ cat >expect <<-\EOF &&
+ refs/heads/main
+ refs/heads/newtag
+ refs/heads/ambiguous
+ EOF
+ git for-each-ref --format="%(refname)" \
+ --sort=contents:size refs/heads/ >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'set up multiple-sort tags' '
for when in 100000 200000
do
@@ -1242,6 +1427,24 @@ test_expect_success 'basic atom: rest must fail' '
test_must_fail git for-each-ref --format="%(rest)" refs/heads/main
'
+test_expect_success 'HEAD atom does not take arguments' '
+ test_must_fail git for-each-ref --format="%(HEAD:foo)" 2>err &&
+ echo "fatal: %(HEAD) does not take arguments" >expect &&
+ test_cmp expect err
+'
+
+test_expect_success 'subject atom rejects unknown arguments' '
+ test_must_fail git for-each-ref --format="%(subject:foo)" 2>err &&
+ echo "fatal: unrecognized %(subject) argument: foo" >expect &&
+ test_cmp expect err
+'
+
+test_expect_success 'refname atom rejects unknown arguments' '
+ test_must_fail git for-each-ref --format="%(refname:foo)" 2>err &&
+ echo "fatal: unrecognized %(refname) argument: foo" >expect &&
+ test_cmp expect err
+'
+
test_expect_success 'trailer parsing not fooled by --- line' '
git commit --allow-empty -F - <<-\EOF &&
this is the subject
@@ -1356,6 +1559,14 @@ test_expect_success 'for-each-ref --ignore-case ignores case' '
test_cmp expect actual
'
+test_expect_success 'for-each-ref --omit-empty works' '
+ git for-each-ref --format="%(refname)" >actual &&
+ test_line_count -gt 1 actual &&
+ git for-each-ref --format="%(if:equals=refs/heads/main)%(refname)%(then)%(refname)%(end)" --omit-empty >actual &&
+ echo refs/heads/main >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'for-each-ref --ignore-case works on multiple sort keys' '
# name refs numerically to avoid case-insensitive filesystem conflicts
nr=0 &&
@@ -1406,4 +1617,282 @@ test_expect_success 'for-each-ref reports broken tags' '
refs/tags/broken-tag-*
'
+test_expect_success 'set up tag with signature and no blank lines' '
+ git tag -F - fake-sig-no-blanks <<-\EOF
+ this is the subject
+ -----BEGIN PGP SIGNATURE-----
+ not a real signature, but we just care about the
+ subject/body parsing. It is important here that
+ there are no blank lines in the signature.
+ -----END PGP SIGNATURE-----
+ EOF
+'
+
+test_atom refs/tags/fake-sig-no-blanks contents:subject 'this is the subject'
+test_atom refs/tags/fake-sig-no-blanks contents:body ''
+test_atom refs/tags/fake-sig-no-blanks contents:signature "$sig"
+
+test_expect_success 'set up tag with CRLF signature' '
+ append_cr <<-\EOF |
+ this is the subject
+ -----BEGIN PGP SIGNATURE-----
+
+ not a real signature, but we just care about
+ the subject/body parsing. It is important here
+ that there is a blank line separating this
+ from the signature header.
+ -----END PGP SIGNATURE-----
+ EOF
+ git tag -F - --cleanup=verbatim fake-sig-crlf
+'
+
+test_atom refs/tags/fake-sig-crlf contents:subject 'this is the subject'
+test_atom refs/tags/fake-sig-crlf contents:body ''
+
+# CRLF is retained in the signature, so we have to pass our expected value
+# through append_cr. But test_atom requires a shell string, which means command
+# substitution, and the shell will strip trailing newlines from the output of
+# the substitution. Hack around it by adding and then removing a dummy line.
+sig_crlf="$(printf "%s" "$sig" | append_cr; echo dummy)"
+sig_crlf=${sig_crlf%dummy}
+test_atom refs/tags/fake-sig-crlf contents:signature "$sig_crlf"
+
+test_expect_success 'git for-each-ref --stdin: empty' '
+ >in &&
+ git for-each-ref --format="%(refname)" --stdin <in >actual &&
+ git for-each-ref --format="%(refname)" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git for-each-ref --stdin: fails if extra args' '
+ >in &&
+ test_must_fail git for-each-ref --format="%(refname)" \
+ --stdin refs/heads/extra <in 2>err &&
+ grep "unknown arguments supplied with --stdin" err
+'
+
+test_expect_success 'git for-each-ref --stdin: matches' '
+ cat >in <<-EOF &&
+ refs/tags/multi*
+ refs/heads/amb*
+ EOF
+
+ cat >expect <<-EOF &&
+ refs/heads/ambiguous
+ refs/tags/multi-ref1-100000-user1
+ refs/tags/multi-ref1-100000-user2
+ refs/tags/multi-ref1-200000-user1
+ refs/tags/multi-ref1-200000-user2
+ refs/tags/multi-ref2-100000-user1
+ refs/tags/multi-ref2-100000-user2
+ refs/tags/multi-ref2-200000-user1
+ refs/tags/multi-ref2-200000-user2
+ refs/tags/multiline
+ EOF
+
+ git for-each-ref --format="%(refname)" --stdin <in >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git for-each-ref with non-existing refs' '
+ cat >in <<-EOF &&
+ refs/heads/this-ref-does-not-exist
+ refs/tags/bogus
+ EOF
+
+ git for-each-ref --format="%(refname)" --stdin <in >actual &&
+ test_must_be_empty actual &&
+
+ xargs git for-each-ref --format="%(refname)" <in >actual &&
+ test_must_be_empty actual
+'
+
+GRADE_FORMAT="%(signature:grade)%0a%(signature:key)%0a%(signature:signer)%0a%(signature:fingerprint)%0a%(signature:primarykeyfingerprint)"
+TRUSTLEVEL_FORMAT="%(signature:trustlevel)%0a%(signature:key)%0a%(signature:signer)%0a%(signature:fingerprint)%0a%(signature:primarykeyfingerprint)"
+
+test_expect_success GPG 'setup for signature atom using gpg' '
+ git checkout -b signed &&
+
+ test_when_finished "test_unconfig commit.gpgSign" &&
+
+ echo "1" >file &&
+ git add file &&
+ test_tick &&
+ git commit -S -m "file: 1" &&
+ git tag first-signed &&
+
+ echo "2" >file &&
+ test_tick &&
+ git commit -a -m "file: 2" &&
+ git tag second-unsigned &&
+
+ git config commit.gpgSign 1 &&
+ echo "3" >file &&
+ test_tick &&
+ git commit -a --no-gpg-sign -m "file: 3" &&
+ git tag third-unsigned &&
+
+ test_tick &&
+ git rebase -f HEAD^^ && git tag second-signed HEAD^ &&
+ git tag third-signed &&
+
+ echo "4" >file &&
+ test_tick &&
+ git commit -a -SB7227189 -m "file: 4" &&
+ git tag fourth-signed &&
+
+ echo "5" >file &&
+ test_tick &&
+ git commit -a --no-gpg-sign -m "file: 5" &&
+ git tag fifth-unsigned &&
+
+ echo "6" >file &&
+ test_tick &&
+ git commit -a --no-gpg-sign -m "file: 6" &&
+
+ test_tick &&
+ git rebase -f HEAD^^ &&
+ git tag fifth-signed HEAD^ &&
+ git tag sixth-signed &&
+
+ echo "7" >file &&
+ test_tick &&
+ git commit -a --no-gpg-sign -m "file: 7" &&
+ git tag seventh-unsigned
+'
+
+test_expect_success GPGSSH 'setup for signature atom using ssh' '
+ test_when_finished "test_unconfig gpg.format user.signingkey" &&
+
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+ echo "8" >file &&
+ test_tick &&
+ git add file &&
+ git commit -S -m "file: 8" &&
+ git tag eighth-signed-ssh
+'
+
+test_expect_success GPG2 'bare signature atom' '
+ git verify-commit first-signed 2>expect &&
+ echo >>expect &&
+ git for-each-ref refs/tags/first-signed \
+ --format="%(signature)" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG 'show good signature with custom format' '
+ git verify-commit first-signed &&
+ cat >expect <<-\EOF &&
+ G
+ 13B6F51ECDDE430D
+ C O Mitter <committer@example.com>
+ 73D758744BE721698EC54E8713B6F51ECDDE430D
+ 73D758744BE721698EC54E8713B6F51ECDDE430D
+ EOF
+ git for-each-ref refs/tags/first-signed \
+ --format="$GRADE_FORMAT" >actual &&
+ test_cmp expect actual
+'
+test_expect_success GPGSSH 'show good signature with custom format
+ with ssh' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") &&
+ cat >expect.tmpl <<-\EOF &&
+ G
+ FINGERPRINT
+ principal with number 1
+ FINGERPRINT
+
+ EOF
+ sed "s|FINGERPRINT|$FINGERPRINT|g" expect.tmpl >expect &&
+ git for-each-ref refs/tags/eighth-signed-ssh \
+ --format="$GRADE_FORMAT" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG 'signature atom with grade option and bad signature' '
+ git cat-file commit third-signed >raw &&
+ sed -e "s/^file: 3/file: 3 forged/" raw >forged1 &&
+ FORGED1=$(git hash-object -w -t commit forged1) &&
+ git update-ref refs/tags/third-signed "$FORGED1" &&
+ test_must_fail git verify-commit "$FORGED1" &&
+
+ cat >expect <<-\EOF &&
+ B
+ 13B6F51ECDDE430D
+ C O Mitter <committer@example.com>
+
+
+ EOF
+ git for-each-ref refs/tags/third-signed \
+ --format="$GRADE_FORMAT" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG 'show untrusted signature with custom format' '
+ cat >expect <<-\EOF &&
+ U
+ 65A0EEA02E30CAD7
+ Eris Discordia <discord@example.net>
+ F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
+ D4BE22311AD3131E5EDA29A461092E85B7227189
+ EOF
+ git for-each-ref refs/tags/fourth-signed \
+ --format="$GRADE_FORMAT" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG 'show untrusted signature with undefined trust level' '
+ cat >expect <<-\EOF &&
+ undefined
+ 65A0EEA02E30CAD7
+ Eris Discordia <discord@example.net>
+ F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
+ D4BE22311AD3131E5EDA29A461092E85B7227189
+ EOF
+ git for-each-ref refs/tags/fourth-signed \
+ --format="$TRUSTLEVEL_FORMAT" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG 'show untrusted signature with ultimate trust level' '
+ cat >expect <<-\EOF &&
+ ultimate
+ 13B6F51ECDDE430D
+ C O Mitter <committer@example.com>
+ 73D758744BE721698EC54E8713B6F51ECDDE430D
+ 73D758744BE721698EC54E8713B6F51ECDDE430D
+ EOF
+ git for-each-ref refs/tags/sixth-signed \
+ --format="$TRUSTLEVEL_FORMAT" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG 'show unknown signature with custom format' '
+ cat >expect <<-\EOF &&
+ E
+ 13B6F51ECDDE430D
+
+
+
+ EOF
+ GNUPGHOME="$GNUPGHOME_NOT_USED" git for-each-ref \
+ refs/tags/sixth-signed --format="$GRADE_FORMAT" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG 'show lack of signature with custom format' '
+ cat >expect <<-\EOF &&
+ N
+
+
+
+
+ EOF
+ git for-each-ref refs/tags/seventh-unsigned \
+ --format="$GRADE_FORMAT" >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t6301-for-each-ref-errors.sh b/t/t6301-for-each-ref-errors.sh
index 40edf9dab5..2667dd13fe 100755
--- a/t/t6301-for-each-ref-errors.sh
+++ b/t/t6301-for-each-ref-errors.sh
@@ -2,6 +2,7 @@
test_description='for-each-ref errors for broken refs'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
ZEROS=$ZERO_OID
@@ -53,4 +54,18 @@ test_expect_success 'Missing objects are reported correctly' '
test_must_be_empty brief-err
'
+test_expect_success 'ahead-behind requires an argument' '
+ test_must_fail git for-each-ref \
+ --format="%(ahead-behind)" 2>err &&
+ echo "fatal: expected format: %(ahead-behind:<committish>)" >expect &&
+ test_cmp expect err
+'
+
+test_expect_success 'missing ahead-behind base' '
+ test_must_fail git for-each-ref \
+ --format="%(ahead-behind:refs/heads/missing)" 2>err &&
+ echo "fatal: failed to find '\''refs/heads/missing'\''" >expect &&
+ test_cmp expect err
+'
+
test_done
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 1ce5f490e9..af223e44d6 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -45,6 +45,8 @@ test_expect_success 'check signed tags with --points-at' '
sed -e "s/Z$//" >expect <<-\EOF &&
refs/heads/side Z
refs/tags/annotated-tag four
+ refs/tags/doubly-annotated-tag An annotated tag
+ refs/tags/doubly-signed-tag A signed tag
refs/tags/four Z
refs/tags/signed-tag four
EOF
diff --git a/t/t6401-merge-criss-cross.sh b/t/t6401-merge-criss-cross.sh
index 9d5e992878..1962310408 100755
--- a/t/t6401-merge-criss-cross.sh
+++ b/t/t6401-merge-criss-cross.sh
@@ -8,6 +8,8 @@
test_description='Test criss-cross merge'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'prepare repository' '
diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh
index 8650a88c40..72f8c1722f 100755
--- a/t/t6406-merge-attr.sh
+++ b/t/t6406-merge-attr.sh
@@ -8,6 +8,7 @@ test_description='per path merge controlled by merge attribute'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
@@ -55,6 +56,12 @@ test_expect_success setup '
) >"$ours+"
cat "$ours+" >"$ours"
rm -f "$ours+"
+
+ if test -f ./please-abort
+ then
+ echo >>./please-abort killing myself
+ kill -9 $$
+ fi
exit "$exit"
EOF
chmod +x ./custom-merge
@@ -161,6 +168,24 @@ test_expect_success 'custom merge backend' '
rm -f $o $a $b
'
+test_expect_success !WINDOWS 'custom merge driver that is killed with a signal' '
+ test_when_finished "rm -f output please-abort" &&
+
+ git reset --hard anchor &&
+ git config --replace-all \
+ merge.custom.driver "./custom-merge %O %A %B 0 %P" &&
+ git config --replace-all \
+ merge.custom.name "custom merge driver for testing" &&
+
+ >./please-abort &&
+ echo "* merge=custom" >.gitattributes &&
+ test_must_fail git merge main 2>err &&
+ grep "^error: failed to execute internal merge" err &&
+ git ls-files -u >output &&
+ git diff --name-only HEAD >>output &&
+ test_must_be_empty output
+'
+
test_expect_success 'up-to-date merge without common ancestor' '
git init repo1 &&
git init repo2 &&
diff --git a/t/t6407-merge-binary.sh b/t/t6407-merge-binary.sh
index e8a28717ce..0753fc95f4 100755
--- a/t/t6407-merge-binary.sh
+++ b/t/t6407-merge-binary.sh
@@ -5,6 +5,7 @@ test_description='ask merge-recursive to merge binary files'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t6415-merge-dir-to-symlink.sh b/t/t6415-merge-dir-to-symlink.sh
index 2655e295f5..ae00492c76 100755
--- a/t/t6415-merge-dir-to-symlink.sh
+++ b/t/t6415-merge-dir-to-symlink.sh
@@ -4,6 +4,7 @@ test_description='merging when a directory was replaced with a symlink'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create a commit where dir a/b changed to symlink' '
diff --git a/t/t6421-merge-partial-clone.sh b/t/t6421-merge-partial-clone.sh
index 5413e5dd9d..711b709e75 100755
--- a/t/t6421-merge-partial-clone.sh
+++ b/t/t6421-merge-partial-clone.sh
@@ -155,7 +155,7 @@ test_setup_repo () {
# Commit A:
# (Rename leap->jump, rename basename/ -> basename/subdir/, rename dir/
# -> folder/, move e into newsubdir, add newfile.rs, remove f, modify
-# both both Makefiles and jumps)
+# both Makefiles and jumps)
# general/{jump1_A, jump2_A}
# basename/subdir/{numbers_A, sequence_A, values_A}
# folder/subdir/{a,b,c,d,Makefile_TOP_A}
@@ -343,7 +343,7 @@ test_expect_merge_algorithm failure success 'Objects downloaded when a directory
# Commit A:
# (Rename leap->jump, rename basename/ -> basename/subdir/, rename dir/
# -> folder/, move e into newsubdir, add newfile.rs, remove f, modify
-# both both Makefiles and jumps)
+# both Makefiles and jumps)
# general/{jump1_A, jump2_A}
# basename/subdir/{numbers_A, sequence_A, values_A}
# folder/subdir/{a,b,c,d,Makefile_TOP_A}
diff --git a/t/t6422-merge-rename-corner-cases.sh b/t/t6422-merge-rename-corner-cases.sh
index 346253c7c8..076b6a74d5 100755
--- a/t/t6422-merge-rename-corner-cases.sh
+++ b/t/t6422-merge-rename-corner-cases.sh
@@ -1159,7 +1159,6 @@ test_conflicts_with_adds_and_renames() {
# 4) There should not be any three~* files in the working
# tree
test_setup_collision_conflict () {
- #test_expect_success "setup simple $sideL/$sideR conflict" '
git init simple_${sideL}_${sideR} &&
(
cd simple_${sideL}_${sideR} &&
@@ -1236,7 +1235,6 @@ test_conflicts_with_adds_and_renames() {
fi &&
test_tick && git commit -m R
)
- #'
}
test_expect_success "check simple $sideL/$sideR conflict" '
diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh
index a4941878fe..944de75b80 100755
--- a/t/t6423-merge-rename-directories.sh
+++ b/t/t6423-merge-rename-directories.sh
@@ -5304,6 +5304,62 @@ test_expect_merge_algorithm failure success '12l (A into B): Rename into each ot
)
'
+# Testcase 12m, Directory rename, plus change of parent dir to symlink
+# Commit O: dir/subdir/file
+# Commit A: renamed-dir/subdir/file
+# Commit B: dir/subdir
+# In words:
+# A: dir/subdir/ -> renamed-dir/subdir
+# B: delete dir/subdir/file, add dir/subdir as symlink
+#
+# Expected: CONFLICT (rename/delete): renamed-dir/subdir/file,
+# CONFLICT (file location): renamed-dir/subdir vs. dir/subdir
+# CONFLICT (directory/file): renamed-dir/subdir symlink has
+# renamed-dir/subdir in the way
+
+test_setup_12m () {
+ git init 12m &&
+ (
+ cd 12m &&
+
+ mkdir -p dir/subdir &&
+ echo 1 >dir/subdir/file &&
+ git add . &&
+ git commit -m "O" &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ git mv dir/ renamed-dir/ &&
+ git add . &&
+ git commit -m "A" &&
+
+ git switch B &&
+ git rm dir/subdir/file &&
+ mkdir dir &&
+ ln -s /dev/null dir/subdir &&
+ git add . &&
+ git commit -m "B"
+ )
+}
+
+test_expect_merge_algorithm failure success '12m: Change parent of renamed-dir to symlink on other side' '
+ test_setup_12m &&
+ (
+ cd 12m &&
+
+ git checkout -q A^0 &&
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&
+
+ test_stdout_line_count = 3 git ls-files -s &&
+ test_stdout_line_count = 2 ls -1 renamed-dir &&
+ test_path_is_missing dir
+ )
+'
+
###########################################################################
# SECTION 13: Checking informational and conflict messages
#
diff --git a/t/t6426-merge-skip-unneeded-updates.sh b/t/t6426-merge-skip-unneeded-updates.sh
index 2bb8e7f09b..fd21c1a486 100755
--- a/t/t6426-merge-skip-unneeded-updates.sh
+++ b/t/t6426-merge-skip-unneeded-updates.sh
@@ -378,42 +378,30 @@ test_expect_success '2c: Modify b & add c VS rename b->c' '
test_i18ngrep "CONFLICT (.*/add):" out &&
test_must_be_empty err &&
- # Make sure c WAS updated
+ git ls-files -s >index_files &&
+ test_line_count = 2 index_files &&
+
+ # Ensure b was removed
+ test_path_is_missing b &&
+
+ # Make sure c WAS updated...
test-tool chmtime --get c >new-mtime &&
- test $(cat old-mtime) -lt $(cat new-mtime)
-
- # FIXME: rename/add conflicts are horribly broken right now;
- # when I get back to my patch series fixing it and
- # rename/rename(2to1) conflicts to bring them in line with
- # how add/add conflicts behave, then checks like the below
- # could be added. But that patch series is waiting until
- # the rename-directory-detection series lands, which this
- # is part of. And in the mean time, I do not want to further
- # enforce broken behavior. So for now, the main test is the
- # one above that err is an empty file.
-
- #git ls-files -s >index_files &&
- #test_line_count = 2 index_files &&
-
- #git rev-parse >actual :2:c :3:c &&
- #git rev-parse >expect A:b A:c &&
- #test_cmp expect actual &&
-
- #git cat-file -p A:b >>merged &&
- #git cat-file -p A:c >>merge-me &&
- #>empty &&
- #test_must_fail git merge-file \
- # -L "Temporary merge branch 1" \
- # -L "" \
- # -L "Temporary merge branch 2" \
- # merged empty merge-me &&
- #sed -e "s/^\([<=>]\)/\1\1\1/" merged >merged-internal &&
-
- #git hash-object c >actual &&
- #git hash-object merged-internal >expect &&
- #test_cmp expect actual &&
-
- #test_path_is_missing b
+ test $(cat old-mtime) -lt $(cat new-mtime) &&
+
+ # ...and has correct index entries and working tree contents
+ git rev-parse >actual :2:c :3:c &&
+ git rev-parse >expect A:c A:b &&
+ test_cmp expect actual &&
+
+ git cat-file -p A:b >>merge-me &&
+ git cat-file -p A:c >>merged &&
+ >empty &&
+ test_must_fail git merge-file \
+ -L "HEAD" \
+ -L "" \
+ -L "B^0" \
+ merged empty merge-me &&
+ test_cmp merged c
)
'
diff --git a/t/t6435-merge-sparse.sh b/t/t6435-merge-sparse.sh
index fde4aa3cd1..78628fb248 100755
--- a/t/t6435-merge-sparse.sh
+++ b/t/t6435-merge-sparse.sh
@@ -3,6 +3,7 @@
test_description='merge with sparse files'
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# test_file $filename $content
diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh
index 52cf0c8769..0cbec57cda 100755
--- a/t/t6439-merge-co-error-msgs.sh
+++ b/t/t6439-merge-co-error-msgs.sh
@@ -5,6 +5,7 @@ test_description='unpack-trees error messages'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh
index cd6c53360d..69509d0c11 100755
--- a/t/t6500-gc.sh
+++ b/t/t6500-gc.sh
@@ -202,6 +202,107 @@ test_expect_success 'one of gc.reflogExpire{Unreachable,}=never does not skip "e
grep -E "^trace: (built-in|exec|run_command): git reflog expire --" trace.out
'
+prepare_cruft_history () {
+ test_commit base &&
+
+ test_commit --no-tag foo &&
+ test_commit --no-tag bar &&
+ git reset HEAD^^
+}
+
+assert_no_cruft_packs () {
+ find .git/objects/pack -name "*.mtimes" >mtimes &&
+ test_must_be_empty mtimes
+}
+
+for argv in \
+ "gc" \
+ "-c gc.cruftPacks=true gc" \
+ "-c gc.cruftPacks=false gc --cruft"
+do
+ test_expect_success "git $argv generates a cruft pack" '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ prepare_cruft_history &&
+ git $argv &&
+
+ find .git/objects/pack -name "*.mtimes" >mtimes &&
+ sed -e 's/\.mtimes$/\.pack/g' mtimes >packs &&
+
+ test_file_not_empty packs &&
+ while read pack
+ do
+ test_path_is_file "$pack" || return 1
+ done <packs
+ )
+ '
+done
+
+for argv in \
+ "gc --no-cruft" \
+ "-c gc.cruftPacks=false gc" \
+ "-c gc.cruftPacks=true gc --no-cruft"
+do
+ test_expect_success "git $argv does not generate a cruft pack" '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ prepare_cruft_history &&
+ git $argv &&
+
+ assert_no_cruft_packs
+ )
+ '
+done
+
+test_expect_success '--keep-largest-pack ignores cruft packs' '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ # Generate a pack for reachable objects (of which there
+ # are 3), and one for unreachable objects (of which
+ # there are 6).
+ prepare_cruft_history &&
+ git gc --cruft &&
+
+ mtimes="$(find .git/objects/pack -type f -name "pack-*.mtimes")" &&
+ sz="$(test_file_size "${mtimes%.mtimes}.pack")" &&
+
+ # Ensure that the cruft pack gets removed (due to
+ # `--prune=now`) despite it being the largest pack.
+ git -c gc.bigPackThreshold=$sz gc --cruft --prune=now &&
+
+ assert_no_cruft_packs
+ )
+'
+
+test_expect_success 'gc.bigPackThreshold ignores cruft packs' '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ # Generate a pack for reachable objects (of which there
+ # are 3), and one for unreachable objects (of which
+ # there are 6).
+ prepare_cruft_history &&
+ git gc --cruft &&
+
+ # Ensure that the cruft pack gets removed (due to
+ # `--prune=now`) despite it being the largest pack.
+ git gc --cruft --prune=now --keep-largest-pack &&
+
+ assert_no_cruft_packs
+ )
+'
+
run_and_wait_for_auto_gc () {
# We read stdout from gc for the side effect of waiting until the
# background gc process exits, closing its fd 9. Furthermore, the
diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh
index 10662456ae..4521508b83 100755
--- a/t/t6501-freshen-objects.sh
+++ b/t/t6501-freshen-objects.sh
@@ -28,6 +28,7 @@ test_description='check pruning of dependent objects'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# We care about reachability, so we do not want to use
@@ -100,7 +101,7 @@ do
'
test_expect_success "simultaneous gc ($title)" '
- git gc --prune=12.hours.ago
+ git gc --no-cruft --prune=12.hours.ago
'
test_expect_success "finish writing out commit ($title)" '
@@ -130,7 +131,7 @@ do
'
test_expect_success "simultaneous gc ($title)" '
- git gc --prune=12.hours.ago
+ git gc --no-cruft --prune=12.hours.ago
'
# tree should have been refreshed by write-tree
@@ -150,8 +151,8 @@ test_expect_success 'do not complain about existing broken links (commit)' '
some message
EOF
commit=$(git hash-object -t commit -w broken-commit) &&
- git gc -q 2>stderr &&
- verbose git cat-file -e $commit &&
+ git gc --no-cruft -q 2>stderr &&
+ git cat-file -e $commit &&
test_must_be_empty stderr
'
@@ -160,7 +161,7 @@ test_expect_success 'do not complain about existing broken links (tree)' '
100644 blob $(test_oid 003) foo
EOF
tree=$(git mktree --missing <broken-tree) &&
- git gc -q 2>stderr &&
+ git gc --no-cruft -q 2>stderr &&
git cat-file -e $tree &&
test_must_be_empty stderr
'
@@ -175,7 +176,7 @@ test_expect_success 'do not complain about existing broken links (tag)' '
this is a broken tag
EOF
tag=$(git hash-object -t tag -w broken-tag) &&
- git gc -q 2>stderr &&
+ git gc --no-cruft -q 2>stderr &&
git cat-file -e $tag &&
test_must_be_empty stderr
'
diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh
index 338a9c46a2..b330945f49 100755
--- a/t/t6600-test-reach.sh
+++ b/t/t6600-test-reach.sh
@@ -443,4 +443,173 @@ test_expect_success 'get_reachable_subset:none' '
test_all_modes get_reachable_subset
'
+test_expect_success 'for-each-ref ahead-behind:linear' '
+ cat >input <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-1-3
+ refs/heads/commit-1-5
+ refs/heads/commit-1-8
+ EOF
+ cat >expect <<-\EOF &&
+ refs/heads/commit-1-1 0 8
+ refs/heads/commit-1-3 0 6
+ refs/heads/commit-1-5 0 4
+ refs/heads/commit-1-8 0 1
+ EOF
+ run_all_modes git for-each-ref \
+ --format="%(refname) %(ahead-behind:commit-1-9)" --stdin
+'
+
+test_expect_success 'for-each-ref ahead-behind:all' '
+ cat >input <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-2-4
+ refs/heads/commit-4-2
+ refs/heads/commit-4-4
+ EOF
+ cat >expect <<-\EOF &&
+ refs/heads/commit-1-1 0 24
+ refs/heads/commit-2-4 0 17
+ refs/heads/commit-4-2 0 17
+ refs/heads/commit-4-4 0 9
+ EOF
+ run_all_modes git for-each-ref \
+ --format="%(refname) %(ahead-behind:commit-5-5)" --stdin
+'
+
+test_expect_success 'for-each-ref ahead-behind:some' '
+ cat >input <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-5-3
+ refs/heads/commit-4-8
+ refs/heads/commit-9-9
+ EOF
+ cat >expect <<-\EOF &&
+ refs/heads/commit-1-1 0 53
+ refs/heads/commit-4-8 8 30
+ refs/heads/commit-5-3 0 39
+ refs/heads/commit-9-9 27 0
+ EOF
+ run_all_modes git for-each-ref \
+ --format="%(refname) %(ahead-behind:commit-9-6)" --stdin
+'
+
+test_expect_success 'for-each-ref ahead-behind:some, multibase' '
+ cat >input <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-5-3
+ refs/heads/commit-7-8
+ refs/heads/commit-4-8
+ refs/heads/commit-9-9
+ EOF
+ cat >expect <<-\EOF &&
+ refs/heads/commit-1-1 0 53 0 53
+ refs/heads/commit-4-8 8 30 0 22
+ refs/heads/commit-5-3 0 39 0 39
+ refs/heads/commit-7-8 14 12 8 6
+ refs/heads/commit-9-9 27 0 27 0
+ EOF
+ run_all_modes git for-each-ref \
+ --format="%(refname) %(ahead-behind:commit-9-6) %(ahead-behind:commit-6-9)" \
+ --stdin
+'
+
+test_expect_success 'for-each-ref ahead-behind:none' '
+ cat >input <<-\EOF &&
+ refs/heads/commit-7-5
+ refs/heads/commit-4-8
+ refs/heads/commit-9-9
+ EOF
+ cat >expect <<-\EOF &&
+ refs/heads/commit-4-8 16 16
+ refs/heads/commit-7-5 7 4
+ refs/heads/commit-9-9 49 0
+ EOF
+ run_all_modes git for-each-ref \
+ --format="%(refname) %(ahead-behind:commit-8-4)" --stdin
+'
+
+test_expect_success 'for-each-ref merged:linear' '
+ cat >input <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-1-3
+ refs/heads/commit-1-5
+ refs/heads/commit-1-8
+ refs/heads/commit-2-1
+ refs/heads/commit-5-1
+ refs/heads/commit-9-1
+ EOF
+ cat >expect <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-1-3
+ refs/heads/commit-1-5
+ refs/heads/commit-1-8
+ EOF
+ run_all_modes git for-each-ref --merged=commit-1-9 \
+ --format="%(refname)" --stdin
+'
+
+test_expect_success 'for-each-ref merged:all' '
+ cat >input <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-2-4
+ refs/heads/commit-4-2
+ refs/heads/commit-4-4
+ EOF
+ cat >expect <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-2-4
+ refs/heads/commit-4-2
+ refs/heads/commit-4-4
+ EOF
+ run_all_modes git for-each-ref --merged=commit-5-5 \
+ --format="%(refname)" --stdin
+'
+
+test_expect_success 'for-each-ref ahead-behind:some' '
+ cat >input <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-5-3
+ refs/heads/commit-4-8
+ refs/heads/commit-9-9
+ EOF
+ cat >expect <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-5-3
+ EOF
+ run_all_modes git for-each-ref --merged=commit-9-6 \
+ --format="%(refname)" --stdin
+'
+
+test_expect_success 'for-each-ref merged:some, multibase' '
+ cat >input <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-5-3
+ refs/heads/commit-7-8
+ refs/heads/commit-4-8
+ refs/heads/commit-9-9
+ EOF
+ cat >expect <<-\EOF &&
+ refs/heads/commit-1-1
+ refs/heads/commit-4-8
+ refs/heads/commit-5-3
+ EOF
+ run_all_modes git for-each-ref \
+ --merged=commit-5-8 \
+ --merged=commit-8-5 \
+ --format="%(refname)" \
+ --stdin
+'
+
+test_expect_success 'for-each-ref merged:none' '
+ cat >input <<-\EOF &&
+ refs/heads/commit-7-5
+ refs/heads/commit-4-8
+ refs/heads/commit-9-9
+ EOF
+ >expect &&
+ run_all_modes git for-each-ref --merged=commit-8-4 \
+ --format="%(refname)" --stdin
+'
+
test_done
diff --git a/t/t6700-tree-depth.sh b/t/t6700-tree-depth.sh
new file mode 100755
index 0000000000..e410c41234
--- /dev/null
+++ b/t/t6700-tree-depth.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+test_description='handling of deep trees in various commands'
+. ./test-lib.sh
+
+# We'll test against two depths here: a small one that will let us check the
+# behavior of the config setting easily, and a large one that should be
+# forbidden by default. Testing the default depth will let us know whether our
+# default is enough to prevent segfaults on systems that run the tests.
+small_depth=50
+big_depth=4100
+
+small_ok="-c core.maxtreedepth=$small_depth"
+small_no="-c core.maxtreedepth=$((small_depth-1))"
+
+# usage: mkdeep <name> <depth>
+# Create a tag <name> containing a file whose path has depth <depth>.
+#
+# We'll use fast-import here for two reasons:
+#
+# 1. It's faster than creating $big_depth tree objects.
+#
+# 2. As we tighten tree limits, it's more likely to allow large sizes
+# than trying to stuff a deep path into the index.
+mkdeep () {
+ {
+ echo "commit refs/tags/$1" &&
+ echo "committer foo <foo@example.com> 1234 -0000" &&
+ echo "data <<EOF" &&
+ echo "the commit message" &&
+ echo "EOF" &&
+
+ printf 'M 100644 inline ' &&
+ i=0 &&
+ while test $i -lt $2
+ do
+ printf 'a/'
+ i=$((i+1))
+ done &&
+ echo "file" &&
+
+ echo "data <<EOF" &&
+ echo "the file contents" &&
+ echo "EOF" &&
+ echo
+ } | git fast-import
+}
+
+test_expect_success 'create small tree' '
+ mkdeep small $small_depth
+'
+
+test_expect_success 'create big tree' '
+ mkdeep big $big_depth
+'
+
+test_expect_success 'limit recursion of git-archive' '
+ git $small_ok archive small >/dev/null &&
+ test_must_fail git $small_no archive small >/dev/null
+'
+
+test_expect_success 'default limit for git-archive fails gracefully' '
+ test_must_fail git archive big >/dev/null
+'
+
+test_expect_success 'limit recursion of ls-tree -r' '
+ git $small_ok ls-tree -r small &&
+ test_must_fail git $small_no ls-tree -r small
+'
+
+test_expect_success 'default limit for ls-tree fails gracefully' '
+ test_must_fail git ls-tree -r big >/dev/null
+'
+
+test_expect_success 'limit recursion of rev-list --objects' '
+ git $small_ok rev-list --objects small >/dev/null &&
+ test_must_fail git $small_no rev-list --objects small >/dev/null
+'
+
+test_expect_success 'default limit for rev-list fails gracefully' '
+ test_must_fail git rev-list --objects big >/dev/null
+'
+
+test_expect_success 'limit recursion of diff-tree -r' '
+ git $small_ok diff-tree -r $EMPTY_TREE small &&
+ test_must_fail git $small_no diff-tree -r $EMPTY_TREE small
+'
+
+test_expect_success 'default limit for diff-tree fails gracefully' '
+ test_must_fail git diff-tree -r $EMPTY_TREE big
+'
+
+test_done
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 8c37bceb33..f136ea76f7 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -4,6 +4,10 @@ test_description='git mv in subdirs'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff-data.sh
+index_at_path () {
+ git ls-files --format='%(objectmode) %(objectname) %(stage)' "$@"
+}
+
test_expect_success 'mv -f refreshes updated index entry' '
echo test >bar &&
git add bar &&
@@ -60,8 +64,8 @@ test_expect_success 'checking the commit' '
test_expect_success 'mv --dry-run does not move file' '
git mv -n path0/COPYING MOVED &&
- test -f path0/COPYING &&
- test ! -f MOVED
+ test_path_is_file path0/COPYING &&
+ test_path_is_missing MOVED
'
test_expect_success 'checking -k on non-existing file' '
@@ -71,25 +75,25 @@ test_expect_success 'checking -k on non-existing file' '
test_expect_success 'checking -k on untracked file' '
>untracked1 &&
git mv -k untracked1 path0 &&
- test -f untracked1 &&
- test ! -f path0/untracked1
+ test_path_is_file untracked1 &&
+ test_path_is_missing path0/untracked1
'
test_expect_success 'checking -k on multiple untracked files' '
>untracked2 &&
git mv -k untracked1 untracked2 path0 &&
- test -f untracked1 &&
- test -f untracked2 &&
- test ! -f path0/untracked1 &&
- test ! -f path0/untracked2
+ test_path_is_file untracked1 &&
+ test_path_is_file untracked2 &&
+ test_path_is_missing path0/untracked1 &&
+ test_path_is_missing path0/untracked2
'
test_expect_success 'checking -f on untracked file with existing target' '
>path0/untracked1 &&
test_must_fail git mv -f untracked1 path0 &&
- test ! -f .git/index.lock &&
- test -f untracked1 &&
- test -f path0/untracked1
+ test_path_is_missing .git/index.lock &&
+ test_path_is_file untracked1 &&
+ test_path_is_file path0/untracked1
'
# clean up the mess in case bad things happen
@@ -170,6 +174,13 @@ test_expect_success 'do not move directory over existing directory' '
test_must_fail git mv path2 path0
'
+test_expect_success 'rename directory to non-existing directory' '
+ mkdir dir-a &&
+ >dir-a/f &&
+ git add dir-a &&
+ git mv dir-a non-existing-dir
+'
+
test_expect_success 'move into "."' '
git mv path1/path2/ .
'
@@ -187,7 +198,8 @@ test_expect_success "Michael Cassar's test case" '
git mv papers/unsorted/Thesis.pdf papers/all-papers/moo-blah.pdf &&
T=$(git write-tree) &&
- git ls-tree -r $T | verbose grep partA/outline.txt
+ git ls-tree -r $T >out &&
+ grep partA/outline.txt out
'
rm -fr papers partA path?
@@ -215,8 +227,8 @@ test_expect_success 'absolute pathname' '
git add sub/file &&
git mv sub "$(pwd)/in" &&
- ! test -d sub &&
- test -d in &&
+ test_path_is_missing sub &&
+ test_path_is_dir in &&
git ls-files --error-unmatch in/file
)
'
@@ -234,8 +246,8 @@ test_expect_success 'absolute pathname outside should fail' '
git add sub/file &&
test_must_fail git mv sub "$out/out" &&
- test -d sub &&
- ! test -d ../in &&
+ test_path_is_dir sub &&
+ test_path_is_missing ../in &&
git ls-files --error-unmatch sub/file
)
'
@@ -260,12 +272,12 @@ test_expect_success 'git mv should not change sha1 of moved cache entry' '
git init &&
echo 1 >dirty &&
git add dirty &&
- entry="$(git ls-files --stage dirty | cut -f 1)" &&
+ entry="$(index_at_path dirty)" &&
git mv dirty dirty2 &&
- test "$entry" = "$(git ls-files --stage dirty2 | cut -f 1)" &&
+ test "$entry" = "$(index_at_path dirty2)" &&
echo 2 >dirty2 &&
git mv dirty2 dirty &&
- test "$entry" = "$(git ls-files --stage dirty | cut -f 1)"
+ test "$entry" = "$(index_at_path dirty)"
'
rm -f dirty dirty2
@@ -295,8 +307,8 @@ test_expect_success 'git mv should overwrite symlink to a file' '
git add moved &&
test_must_fail git mv moved symlink &&
git mv -f moved symlink &&
- ! test -e moved &&
- test -f symlink &&
+ test_path_is_missing moved &&
+ test_path_is_file symlink &&
test "$(cat symlink)" = 1 &&
git update-index --refresh &&
git diff-files --quiet
@@ -312,13 +324,13 @@ test_expect_success 'git mv should overwrite file with a symlink' '
git add moved &&
test_must_fail git mv symlink moved &&
git mv -f symlink moved &&
- ! test -e symlink &&
+ test_path_is_missing symlink &&
git update-index --refresh &&
git diff-files --quiet
'
test_expect_success SYMLINKS 'check moved symlink' '
- test -h moved
+ test_path_is_symlink moved
'
rm -f moved symlink
@@ -342,7 +354,7 @@ test_expect_success 'git mv cannot move a submodule in a file' '
'
test_expect_success 'git mv moves a submodule with a .git directory and no .gitmodules' '
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
git rm .gitmodules &&
(
cd sub &&
@@ -352,8 +364,8 @@ test_expect_success 'git mv moves a submodule with a .git directory and no .gitm
) &&
mkdir mod &&
git mv sub mod/sub &&
- ! test -e sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test_path_is_missing sub &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
git update-index --refresh &&
git diff-files --quiet
@@ -363,7 +375,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and .gitmodu
rm -rf mod &&
git reset --hard &&
git submodule update &&
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
(
cd sub &&
rm -f .git &&
@@ -372,8 +384,8 @@ test_expect_success 'git mv moves a submodule with a .git directory and .gitmodu
) &&
mkdir mod &&
git mv sub mod/sub &&
- ! test -e sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test_path_is_missing sub &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
echo mod/sub >expected &&
git config -f .gitmodules submodule.sub.path >actual &&
@@ -386,11 +398,11 @@ test_expect_success 'git mv moves a submodule with gitfile' '
rm -rf mod &&
git reset --hard &&
git submodule update &&
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
mkdir mod &&
git -C mod mv ../sub/ . &&
- ! test -e sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test_path_is_missing sub &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
echo mod/sub >expected &&
git config -f .gitmodules submodule.sub.path >actual &&
@@ -404,12 +416,12 @@ test_expect_success 'mv does not complain when no .gitmodules file is found' '
git reset --hard &&
git submodule update &&
git rm .gitmodules &&
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
mkdir mod &&
git mv sub mod/sub 2>actual.err &&
test_must_be_empty actual.err &&
- ! test -e sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test_path_is_missing sub &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
git update-index --refresh &&
git diff-files --quiet
@@ -420,17 +432,17 @@ test_expect_success 'mv will error out on a modified .gitmodules file unless sta
git reset --hard &&
git submodule update &&
git config -f .gitmodules foo.bar true &&
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
mkdir mod &&
test_must_fail git mv sub mod/sub 2>actual.err &&
- test -s actual.err &&
- test -e sub &&
+ test_file_not_empty actual.err &&
+ test_path_exists sub &&
git diff-files --quiet -- sub &&
git add .gitmodules &&
git mv sub mod/sub 2>actual.err &&
test_must_be_empty actual.err &&
- ! test -e sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test_path_is_missing sub &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
git update-index --refresh &&
git diff-files --quiet
@@ -442,13 +454,13 @@ test_expect_success 'mv issues a warning when section is not found in .gitmodule
git submodule update &&
git config -f .gitmodules --remove-section submodule.sub &&
git add .gitmodules &&
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
echo "warning: Could not find section in .gitmodules where path=sub" >expect.err &&
mkdir mod &&
git mv sub mod/sub 2>actual.err &&
test_cmp expect.err actual.err &&
- ! test -e sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test_path_is_missing sub &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
git update-index --refresh &&
git diff-files --quiet
@@ -460,7 +472,7 @@ test_expect_success 'mv --dry-run does not touch the submodule or .gitmodules' '
git submodule update &&
mkdir mod &&
git mv -n sub mod/sub 2>actual.err &&
- test -f sub/.git &&
+ test_path_is_file sub/.git &&
git diff-index --exit-code HEAD &&
git update-index --refresh &&
git diff-files --quiet -- sub .gitmodules
@@ -474,10 +486,10 @@ test_expect_success 'checking out a commit before submodule moved needs manual u
git status -s sub2 >actual &&
echo "?? sub2/" >expected &&
test_cmp expected actual &&
- ! test -f sub/.git &&
- test -f sub2/.git &&
+ test_path_is_missing sub/.git &&
+ test_path_is_file sub2/.git &&
git submodule update &&
- test -f sub/.git &&
+ test_path_is_file sub/.git &&
rm -rf sub2 &&
git diff-index --exit-code HEAD &&
git update-index --refresh &&
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index e18a218952..f6aebe92ff 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -49,7 +49,7 @@ test_expect_success 'result is really identical' '
test_expect_success 'rewrite bare repository identically' '
(git config core.bare true && cd .git &&
git filter-branch branch > filter-output 2>&1 &&
- ! fgrep fatal filter-output)
+ ! grep fatal filter-output)
'
git config core.bare false
test_expect_success 'result is really identical' '
@@ -506,7 +506,7 @@ test_expect_success 'rewrite repository including refs that point at non-commit
git tag -a -m "tag to a tree" treetag $new_tree &&
git reset --hard HEAD &&
git filter-branch -f -- --all >filter-output 2>&1 &&
- ! fgrep fatal filter-output
+ ! grep fatal filter-output
'
test_expect_success 'filter-branch handles ref deletion' '
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 9aa1660651..e689db4292 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -792,6 +792,34 @@ test_expect_success 'annotations for blobs are empty' '
test_cmp expect actual
'
+# Run this before doing any signing, so the test has the same results
+# regardless of the GPG prereq.
+test_expect_success 'git tag --format with ahead-behind' '
+ test_when_finished git reset --hard tag-one-line &&
+ git commit --allow-empty -m "left" &&
+ git tag -a -m left tag-left &&
+ git reset --hard HEAD~1 &&
+ git commit --allow-empty -m "right" &&
+ git tag -a -m left tag-right &&
+
+ # Use " !" at the end to demonstrate whitespace
+ # around empty ahead-behind token for tag-blob.
+ cat >expect <<-EOF &&
+ refs/tags/tag-blob !
+ refs/tags/tag-left 1 1 !
+ refs/tags/tag-lines 0 1 !
+ refs/tags/tag-one-line 0 1 !
+ refs/tags/tag-right 0 0 !
+ refs/tags/tag-zero-lines 0 1 !
+ EOF
+ git tag -l --format="%(refname) %(ahead-behind:HEAD) !" >actual 2>err &&
+ grep "refs/tags/tag" actual >actual.focus &&
+ test_cmp expect actual.focus &&
+
+ # Error reported for tags that point to non-commits.
+ grep "error: object [0-9a-f]* is a blob, not a commit" err
+'
+
# trying to verify annotated non-signed tags:
test_expect_success GPG \
@@ -1843,6 +1871,23 @@ test_expect_success 'invalid sort parameter in configuratoin' '
test_must_fail git tag -l "foo*"
'
+test_expect_success 'version sort handles empty value for versionsort.{prereleaseSuffix,suffix}' '
+ cp .git/config .git/config.orig &&
+ test_when_finished mv .git/config.orig .git/config &&
+
+ cat >>.git/config <<-\EOF &&
+ [versionsort]
+ prereleaseSuffix
+ suffix
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''versionsort.suffix'\''
+ error: missing value for '\''versionsort.prereleasesuffix'\''
+ EOF
+ git tag -l --sort=version:refname 2>actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'version sort with prerelease reordering' '
test_config versionsort.prereleaseSuffix -rc &&
git tag foo1.6-rc1 &&
@@ -2001,6 +2046,22 @@ test_expect_success '--format should list tags as per format given' '
test_cmp expect actual
'
+test_expect_success '--format --omit-empty works' '
+ cat >expect <<-\EOF &&
+ refname : refs/tags/v1.0
+
+ refname : refs/tags/v1.1.3
+ EOF
+ git tag -l --format="%(if:notequals=refs/tags/v1.0.1)%(refname)%(then)refname : %(refname)%(end)" "v1*" >actual &&
+ test_cmp expect actual &&
+ cat >expect <<-\EOF &&
+ refname : refs/tags/v1.0
+ refname : refs/tags/v1.1.3
+ EOF
+ git tag -l --omit-empty --format="%(if:notequals=refs/tags/v1.0.1)%(refname)%(then)refname : %(refname)%(end)" "v1*" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'git tag -l with --format="%(rest)" must fail' '
test_must_fail git tag -l --format="%(rest)" "v1*"
'
@@ -2127,4 +2188,23 @@ test_expect_success 'Does --[no-]contains stop at commits? Yes!' '
test_cmp expected actual
'
+test_expect_success 'If tag is created then tag message file is unlinked' '
+ test_when_finished "git tag -d foo" &&
+ write_script fakeeditor <<-\EOF &&
+ echo Message >.git/TAG_EDITMSG
+ EOF
+ GIT_EDITOR=./fakeeditor git tag -a foo &&
+ test_path_is_missing .git/TAG_EDITMSG
+'
+
+test_expect_success 'If tag cannot be created then tag message file is not unlinked' '
+ test_when_finished "git tag -d foo/bar && rm .git/TAG_EDITMSG" &&
+ write_script fakeeditor <<-\EOF &&
+ echo Message >.git/TAG_EDITMSG
+ EOF
+ git tag foo/bar &&
+ test_must_fail env GIT_EDITOR=./fakeeditor git tag -a foo &&
+ test_path_exists .git/TAG_EDITMSG
+'
+
test_done
diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh
index 10faa64515..6f526c37c2 100755
--- a/t/t7030-verify-tag.sh
+++ b/t/t7030-verify-tag.sh
@@ -115,7 +115,7 @@ test_expect_success GPGSM 'verify and show signatures x509 with high minTrustLev
test_expect_success GPG 'detect fudged signature' '
git cat-file tag seventh-signed >raw &&
- sed -e "/^tag / s/seventh/7th forged/" raw >forged1 &&
+ sed -e "/^tag / s/seventh/7th-forged/" raw >forged1 &&
git hash-object -w -t tag forged1 >forged1.tag &&
test_must_fail git verify-tag $(cat forged1.tag) 2>actual1 &&
grep "BAD signature from" actual1 &&
diff --git a/t/t7031-verify-tag-signed-ssh.sh b/t/t7031-verify-tag-signed-ssh.sh
index 1cb36b9ab8..20913b3713 100755
--- a/t/t7031-verify-tag-signed-ssh.sh
+++ b/t/t7031-verify-tag-signed-ssh.sh
@@ -125,7 +125,7 @@ test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'verify-tag failes with tag date ou
test_expect_success GPGSSH 'detect fudged ssh signature' '
test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
git cat-file tag seventh-signed >raw &&
- sed -e "/^tag / s/seventh/7th forged/" raw >forged1 &&
+ sed -e "/^tag / s/seventh/7th-forged/" raw >forged1 &&
git hash-object -w -t tag forged1 >forged1.tag &&
test_must_fail git verify-tag $(cat forged1.tag) 2>actual1 &&
grep "${GPGSSH_BAD_SIGNATURE}" actual1 &&
@@ -200,4 +200,14 @@ test_expect_success GPGSSH 'verifying a forged tag with --format should fail sil
test_must_be_empty actual-forged
'
+test_expect_success GPGSSH 'rev-list --format=%G' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git rev-list -1 --format="%G? %H" sixth-signed >actual &&
+ cat >expect <<-EOF &&
+ commit $(git rev-parse sixth-signed^0)
+ G $(git rev-parse sixth-signed^0)
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7101-reset-empty-subdirs.sh b/t/t7101-reset-empty-subdirs.sh
index 638bb04e21..89cf98b30c 100755
--- a/t/t7101-reset-empty-subdirs.sh
+++ b/t/t7101-reset-empty-subdirs.sh
@@ -10,57 +10,57 @@ TEST_PASSES_SANITIZE_LEAK=true
. "$TEST_DIRECTORY"/lib-diff-data.sh
test_expect_success 'creating initial files' '
- mkdir path0 &&
- COPYING_test_data >path0/COPYING &&
- git add path0/COPYING &&
- git commit -m add -a
+ mkdir path0 &&
+ COPYING_test_data >path0/COPYING &&
+ git add path0/COPYING &&
+ git commit -m add -a
'
test_expect_success 'creating second files' '
- mkdir path1 &&
- mkdir path1/path2 &&
- COPYING_test_data >path1/path2/COPYING &&
- COPYING_test_data >path1/COPYING &&
- COPYING_test_data >COPYING &&
- COPYING_test_data >path0/COPYING-TOO &&
- git add path1/path2/COPYING &&
- git add path1/COPYING &&
- git add COPYING &&
- git add path0/COPYING-TOO &&
- git commit -m change -a
+ mkdir path1 &&
+ mkdir path1/path2 &&
+ COPYING_test_data >path1/path2/COPYING &&
+ COPYING_test_data >path1/COPYING &&
+ COPYING_test_data >COPYING &&
+ COPYING_test_data >path0/COPYING-TOO &&
+ git add path1/path2/COPYING &&
+ git add path1/COPYING &&
+ git add COPYING &&
+ git add path0/COPYING-TOO &&
+ git commit -m change -a
'
test_expect_success 'resetting tree HEAD^' '
- git reset --hard HEAD^
+ git reset --hard HEAD^
'
test_expect_success 'checking initial files exist after rewind' '
- test -d path0 &&
- test -f path0/COPYING
+ test -d path0 &&
+ test -f path0/COPYING
'
test_expect_success 'checking lack of path1/path2/COPYING' '
- ! test -f path1/path2/COPYING
+ ! test -f path1/path2/COPYING
'
test_expect_success 'checking lack of path1/COPYING' '
- ! test -f path1/COPYING
+ ! test -f path1/COPYING
'
test_expect_success 'checking lack of COPYING' '
- ! test -f COPYING
+ ! test -f COPYING
'
test_expect_success 'checking checking lack of path1/COPYING-TOO' '
- ! test -f path0/COPYING-TOO
+ ! test -f path0/COPYING-TOO
'
test_expect_success 'checking lack of path1/path2' '
- ! test -d path1/path2
+ ! test -d path1/path2
'
test_expect_success 'checking lack of path1' '
- ! test -d path1
+ ! test -d path1
'
test_done
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index 22477f3a31..4287863ae6 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -71,6 +71,16 @@ check_changes () {
done | test_cmp .cat_expect -
}
+# no negated form for various type of resets
+for opt in soft mixed hard merge keep
+do
+ test_expect_success "no 'git reset --no-$opt'" '
+ test_when_finished "rm -f err" &&
+ test_must_fail git reset --no-$opt 2>err &&
+ grep "error: unknown option .no-$opt." err
+ '
+done
+
test_expect_success 'reset --hard message' '
hex=$(git log -1 --format="%h") &&
git reset --hard >.actual &&
diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh
index a60153f9f3..18bbd9975e 100755
--- a/t/t7103-reset-bare.sh
+++ b/t/t7103-reset-bare.sh
@@ -63,7 +63,7 @@ test_expect_success '"mixed" reset is not allowed in bare' '
test_must_fail git reset --mixed HEAD^
'
-test_expect_success !SANITIZE_LEAK '"soft" reset is allowed in bare' '
+test_expect_success '"soft" reset is allowed in bare' '
git reset --soft HEAD^ &&
git show --pretty=format:%s >out &&
echo one >expect &&
diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh
index fc2a6cf5c7..9b46da7aaa 100755
--- a/t/t7105-reset-patch.sh
+++ b/t/t7105-reset-patch.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git reset --patch'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-patch-mode.sh
test_expect_success PERL 'setup' '
diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh
index ecb85c3b82..a0b67a0b84 100755
--- a/t/t7106-reset-unborn-branch.sh
+++ b/t/t7106-reset-unborn-branch.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git reset should work on unborn branch'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh
index 523efbecde..af5ea406db 100755
--- a/t/t7107-reset-pathspec-file.sh
+++ b/t/t7107-reset-pathspec-file.sh
@@ -2,6 +2,7 @@
test_description='reset --pathspec-from-file'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_tick
diff --git a/t/t7110-reset-merge.sh b/t/t7110-reset-merge.sh
index eb881be95b..772480a345 100755
--- a/t/t7110-reset-merge.sh
+++ b/t/t7110-reset-merge.sh
@@ -9,17 +9,17 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
- printf "line %d\n" 1 2 3 >file1 &&
- cat file1 >file2 &&
- git add file1 file2 &&
- test_tick &&
- git commit -m "Initial commit" &&
- git tag initial &&
- echo line 4 >>file1 &&
- cat file1 >file2 &&
- test_tick &&
- git commit -m "add line 4 to file1" file1 &&
- git tag second
+ printf "line %d\n" 1 2 3 >file1 &&
+ cat file1 >file2 &&
+ git add file1 file2 &&
+ test_tick &&
+ git commit -m "Initial commit" &&
+ git tag initial &&
+ echo line 4 >>file1 &&
+ cat file1 >file2 &&
+ test_tick &&
+ git commit -m "add line 4 to file1" file1 &&
+ git tag second
'
# The next test will test the following:
@@ -29,19 +29,19 @@ test_expect_success setup '
# file1: C C C D --merge D D D
# file2: C D D D --merge C D D
test_expect_success 'reset --merge is ok with changes in file it does not touch' '
- git reset --merge HEAD^ &&
- ! grep 4 file1 &&
- grep 4 file2 &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
- test -z "$(git diff --cached)"
+ git reset --merge HEAD^ &&
+ ! grep 4 file1 &&
+ grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
+ test -z "$(git diff --cached)"
'
test_expect_success 'reset --merge is ok when switching back' '
- git reset --merge second &&
- grep 4 file1 &&
- grep 4 file2 &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
- test -z "$(git diff --cached)"
+ git reset --merge second &&
+ grep 4 file1 &&
+ grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+ test -z "$(git diff --cached)"
'
# The next test will test the following:
@@ -51,21 +51,21 @@ test_expect_success 'reset --merge is ok when switching back' '
# file1: C C C D --keep D D D
# file2: C D D D --keep C D D
test_expect_success 'reset --keep is ok with changes in file it does not touch' '
- git reset --hard second &&
- cat file1 >file2 &&
- git reset --keep HEAD^ &&
- ! grep 4 file1 &&
- grep 4 file2 &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
- test -z "$(git diff --cached)"
+ git reset --hard second &&
+ cat file1 >file2 &&
+ git reset --keep HEAD^ &&
+ ! grep 4 file1 &&
+ grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
+ test -z "$(git diff --cached)"
'
test_expect_success 'reset --keep is ok when switching back' '
- git reset --keep second &&
- grep 4 file1 &&
- grep 4 file2 &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
- test -z "$(git diff --cached)"
+ git reset --keep second &&
+ grep 4 file1 &&
+ grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+ test -z "$(git diff --cached)"
'
# The next test will test the following:
@@ -75,28 +75,28 @@ test_expect_success 'reset --keep is ok when switching back' '
# file1: B B C D --merge D D D
# file2: C D D D --merge C D D
test_expect_success 'reset --merge discards changes added to index (1)' '
- git reset --hard second &&
- cat file1 >file2 &&
- echo "line 5" >> file1 &&
- git add file1 &&
- git reset --merge HEAD^ &&
- ! grep 4 file1 &&
- ! grep 5 file1 &&
- grep 4 file2 &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
- test -z "$(git diff --cached)"
+ git reset --hard second &&
+ cat file1 >file2 &&
+ echo "line 5" >> file1 &&
+ git add file1 &&
+ git reset --merge HEAD^ &&
+ ! grep 4 file1 &&
+ ! grep 5 file1 &&
+ grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
+ test -z "$(git diff --cached)"
'
test_expect_success 'reset --merge is ok again when switching back (1)' '
- git reset --hard initial &&
- echo "line 5" >> file2 &&
- git add file2 &&
- git reset --merge second &&
- ! grep 4 file2 &&
- ! grep 5 file1 &&
- grep 4 file1 &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
- test -z "$(git diff --cached)"
+ git reset --hard initial &&
+ echo "line 5" >> file2 &&
+ git add file2 &&
+ git reset --merge second &&
+ ! grep 4 file2 &&
+ ! grep 5 file1 &&
+ grep 4 file1 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+ test -z "$(git diff --cached)"
'
# The next test will test the following:
@@ -105,10 +105,10 @@ test_expect_success 'reset --merge is ok again when switching back (1)' '
# ----------------------------------------------------
# file1: B B C D --keep (disallowed)
test_expect_success 'reset --keep fails with changes in index in files it touches' '
- git reset --hard second &&
- echo "line 5" >> file1 &&
- git add file1 &&
- test_must_fail git reset --keep HEAD^
+ git reset --hard second &&
+ echo "line 5" >> file1 &&
+ git add file1 &&
+ test_must_fail git reset --keep HEAD^
'
# The next test will test the following:
@@ -118,23 +118,23 @@ test_expect_success 'reset --keep fails with changes in index in files it touche
# file1: C C C D --merge D D D
# file2: C C D D --merge D D D
test_expect_success 'reset --merge discards changes added to index (2)' '
- git reset --hard second &&
- echo "line 4" >> file2 &&
- git add file2 &&
- git reset --merge HEAD^ &&
- ! grep 4 file2 &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
- test -z "$(git diff)" &&
- test -z "$(git diff --cached)"
+ git reset --hard second &&
+ echo "line 4" >> file2 &&
+ git add file2 &&
+ git reset --merge HEAD^ &&
+ ! grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
+ test -z "$(git diff)" &&
+ test -z "$(git diff --cached)"
'
test_expect_success 'reset --merge is ok again when switching back (2)' '
- git reset --hard initial &&
- git reset --merge second &&
- ! grep 4 file2 &&
- grep 4 file1 &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
- test -z "$(git diff --cached)"
+ git reset --hard initial &&
+ git reset --merge second &&
+ ! grep 4 file2 &&
+ grep 4 file1 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+ test -z "$(git diff --cached)"
'
# The next test will test the following:
@@ -144,21 +144,21 @@ test_expect_success 'reset --merge is ok again when switching back (2)' '
# file1: C C C D --keep D D D
# file2: C C D D --keep C D D
test_expect_success 'reset --keep keeps changes it does not touch' '
- git reset --hard second &&
- echo "line 4" >> file2 &&
- git add file2 &&
- git reset --keep HEAD^ &&
- grep 4 file2 &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
- test -z "$(git diff --cached)"
+ git reset --hard second &&
+ echo "line 4" >> file2 &&
+ git add file2 &&
+ git reset --keep HEAD^ &&
+ grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
+ test -z "$(git diff --cached)"
'
test_expect_success 'reset --keep keeps changes when switching back' '
- git reset --keep second &&
- grep 4 file2 &&
- grep 4 file1 &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
- test -z "$(git diff --cached)"
+ git reset --keep second &&
+ grep 4 file2 &&
+ grep 4 file1 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+ test -z "$(git diff --cached)"
'
# The next test will test the following:
@@ -167,14 +167,14 @@ test_expect_success 'reset --keep keeps changes when switching back' '
# ----------------------------------------------------
# file1: A B B C --merge (disallowed)
test_expect_success 'reset --merge fails with changes in file it touches' '
- git reset --hard second &&
- echo "line 5" >> file1 &&
- test_tick &&
- git commit -m "add line 5" file1 &&
- sed -e "s/line 1/changed line 1/" <file1 >file3 &&
- mv file3 file1 &&
- test_must_fail git reset --merge HEAD^ 2>err.log &&
- grep file1 err.log | grep "not uptodate"
+ git reset --hard second &&
+ echo "line 5" >> file1 &&
+ test_tick &&
+ git commit -m "add line 5" file1 &&
+ sed -e "s/line 1/changed line 1/" <file1 >file3 &&
+ mv file3 file1 &&
+ test_must_fail git reset --merge HEAD^ 2>err.log &&
+ grep file1 err.log | grep "not uptodate"
'
# The next test will test the following:
@@ -183,36 +183,36 @@ test_expect_success 'reset --merge fails with changes in file it touches' '
# ----------------------------------------------------
# file1: A B B C --keep (disallowed)
test_expect_success 'reset --keep fails with changes in file it touches' '
- git reset --hard second &&
- echo "line 5" >> file1 &&
- test_tick &&
- git commit -m "add line 5" file1 &&
- sed -e "s/line 1/changed line 1/" <file1 >file3 &&
- mv file3 file1 &&
- test_must_fail git reset --keep HEAD^ 2>err.log &&
- grep file1 err.log | grep "not uptodate"
+ git reset --hard second &&
+ echo "line 5" >> file1 &&
+ test_tick &&
+ git commit -m "add line 5" file1 &&
+ sed -e "s/line 1/changed line 1/" <file1 >file3 &&
+ mv file3 file1 &&
+ test_must_fail git reset --keep HEAD^ 2>err.log &&
+ grep file1 err.log | grep "not uptodate"
'
test_expect_success 'setup 3 different branches' '
- git reset --hard second &&
- git branch branch1 &&
- git branch branch2 &&
- git branch branch3 &&
- git checkout branch1 &&
- echo "line 5 in branch1" >> file1 &&
- test_tick &&
- git commit -a -m "change in branch1" &&
- git checkout branch2 &&
- echo "line 5 in branch2" >> file1 &&
- test_tick &&
- git commit -a -m "change in branch2" &&
- git tag third &&
- git checkout branch3 &&
- echo a new file >file3 &&
- rm -f file1 &&
- git add file3 &&
- test_tick &&
- git commit -a -m "change in branch3"
+ git reset --hard second &&
+ git branch branch1 &&
+ git branch branch2 &&
+ git branch branch3 &&
+ git checkout branch1 &&
+ echo "line 5 in branch1" >> file1 &&
+ test_tick &&
+ git commit -a -m "change in branch1" &&
+ git checkout branch2 &&
+ echo "line 5 in branch2" >> file1 &&
+ test_tick &&
+ git commit -a -m "change in branch2" &&
+ git tag third &&
+ git checkout branch3 &&
+ echo a new file >file3 &&
+ rm -f file1 &&
+ git add file3 &&
+ test_tick &&
+ git commit -a -m "change in branch3"
'
# The next test will test the following:
@@ -221,12 +221,12 @@ test_expect_success 'setup 3 different branches' '
# ----------------------------------------------------
# file1: X U B C --merge C C C
test_expect_success '"reset --merge HEAD^" is ok with pending merge' '
- git checkout third &&
- test_must_fail git merge branch1 &&
- git reset --merge HEAD^ &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
- test -z "$(git diff --cached)" &&
- test -z "$(git diff)"
+ git checkout third &&
+ test_must_fail git merge branch1 &&
+ git reset --merge HEAD^ &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+ test -z "$(git diff --cached)" &&
+ test -z "$(git diff)"
'
# The next test will test the following:
@@ -235,10 +235,10 @@ test_expect_success '"reset --merge HEAD^" is ok with pending merge' '
# ----------------------------------------------------
# file1: X U B C --keep (disallowed)
test_expect_success '"reset --keep HEAD^" fails with pending merge' '
- git reset --hard third &&
- test_must_fail git merge branch1 &&
- test_must_fail git reset --keep HEAD^ 2>err.log &&
- test_i18ngrep "middle of a merge" err.log
+ git reset --hard third &&
+ test_must_fail git merge branch1 &&
+ test_must_fail git reset --keep HEAD^ 2>err.log &&
+ test_i18ngrep "middle of a merge" err.log
'
# The next test will test the following:
@@ -247,12 +247,12 @@ test_expect_success '"reset --keep HEAD^" fails with pending merge' '
# ----------------------------------------------------
# file1: X U B B --merge B B B
test_expect_success '"reset --merge HEAD" is ok with pending merge' '
- git reset --hard third &&
- test_must_fail git merge branch1 &&
- git reset --merge HEAD &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse third)" &&
- test -z "$(git diff --cached)" &&
- test -z "$(git diff)"
+ git reset --hard third &&
+ test_must_fail git merge branch1 &&
+ git reset --merge HEAD &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse third)" &&
+ test -z "$(git diff --cached)" &&
+ test -z "$(git diff)"
'
# The next test will test the following:
@@ -261,36 +261,36 @@ test_expect_success '"reset --merge HEAD" is ok with pending merge' '
# ----------------------------------------------------
# file1: X U B B --keep (disallowed)
test_expect_success '"reset --keep HEAD" fails with pending merge' '
- git reset --hard third &&
- test_must_fail git merge branch1 &&
- test_must_fail git reset --keep HEAD 2>err.log &&
- test_i18ngrep "middle of a merge" err.log
+ git reset --hard third &&
+ test_must_fail git merge branch1 &&
+ test_must_fail git reset --keep HEAD 2>err.log &&
+ test_i18ngrep "middle of a merge" err.log
'
test_expect_success '--merge is ok with added/deleted merge' '
- git reset --hard third &&
- rm -f file2 &&
- test_must_fail git merge branch3 &&
- ! test -f file2 &&
- test -f file3 &&
- git diff --exit-code file3 &&
- git diff --exit-code branch3 file3 &&
- git reset --merge HEAD &&
- ! test -f file3 &&
- ! test -f file2 &&
- git diff --exit-code --cached
+ git reset --hard third &&
+ rm -f file2 &&
+ test_must_fail git merge branch3 &&
+ ! test -f file2 &&
+ test -f file3 &&
+ git diff --exit-code file3 &&
+ git diff --exit-code branch3 file3 &&
+ git reset --merge HEAD &&
+ ! test -f file3 &&
+ ! test -f file2 &&
+ git diff --exit-code --cached
'
test_expect_success '--keep fails with added/deleted merge' '
- git reset --hard third &&
- rm -f file2 &&
- test_must_fail git merge branch3 &&
- ! test -f file2 &&
- test -f file3 &&
- git diff --exit-code file3 &&
- git diff --exit-code branch3 file3 &&
- test_must_fail git reset --keep HEAD 2>err.log &&
- test_i18ngrep "middle of a merge" err.log
+ git reset --hard third &&
+ rm -f file2 &&
+ test_must_fail git merge branch3 &&
+ ! test -f file2 &&
+ test -f file3 &&
+ git diff --exit-code file3 &&
+ git diff --exit-code branch3 file3 &&
+ test_must_fail git reset --keep HEAD 2>err.log &&
+ test_i18ngrep "middle of a merge" err.log
'
test_done
diff --git a/t/t7111-reset-table.sh b/t/t7111-reset-table.sh
index 78f25c1c7e..01b7c3503c 100755
--- a/t/t7111-reset-table.sh
+++ b/t/t7111-reset-table.sh
@@ -10,9 +10,9 @@ TEST_PASSES_SANITIZE_LEAK=true
test_expect_success 'creating initial commits' '
- test_commit E file1 &&
- test_commit D file1 &&
- test_commit C file1
+ test_commit E file1 &&
+ test_commit D file1 &&
+ test_commit C file1
'
while read W1 I1 H1 T opt W2 I2 H2
@@ -74,13 +74,13 @@ B C C C keep B C C
EOF
test_expect_success 'setting up branches to test with unmerged entries' '
- git reset --hard C &&
- git branch branch1 &&
- git branch branch2 &&
- git checkout branch1 &&
- test_commit B1 file1 &&
- git checkout branch2 &&
- test_commit B file1
+ git reset --hard C &&
+ git branch branch1 &&
+ git branch branch2 &&
+ git checkout branch1 &&
+ test_commit B1 file1 &&
+ git checkout branch2 &&
+ test_commit B file1
'
while read W1 I1 H1 T opt W2 I2 H2
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 61ad47b0c1..35b9e6ed6b 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -372,75 +372,75 @@ test_expect_success 'checkout specific path while in subdirectory' '
'
test_expect_success 'checkout w/--track sets up tracking' '
- git config branch.autosetupmerge false &&
- git checkout main &&
- git checkout --track -b track1 &&
- test "$(git config branch.track1.remote)" &&
- test "$(git config branch.track1.merge)"
+ git config branch.autosetupmerge false &&
+ git checkout main &&
+ git checkout --track -b track1 &&
+ test "$(git config branch.track1.remote)" &&
+ test "$(git config branch.track1.merge)"
'
test_expect_success 'checkout w/autosetupmerge=always sets up tracking' '
- test_when_finished git config branch.autosetupmerge false &&
- git config branch.autosetupmerge always &&
- git checkout main &&
- git checkout -b track2 &&
- test "$(git config branch.track2.remote)" &&
- test "$(git config branch.track2.merge)"
+ test_when_finished git config branch.autosetupmerge false &&
+ git config branch.autosetupmerge always &&
+ git checkout main &&
+ git checkout -b track2 &&
+ test "$(git config branch.track2.remote)" &&
+ test "$(git config branch.track2.merge)"
'
test_expect_success 'checkout w/--track from non-branch HEAD fails' '
- git checkout main^0 &&
- test_must_fail git symbolic-ref HEAD &&
- test_must_fail git checkout --track -b track &&
- test_must_fail git rev-parse --verify track &&
- test_must_fail git symbolic-ref HEAD &&
- test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)"
+ git checkout main^0 &&
+ test_must_fail git symbolic-ref HEAD &&
+ test_must_fail git checkout --track -b track &&
+ test_must_fail git rev-parse --verify track &&
+ test_must_fail git symbolic-ref HEAD &&
+ test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)"
'
test_expect_success 'checkout w/--track from tag fails' '
- git checkout main^0 &&
- test_must_fail git symbolic-ref HEAD &&
- test_must_fail git checkout --track -b track frotz &&
- test_must_fail git rev-parse --verify track &&
- test_must_fail git symbolic-ref HEAD &&
- test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)"
+ git checkout main^0 &&
+ test_must_fail git symbolic-ref HEAD &&
+ test_must_fail git checkout --track -b track frotz &&
+ test_must_fail git rev-parse --verify track &&
+ test_must_fail git symbolic-ref HEAD &&
+ test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)"
'
test_expect_success 'detach a symbolic link HEAD' '
- git checkout main &&
- git config --bool core.prefersymlinkrefs yes &&
- git checkout side &&
- git checkout main &&
- it=$(git symbolic-ref HEAD) &&
- test "z$it" = zrefs/heads/main &&
- here=$(git rev-parse --verify refs/heads/main) &&
- git checkout side^ &&
- test "z$(git rev-parse --verify refs/heads/main)" = "z$here"
+ git checkout main &&
+ git config --bool core.prefersymlinkrefs yes &&
+ git checkout side &&
+ git checkout main &&
+ it=$(git symbolic-ref HEAD) &&
+ test "z$it" = zrefs/heads/main &&
+ here=$(git rev-parse --verify refs/heads/main) &&
+ git checkout side^ &&
+ test "z$(git rev-parse --verify refs/heads/main)" = "z$here"
'
test_expect_success 'checkout with --track fakes a sensible -b <name>' '
- git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" &&
- git update-ref refs/remotes/origin/koala/bear renamer &&
+ git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" &&
+ git update-ref refs/remotes/origin/koala/bear renamer &&
- git checkout --track origin/koala/bear &&
- test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
+ git checkout --track origin/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
- git checkout main && git branch -D koala/bear &&
+ git checkout main && git branch -D koala/bear &&
- git checkout --track refs/remotes/origin/koala/bear &&
- test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
+ git checkout --track refs/remotes/origin/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
- git checkout main && git branch -D koala/bear &&
+ git checkout main && git branch -D koala/bear &&
- git checkout --track remotes/origin/koala/bear &&
- test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
+ git checkout --track remotes/origin/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
'
test_expect_success 'checkout with --track, but without -b, fails with too short tracked name' '
- test_must_fail git checkout --track renamer
+ test_must_fail git checkout --track renamer
'
setup_conflicting_index () {
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index c975eb54d2..0ef7b78457 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -120,7 +120,7 @@ test_expect_success 'git clean with relative prefix' '
grep part3 |
sed -n -e "s|^Would remove ||p"
) &&
- verbose test "$would_clean" = ../src/part3.c
+ test "$would_clean" = ../src/part3.c
'
test_expect_success 'git clean with absolute path' '
@@ -133,7 +133,7 @@ test_expect_success 'git clean with absolute path' '
grep part3 |
sed -n -e "s|^Would remove ||p"
) &&
- verbose test "$would_clean" = ../src/part3.c
+ test "$would_clean" = ../src/part3.c
'
test_expect_success 'git clean with out of work tree relative path' '
diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh
index a07e8b86de..d82a3210a1 100755
--- a/t/t7301-clean-interactive.sh
+++ b/t/t7301-clean-interactive.sh
@@ -2,6 +2,7 @@
test_description='git clean -i basic tests'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index a989aafaf5..d9fbabb2b9 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -579,6 +579,16 @@ test_expect_success 'status should be "modified" after submodule commit' '
grep "^+$rev2" list
'
+test_expect_success '"submodule --cached" command forms should be identical' '
+ git submodule status --cached >expect &&
+
+ git submodule --cached >actual &&
+ test_cmp expect actual &&
+
+ git submodule --cached status >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'the --cached sha1 should be rev1' '
git submodule --cached status >list &&
grep "^+$rev1" list
@@ -1341,6 +1351,22 @@ test_expect_success 'clone active submodule without submodule url set' '
)
'
+test_expect_success 'update submodules without url set in .gitconfig' '
+ test_when_finished "rm -rf multisuper_clone" &&
+ git clone file://"$pwd"/multisuper multisuper_clone &&
+
+ git -C multisuper_clone submodule init &&
+ for s in sub0 sub1 sub2 sub3
+ do
+ key=submodule.$s.url &&
+ git -C multisuper_clone config --local --unset $key &&
+ git -C multisuper_clone config --file .gitmodules --unset $key || return 1
+ done &&
+
+ test_must_fail git -C multisuper_clone submodule update 2>err &&
+ grep "cannot clone submodule .sub[0-3]. without a URL" err
+'
+
test_expect_success 'clone --recurse-submodules with a pathspec works' '
test_when_finished "rm -rf multisuper_clone" &&
cat >expected <<-\EOF &&
diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh
index ebeca12a71..2b3c363078 100755
--- a/t/t7402-submodule-rebase.sh
+++ b/t/t7402-submodule-rebase.sh
@@ -5,6 +5,7 @@
test_description='Test rebasing, stashing, etc. with submodules'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
@@ -55,12 +56,15 @@ chmod a+x fake-editor.sh
test_expect_success 'interactive rebase with a dirty submodule' '
- test submodule = $(git diff --name-only) &&
+ echo submodule >expect &&
+ git diff --name-only >actual &&
+ test_cmp expect actual &&
HEAD=$(git rev-parse HEAD) &&
GIT_EDITOR="\"$(pwd)/fake-editor.sh\"" EDITOR_TEXT="pick $HEAD" \
git rebase -i HEAD^ &&
- test submodule = $(git diff --name-only)
-
+ echo submodule >expect &&
+ git diff --name-only >actual &&
+ test_cmp expect actual
'
test_expect_success 'rebase with dirty file and submodule fails' '
@@ -82,11 +86,19 @@ test_expect_success 'stash with a dirty submodule' '
CURRENT=$(cd submodule && git rev-parse HEAD) &&
git stash &&
test new != $(cat file) &&
- test submodule = $(git diff --name-only) &&
- test $CURRENT = $(cd submodule && git rev-parse HEAD) &&
+ echo submodule >expect &&
+ git diff --name-only >actual &&
+ test_cmp expect actual &&
+
+ echo "$CURRENT" >expect &&
+ git -C submodule rev-parse HEAD >actual &&
+ test_cmp expect actual &&
+
git stash apply &&
test new = $(cat file) &&
- test $CURRENT = $(cd submodule && git rev-parse HEAD)
+ echo "$CURRENT" >expect &&
+ git -C submodule rev-parse HEAD >actual &&
+ test_cmp expect actual
'
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index ea92ef52a5..ff09443a0a 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -11,6 +11,7 @@ These tests exercise the "git submodule sync" subcommand.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index f094e3d7f3..00651c25cb 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -1179,4 +1179,27 @@ test_expect_success 'submodule update --recursive skip submodules with strategy=
test_cmp expect.err actual.err
'
+add_submodule_commit_and_validate () {
+ HASH=$(git rev-parse HEAD) &&
+ git update-index --add --cacheinfo 160000,$HASH,sub &&
+ git commit -m "create submodule" &&
+ echo "160000 commit $HASH sub" >expect &&
+ git ls-tree HEAD -- sub >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'commit with staged submodule change' '
+ add_submodule_commit_and_validate
+'
+
+test_expect_success 'commit with staged submodule change with ignoreSubmodules dirty' '
+ test_config diff.ignoreSubmodules dirty &&
+ add_submodule_commit_and_validate
+'
+
+test_expect_success 'commit with staged submodule change with ignoreSubmodules all' '
+ test_config diff.ignoreSubmodules all &&
+ add_submodule_commit_and_validate
+'
+
test_done
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index 59bd150166..8d7b234beb 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -154,6 +154,11 @@ test_expect_success 'use "submodule foreach" to checkout 2nd level submodule' '
)
'
+test_expect_success 'usage: foreach -- --not-an-option' '
+ test_expect_code 1 git submodule foreach -- --not-an-option &&
+ test_expect_code 1 git -C clone2 submodule foreach -- --not-an-option
+'
+
test_expect_success 'use "foreach --recursive" to checkout all submodules' '
(
cd clone2 &&
diff --git a/t/t7409-submodule-detached-work-tree.sh b/t/t7409-submodule-detached-work-tree.sh
index 374ed481e9..574a6fc526 100755
--- a/t/t7409-submodule-detached-work-tree.sh
+++ b/t/t7409-submodule-detached-work-tree.sh
@@ -13,6 +13,7 @@ TEST_NO_CREATE_REPO=1
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh
index c583c4e373..c0167944ab 100755
--- a/t/t7411-submodule-config.sh
+++ b/t/t7411-submodule-config.sh
@@ -137,44 +137,44 @@ test_expect_success 'error in history in fetchrecursesubmodule lets continue' '
)
'
-test_expect_success 'reading submodules config from the working tree with "submodule--helper config"' '
+test_expect_success 'reading submodules config from the working tree' '
(cd super &&
echo "../submodule" >expect &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
)
'
-test_expect_success 'unsetting submodules config from the working tree with "submodule--helper config --unset"' '
+test_expect_success 'unsetting submodules config from the working tree' '
(cd super &&
- git submodule--helper config --unset submodule.submodule.url &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-unset submodule.submodule.url &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_must_be_empty actual
)
'
-test_expect_success 'writing submodules config with "submodule--helper config"' '
+test_expect_success 'writing submodules config' '
(cd super &&
echo "new_url" >expect &&
- git submodule--helper config submodule.submodule.url "new_url" &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-set submodule.submodule.url "new_url" &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
)
'
-test_expect_success 'overwriting unstaged submodules config with "submodule--helper config"' '
+test_expect_success 'overwriting unstaged submodules config' '
test_when_finished "git -C super checkout .gitmodules" &&
(cd super &&
echo "newer_url" >expect &&
- git submodule--helper config submodule.submodule.url "newer_url" &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-set submodule.submodule.url "newer_url" &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
)
'
test_expect_success 'writeable .gitmodules when it is in the working tree' '
- git -C super submodule--helper config --check-writeable
+ test-tool -C super submodule config-writeable
'
test_expect_success 'writeable .gitmodules when it is nowhere in the repository' '
@@ -183,7 +183,7 @@ test_expect_success 'writeable .gitmodules when it is nowhere in the repository'
(cd super &&
git rm .gitmodules &&
git commit -m "remove .gitmodules from the current branch" &&
- git submodule--helper config --check-writeable
+ test-tool submodule config-writeable
)
'
@@ -191,7 +191,7 @@ test_expect_success 'non-writeable .gitmodules when it is in the index but not i
test_when_finished "git -C super checkout .gitmodules" &&
(cd super &&
rm -f .gitmodules &&
- test_must_fail git submodule--helper config --check-writeable
+ test_must_fail test-tool submodule config-writeable
)
'
@@ -200,7 +200,7 @@ test_expect_success 'non-writeable .gitmodules when it is in the current branch
test_when_finished "git -C super reset --hard $ORIG" &&
(cd super &&
git rm .gitmodules &&
- test_must_fail git submodule--helper config --check-writeable
+ test_must_fail test-tool submodule config-writeable
)
'
@@ -208,11 +208,11 @@ test_expect_success 'reading submodules config from the index when .gitmodules i
ORIG=$(git -C super rev-parse HEAD) &&
test_when_finished "git -C super reset --hard $ORIG" &&
(cd super &&
- git submodule--helper config submodule.submodule.url "staged_url" &&
+ test-tool submodule config-set submodule.submodule.url "staged_url" &&
git add .gitmodules &&
rm -f .gitmodules &&
echo "staged_url" >expect &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
)
'
@@ -223,7 +223,7 @@ test_expect_success 'reading submodules config from the current branch when .git
(cd super &&
git rm .gitmodules &&
echo "../submodule" >expect &&
- git submodule--helper config submodule.submodule.url >actual &&
+ test-tool submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
)
'
diff --git a/t/t7412-submodule-absorbgitdirs.sh b/t/t7412-submodule-absorbgitdirs.sh
index 2859695c6d..f778321857 100755
--- a/t/t7412-submodule-absorbgitdirs.sh
+++ b/t/t7412-submodule-absorbgitdirs.sh
@@ -10,6 +10,7 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a real submodule' '
+ cwd="$(pwd)" &&
git init sub1 &&
test_commit -C sub1 first &&
git submodule add ./sub1 &&
@@ -18,13 +19,21 @@ test_expect_success 'setup a real submodule' '
'
test_expect_success 'absorb the git dir' '
+ >expect &&
+ >actual &&
>expect.1 &&
>expect.2 &&
>actual.1 &&
>actual.2 &&
git status >expect.1 &&
git -C sub1 rev-parse HEAD >expect.2 &&
- git submodule absorbgitdirs &&
+ cat >expect <<-EOF &&
+ Migrating git directory of '\''sub1'\'' from
+ '\''$cwd/sub1/.git'\'' to
+ '\''$cwd/.git/modules/sub1'\''
+ EOF
+ git submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual &&
git fsck &&
test -f sub1/.git &&
test -d .git/modules/sub1 &&
@@ -37,7 +46,8 @@ test_expect_success 'absorb the git dir' '
test_expect_success 'absorbing does not fail for deinitialized submodules' '
test_when_finished "git submodule update --init" &&
git submodule deinit --all &&
- git submodule absorbgitdirs &&
+ git submodule absorbgitdirs 2>err &&
+ test_must_be_empty err &&
test -d .git/modules/sub1 &&
test -d sub1 &&
! test -e sub1/.git
@@ -56,7 +66,13 @@ test_expect_success 'setup nested submodule' '
test_expect_success 'absorb the git dir in a nested submodule' '
git status >expect.1 &&
git -C sub1/nested rev-parse HEAD >expect.2 &&
- git submodule absorbgitdirs &&
+ cat >expect <<-EOF &&
+ Migrating git directory of '\''sub1/nested'\'' from
+ '\''$cwd/sub1/nested/.git'\'' to
+ '\''$cwd/.git/modules/sub1/modules/nested'\''
+ EOF
+ git submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual &&
test -f sub1/nested/.git &&
test -d .git/modules/sub1/modules/nested &&
git status >actual.1 &&
@@ -87,7 +103,13 @@ test_expect_success 're-setup nested submodule' '
test_expect_success 'absorb the git dir in a nested submodule' '
git status >expect.1 &&
git -C sub1/nested rev-parse HEAD >expect.2 &&
- git submodule absorbgitdirs &&
+ cat >expect <<-EOF &&
+ Migrating git directory of '\''sub1'\'' from
+ '\''$cwd/sub1/.git'\'' to
+ '\''$cwd/.git/modules/sub1'\''
+ EOF
+ git submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual &&
test -f sub1/.git &&
test -f sub1/nested/.git &&
test -d .git/modules/sub1/modules/nested &&
@@ -97,6 +119,27 @@ test_expect_success 'absorb the git dir in a nested submodule' '
test_cmp expect.2 actual.2
'
+test_expect_success 'absorb the git dir outside of primary worktree' '
+ test_when_finished "rm -rf repo-bare.git" &&
+ git clone --bare . repo-bare.git &&
+ test_when_finished "rm -rf repo-wt" &&
+ git -C repo-bare.git worktree add ../repo-wt &&
+
+ test_when_finished "rm -f .gitconfig" &&
+ test_config_global protocol.file.allow always &&
+ git -C repo-wt submodule update --init &&
+ git init repo-wt/sub2 &&
+ test_commit -C repo-wt/sub2 A &&
+ git -C repo-wt submodule add ./sub2 sub2 &&
+ cat >expect <<-EOF &&
+ Migrating git directory of '\''sub2'\'' from
+ '\''$cwd/repo-wt/sub2/.git'\'' to
+ '\''$cwd/repo-bare.git/worktrees/repo-wt/modules/sub2'\''
+ EOF
+ git -C repo-wt submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'setup a gitlink with missing .gitmodules entry' '
git init sub2 &&
test_commit -C sub2 first &&
@@ -107,7 +150,11 @@ test_expect_success 'setup a gitlink with missing .gitmodules entry' '
test_expect_success 'absorbing the git dir fails for incomplete submodules' '
git status >expect.1 &&
git -C sub2 rev-parse HEAD >expect.2 &&
- test_must_fail git submodule absorbgitdirs &&
+ cat >expect <<-\EOF &&
+ fatal: could not lookup name for submodule '\''sub2'\''
+ EOF
+ test_must_fail git submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual &&
git -C sub2 fsck &&
test -d sub2/.git &&
git status >actual &&
@@ -127,8 +174,11 @@ test_expect_success 'setup a submodule with multiple worktrees' '
'
test_expect_success 'absorbing fails for a submodule with multiple worktrees' '
- test_must_fail git submodule absorbgitdirs sub3 2>error &&
- test_i18ngrep "not supported" error
+ cat >expect <<-\EOF &&
+ fatal: could not lookup name for submodule '\''sub2'\''
+ EOF
+ test_must_fail git submodule absorbgitdirs 2>actual &&
+ test_cmp expect actual
'
test_done
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index 7cdc263764..887d181b72 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -51,6 +51,22 @@ test_expect_success 'is-active works with submodule.<name>.active config' '
test-tool -C super submodule is-active sub1
'
+test_expect_success 'is-active handles submodule.active config missing a value' '
+ cp super/.git/config super/.git/config.orig &&
+ test_when_finished mv super/.git/config.orig super/.git/config &&
+
+ cat >>super/.git/config <<-\EOF &&
+ [submodule]
+ active
+ EOF
+
+ cat >expect <<-\EOF &&
+ error: missing value for '\''submodule.active'\''
+ EOF
+ test-tool -C super submodule is-active sub1 2>actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'is-active works with basic submodule.active config' '
test_when_finished "git -C super config submodule.sub1.URL ../sub" &&
test_when_finished "git -C super config --unset-all submodule.active" &&
diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
index 3ebd985981..7cf72b9a07 100755
--- a/t/t7416-submodule-dash-url.sh
+++ b/t/t7416-submodule-dash-url.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='check handling of disallowed .gitmodule urls'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7418-submodule-sparse-gitmodules.sh b/t/t7418-submodule-sparse-gitmodules.sh
index d5874200fd..dde11ecce8 100755
--- a/t/t7418-submodule-sparse-gitmodules.sh
+++ b/t/t7418-submodule-sparse-gitmodules.sh
@@ -50,12 +50,12 @@ test_expect_success 'sparse checkout setup which hides .gitmodules' '
test_expect_success 'reading gitmodules config file when it is not checked out' '
echo "../submodule" >expect &&
- git -C super submodule--helper config submodule.submodule.url >actual &&
+ test-tool -C super submodule config-list submodule.submodule.url >actual &&
test_cmp expect actual
'
test_expect_success 'not writing gitmodules config file when it is not checked out' '
- test_must_fail git -C super submodule--helper config submodule.submodule.url newurl &&
+ test_must_fail test-tool -C super submodule config-set submodule.submodule.url newurl &&
test_path_is_missing super/.gitmodules
'
diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh
new file mode 100755
index 0000000000..ab946ec940
--- /dev/null
+++ b/t/t7422-submodule-output.sh
@@ -0,0 +1,170 @@
+#!/bin/sh
+
+test_description='submodule --cached, --quiet etc. output'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-t3100.sh
+
+setup_sub () {
+ local d="$1" &&
+ shift &&
+ git $@ clone . "$d" &&
+ git $@ submodule add ./"$d"
+}
+
+normalize_status () {
+ sed -e 's/-g[0-9a-f]*/-gHASH/'
+}
+
+test_expect_success 'setup' '
+ test_commit A &&
+ test_commit B &&
+ setup_sub S &&
+ setup_sub S.D &&
+ setup_sub S.C &&
+ setup_sub S.C.D &&
+ setup_sub X &&
+ git add S* &&
+ test_commit C &&
+
+ # recursive in X/
+ git -C X pull &&
+ GIT_ALLOW_PROTOCOL=file git -C X submodule update --init &&
+
+ # dirty
+ for d in S.D X/S.D
+ do
+ echo dirty >"$d"/A.t || return 1
+ done &&
+
+ # commit (for --cached)
+ for d in S.C* X/S.C*
+ do
+ git -C "$d" reset --hard A || return 1
+ done &&
+
+ # dirty
+ for d in S*.D X/S*.D
+ do
+ echo dirty >"$d/C2.t" || return 1
+ done &&
+
+ for ref in A B C
+ do
+ # Not different with SHA-1 and SHA-256, just (ab)using
+ # test_oid_cache as a variable bag to avoid using
+ # $(git rev-parse ...).
+ oid=$(git rev-parse $ref) &&
+ test_oid_cache <<-EOF || return 1
+ $ref sha1:$oid
+ $ref sha256:$oid
+ EOF
+ done
+'
+
+for opts in "" "status"
+do
+ test_expect_success "git submodule $opts" '
+ sed -e "s/^>//" >expect <<-EOF &&
+ > $(test_oid B) S (B)
+ >+$(test_oid A) S.C (A)
+ >+$(test_oid A) S.C.D (A)
+ > $(test_oid B) S.D (B)
+ >+$(test_oid C) X (C)
+ EOF
+ git submodule $opts >actual.raw &&
+ normalize_status <actual.raw >actual &&
+ test_cmp expect actual
+ '
+done
+
+for opts in \
+ "status --recursive"
+do
+ test_expect_success "git submodule $opts" '
+ sed -e "s/^>//" >expect <<-EOF &&
+ > $(test_oid B) S (B)
+ >+$(test_oid A) S.C (A)
+ >+$(test_oid A) S.C.D (A)
+ > $(test_oid B) S.D (B)
+ >+$(test_oid C) X (C)
+ > $(test_oid B) X/S (B)
+ >+$(test_oid A) X/S.C (A)
+ >+$(test_oid A) X/S.C.D (A)
+ > $(test_oid B) X/S.D (B)
+ > $(test_oid B) X/X (B)
+ EOF
+ git submodule $opts >actual.raw &&
+ normalize_status <actual.raw >actual &&
+ test_cmp expect actual
+ '
+done
+
+for opts in \
+ "--quiet" \
+ "--quiet status" \
+ "status --quiet"
+do
+ test_expect_success "git submodule $opts" '
+ git submodule $opts >out &&
+ test_must_be_empty out
+ '
+done
+
+for opts in \
+ "--cached" \
+ "--cached status" \
+ "status --cached"
+do
+ test_expect_success "git submodule $opts" '
+ sed -e "s/^>//" >expect <<-EOF &&
+ > $(test_oid B) S (B)
+ >+$(test_oid B) S.C (B)
+ >+$(test_oid B) S.C.D (B)
+ > $(test_oid B) S.D (B)
+ >+$(test_oid B) X (B)
+ EOF
+ git submodule $opts >actual.raw &&
+ normalize_status <actual.raw >actual &&
+ test_cmp expect actual
+ '
+done
+
+for opts in \
+ "--cached --quiet" \
+ "--cached --quiet status" \
+ "--cached status --quiet" \
+ "--quiet status --cached" \
+ "status --cached --quiet"
+do
+ test_expect_success "git submodule $opts" '
+ git submodule $opts >out &&
+ test_must_be_empty out
+ '
+done
+
+for opts in \
+ "status --cached --recursive" \
+ "--cached status --recursive"
+do
+ test_expect_success "git submodule $opts" '
+ sed -e "s/^>//" >expect <<-EOF &&
+ > $(test_oid B) S (B)
+ >+$(test_oid B) S.C (B)
+ >+$(test_oid B) S.C.D (B)
+ > $(test_oid B) S.D (B)
+ >+$(test_oid B) X (B)
+ > $(test_oid B) X/S (B)
+ >+$(test_oid B) X/S.C (B)
+ >+$(test_oid B) X/S.C.D (B)
+ > $(test_oid B) X/S.D (B)
+ > $(test_oid B) X/X (B)
+ EOF
+ git submodule $opts >actual.raw &&
+ normalize_status <actual.raw >actual &&
+ test_cmp expect actual
+ '
+done
+
+test_done
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index ba1f569bcb..0d0c3f2c68 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -12,6 +12,8 @@ Such as:
- symlinked .gitmodules, etc
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-pack.sh
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index 38a532d81c..b5bf7de7cd 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -466,6 +466,25 @@ test_expect_success 'commit --trailer with -c and command' '
test_cmp expected actual
'
+test_expect_success 'commit --trailer not confused by --- separator' '
+ cat >msg <<-\EOF &&
+ subject
+
+ body with dashes
+ ---
+ in it
+ EOF
+ git commit --allow-empty --trailer="my-trailer: value" -F msg &&
+ {
+ cat msg &&
+ echo &&
+ echo "my-trailer: value"
+ } >expected &&
+ git cat-file commit HEAD >commit.msg &&
+ sed -e "1,/^\$/d" commit.msg >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'multiple -m' '
>negative &&
diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh
index a39de8c112..d1255228d5 100755
--- a/t/t7504-commit-msg-hook.sh
+++ b/t/t7504-commit-msg-hook.sh
@@ -5,6 +5,7 @@ test_description='commit-msg hook'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'with no hook' '
@@ -101,7 +102,9 @@ test_expect_success 'setup: commit-msg hook that always fails' '
'
commit_msg_is () {
- test "$(git log --pretty=format:%s%b -1)" = "$1"
+ printf "%s" "$1" >expect &&
+ git log --pretty=format:%s%b -1 >actual &&
+ test_cmp expect actual
}
test_expect_success 'with failing hook' '
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index 2b7ef6c41a..6928fd89f5 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -5,6 +5,7 @@
test_description='git status'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
@@ -91,7 +92,7 @@ test_expect_success 'status --column' '
# On branch main
# Your branch and '\''upstream'\'' have diverged,
# and have 1 and 2 different commits each, respectively.
-# (use "git pull" to merge the remote branch into yours)
+# (use "git pull" if you want to integrate the remote branch with yours)
#
# Changes to be committed:
# (use "git restore --staged <file>..." to unstage)
@@ -122,7 +123,7 @@ cat >expect <<\EOF
# On branch main
# Your branch and 'upstream' have diverged,
# and have 1 and 2 different commits each, respectively.
-# (use "git pull" to merge the remote branch into yours)
+# (use "git pull" if you want to integrate the remote branch with yours)
#
# Changes to be committed:
# (use "git restore --staged <file>..." to unstage)
@@ -269,7 +270,7 @@ test_expect_success 'status with gitignore' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -334,7 +335,7 @@ test_expect_success 'status with gitignore (nothing untracked)' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -404,7 +405,7 @@ test_expect_success 'status -uno' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -466,7 +467,7 @@ test_expect_success 'status -unormal' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -521,7 +522,7 @@ test_expect_success 'status -uall' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -581,7 +582,7 @@ test_expect_success 'status with relative paths' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -649,7 +650,7 @@ test_expect_success TTY 'status with color.ui' '
On branch <GREEN>main<RESET>
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -772,7 +773,7 @@ test_expect_success 'status without relative paths' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -846,7 +847,6 @@ test_expect_success 'dry-run of partial commit excluding new file in index' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -900,7 +900,7 @@ test_expect_success 'status submodule summary is disabled by default' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -957,7 +957,7 @@ test_expect_success 'status submodule summary' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 1 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -1012,11 +1012,11 @@ test_expect_success 'status -s submodule summary' '
'
test_expect_success 'status submodule summary (clean submodule): commit' '
- cat >expect <<EOF &&
+ cat >expect-status <<EOF &&
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 2 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
@@ -1032,12 +1032,13 @@ Untracked files:
no changes added to commit (use "git add" and/or "git commit -a")
EOF
+ sed "/git pull/d" expect-status > expect-commit &&
git commit -m "commit submodule" &&
git config status.submodulesummary 10 &&
test_must_fail git commit --dry-run >output &&
- test_cmp expect output &&
+ test_cmp expect-commit output &&
git status >output &&
- test_cmp expect output
+ test_cmp expect-status output
'
cat >expect <<EOF
@@ -1064,7 +1065,6 @@ test_expect_success 'commit --dry-run submodule summary (--amend)' '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 2 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
Changes to be committed:
(use "git restore --source=HEAD^1 --staged <file>..." to unstage)
@@ -1116,7 +1116,7 @@ test_expect_success '--ignore-submodules=untracked suppresses submodules with un
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 2 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -1225,7 +1225,7 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodules w
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 2 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -1282,7 +1282,7 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodule su
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 2 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -1363,7 +1363,7 @@ cat > expect << EOF
; On branch main
; Your branch and 'upstream' have diverged,
; and have 2 and 2 different commits each, respectively.
-; (use "git pull" to merge the remote branch into yours)
+; (use "git pull" if you want to integrate the remote branch with yours)
;
; Changes to be committed:
; (use "git restore --staged <file>..." to unstage)
@@ -1411,7 +1411,7 @@ test_expect_success "--ignore-submodules=all suppresses submodule summary" '
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 2 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
@@ -1437,7 +1437,7 @@ test_expect_success '.gitmodules ignore=all suppresses unstaged submodule summar
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 2 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
+ (use "git pull" if you want to integrate the remote branch with yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -1519,8 +1519,8 @@ test_expect_success '"status.branch=true" weaker than "--no-branch"' '
'
test_expect_success '"status.branch=true" weaker than "--porcelain"' '
- git -c status.branch=true status --porcelain >actual &&
- test_cmp expected_nobranch actual
+ git -c status.branch=true status --porcelain >actual &&
+ test_cmp expected_nobranch actual
'
test_expect_success '"status.branch=false" same as "--no-branch"' '
@@ -1557,7 +1557,6 @@ test_expect_success 'git commit --dry-run will show a staged but ignored submodu
On branch main
Your branch and '\''upstream'\'' have diverged,
and have 2 and 2 different commits each, respectively.
- (use "git pull" to merge the remote branch into yours)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
@@ -1676,4 +1675,74 @@ test_expect_success 'racy timestamps will be fixed for dirty worktree' '
! test_is_magic_mtime .git/index
'
+test_expect_success 'setup slow status advice' '
+ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main git init slowstatus &&
+ (
+ cd slowstatus &&
+ cat >.gitignore <<-\EOF &&
+ /actual
+ /expected
+ /out
+ EOF
+ git add .gitignore &&
+ git commit -m "Add .gitignore" &&
+ git config advice.statusuoption true
+ )
+'
+
+test_expect_success 'slow status advice when core.untrackedCache and fsmonitor are unset' '
+ (
+ cd slowstatus &&
+ git config core.untrackedCache false &&
+ git config core.fsmonitor false &&
+ GIT_TEST_UF_DELAY_WARNING=1 git status >actual &&
+ cat >expected <<-\EOF &&
+ On branch main
+
+ It took 3.25 seconds to enumerate untracked files.
+ See '\''git help status'\'' for information on how to improve this.
+
+ nothing to commit, working tree clean
+ EOF
+ test_cmp expected actual
+ )
+'
+
+test_expect_success 'slow status advice when core.untrackedCache true, but not fsmonitor' '
+ (
+ cd slowstatus &&
+ git config core.untrackedCache true &&
+ git config core.fsmonitor false &&
+ GIT_TEST_UF_DELAY_WARNING=1 git status >actual &&
+ cat >expected <<-\EOF &&
+ On branch main
+
+ It took 3.25 seconds to enumerate untracked files.
+ See '\''git help status'\'' for information on how to improve this.
+
+ nothing to commit, working tree clean
+ EOF
+ test_cmp expected actual
+ )
+'
+
+test_expect_success 'slow status advice when core.untrackedCache true, and fsmonitor' '
+ (
+ cd slowstatus &&
+ git config core.untrackedCache true &&
+ git config core.fsmonitor true &&
+ GIT_TEST_UF_DELAY_WARNING=1 git status >actual &&
+ cat >expected <<-\EOF &&
+ On branch main
+
+ It took 3.25 seconds to enumerate untracked files,
+ but the results were cached, and subsequent runs may be faster.
+ See '\''git help status'\'' for information on how to improve this.
+
+ nothing to commit, working tree clean
+ EOF
+ test_cmp expected actual
+ )
+'
+
test_done
diff --git a/t/t7509-commit-authorship.sh b/t/t7509-commit-authorship.sh
index 21c668f75e..5d890949f7 100755
--- a/t/t7509-commit-authorship.sh
+++ b/t/t7509-commit-authorship.sh
@@ -105,7 +105,7 @@ test_expect_success '--amend option with empty author' '
test_expect_success '--amend option with missing author' '
git cat-file commit Initial >tmp &&
sed "s/author [^<]* </author </" tmp >malformed &&
- sha=$(git hash-object -t commit -w malformed) &&
+ sha=$(git hash-object --literally -t commit -w malformed) &&
test_when_finished "remove_object $sha" &&
git checkout $sha &&
test_when_finished "git checkout Initial" &&
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 8593b7e3cb..0d2dd29fe6 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -202,7 +202,7 @@ test_expect_success GPG 'detect fudged signature with NUL' '
git cat-file commit seventh-signed >raw &&
cat raw >forged2 &&
echo Qwik | tr "Q" "\000" >>forged2 &&
- git hash-object -w -t commit forged2 >forged2.commit &&
+ git hash-object --literally -w -t commit forged2 >forged2.commit &&
test_must_fail git verify-commit $(cat forged2.commit) &&
git show --pretty=short --show-signature $(cat forged2.commit) >actual2 &&
grep "BAD signature from" actual2 &&
@@ -218,87 +218,101 @@ test_expect_success GPG 'amending already signed commit' '
! grep "BAD signature from" actual
'
+test_expect_success GPG2 'bare signature' '
+ git verify-commit fifth-signed 2>expect &&
+ echo >>expect &&
+ git log -1 --format="%GG" fifth-signed >actual &&
+ test_cmp expect actual
+'
+
test_expect_success GPG 'show good signature with custom format' '
cat >expect <<-\EOF &&
G
+ ultimate
13B6F51ECDDE430D
C O Mitter <committer@example.com>
73D758744BE721698EC54E8713B6F51ECDDE430D
73D758744BE721698EC54E8713B6F51ECDDE430D
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show bad signature with custom format' '
cat >expect <<-\EOF &&
B
+ undefined
13B6F51ECDDE430D
C O Mitter <committer@example.com>
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show untrusted signature with custom format' '
cat >expect <<-\EOF &&
U
+ undefined
65A0EEA02E30CAD7
Eris Discordia <discord@example.net>
F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
D4BE22311AD3131E5EDA29A461092E85B7227189
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show untrusted signature with undefined trust level' '
cat >expect <<-\EOF &&
+ U
undefined
65A0EEA02E30CAD7
Eris Discordia <discord@example.net>
F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
D4BE22311AD3131E5EDA29A461092E85B7227189
EOF
- git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show untrusted signature with ultimate trust level' '
cat >expect <<-\EOF &&
+ G
ultimate
13B6F51ECDDE430D
C O Mitter <committer@example.com>
73D758744BE721698EC54E8713B6F51ECDDE430D
73D758744BE721698EC54E8713B6F51ECDDE430D
EOF
- git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show unknown signature with custom format' '
cat >expect <<-\EOF &&
E
+ undefined
65A0EEA02E30CAD7
EOF
- GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show lack of signature with custom format' '
cat >expect <<-\EOF &&
N
+ undefined
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual &&
test_cmp expect actual
'
@@ -387,4 +401,48 @@ test_expect_success GPG 'verify-commit verifies multiply signed commits' '
! grep "BAD signature from" actual
'
+test_expect_success 'custom `gpg.program`' '
+ write_script fake-gpg <<-\EOF &&
+ args="$*"
+
+ # skip uninteresting options
+ while case "$1" in
+ --status-fd=*|--keyid-format=*) ;; # skip
+ *) break;;
+ esac; do shift; done
+
+ case "$1" in
+ -bsau)
+ test -z "$LET_GPG_PROGRAM_FAIL" || {
+ echo "zOMG signing failed!" >&2
+ exit 1
+ }
+ cat >sign.file
+ echo "[GNUPG:] SIG_CREATED $args" >&2
+ echo "-----BEGIN PGP MESSAGE-----"
+ echo "$args"
+ echo "-----END PGP MESSAGE-----"
+ ;;
+ --verify)
+ cat "$2" >verify.file
+ exit 0
+ ;;
+ *)
+ echo "Unhandled args: $*" >&2
+ exit 1
+ ;;
+ esac
+ EOF
+
+ test_config gpg.program "$(pwd)/fake-gpg" &&
+ git commit -S --allow-empty -m signed-commit &&
+ test_path_exists sign.file &&
+ git show --show-signature &&
+ test_path_exists verify.file &&
+
+ test_must_fail env LET_GPG_PROGRAM_FAIL=1 \
+ git commit -S --allow-empty -m must-fail 2>err &&
+ grep zOMG err
+'
+
test_done
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 2f16d5787e..c2ab8a444a 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -774,6 +774,28 @@ EOF
test_cmp expected actual
'
+test_expect_success 'status when cherry-picking multiple commits' '
+ git reset --hard cherry_branch &&
+ test_when_finished "git cherry-pick --abort" &&
+ test_must_fail git cherry-pick cherry_branch_second one_cherry &&
+ TO_CHERRY_PICK=$(git rev-parse --short CHERRY_PICK_HEAD) &&
+ cat >expected <<EOF &&
+On branch cherry_branch
+You are currently cherry-picking commit $TO_CHERRY_PICK.
+ (fix conflicts and run "git cherry-pick --continue")
+ (use "git cherry-pick --skip" to skip this patch)
+ (use "git cherry-pick --abort" to cancel the cherry-pick operation)
+
+Unmerged paths:
+ (use "git add <file>..." to mark resolution)
+ both modified: main.txt
+
+no changes added to commit (use "git add" and/or "git commit -a")
+EOF
+ git status --untracked-files=no >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'status when cherry-picking after committing conflict resolution' '
git reset --hard cherry_branch &&
test_when_finished "git cherry-pick --abort" &&
diff --git a/t/t7516-commit-races.sh b/t/t7516-commit-races.sh
index f2ce14e907..bb95f09810 100755
--- a/t/t7516-commit-races.sh
+++ b/t/t7516-commit-races.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git commit races'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'race to create orphan commit' '
@@ -10,7 +12,8 @@ test_expect_success 'race to create orphan commit' '
test_must_fail env EDITOR=./hare-editor git commit --allow-empty -m tortoise -e &&
git show -s --pretty=format:%s >subject &&
grep hare subject &&
- test -z "$(git show -s --pretty=format:%P)"
+ git show -s --pretty=format:%P >out &&
+ test_must_be_empty out
'
test_expect_success 'race to create non-orphan commit' '
diff --git a/t/t7517-per-repo-email.sh b/t/t7517-per-repo-email.sh
index 163ae80468..efc6496e2b 100755
--- a/t/t7517-per-repo-email.sh
+++ b/t/t7517-per-repo-email.sh
@@ -9,6 +9,7 @@ test_description='per-repo forced setting of email address'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup a likely user.useConfigOnly use case' '
diff --git a/t/t7518-ident-corner-cases.sh b/t/t7518-ident-corner-cases.sh
index fffdb6ff2e..9ab2ae2f3b 100755
--- a/t/t7518-ident-corner-cases.sh
+++ b/t/t7518-ident-corner-cases.sh
@@ -20,10 +20,19 @@ test_expect_success 'empty name and missing email' '
'
test_expect_success 'commit rejects all-crud name' '
- test_must_fail env GIT_AUTHOR_NAME=" .;<>" \
+ test_must_fail env GIT_AUTHOR_NAME=" ,;<>" \
git commit --allow-empty -m foo
'
+test_expect_success 'commit does not strip trailing dot' '
+ author_name="Pat Doe Jr." &&
+ env GIT_AUTHOR_NAME="$author_name" \
+ git commit --allow-empty -m foo &&
+ git log -1 --format=%an >actual &&
+ echo "$author_name" >expected &&
+ test_cmp actual expected
+'
+
# We must test the actual error message here, as an unwanted
# auto-detection could fail for other reasons.
test_expect_success 'empty configured name does not auto-detect' '
diff --git a/t/t7520-ignored-hook-warning.sh b/t/t7520-ignored-hook-warning.sh
index dc57526e6f..184b258989 100755
--- a/t/t7520-ignored-hook-warning.sh
+++ b/t/t7520-ignored-hook-warning.sh
@@ -2,6 +2,7 @@
test_description='ignored hook warning'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh
index d419085379..78503158fd 100755
--- a/t/t7527-builtin-fsmonitor.sh
+++ b/t/t7527-builtin-fsmonitor.sh
@@ -809,6 +809,11 @@ my_match_and_clean () {
status --porcelain=v2 >actual.without &&
test_cmp actual.with actual.without &&
+ git -C super --no-optional-locks diff-index --name-status HEAD >actual.with &&
+ git -C super --no-optional-locks -c core.fsmonitor=false \
+ diff-index --name-status HEAD >actual.without &&
+ test_cmp actual.with actual.without &&
+
git -C super/dir_1/dir_2/sub reset --hard &&
git -C super/dir_1/dir_2/sub clean -d -f
}
@@ -866,27 +871,9 @@ test_expect_success 'submodule always visited' '
# the submodule, and someone does a `git submodule absorbgitdirs`
# in the super, Git will recursively invoke `git submodule--helper`
# to do the work and this may try to read the index. This will
-# try to start the daemon in the submodule *and* pass (either
-# directly or via inheritance) the `--super-prefix` arg to the
-# `git fsmonitor--daemon start` command inside the submodule.
-# This causes a warning because fsmonitor--daemon does take that
-# global arg (see the table in git.c)
-#
-# This causes a warning when trying to start the daemon that is
-# somewhat confusing. It does not seem to hurt anything because
-# the fsmonitor code maps the query failure into a trivial response
-# and does the work anyway.
-#
-# It would be nice to silence the warning, however.
+# try to start the daemon in the submodule.
-have_t2_error_event () {
- log=$1
- msg="fsmonitor--daemon doesnQt support --super-prefix" &&
-
- tr '\047' Q <$1 | grep -e "$msg"
-}
-
-test_expect_success "stray submodule super-prefix warning" '
+test_expect_success "submodule absorbgitdirs implicitly starts daemon" '
test_when_finished "rm -rf super; \
rm -rf sub; \
rm super-sub.trace" &&
@@ -904,21 +891,31 @@ test_expect_success "stray submodule super-prefix warning" '
test_path_is_dir super/dir_1/dir_2/sub/.git &&
+ cwd="$(cd super && pwd)" &&
+ cat >expect <<-EOF &&
+ Migrating git directory of '\''dir_1/dir_2/sub'\'' from
+ '\''$cwd/dir_1/dir_2/sub/.git'\'' to
+ '\''$cwd/.git/modules/dir_1/dir_2/sub'\''
+ EOF
GIT_TRACE2_EVENT="$PWD/super-sub.trace" \
- git -C super submodule absorbgitdirs &&
+ git -C super submodule absorbgitdirs >out 2>actual &&
+ test_cmp expect actual &&
+ test_must_be_empty out &&
- ! have_t2_error_event super-sub.trace
+ # Confirm that the trace2 log contains a record of the
+ # daemon starting.
+ test_subcommand git fsmonitor--daemon start <super-sub.trace
'
# On a case-insensitive file system, confirm that the daemon
# notices when the .git directory is moved/renamed/deleted
-# regardless of how it is spelled in the the FS event.
+# regardless of how it is spelled in the FS event.
# That is, does the FS event receive the spelling of the
# operation or does it receive the spelling preserved with
# the file/directory.
#
test_expect_success CASE_INSENSITIVE_FS 'case insensitive+preserving' '
-# test_when_finished "stop_daemon_delete_repo test_insensitive" &&
+ test_when_finished "stop_daemon_delete_repo test_insensitive" &&
git init test_insensitive &&
@@ -930,8 +927,8 @@ test_expect_success CASE_INSENSITIVE_FS 'case insensitive+preserving' '
test_path_is_dir test_insensitive/.git &&
test_path_is_dir test_insensitive/.GIT &&
- # Rename .git using an alternate spelling to verify that that
- # daemon detects it and automatically shuts down.
+ # Rename .git using an alternate spelling to verify that
+ # the daemon detects it and automatically shuts down.
mv test_insensitive/.GIT test_insensitive/.FOO &&
# See [1] above.
@@ -943,9 +940,9 @@ test_expect_success CASE_INSENSITIVE_FS 'case insensitive+preserving' '
# directories and files that we touched. We may or may not get a
# trailing slash on modified directories.
#
- egrep "^event: abc/?$" ./insensitive.trace &&
- egrep "^event: abc/def/?$" ./insensitive.trace &&
- egrep "^event: abc/def/xyz$" ./insensitive.trace
+ grep -E "^event: abc/?$" ./insensitive.trace &&
+ grep -E "^event: abc/def/?$" ./insensitive.trace &&
+ grep -E "^event: abc/def/xyz$" ./insensitive.trace
'
# The variable "unicode_debug" is defined in the following library
@@ -987,20 +984,57 @@ test_expect_success !UNICODE_COMPOSITION_SENSITIVE 'Unicode nfc/nfd' '
then
# We should have seen NFC event from OS.
# We should not have synthesized an NFD event.
- egrep "^event: nfc/c_${utf8_nfc}/?$" ./unicode.trace &&
- egrep -v "^event: nfc/c_${utf8_nfd}/?$" ./unicode.trace
+ grep -E "^event: nfc/c_${utf8_nfc}/?$" ./unicode.trace &&
+ grep -E -v "^event: nfc/c_${utf8_nfd}/?$" ./unicode.trace
else
# We should have seen NFD event from OS.
# We should have synthesized an NFC event.
- egrep "^event: nfc/c_${utf8_nfd}/?$" ./unicode.trace &&
- egrep "^event: nfc/c_${utf8_nfc}/?$" ./unicode.trace
+ grep -E "^event: nfc/c_${utf8_nfd}/?$" ./unicode.trace &&
+ grep -E "^event: nfc/c_${utf8_nfc}/?$" ./unicode.trace
fi &&
# We assume UNICODE_NFD_PRESERVED.
# We should have seen explicit NFD from OS.
# We should have synthesized an NFC event.
- egrep "^event: nfd/d_${utf8_nfd}/?$" ./unicode.trace &&
- egrep "^event: nfd/d_${utf8_nfc}/?$" ./unicode.trace
+ grep -E "^event: nfd/d_${utf8_nfd}/?$" ./unicode.trace &&
+ grep -E "^event: nfd/d_${utf8_nfc}/?$" ./unicode.trace
+'
+
+test_expect_success 'split-index and FSMonitor work well together' '
+ git init split-index &&
+ test_when_finished "git -C \"$PWD/split-index\" \
+ fsmonitor--daemon stop" &&
+ (
+ cd split-index &&
+ git config core.splitIndex true &&
+ # force split-index in most cases
+ git config splitIndex.maxPercentChange 99 &&
+ git config core.fsmonitor true &&
+
+ # Create the following commit topology:
+ #
+ # * merge three
+ # |\
+ # | * three
+ # * | merge two
+ # |\|
+ # | * two
+ # * | one
+ # |/
+ # * 5a5efd7 initial
+
+ test_commit initial &&
+ test_commit two &&
+ test_commit three &&
+ git reset --hard initial &&
+ test_commit one &&
+ test_tick &&
+ git merge two &&
+ test_tick &&
+ git merge three &&
+
+ git rebase --force-rebase -r one
+ )
'
test_done
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
index f47e995179..065f780636 100755
--- a/t/t7528-signed-commit-ssh.sh
+++ b/t/t7528-signed-commit-ssh.sh
@@ -270,7 +270,7 @@ test_expect_success GPGSSH 'detect fudged signature with NUL' '
git cat-file commit seventh-signed >raw &&
cat raw >forged2 &&
echo Qwik | tr "Q" "\000" >>forged2 &&
- git hash-object -w -t commit forged2 >forged2.commit &&
+ git hash-object --literally -w -t commit forged2 >forged2.commit &&
test_must_fail git verify-commit $(cat forged2.commit) &&
git show --pretty=short --show-signature $(cat forged2.commit) >actual2 &&
grep "${GPGSSH_BAD_SIGNATURE}" actual2 &&
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 7c3f6ed994..fdc607277c 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -105,7 +105,7 @@ verify_mergeheads () {
test_write_lines "$@" >mergehead.expected &&
while read sha1 rest
do
- git rev-parse $sha1
+ git rev-parse $sha1 || return 1
done <.git/MERGE_HEAD >mergehead.actual &&
test_cmp mergehead.expected mergehead.actual
}
@@ -639,41 +639,41 @@ test_expect_success 'merge log message' '
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c0, c2, c0, and c1' '
- git reset --hard c1 &&
- test_tick &&
- git merge c0 c2 c0 c1 &&
- verify_merge file result.1-5 &&
- verify_parents $c1 $c2
+ git reset --hard c1 &&
+ test_tick &&
+ git merge c0 c2 c0 c1 &&
+ verify_merge file result.1-5 &&
+ verify_parents $c1 $c2
'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c0, c2, c0, and c1' '
- git reset --hard c1 &&
- test_tick &&
- git merge c0 c2 c0 c1 &&
- verify_merge file result.1-5 &&
- verify_parents $c1 $c2
+ git reset --hard c1 &&
+ test_tick &&
+ git merge c0 c2 c0 c1 &&
+ verify_merge file result.1-5 &&
+ verify_parents $c1 $c2
'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c1 and c2' '
- git reset --hard c1 &&
- test_tick &&
- git merge c1 c2 &&
- verify_merge file result.1-5 &&
- verify_parents $c1 $c2
+ git reset --hard c1 &&
+ test_tick &&
+ git merge c1 c2 &&
+ verify_merge file result.1-5 &&
+ verify_parents $c1 $c2
'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge fast-forward in a dirty tree' '
- git reset --hard c0 &&
- mv file file1 &&
- cat file1 >file &&
- rm -f file1 &&
- git merge c2
+ git reset --hard c0 &&
+ mv file file1 &&
+ cat file1 >file &&
+ rm -f file1 &&
+ git merge c2
'
test_debug 'git log --graph --decorate --oneline --all'
diff --git a/t/t7605-merge-resolve.sh b/t/t7605-merge-resolve.sh
index 5d56c38546..62d935d31c 100755
--- a/t/t7605-merge-resolve.sh
+++ b/t/t7605-merge-resolve.sh
@@ -4,6 +4,7 @@ test_description='git merge
Testing the resolve strategy.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 8cc64729ad..22b3a85b3e 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -33,7 +33,7 @@ test_expect_success 'setup' '
git add foo &&
git commit -m "Add foo"
) &&
- git submodule add git://example.com/submod submod &&
+ git submodule add file:///dev/null submod &&
git add file1 "spaced name" file1[1-4] subdir/file3 .gitmodules submod &&
git commit -m "add initial versions" &&
@@ -614,7 +614,7 @@ test_expect_success 'submodule in subdirectory' '
)
) &&
test_when_finished "rm -rf subdir/subdir_module" &&
- git submodule add git://example.com/subsubmodule subdir/subdir_module &&
+ git submodule add file:///dev/null subdir/subdir_module &&
git add subdir/subdir_module &&
git commit -m "add submodule in subdirectory" &&
@@ -860,4 +860,42 @@ test_expect_success 'mergetool hideResolved' '
git commit -m "test resolved with mergetool"
'
+test_expect_success 'mergetool with guiDefault' '
+ test_config merge.guitool myguitool &&
+ test_config mergetool.myguitool.cmd "(printf \"gui \" && cat \"\$REMOTE\") >\"\$MERGED\"" &&
+ test_config mergetool.myguitool.trustExitCode true &&
+ test_when_finished "git reset --hard" &&
+ git checkout -b test$test_count branch1 &&
+ git submodule update -N &&
+ test_must_fail git merge main &&
+
+ test_config mergetool.guiDefault auto &&
+ DISPLAY=SOMETHING && export DISPLAY &&
+ yes "" | git mergetool both &&
+ yes "" | git mergetool file1 file1 &&
+
+ DISPLAY= && export DISPLAY &&
+ yes "" | git mergetool file2 "spaced name" &&
+
+ test_config mergetool.guiDefault true &&
+ yes "" | git mergetool subdir/file3 &&
+
+ yes "d" | git mergetool file11 &&
+ yes "d" | git mergetool file12 &&
+ yes "l" | git mergetool submod &&
+
+ echo "gui main updated" >expect &&
+ test_cmp expect file1 &&
+
+ echo "main new" >expect &&
+ test_cmp expect file2 &&
+
+ echo "gui main new sub" >expect &&
+ test_cmp expect subdir/file3 &&
+
+ echo "branch1 submodule" >expect &&
+ test_cmp expect submod/bar &&
+ git commit -m "branch1 resolved with mergetool"
+'
+
test_done
diff --git a/t/t7612-merge-verify-signatures.sh b/t/t7612-merge-verify-signatures.sh
index 61330f71b1..f5c90cc22a 100755
--- a/t/t7612-merge-verify-signatures.sh
+++ b/t/t7612-merge-verify-signatures.sh
@@ -4,6 +4,7 @@ test_description='merge signature verification tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t7614-merge-signoff.sh b/t/t7614-merge-signoff.sh
index fee258d4f0..cf96a35e8e 100755
--- a/t/t7614-merge-signoff.sh
+++ b/t/t7614-merge-signoff.sh
@@ -8,6 +8,7 @@ This test runs git merge --signoff and makes sure that it works.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Setup test files
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index ca45c4cd2c..27b66807cd 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -10,6 +10,10 @@ test_description='git repack works correctly'
commit_and_pack () {
test_commit "$@" 1>&2 &&
incrpackid=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&
+ # Remove any loose object(s) created by test_commit, since they have
+ # already been packed. Leaving these around can create subtly different
+ # packs with `pack-objects`'s `--unpacked` option.
+ git prune-packed 1>&2 &&
echo pack-${incrpackid}.pack
}
@@ -90,6 +94,39 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '
test_has_duplicate_object false
'
+test_expect_success SYMLINKS '--local keeps packs when alternate is objectdir ' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo A &&
+ (
+ cd repo &&
+ git repack -a &&
+ ls .git/objects/pack/*.pack >../expect &&
+ ln -s objects .git/alt_objects &&
+ echo "$(pwd)/.git/alt_objects" >.git/objects/info/alternates &&
+ git repack -a -d -l &&
+ ls .git/objects/pack/*.pack >../actual
+ ) &&
+ test_cmp expect actual
+'
+
+test_expect_success '--local disables writing bitmaps when connected to alternate ODB' '
+ test_when_finished "rm -rf shared member" &&
+
+ git init shared &&
+ git clone --shared shared member &&
+ (
+ cd member &&
+ test_commit "object" &&
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adl --write-bitmap-index 2>err &&
+ cat >expect <<-EOF &&
+ warning: disabling bitmap writing, as some objects are not being packed
+ EOF
+ test_cmp expect err &&
+ test_path_is_missing .git/objects/pack-*.bitmap
+ )
+'
+
test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
mkdir alt_objects/pack &&
mv .git/objects/pack/* alt_objects/pack &&
@@ -176,6 +213,8 @@ test_expect_success 'repack --keep-pack' '
test_create_repo keep-pack &&
(
cd keep-pack &&
+ # avoid producing different packs due to delta/base choices
+ git config pack.window 0 &&
P1=$(commit_and_pack 1) &&
P2=$(commit_and_pack 2) &&
P3=$(commit_and_pack 3) &&
@@ -187,10 +226,61 @@ test_expect_success 'repack --keep-pack' '
grep -q $P1 new-counts &&
grep -q $P4 new-counts &&
test_line_count = 3 new-counts &&
+ git fsck &&
+
+ P5=$(commit_and_pack --no-tag 5) &&
+ git reset --hard HEAD^ &&
+ git reflog expire --all --expire=all &&
+ rm -f ".git/objects/pack/${P5%.pack}.idx" &&
+ rm -f ".git/objects/info/commit-graph" &&
+ for from in $(find .git/objects/pack -type f -name "${P5%.pack}.*")
+ do
+ to="$(dirname "$from")/.tmp-1234-$(basename "$from")" &&
+ mv "$from" "$to" || return 1
+ done &&
+
+ # A .idx file without a .pack should not stop us from
+ # repacking what we can.
+ touch .git/objects/pack/pack-does-not-exist.idx &&
+
+ git repack --cruft -d --keep-pack $P1 --keep-pack $P4 &&
+
+ ls .git/objects/pack/*.pack >newer-counts &&
+ test_cmp new-counts newer-counts &&
git fsck
)
'
+test_expect_success 'repacking fails when missing .pack actually means missing objects' '
+ test_create_repo idx-without-pack &&
+ (
+ cd idx-without-pack &&
+
+ # Avoid producing different packs due to delta/base choices
+ git config pack.window 0 &&
+ P1=$(commit_and_pack 1) &&
+ P2=$(commit_and_pack 2) &&
+ P3=$(commit_and_pack 3) &&
+ P4=$(commit_and_pack 4) &&
+ ls .git/objects/pack/*.pack >old-counts &&
+ test_line_count = 4 old-counts &&
+
+ # Remove one .pack file
+ rm .git/objects/pack/$P2 &&
+
+ ls .git/objects/pack/*.pack >before-pack-dir &&
+
+ test_must_fail git fsck &&
+ test_must_fail git repack --cruft -d 2>err &&
+ grep "bad object" err &&
+
+ # Before failing, the repack did not modify the
+ # pack directory.
+ ls .git/objects/pack/*.pack >after-pack-dir &&
+ test_cmp before-pack-dir after-pack-dir
+ )
+'
+
test_expect_success 'bitmaps are created by default in bare repos' '
git clone --bare .git bare.git &&
rm -f bare.git/objects/pack/*.bitmap &&
@@ -426,12 +516,73 @@ test_expect_success '--write-midx -b packs non-kept objects' '
)
'
+test_expect_success '--write-midx removes stale pack-based bitmaps' '
+ rm -fr repo &&
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit base &&
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack -Ab &&
+
+ pack_bitmap=$(ls $objdir/pack/pack-*.bitmap) &&
+ test_path_is_file "$pack_bitmap" &&
+
+ test_commit tip &&
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack -bm &&
+
+ test_path_is_file $midx &&
+ test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
+ test_path_is_missing $pack_bitmap
+ )
+'
+
+test_expect_success '--write-midx with --pack-kept-objects' '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit one &&
+ test_commit two &&
+
+ one="$(echo "one" | git pack-objects --revs $objdir/pack/pack)" &&
+ two="$(echo "one..two" | git pack-objects --revs $objdir/pack/pack)" &&
+
+ keep="$objdir/pack/pack-$one.keep" &&
+ touch "$keep" &&
+
+ git repack --write-midx --write-bitmap-index --geometric=2 -d \
+ --pack-kept-objects &&
+
+ test_path_is_file $keep &&
+ test_path_is_file $midx &&
+ test_path_is_file $midx-$(midx_checksum $objdir).bitmap
+ )
+'
+
test_expect_success TTY '--quiet disables progress' '
test_terminal env GIT_PROGRESS_DELAY=0 \
git -C midx repack -ad --quiet --write-midx 2>stderr &&
test_must_be_empty stderr
'
+test_expect_success 'clean up .tmp-* packs on error' '
+ test_must_fail ok=sigpipe git \
+ -c repack.cruftwindow=bogus \
+ repack -ad --cruft &&
+ find $objdir/pack -name '.tmp-*' >tmpfiles &&
+ test_must_be_empty tmpfiles
+'
+
+test_expect_success 'repack -ad cleans up old .tmp-* packs' '
+ git rev-parse HEAD >input &&
+ git pack-objects $objdir/pack/.tmp-1234 <input &&
+ git repack -ad &&
+ find $objdir/pack -name '.tmp-*' >tmpfiles &&
+ test_must_be_empty tmpfiles
+'
+
test_expect_success 'setup for update-server-info' '
git init update-server-info &&
test_commit -C update-server-info message
@@ -482,4 +633,125 @@ test_expect_success '-n overrides repack.updateServerInfo=true' '
test_server_info_missing
'
+test_expect_success '--expire-to stores pruned objects (now)' '
+ git init expire-to-now &&
+ (
+ cd expire-to-now &&
+
+ git branch -M main &&
+
+ test_commit base &&
+
+ git checkout -b cruft &&
+ test_commit --no-tag cruft &&
+
+ git rev-list --objects --no-object-names main..cruft >moved.raw &&
+ sort moved.raw >moved.want &&
+
+ git rev-list --all --objects --no-object-names >expect.raw &&
+ sort expect.raw >expect &&
+
+ git checkout main &&
+ git branch -D cruft &&
+ git reflog expire --all --expire=all &&
+
+ git init --bare expired.git &&
+ git repack -d \
+ --cruft --cruft-expiration="now" \
+ --expire-to="expired.git/objects/pack/pack" &&
+
+ expired="$(ls expired.git/objects/pack/pack-*.idx)" &&
+ test_path_is_file "${expired%.idx}.mtimes" &&
+
+ # Since the `--cruft-expiration` is "now", the effective
+ # behavior is to move _all_ unreachable objects out to
+ # the location in `--expire-to`.
+ git show-index <$expired >expired.raw &&
+ cut -d" " -f2 expired.raw | sort >expired.objects &&
+ git rev-list --all --objects --no-object-names \
+ >remaining.objects &&
+
+ # ...in other words, the combined contents of this
+ # repository and expired.git should be the same as the
+ # set of objects we started with.
+ cat expired.objects remaining.objects | sort >actual &&
+ test_cmp expect actual &&
+
+ # The "moved" objects (i.e., those in expired.git)
+ # should be the same as the cruft objects which were
+ # expired in the previous step.
+ test_cmp moved.want expired.objects
+ )
+'
+
+test_expect_success '--expire-to stores pruned objects (5.minutes.ago)' '
+ git init expire-to-5.minutes.ago &&
+ (
+ cd expire-to-5.minutes.ago &&
+
+ git branch -M main &&
+
+ test_commit base &&
+
+ # Create two classes of unreachable objects, one which
+ # is older than 5 minutes (stale), and another which is
+ # newer (recent).
+ for kind in stale recent
+ do
+ git checkout -b $kind main &&
+ test_commit --no-tag $kind || return 1
+ done &&
+
+ git rev-list --objects --no-object-names main..stale >in &&
+ stale="$(git pack-objects $objdir/pack/pack <in)" &&
+ mtime="$(test-tool chmtime --get =-600 $objdir/pack/pack-$stale.pack)" &&
+
+ # expect holds the set of objects we expect to find in
+ # this repository after repacking
+ git rev-list --objects --no-object-names recent >expect.raw &&
+ sort expect.raw >expect &&
+
+ # moved.want holds the set of objects we expect to find
+ # in expired.git
+ git rev-list --objects --no-object-names main..stale >out &&
+ sort out >moved.want &&
+
+ git checkout main &&
+ git branch -D stale recent &&
+ git reflog expire --all --expire=all &&
+ git prune-packed &&
+
+ git init --bare expired.git &&
+ git repack -d \
+ --cruft --cruft-expiration=5.minutes.ago \
+ --expire-to="expired.git/objects/pack/pack" &&
+
+ # Some of the remaining objects in this repository are
+ # unreachable, so use `cat-file --batch-all-objects`
+ # instead of `rev-list` to get their names
+ git cat-file --batch-all-objects --batch-check="%(objectname)" \
+ >remaining.objects &&
+ sort remaining.objects >actual &&
+ test_cmp expect actual &&
+
+ (
+ cd expired.git &&
+
+ expired="$(ls objects/pack/pack-*.mtimes)" &&
+ test-tool pack-mtimes $(basename $expired) >out &&
+ cut -d" " -f1 out | sort >../moved.got &&
+
+ # Ensure that there are as many objects with the
+ # expected mtime as were moved to expired.git.
+ #
+ # In other words, ensure that the recorded
+ # mtimes of any moved objects was written
+ # correctly.
+ grep " $mtime$" out >matching &&
+ test_line_count = $(wc -l <../moved.want) matching
+ ) &&
+ test_cmp moved.want moved.got
+ )
+'
+
test_done
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index 937f89ee8c..fe6c3e77a3 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -5,6 +5,7 @@ test_description='git repack works correctly'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
fsha1=
@@ -35,7 +36,7 @@ test_expect_success '-A with -d option leaves unreachable objects unpacked' '
git repack -A -d -l &&
# verify objects are packed in repository
test 3 = $(git verify-pack -v -- .git/objects/pack/*.idx |
- egrep "^($fsha1|$csha1|$tsha1) " |
+ grep -E "^($fsha1|$csha1|$tsha1) " |
sort | uniq | wc -l) &&
git show $fsha1 &&
git show $csha1 &&
@@ -49,7 +50,7 @@ test_expect_success '-A with -d option leaves unreachable objects unpacked' '
git repack -A -d -l &&
# verify objects are retained unpacked
test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
- egrep "^($fsha1|$csha1|$tsha1) " |
+ grep -E "^($fsha1|$csha1|$tsha1) " |
sort | uniq | wc -l) &&
git show $fsha1 &&
git show $csha1 &&
@@ -112,6 +113,48 @@ test_expect_success 'do not bother loosening old objects' '
test_must_fail git cat-file -p $obj2
'
+test_expect_success 'gc.recentObjectsHook' '
+ obj1=$(echo one | git hash-object -w --stdin) &&
+ obj2=$(echo two | git hash-object -w --stdin) &&
+ obj3=$(echo three | git hash-object -w --stdin) &&
+ pack1=$(echo $obj1 | git pack-objects .git/objects/pack/pack) &&
+ pack2=$(echo $obj2 | git pack-objects .git/objects/pack/pack) &&
+ pack3=$(echo $obj3 | git pack-objects .git/objects/pack/pack) &&
+ git prune-packed &&
+
+ git cat-file -p $obj1 &&
+ git cat-file -p $obj2 &&
+ git cat-file -p $obj3 &&
+
+ # make an unreachable annotated tag object to ensure we rescue objects
+ # which are reachable from non-pruned unreachable objects
+ obj2_tag="$(git mktag <<-EOF
+ object $obj2
+ type blob
+ tag obj2-tag
+ tagger T A Gger <tagger@example.com> 1234567890 -0000
+ EOF
+ )" &&
+
+ obj2_tag_pack="$(echo $obj2_tag | git pack-objects .git/objects/pack/pack)" &&
+ git prune-packed &&
+
+ write_script precious-objects <<-EOF &&
+ echo $obj2_tag
+ EOF
+ git config gc.recentObjectsHook ./precious-objects &&
+
+ test-tool chmtime =-86400 .git/objects/pack/pack-$pack2.pack &&
+ test-tool chmtime =-86400 .git/objects/pack/pack-$pack3.pack &&
+ test-tool chmtime =-86400 .git/objects/pack/pack-$obj2_tag_pack.pack &&
+ git repack -A -d --unpack-unreachable=1.hour.ago &&
+
+ git cat-file -p $obj1 &&
+ git cat-file -p $obj2 &&
+ git cat-file -p $obj2_tag &&
+ test_must_fail git cat-file -p $obj3
+'
+
test_expect_success 'keep packed objects found only in index' '
echo my-unique-content >file &&
git add file &&
diff --git a/t/t7703-repack-geometric.sh b/t/t7703-repack-geometric.sh
index da87f8b2d8..00f28fb558 100755
--- a/t/t7703-repack-geometric.sh
+++ b/t/t7703-repack-geometric.sh
@@ -10,6 +10,12 @@ objdir=.git/objects
packdir=$objdir/pack
midx=$objdir/pack/multi-pack-index
+packed_objects () {
+ git show-index <"$1" >tmp-object-list &&
+ cut -d' ' -f2 tmp-object-list | sort &&
+ rm tmp-object-list
+ }
+
test_expect_success '--geometric with no packs' '
git init geometric &&
test_when_finished "rm -fr geometric" &&
@@ -176,8 +182,12 @@ test_expect_success '--geometric ignores kept packs' '
# be repacked, too.
git repack --geometric 2 -d --pack-kept-objects &&
+ # After repacking, two packs remain: one new one (containing the
+ # objects in both the .keep and non-kept pack), and the .keep
+ # pack (since `--pack-kept-objects -d` does not actually delete
+ # the kept pack).
find $objdir/pack -name "*.pack" >after &&
- test_line_count = 1 after
+ test_line_count = 2 after
)
'
@@ -277,4 +287,162 @@ test_expect_success '--geometric with pack.packSizeLimit' '
)
'
+test_expect_success '--geometric --write-midx with packfiles in main and alternate ODB' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Create a shared repository that will serve as the alternate object
+ # database for the member linked to it. It has got some objects on its
+ # own that are packed into a single packfile.
+ git init shared &&
+ test_commit -C shared common-object &&
+ git -C shared repack -ad &&
+
+ # We create member so that its alternates file points to the shared
+ # repository. We then create a commit in it so that git-repack(1) has
+ # something to repack.
+ # of the shared object database.
+ git clone --shared shared member &&
+ test_commit -C member unique-object &&
+ git -C member repack --geometric=2 --write-midx 2>err &&
+ test_must_be_empty err &&
+
+ # We should see that a new packfile was generated.
+ find shared/.git/objects/pack -type f -name "*.pack" >packs &&
+ test_line_count = 1 packs &&
+
+ # We should also see a multi-pack-index. This multi-pack-index should
+ # never refer to any packfiles in the alternate object database.
+ test_path_is_file member/.git/objects/pack/multi-pack-index &&
+ test-tool read-midx member/.git/objects >packs.midx &&
+ grep "^pack-.*\.idx$" packs.midx | sort >actual &&
+ basename member/.git/objects/pack/pack-*.idx >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success '--geometric --with-midx with no local objects' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Create a repository with a single packfile that acts as alternate
+ # object database.
+ git init shared &&
+ test_commit -C shared "shared-objects" &&
+ git -C shared repack -ad &&
+
+ # Create a second repository linked to the first one and perform a
+ # geometric repack on it.
+ git clone --shared shared member &&
+ git -C member repack --geometric 2 --write-midx 2>err &&
+ test_must_be_empty err &&
+
+ # Assert that we wrote neither a new packfile nor a multi-pack-index.
+ # We should not have a packfile because the single packfile in the
+ # alternate object database does not invalidate the geometric sequence.
+ # And we should not have a multi-pack-index because these only index
+ # local packfiles, and there are none.
+ test_dir_is_empty member/$packdir
+'
+
+test_expect_success '--geometric with same pack in main and alternate ODB' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Create a repository with a single packfile that acts as alternate
+ # object database.
+ git init shared &&
+ test_commit -C shared "shared-objects" &&
+ git -C shared repack -ad &&
+
+ # We create the member repository as an exact copy so that it has the
+ # same packfile.
+ cp -r shared member &&
+ test-tool path-utils real_path shared/.git/objects >member/.git/objects/info/alternates &&
+ find shared/.git/objects -type f >expected-files &&
+
+ # Verify that we can repack objects as expected without observing any
+ # error. Having the same packfile in both ODBs used to cause an error
+ # in git-pack-objects(1).
+ git -C member repack --geometric 2 2>err &&
+ test_must_be_empty err &&
+ # Nothing should have changed.
+ find shared/.git/objects -type f >actual-files &&
+ test_cmp expected-files actual-files
+'
+
+test_expect_success '--geometric -l with non-intact geometric sequence across ODBs' '
+ test_when_finished "rm -fr shared member" &&
+
+ git init shared &&
+ test_commit_bulk -C shared --start=1 1 &&
+
+ git clone --shared shared member &&
+ test_commit_bulk -C member --start=2 1 &&
+
+ # Verify that our assumptions actually hold: both generated packfiles
+ # should have three objects and should be non-equal.
+ packed_objects shared/.git/objects/pack/pack-*.idx >shared-objects &&
+ packed_objects member/.git/objects/pack/pack-*.idx >member-objects &&
+ test_line_count = 3 shared-objects &&
+ test_line_count = 3 member-objects &&
+ ! test_cmp shared-objects member-objects &&
+
+ # Perform the geometric repack. With `-l`, we should only see the local
+ # packfile and thus arrive at the conclusion that the geometric
+ # sequence is intact. We thus expect no changes.
+ #
+ # Note that we are tweaking mtimes of the packfiles so that we can
+ # verify they did not change. This is done in order to detect the case
+ # where we do repack objects, but the resulting packfile is the same.
+ test-tool chmtime --verbose =0 member/.git/objects/pack/* >expected-member-packs &&
+ git -C member repack --geometric=2 -l -d &&
+ test-tool chmtime --verbose member/.git/objects/pack/* >actual-member-packs &&
+ test_cmp expected-member-packs actual-member-packs &&
+
+ {
+ packed_objects shared/.git/objects/pack/pack-*.idx &&
+ packed_objects member/.git/objects/pack/pack-*.idx
+ } | sort >expected-objects &&
+
+ # On the other hand, when doing a non-local geometric repack we should
+ # see both packfiles and thus repack them. We expect that the shared
+ # object database was not changed.
+ test-tool chmtime --verbose =0 shared/.git/objects/pack/* >expected-shared-packs &&
+ git -C member repack --geometric=2 -d &&
+ test-tool chmtime --verbose shared/.git/objects/pack/* >actual-shared-packs &&
+ test_cmp expected-shared-packs actual-shared-packs &&
+
+ # Furthermore, we expect that the member repository now has a single
+ # packfile that contains the combined shared and non-shared objects.
+ ls member/.git/objects/pack/pack-*.idx >actual &&
+ test_line_count = 1 actual &&
+ packed_objects member/.git/objects/pack/pack-*.idx >actual-objects &&
+ test_line_count = 6 actual-objects &&
+ test_cmp expected-objects actual-objects
+'
+
+test_expect_success '--geometric -l disables writing bitmaps with non-local packfiles' '
+ test_when_finished "rm -fr shared member" &&
+
+ git init shared &&
+ test_commit_bulk -C shared --start=1 1 &&
+
+ git clone --shared shared member &&
+ test_commit_bulk -C member --start=2 1 &&
+
+ # When performing a geometric repack with `-l` while connected to an
+ # alternate object database that has a packfile we do not have full
+ # coverage of objects. As a result, we expect that writing the bitmap
+ # will be disabled.
+ git -C member repack -l --geometric=2 --write-midx --write-bitmap-index 2>err &&
+ cat >expect <<-EOF &&
+ warning: disabling bitmap writing, as some objects are not being packed
+ EOF
+ test_cmp expect err &&
+ test_path_is_missing member/.git/objects/pack/multi-pack-index-*.bitmap &&
+
+ # On the other hand, when we repack without `-l`, we should see that
+ # the bitmap gets created.
+ git -C member repack --geometric=2 --write-midx --write-bitmap-index 2>err &&
+ test_must_be_empty err &&
+ test_path_is_file member/.git/objects/pack/multi-pack-index-*.bitmap
+'
+
test_done
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 24297e26ca..59d3847bf8 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -155,6 +155,58 @@ test_expect_success 'difftool honors --gui' '
test_cmp expect actual
'
+test_expect_success 'difftool with guiDefault auto selects gui tool when there is DISPLAY' '
+ difftool_test_setup &&
+ test_config merge.tool bogus-tool &&
+ test_config diff.tool bogus-tool &&
+ test_config diff.guitool test-tool &&
+ test_config difftool.guiDefault auto &&
+ DISPLAY=SOMETHING && export DISPLAY &&
+
+ echo branch >expect &&
+ git difftool --no-prompt branch >actual &&
+ test_cmp expect actual
+'
+test_expect_success 'difftool with guiDefault auto selects regular tool when no DISPLAY' '
+ difftool_test_setup &&
+ test_config diff.guitool bogus-tool &&
+ test_config diff.tool test-tool &&
+ test_config difftool.guiDefault Auto &&
+ DISPLAY= && export DISPLAY &&
+
+ echo branch >expect &&
+ git difftool --no-prompt branch >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'difftool with guiDefault true selects gui tool' '
+ difftool_test_setup &&
+ test_config diff.tool bogus-tool &&
+ test_config diff.guitool test-tool &&
+ test_config difftool.guiDefault true &&
+
+ DISPLAY= && export DISPLAY &&
+ echo branch >expect &&
+ git difftool --no-prompt branch >actual &&
+ test_cmp expect actual &&
+
+ DISPLAY=Something && export DISPLAY &&
+ echo branch >expect &&
+ git difftool --no-prompt branch >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'difftool --no-gui trumps config guiDefault' '
+ difftool_test_setup &&
+ test_config diff.guitool bogus-tool &&
+ test_config diff.tool test-tool &&
+ test_config difftool.guiDefault true &&
+
+ echo branch >expect &&
+ git difftool --no-prompt --no-gui branch >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'difftool --gui last setting wins' '
difftool_test_setup &&
: >expect &&
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 0f937990a0..39d6d713ec 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -18,6 +18,9 @@ test_invalid_grep_expression() {
'
}
+LC_ALL=en_US.UTF-8 test-tool regex '^.$' '¿' &&
+ test_set_prereq MB_REGEX
+
cat >hello.c <<EOF
#include <assert.h>
#include <stdio.h>
@@ -88,6 +91,10 @@ test_expect_success setup '
echo unusual >"\"unusual\" pathname" &&
echo unusual >"t/nested \"unusual\" pathname"
fi &&
+ if test_have_prereq MB_REGEX
+ then
+ echo "¿" >reverse-question-mark
+ fi &&
git add . &&
test_tick &&
git commit -m initial
@@ -569,6 +576,14 @@ do
'
done
+test_expect_success MB_REGEX 'grep exactly one char in single-char multibyte file' '
+ LC_ALL=en_US.UTF-8 git grep "^.$" reverse-question-mark
+'
+
+test_expect_success MB_REGEX 'grep two chars in single-char multibyte file' '
+ LC_ALL=en_US.UTF-8 test_expect_code 1 git grep ".." reverse-question-mark
+'
+
cat >expected <<EOF
file
EOF
@@ -986,7 +1001,9 @@ test_expect_success 'log --committer does not search in timestamp' '
test_expect_success 'grep with CE_VALID file' '
git update-index --assume-unchanged t/t &&
rm t/t &&
- test "$(git grep test)" = "t/t:test" &&
+ echo "t/t:test" >expect &&
+ git grep test >actual &&
+ test_cmp expect actual &&
git update-index --no-assume-unchanged t/t &&
git checkout t/t
'
diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh
index 8143817b19..d37c83b464 100755
--- a/t/t7814-grep-recurse-submodules.sh
+++ b/t/t7814-grep-recurse-submodules.sh
@@ -594,4 +594,44 @@ test_expect_success 'grep partially-cloned submodule' '
)
'
+test_expect_success 'check scope of core.useReplaceRefs' '
+ git init base &&
+ git init base/sub &&
+
+ echo A >base/a &&
+ echo B >base/b &&
+ echo C >base/sub/c &&
+ echo D >base/sub/d &&
+
+ git -C base/sub add c d &&
+ git -C base/sub commit -m "Add files" &&
+
+ git -C base submodule add ./sub &&
+ git -C base add a b sub &&
+ git -C base commit -m "Add files and submodule" &&
+
+ A=$(git -C base rev-parse HEAD:a) &&
+ B=$(git -C base rev-parse HEAD:b) &&
+ C=$(git -C base/sub rev-parse HEAD:c) &&
+ D=$(git -C base/sub rev-parse HEAD:d) &&
+
+ git -C base replace $A $B &&
+ git -C base/sub replace $C $D &&
+
+ test_must_fail git -C base grep --cached --recurse-submodules A &&
+ test_must_fail git -C base grep --cached --recurse-submodules C &&
+
+ git -C base config core.useReplaceRefs false &&
+ git -C base grep --recurse-submodules A &&
+ test_must_fail git -C base grep --cached --recurse-submodules C &&
+
+ git -C base/sub config core.useReplaceRefs false &&
+ git -C base grep --cached --recurse-submodules A &&
+ git -C base grep --cached --recurse-submodules C &&
+
+ git -C base config --unset core.useReplaceRefs &&
+ test_must_fail git -C base grep --cached --recurse-submodules A &&
+ git -C base grep --cached --recurse-submodules C
+'
+
test_done
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 2724a44fe3..e56f5980dc 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -480,6 +480,11 @@ test_expect_success 'maintenance.strategy inheritance' '
test_expect_success 'register and unregister' '
test_when_finished git config --global --unset-all maintenance.repo &&
+
+ test_must_fail git maintenance unregister 2>err &&
+ grep "is not registered" err &&
+ git maintenance unregister --force &&
+
git config --global --add maintenance.repo /existing1 &&
git config --global --add maintenance.repo /existing2 &&
git config --global --get-all maintenance.repo >before &&
@@ -493,7 +498,68 @@ test_expect_success 'register and unregister' '
git maintenance unregister &&
git config --global --get-all maintenance.repo >actual &&
- test_cmp before actual
+ test_cmp before actual &&
+
+ git config --file ./other --add maintenance.repo /existing1 &&
+ git config --file ./other --add maintenance.repo /existing2 &&
+ git config --file ./other --get-all maintenance.repo >before &&
+
+ git maintenance register --config-file ./other &&
+ test_cmp_config false maintenance.auto &&
+ git config --file ./other --get-all maintenance.repo >between &&
+ cp before expect &&
+ pwd >>expect &&
+ test_cmp expect between &&
+
+ git maintenance unregister --config-file ./other &&
+ git config --file ./other --get-all maintenance.repo >actual &&
+ test_cmp before actual &&
+
+ test_must_fail git maintenance unregister 2>err &&
+ grep "is not registered" err &&
+ git maintenance unregister --force &&
+
+ test_must_fail git maintenance unregister --config-file ./other 2>err &&
+ grep "is not registered" err &&
+ git maintenance unregister --config-file ./other --force
+'
+
+test_expect_success 'register with no value for maintenance.repo' '
+ cp .git/config .git/config.orig &&
+ test_when_finished mv .git/config.orig .git/config &&
+
+ cat >>.git/config <<-\EOF &&
+ [maintenance]
+ repo
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''maintenance.repo'\''
+ EOF
+ git maintenance register 2>actual &&
+ test_cmp expect actual &&
+ git config maintenance.repo
+'
+
+test_expect_success 'unregister with no value for maintenance.repo' '
+ cp .git/config .git/config.orig &&
+ test_when_finished mv .git/config.orig .git/config &&
+
+ cat >>.git/config <<-\EOF &&
+ [maintenance]
+ repo
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''maintenance.repo'\''
+ EOF
+ test_expect_code 128 git maintenance unregister 2>actual.raw &&
+ grep ^error actual.raw >actual &&
+ test_cmp expect actual &&
+ git config maintenance.repo &&
+
+ git maintenance unregister --force 2>actual.raw &&
+ grep ^error actual.raw >actual &&
+ test_cmp expect actual &&
+ git config maintenance.repo
'
test_expect_success !MINGW 'register and unregister with regex metacharacters' '
@@ -678,7 +744,15 @@ test_expect_success 'start and stop Linux/systemd maintenance' '
# start registers the repo
git config --get --global --fixed-value maintenance.repo "$(pwd)" &&
- test_systemd_analyze_verify "systemd/user/git-maintenance@.service" &&
+ for schedule in hourly daily weekly
+ do
+ test_path_is_file "systemd/user/git-maintenance@$schedule.timer" || return 1
+ done &&
+ test_path_is_file "systemd/user/git-maintenance@.service" &&
+
+ test_systemd_analyze_verify "systemd/user/git-maintenance@hourly.service" &&
+ test_systemd_analyze_verify "systemd/user/git-maintenance@daily.service" &&
+ test_systemd_analyze_verify "systemd/user/git-maintenance@weekly.service" &&
printf -- "--user enable --now git-maintenance@%s.timer\n" hourly daily weekly >expect &&
test_cmp expect args &&
@@ -689,7 +763,10 @@ test_expect_success 'start and stop Linux/systemd maintenance' '
# stop does not unregister the repo
git config --get --global --fixed-value maintenance.repo "$(pwd)" &&
- test_path_is_missing "systemd/user/git-maintenance@.timer" &&
+ for schedule in hourly daily weekly
+ do
+ test_path_is_missing "systemd/user/git-maintenance@$schedule.timer" || return 1
+ done &&
test_path_is_missing "systemd/user/git-maintenance@.service" &&
printf -- "--user disable --now git-maintenance@%s.timer\n" hourly daily weekly >expect &&
@@ -772,4 +849,17 @@ test_expect_success 'register and unregister bare repo' '
)
'
+test_expect_success 'failed schedule prevents config change' '
+ git init --bare failcase &&
+
+ for scheduler in crontab launchctl schtasks systemctl
+ do
+ GIT_TEST_MAINT_SCHEDULER="$scheduler:false" &&
+ export GIT_TEST_MAINT_SCHEDULER &&
+ test_must_fail \
+ git -C failcase maintenance start &&
+ test_must_fail git -C failcase config maintenance.auto || return 1
+ done
+'
+
test_done
diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh
index d751d48b7d..8bcd39e81b 100755
--- a/t/t8003-blame-corner-cases.sh
+++ b/t/t8003-blame-corner-cases.sh
@@ -201,7 +201,7 @@ committer David Reiss <dreiss@facebook.com> 1234567890 +0000
some message
EOF
- COMMIT=$(git hash-object -t commit -w badcommit) &&
+ COMMIT=$(git hash-object --literally -t commit -w badcommit) &&
git --no-pager blame $COMMIT -- uno >/dev/null
'
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 01c74b8b07..263db3ad17 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -12,7 +12,7 @@ PREREQ="PERL"
replace_variable_fields () {
sed -e "s/^\(Date:\).*/\1 DATE-STRING/" \
- -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
+ -e "s/^\(Message-ID:\).*/\1 MESSAGE-ID-STRING/" \
-e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/"
}
@@ -47,7 +47,7 @@ clean_fake_sendmail () {
test_expect_success $PREREQ 'Extract patches' '
patches=$(git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1) &&
- threaded_patches=$(git format-patch -o threaded -s --in-reply-to="format" HEAD^1)
+ threaded_patches=$(git format-patch -o threaded --thread=shallow -s --in-reply-to="format" HEAD^1)
'
# Test no confirm early to ensure remaining tests will not hang
@@ -61,8 +61,8 @@ test_no_confirm () {
--smtp-server="$(pwd)/fake.sendmail" \
$@ \
$patches >stdout &&
- ! grep "Send this email" stdout &&
- >no_confirm_okay
+ ! grep "Send this email" stdout &&
+ >no_confirm_okay
}
# Exit immediately to prevent hang if a no-confirm test fails
@@ -225,7 +225,7 @@ Cc: cc@example.com,
two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
In-Reply-To: <unique-message-id@example.com>
References: <unique-message-id@example.com>
@@ -337,13 +337,14 @@ test_expect_success $PREREQ 'Show all headers' '
test_expect_success $PREREQ 'Prompting works' '
clean_fake_sendmail &&
(echo "to@example.com" &&
- echo ""
+ echo "my-message-id@example.com"
) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
--smtp-server="$(pwd)/fake.sendmail" \
$patches \
2>errors &&
grep "^From: A U Thor <author@example.com>\$" msgtxt1 &&
- grep "^To: to@example.com\$" msgtxt1
+ grep "^To: to@example.com\$" msgtxt1 &&
+ grep "^In-Reply-To: <my-message-id@example.com>" msgtxt1
'
test_expect_success $PREREQ,AUTOIDENT 'implicit ident is allowed' '
@@ -374,13 +375,16 @@ test_expect_success $PREREQ,!AUTOIDENT 'broken implicit ident aborts send-email'
)
'
-test_expect_success $PREREQ 'setup tocmd and cccmd scripts' '
+test_expect_success $PREREQ 'setup cmd scripts' '
write_script tocmd-sed <<-\EOF &&
sed -n -e "s/^tocmd--//p" "$1"
EOF
- write_script cccmd-sed <<-\EOF
+ write_script cccmd-sed <<-\EOF &&
sed -n -e "s/^cccmd--//p" "$1"
EOF
+ write_script headercmd-sed <<-\EOF
+ sed -n -e "s/^headercmd--//p" "$1"
+ EOF
'
test_expect_success $PREREQ 'tocmd works' '
@@ -410,6 +414,70 @@ test_expect_success $PREREQ 'cccmd works' '
grep "^ cccmd@example.com" msgtxt1
'
+test_expect_success $PREREQ 'headercmd works' '
+ clean_fake_sendmail &&
+ cp $patches headercmd.patch &&
+ echo "headercmd--X-Debbugs-CC: dummy@example.com" >>headercmd.patch &&
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --header-cmd=./headercmd-sed \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ headercmd.patch \
+ &&
+ grep "^X-Debbugs-CC: dummy@example.com" msgtxt1
+'
+
+test_expect_success $PREREQ '--no-header-cmd works' '
+ clean_fake_sendmail &&
+ cp $patches headercmd.patch &&
+ echo "headercmd--X-Debbugs-CC: dummy@example.com" >>headercmd.patch &&
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --header-cmd=./headercmd-sed \
+ --no-header-cmd \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ headercmd.patch \
+ &&
+ ! grep "^X-Debbugs-CC: dummy@example.com" msgtxt1
+'
+
+test_expect_success $PREREQ 'multiline fields are correctly unfolded' '
+ clean_fake_sendmail &&
+ cp $patches headercmd.patch &&
+ write_script headercmd-multiline <<-\EOF &&
+ echo "X-Debbugs-CC: someone@example.com
+FoldedField: This is a tale
+ best told using
+ multiple lines."
+ EOF
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --header-cmd=./headercmd-multiline \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ headercmd.patch &&
+ grep "^FoldedField: This is a tale best told using multiple lines.$" msgtxt1
+'
+
+# Blank lines in the middle of the output of a command are invalid.
+test_expect_success $PREREQ 'malform output reported on blank lines in command output' '
+ clean_fake_sendmail &&
+ cp $patches headercmd.patch &&
+ write_script headercmd-malformed-output <<-\EOF &&
+ echo "X-Debbugs-CC: someone@example.com
+
+SomeOtherField: someone-else@example.com"
+ EOF
+ ! git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --header-cmd=./headercmd-malformed-output \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ headercmd.patch
+'
+
test_expect_success $PREREQ 'reject long lines' '
z8=zzzzzzzz &&
z64=$z8$z8$z8$z8$z8$z8$z8$z8 &&
@@ -540,7 +608,7 @@ test_expect_success $PREREQ "--validate respects relative core.hooksPath path" '
test_path_is_file my-hooks.ran &&
cat >expect <<-EOF &&
fatal: longline.patch: rejected by sendemail-validate hook
- fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1
+ fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1
warning: no patches were sent
EOF
test_cmp expect actual
@@ -559,12 +627,49 @@ test_expect_success $PREREQ "--validate respects absolute core.hooksPath path" '
test_path_is_file my-hooks.ran &&
cat >expect <<-EOF &&
fatal: longline.patch: rejected by sendemail-validate hook
- fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1
+ fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1
warning: no patches were sent
EOF
test_cmp expect actual
'
+test_expect_success $PREREQ "--validate hook supports header argument" '
+ write_script my-hooks/sendemail-validate <<-\EOF &&
+ if test "$#" -ge 2
+ then
+ grep "X-test-header: v1.0" "$2"
+ else
+ echo "No header arg passed"
+ exit 1
+ fi
+ EOF
+ test_config core.hooksPath "my-hooks" &&
+ rm -fr outdir &&
+ git format-patch \
+ --add-header="X-test-header: v1.0" \
+ -n HEAD^1 -o outdir &&
+ git send-email \
+ --dry-run \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --validate \
+ outdir/000?-*.patch
+'
+
+test_expect_success $PREREQ 'clear message-id before parsing a new message' '
+ clean_fake_sendmail &&
+ echo true | write_script my-hooks/sendemail-validate &&
+ test_config core.hooksPath my-hooks &&
+ git send-email --validate --to=recipient@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches $threaded_patches &&
+ id0=$(grep "^Message-ID: " $threaded_patches) &&
+ id1=$(grep "^Message-ID: " msgtxt1) &&
+ id2=$(grep "^Message-ID: " msgtxt2) &&
+ test "z$id0" = "z$id2" &&
+ test "z$id1" != "z$id2"
+'
+
for enc in 7bit 8bit quoted-printable base64
do
test_expect_success $PREREQ "--transfer-encoding=$enc produces correct header" '
@@ -617,7 +722,7 @@ test_expect_success $PREREQ 'In-Reply-To without --chain-reply-to' '
sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt1 >actual &&
test_cmp expect actual &&
# Second and subsequent messages are replies to the first one
- sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt1 >expect &&
+ sed -n -e "s/^Message-ID: *\(.*\)/\1/p" msgtxt1 >expect &&
sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt2 >actual &&
test_cmp expect actual &&
sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt3 >actual &&
@@ -637,10 +742,10 @@ test_expect_success $PREREQ 'In-Reply-To with --chain-reply-to' '
2>errors &&
sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt1 >actual &&
test_cmp expect actual &&
- sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt1 >expect &&
+ sed -n -e "s/^Message-ID: *\(.*\)/\1/p" msgtxt1 >expect &&
sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt2 >actual &&
test_cmp expect actual &&
- sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt2 >expect &&
+ sed -n -e "s/^Message-ID: *\(.*\)/\1/p" msgtxt2 >expect &&
sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt3 >actual &&
test_cmp expect actual
'
@@ -713,7 +818,7 @@ Cc: cc@example.com,
two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
@@ -759,7 +864,7 @@ Cc: A <author@example.com>,
two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
@@ -796,7 +901,7 @@ Cc: A <author@example.com>,
C O Mitter <committer@example.com>
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
@@ -824,7 +929,7 @@ From: Example <from@example.com>
To: to@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
@@ -860,7 +965,7 @@ Cc: A <author@example.com>,
cc-cmd@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
@@ -893,7 +998,7 @@ Cc: A <author@example.com>,
two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
@@ -926,7 +1031,7 @@ Cc: A <author@example.com>,
two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
@@ -963,7 +1068,7 @@ Cc: A <author@example.com>,
C O Mitter <committer@example.com>
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
@@ -993,7 +1098,7 @@ Cc: A <author@example.com>,
C O Mitter <committer@example.com>
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
-Message-Id: MESSAGE-ID-STRING
+Message-ID: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
@@ -1478,7 +1583,7 @@ test_expect_success $PREREQ 'To headers from files reset each patch' '
test_expect_success $PREREQ 'setup expect' '
cat >email-using-8bit <<\EOF
From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
-Message-Id: <bogus-message-id@example.com>
+Message-ID: <bogus-message-id@example.com>
From: author@example.com
Date: Sat, 12 Jun 2010 15:53:58 +0200
Subject: subject goes here
@@ -1519,7 +1624,7 @@ test_expect_success $PREREQ 'asks about and fixes 8bit encodings' '
grep "do not declare a Content-Transfer-Encoding" stdout &&
grep email-using-8bit stdout &&
grep "Which 8bit encoding" stdout &&
- egrep "Content|MIME" msgtxt1 >actual &&
+ grep -E "Content|MIME" msgtxt1 >actual &&
test_cmp content-type-decl actual
'
@@ -1530,7 +1635,7 @@ test_expect_success $PREREQ 'sendemail.8bitEncoding works' '
git send-email --from=author@example.com --to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
email-using-8bit >stdout &&
- egrep "Content|MIME" msgtxt1 >actual &&
+ grep -E "Content|MIME" msgtxt1 >actual &&
test_cmp content-type-decl actual
'
@@ -1545,7 +1650,7 @@ test_expect_success $PREREQ 'sendemail.8bitEncoding in .git/config overrides --g
git send-email --from=author@example.com --to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
email-using-8bit >stdout &&
- egrep "Content|MIME" msgtxt1 >actual &&
+ grep -E "Content|MIME" msgtxt1 >actual &&
test_cmp content-type-decl actual
'
@@ -1557,14 +1662,14 @@ test_expect_success $PREREQ '--8bit-encoding overrides sendemail.8bitEncoding' '
--smtp-server="$(pwd)/fake.sendmail" \
--8bit-encoding=UTF-8 \
email-using-8bit >stdout &&
- egrep "Content|MIME" msgtxt1 >actual &&
+ grep -E "Content|MIME" msgtxt1 >actual &&
test_cmp content-type-decl actual
'
test_expect_success $PREREQ 'setup expect' '
cat >email-using-8bit <<-\EOF
From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
- Message-Id: <bogus-message-id@example.com>
+ Message-ID: <bogus-message-id@example.com>
From: author@example.com
Date: Sat, 12 Jun 2010 15:53:58 +0200
Subject: Dieser Betreff enthält auch einen Umlaut!
@@ -1593,7 +1698,7 @@ test_expect_success $PREREQ '--8bit-encoding also treats subject' '
test_expect_success $PREREQ 'setup expect' '
cat >email-using-8bit <<-\EOF
From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
- Message-Id: <bogus-message-id@example.com>
+ Message-ID: <bogus-message-id@example.com>
From: A U Thor <author@example.com>
Date: Sat, 12 Jun 2010 15:53:58 +0200
Content-Type: text/plain; charset=UTF-8
@@ -1674,7 +1779,7 @@ test_expect_success $PREREQ '8-bit and sendemail.transferencoding=base64' '
test_expect_success $PREREQ 'setup expect' '
cat >email-using-qp <<-\EOF
From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
- Message-Id: <bogus-message-id@example.com>
+ Message-ID: <bogus-message-id@example.com>
From: A U Thor <author@example.com>
Date: Sat, 12 Jun 2010 15:53:58 +0200
MIME-Version: 1.0
@@ -1700,7 +1805,7 @@ test_expect_success $PREREQ 'convert from quoted-printable to base64' '
test_expect_success $PREREQ 'setup expect' "
tr -d '\\015' | tr '%' '\\015' >email-using-crlf <<EOF
From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
-Message-Id: <bogus-message-id@example.com>
+Message-ID: <bogus-message-id@example.com>
From: A U Thor <author@example.com>
Date: Sat, 12 Jun 2010 15:53:58 +0200
Content-Type: text/plain; charset=UTF-8
@@ -2326,6 +2431,37 @@ test_expect_success $PREREQ 'invoke hook' '
)
'
+expected_file_counter_output () {
+ total=$1
+ count=0
+ while test $count -ne $total
+ do
+ count=$((count + 1)) &&
+ echo "$count/$total" || return
+ done
+}
+
+test_expect_success $PREREQ '--validate hook allows counting of messages' '
+ test_when_finished "rm -rf my-hooks.log" &&
+ test_config core.hooksPath "my-hooks" &&
+ mkdir -p my-hooks &&
+
+ write_script my-hooks/sendemail-validate <<-\EOF &&
+ num=$GIT_SENDEMAIL_FILE_COUNTER &&
+ tot=$GIT_SENDEMAIL_FILE_TOTAL &&
+ echo "$num/$tot" >>my-hooks.log || exit 1
+ EOF
+
+ >my-hooks.log &&
+ expected_file_counter_output 4 >expect &&
+ git send-email \
+ --from="Example <from@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --validate -3 --cover-letter --force &&
+ test_cmp expect my-hooks.log
+'
+
test_expect_success $PREREQ 'test that send-email works outside a repo' '
nongit git send-email \
--from="Example <nobody@example.com>" \
@@ -2334,6 +2470,12 @@ test_expect_success $PREREQ 'test that send-email works outside a repo' '
"$(pwd)/0001-add-main.patch"
'
+test_expect_success $PREREQ 'send-email relays -v 3 to format-patch' '
+ test_when_finished "rm -f out" &&
+ git send-email --dry-run -v 3 -1 >out &&
+ grep "PATCH v3" out
+'
+
test_expect_success $PREREQ 'test that sendmail config is rejected' '
test_config sendmail.program sendmail &&
test_must_fail git send-email \
diff --git a/t/t9003-help-autocorrect.sh b/t/t9003-help-autocorrect.sh
index f00deaf381..14a704d0a8 100755
--- a/t/t9003-help-autocorrect.sh
+++ b/t/t9003-help-autocorrect.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='help.autocorrect finding a match'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
@@ -60,4 +62,10 @@ test_expect_success 'autocorrect can be declined altogether' '
test_line_count = 1 actual
'
+test_expect_success 'autocorrect works in work tree created from bare repo' '
+ git clone --bare . bare.git &&
+ git -C bare.git worktree add ../worktree &&
+ git -C worktree -c help.autocorrect=immediate stauts
+'
+
test_done
diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh
index fea41b3c36..af28b01fef 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -21,7 +21,7 @@ test_expect_success 'git svn help works anywhere' '
'
test_expect_success \
- 'initialize git svn' '
+ 'initialize git svn' '
mkdir import &&
(
cd import &&
@@ -38,9 +38,9 @@ test_expect_success \
rm -rf import &&
git svn init "$svnrepo"'
-test_expect_success \
- 'import an SVN revision into git' \
- 'git svn fetch'
+test_expect_success 'import an SVN revision into git' '
+ git svn fetch
+'
test_expect_success "checkout from svn" 'svn co "$svnrepo" "$SVN_TREE"'
@@ -233,27 +233,26 @@ test_expect_success POSIXPERM,SYMLINKS "$name" '
'
test_expect_success 'exit if remote refs are ambigious' '
- git config --add svn-remote.svn.fetch \
+ git config --add svn-remote.svn.fetch \
bar:refs/remotes/git-svn &&
test_must_fail git svn migrate
'
test_expect_success 'exit if init-ing a would clobber a URL' '
- svnadmin create "${PWD}/svnrepo2" &&
- svn mkdir -m "mkdir bar" "${svnrepo}2/bar" &&
- git config --unset svn-remote.svn.fetch \
+ svnadmin create "${PWD}/svnrepo2" &&
+ svn mkdir -m "mkdir bar" "${svnrepo}2/bar" &&
+ git config --unset svn-remote.svn.fetch \
"^bar:refs/remotes/git-svn$" &&
test_must_fail git svn init "${svnrepo}2/bar"
'
-test_expect_success \
- 'init allows us to connect to another directory in the same repo' '
- git svn init --minimize-url -i bar "$svnrepo/bar" &&
- git config --get svn-remote.svn.fetch \
- "^bar:refs/remotes/bar$" &&
- git config --get svn-remote.svn.fetch \
- "^:refs/remotes/git-svn$"
- '
+test_expect_success 'init allows us to connect to another directory in the same repo' '
+ git svn init --minimize-url -i bar "$svnrepo/bar" &&
+ git config --get svn-remote.svn.fetch \
+ "^bar:refs/remotes/bar$" &&
+ git config --get svn-remote.svn.fetch \
+ "^:refs/remotes/git-svn$"
+'
test_expect_success 'dcommit $rev does not clobber current branch' '
git svn fetch -i bar &&
diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh
index 85d735861f..b5845e28fe 100755
--- a/t/t9104-git-svn-follow-parent.sh
+++ b/t/t9104-git-svn-follow-parent.sh
@@ -41,51 +41,51 @@ test_expect_success 'init and fetch a moved directory' '
'
test_expect_success 'init and fetch from one svn-remote' '
- git config svn-remote.svn.url "$svnrepo" &&
- git config --add svn-remote.svn.fetch \
- trunk:refs/remotes/svn/trunk &&
- git config --add svn-remote.svn.fetch \
- thunk:refs/remotes/svn/thunk &&
- git svn fetch -i svn/thunk &&
+ git config svn-remote.svn.url "$svnrepo" &&
+ git config --add svn-remote.svn.fetch \
+ trunk:refs/remotes/svn/trunk &&
+ git config --add svn-remote.svn.fetch \
+ thunk:refs/remotes/svn/thunk &&
+ git svn fetch -i svn/thunk &&
test "$(git rev-parse --verify refs/remotes/svn/trunk)" \
- = "$(git rev-parse --verify refs/remotes/svn/thunk~1)" &&
+ = "$(git rev-parse --verify refs/remotes/svn/thunk~1)" &&
git cat-file blob refs/remotes/svn/thunk:readme >actual &&
test "$(sed -n -e "3p" actual)" = goodbye
- '
+'
test_expect_success 'follow deleted parent' '
- (svn_cmd cp -m "resurrecting trunk as junk" \
- "$svnrepo"/trunk@2 "$svnrepo"/junk ||
- svn cp -m "resurrecting trunk as junk" \
- -r2 "$svnrepo"/trunk "$svnrepo"/junk) &&
- git config --add svn-remote.svn.fetch \
- junk:refs/remotes/svn/junk &&
- git svn fetch -i svn/thunk &&
- git svn fetch -i svn/junk &&
+ (svn_cmd cp -m "resurrecting trunk as junk" \
+ "$svnrepo"/trunk@2 "$svnrepo"/junk ||
+ svn cp -m "resurrecting trunk as junk" \
+ -r2 "$svnrepo"/trunk "$svnrepo"/junk) &&
+ git config --add svn-remote.svn.fetch \
+ junk:refs/remotes/svn/junk &&
+ git svn fetch -i svn/thunk &&
+ git svn fetch -i svn/junk &&
test -z "$(git diff svn/junk svn/trunk)" &&
test "$(git merge-base svn/junk svn/trunk)" \
- = "$(git rev-parse svn/trunk)"
- '
+ = "$(git rev-parse svn/trunk)"
+'
test_expect_success 'follow larger parent' '
- mkdir -p import/trunk/thunk/bump/thud &&
- echo hi > import/trunk/thunk/bump/thud/file &&
- svn import -m "import a larger parent" import "$svnrepo"/larger-parent &&
- svn cp -m "hi" "$svnrepo"/larger-parent "$svnrepo"/another-larger &&
- git svn init --minimize-url -i larger \
- "$svnrepo"/larger-parent/trunk/thunk/bump/thud &&
- git svn fetch -i larger &&
+ mkdir -p import/trunk/thunk/bump/thud &&
+ echo hi > import/trunk/thunk/bump/thud/file &&
+ svn import -m "import a larger parent" import "$svnrepo"/larger-parent &&
+ svn cp -m "hi" "$svnrepo"/larger-parent "$svnrepo"/another-larger &&
+ git svn init --minimize-url -i larger \
+ "$svnrepo"/larger-parent/trunk/thunk/bump/thud &&
+ git svn fetch -i larger &&
git svn init --minimize-url -i larger-parent \
- "$svnrepo"/another-larger/trunk/thunk/bump/thud &&
+ "$svnrepo"/another-larger/trunk/thunk/bump/thud &&
git svn fetch -i larger-parent &&
- git rev-parse --verify refs/remotes/larger &&
- git rev-parse --verify \
- refs/remotes/larger-parent &&
+ git rev-parse --verify refs/remotes/larger &&
+ git rev-parse --verify \
+ refs/remotes/larger-parent &&
test "$(git merge-base \
refs/remotes/larger-parent \
refs/remotes/larger)" = \
- "$(git rev-parse refs/remotes/larger)"
- '
+ "$(git rev-parse refs/remotes/larger)"
+'
test_expect_success 'follow higher-level parent' '
svn mkdir -m "follow higher-level parent" "$svnrepo"/blob &&
diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh
index 3cab0b9720..bca496c40e 100755
--- a/t/t9106-git-svn-commit-diff-clobber.sh
+++ b/t/t9106-git-svn-commit-diff-clobber.sh
@@ -3,7 +3,6 @@
# Copyright (c) 2006 Eric Wong
test_description='git svn commit-diff clobber'
-TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
test_expect_success 'initialize repo' '
diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh
index 419f055721..743fbe1fe4 100755
--- a/t/t9115-git-svn-dcommit-funky-renames.sh
+++ b/t/t9115-git-svn-dcommit-funky-renames.sh
@@ -5,7 +5,6 @@
test_description='git svn dcommit can commit renames of files with ugly names'
-TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
test_expect_success 'load repository with strange names' '
diff --git a/t/t9119-git-svn-info.sh b/t/t9119-git-svn-info.sh
index 8201c3e808..088d1c57a8 100755
--- a/t/t9119-git-svn-info.sh
+++ b/t/t9119-git-svn-info.sh
@@ -28,7 +28,7 @@ test_cmp_info () {
rm -f tmp.expect tmp.actual
}
-quoted_svnrepo="$(echo $svnrepo | sed 's/ /%20/')"
+quoted_svnrepo="$(echo $svnrepo | test_uri_escape)"
test_expect_success 'setup repository and import' '
mkdir info &&
diff --git a/t/t9133-git-svn-nested-git-repo.sh b/t/t9133-git-svn-nested-git-repo.sh
index f894860867..d8d536269c 100755
--- a/t/t9133-git-svn-nested-git-repo.sh
+++ b/t/t9133-git-svn-nested-git-repo.sh
@@ -35,7 +35,7 @@ test_expect_success 'SVN-side change outside of .git' '
echo b >> a &&
svn_cmd commit -m "SVN-side change outside of .git" &&
svn_cmd up &&
- svn_cmd log -v | fgrep "SVN-side change outside of .git"
+ svn_cmd log -v | grep -F "SVN-side change outside of .git"
)
'
@@ -59,7 +59,7 @@ test_expect_success 'SVN-side change inside of .git' '
svn_cmd add --force .git &&
svn_cmd commit -m "SVN-side change inside of .git" &&
svn_cmd up &&
- svn_cmd log -v | fgrep "SVN-side change inside of .git"
+ svn_cmd log -v | grep -F "SVN-side change inside of .git"
)
'
@@ -82,7 +82,7 @@ test_expect_success 'SVN-side change in and out of .git' '
git commit -m "add a inside an SVN repo" &&
svn_cmd commit -m "SVN-side change in and out of .git" &&
svn_cmd up &&
- svn_cmd log -v | fgrep "SVN-side change in and out of .git"
+ svn_cmd log -v | grep -F "SVN-side change in and out of .git"
)
'
diff --git a/t/t9134-git-svn-ignore-paths.sh b/t/t9134-git-svn-ignore-paths.sh
index 4a77eb9f60..3188400226 100755
--- a/t/t9134-git-svn-ignore-paths.sh
+++ b/t/t9134-git-svn-ignore-paths.sh
@@ -43,7 +43,7 @@ test_expect_success 'init+fetch an SVN repository with ignored www directory' '
test_expect_success 'verify ignore-paths config saved by clone' '
(
cd g &&
- git config --get svn-remote.svn.ignore-paths | fgrep "www"
+ git config --get svn-remote.svn.ignore-paths | grep www
)
'
@@ -53,7 +53,7 @@ test_expect_success 'SVN-side change outside of www' '
echo b >> qqq/test_qqq.txt &&
svn_cmd commit -m "SVN-side change outside of www" &&
svn_cmd up &&
- svn_cmd log -v | fgrep "SVN-side change outside of www"
+ svn_cmd log -v | grep "SVN-side change outside of www"
)
'
@@ -85,7 +85,7 @@ test_expect_success 'SVN-side change inside of ignored www' '
echo zaq >> www/test_www.txt &&
svn_cmd commit -m "SVN-side change inside of www/test_www.txt" &&
svn_cmd up &&
- svn_cmd log -v | fgrep "SVN-side change inside of www/test_www.txt"
+ svn_cmd log -v | grep -F "SVN-side change inside of www/test_www.txt"
)
'
@@ -118,7 +118,7 @@ test_expect_success 'SVN-side change in and out of ignored www' '
echo ygg >> qqq/test_qqq.txt &&
svn_cmd commit -m "SVN-side change in and out of ignored www" &&
svn_cmd up &&
- svn_cmd log -v | fgrep "SVN-side change in and out of ignored www"
+ svn_cmd log -v | grep "SVN-side change in and out of ignored www"
)
'
diff --git a/t/t9140-git-svn-reset.sh b/t/t9140-git-svn-reset.sh
index e855904629..a420b2a87a 100755
--- a/t/t9140-git-svn-reset.sh
+++ b/t/t9140-git-svn-reset.sh
@@ -43,7 +43,7 @@ test_expect_success 'fetch fails on modified hidden file' '
git svn find-rev refs/remotes/git-svn > ../expect &&
test_must_fail git svn fetch 2> ../errors &&
git svn find-rev refs/remotes/git-svn > ../expect2 ) &&
- fgrep "not found in commit" errors &&
+ grep "not found in commit" errors &&
test_cmp expect expect2
'
@@ -59,7 +59,7 @@ test_expect_success 'refetch succeeds not ignoring any files' '
( cd g &&
git svn fetch &&
git svn rebase &&
- fgrep "mod hidden" hid/hid.txt
+ grep "mod hidden" hid/hid.txt
)
'
diff --git a/t/t9146-git-svn-empty-dirs.sh b/t/t9146-git-svn-empty-dirs.sh
index 79c26ed69c..09606f1b3c 100755
--- a/t/t9146-git-svn-empty-dirs.sh
+++ b/t/t9146-git-svn-empty-dirs.sh
@@ -4,7 +4,6 @@
test_description='git svn creates empty directories'
-TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
test_expect_success 'initialize repo' '
diff --git a/t/t9147-git-svn-include-paths.sh b/t/t9147-git-svn-include-paths.sh
index 257fc8f2f8..63fa0b6732 100755
--- a/t/t9147-git-svn-include-paths.sh
+++ b/t/t9147-git-svn-include-paths.sh
@@ -45,7 +45,7 @@ test_expect_success 'init+fetch an SVN repository with included qqq directory' '
test_expect_success 'verify include-paths config saved by clone' '
(
cd g &&
- git config --get svn-remote.svn.include-paths | fgrep "qqq"
+ git config --get svn-remote.svn.include-paths | grep qqq
)
'
@@ -55,7 +55,7 @@ test_expect_success 'SVN-side change outside of www' '
echo b >> qqq/test_qqq.txt &&
svn_cmd commit -m "SVN-side change outside of www" &&
svn_cmd up &&
- svn_cmd log -v | fgrep "SVN-side change outside of www"
+ svn_cmd log -v | grep "SVN-side change outside of www"
)
'
@@ -87,7 +87,7 @@ test_expect_success 'SVN-side change inside of ignored www' '
echo zaq >> www/test_www.txt &&
svn_cmd commit -m "SVN-side change inside of www/test_www.txt" &&
svn_cmd up &&
- svn_cmd log -v | fgrep "SVN-side change inside of www/test_www.txt"
+ svn_cmd log -v | grep "SVN-side change inside of www/test_www.txt"
)
'
@@ -120,7 +120,7 @@ test_expect_success 'SVN-side change in and out of included qqq' '
echo ygg >> qqq/test_qqq.txt &&
svn_cmd commit -m "SVN-side change in and out of ignored www" &&
svn_cmd up &&
- svn_cmd log -v | fgrep "SVN-side change in and out of ignored www"
+ svn_cmd log -v | grep "SVN-side change in and out of ignored www"
)
'
diff --git a/t/t9148-git-svn-propset.sh b/t/t9148-git-svn-propset.sh
index 6cc76a07b3..aebb28995e 100755
--- a/t/t9148-git-svn-propset.sh
+++ b/t/t9148-git-svn-propset.sh
@@ -5,7 +5,6 @@
test_description='git svn propset tests'
-TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
test_expect_success 'setup propset via import' '
diff --git a/t/t9160-git-svn-preserve-empty-dirs.sh b/t/t9160-git-svn-preserve-empty-dirs.sh
index 9cf7a1427a..36c6b1a12f 100755
--- a/t/t9160-git-svn-preserve-empty-dirs.sh
+++ b/t/t9160-git-svn-preserve-empty-dirs.sh
@@ -9,7 +9,6 @@ This test uses git to clone a Subversion repository that contains empty
directories, and checks that corresponding directories are created in the
local Git repository with placeholder files.'
-TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
GIT_REPO=git-svn-repo
diff --git a/t/t9164-git-svn-dcommit-concurrent.sh b/t/t9164-git-svn-dcommit-concurrent.sh
index 1465156072..c8e6c0733f 100755
--- a/t/t9164-git-svn-dcommit-concurrent.sh
+++ b/t/t9164-git-svn-dcommit-concurrent.sh
@@ -5,7 +5,6 @@
test_description='concurrent git svn dcommit'
-TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index c5946cb0b8..a44eabf0d8 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -50,56 +50,56 @@ check_entries () {
fi
}
-test_expect_success \
- 'New file' \
- 'mkdir A B C D E F &&
- echo hello1 >A/newfile1.txt &&
- echo hello2 >B/newfile2.txt &&
- cp "$TEST_DIRECTORY"/test-binary-1.png C/newfile3.png &&
- cp "$TEST_DIRECTORY"/test-binary-1.png D/newfile4.png &&
- git add A/newfile1.txt &&
- git add B/newfile2.txt &&
- git add C/newfile3.png &&
- git add D/newfile4.png &&
- git commit -a -m "Test: New file" &&
- id=$(git rev-list --max-count=1 HEAD) &&
- (cd "$CVSWORK" &&
- git cvsexportcommit -c $id &&
- check_entries A "newfile1.txt/1.1/" &&
- check_entries B "newfile2.txt/1.1/" &&
- check_entries C "newfile3.png/1.1/-kb" &&
- check_entries D "newfile4.png/1.1/-kb" &&
- test_cmp A/newfile1.txt ../A/newfile1.txt &&
- test_cmp B/newfile2.txt ../B/newfile2.txt &&
- test_cmp C/newfile3.png ../C/newfile3.png &&
- test_cmp D/newfile4.png ../D/newfile4.png
- )'
+test_expect_success 'New file' '
+ mkdir A B C D E F &&
+ echo hello1 >A/newfile1.txt &&
+ echo hello2 >B/newfile2.txt &&
+ cp "$TEST_DIRECTORY"/test-binary-1.png C/newfile3.png &&
+ cp "$TEST_DIRECTORY"/test-binary-1.png D/newfile4.png &&
+ git add A/newfile1.txt &&
+ git add B/newfile2.txt &&
+ git add C/newfile3.png &&
+ git add D/newfile4.png &&
+ git commit -a -m "Test: New file" &&
+ id=$(git rev-list --max-count=1 HEAD) &&
+ (cd "$CVSWORK" &&
+ git cvsexportcommit -c $id &&
+ check_entries A "newfile1.txt/1.1/" &&
+ check_entries B "newfile2.txt/1.1/" &&
+ check_entries C "newfile3.png/1.1/-kb" &&
+ check_entries D "newfile4.png/1.1/-kb" &&
+ test_cmp A/newfile1.txt ../A/newfile1.txt &&
+ test_cmp B/newfile2.txt ../B/newfile2.txt &&
+ test_cmp C/newfile3.png ../C/newfile3.png &&
+ test_cmp D/newfile4.png ../D/newfile4.png
+ )
+'
-test_expect_success \
- 'Remove two files, add two and update two' \
- 'echo Hello1 >>A/newfile1.txt &&
- rm -f B/newfile2.txt &&
- rm -f C/newfile3.png &&
- echo Hello5 >E/newfile5.txt &&
- cp "$TEST_DIRECTORY"/test-binary-2.png D/newfile4.png &&
- cp "$TEST_DIRECTORY"/test-binary-1.png F/newfile6.png &&
- git add E/newfile5.txt &&
- git add F/newfile6.png &&
- git commit -a -m "Test: Remove, add and update" &&
- id=$(git rev-list --max-count=1 HEAD) &&
- (cd "$CVSWORK" &&
- git cvsexportcommit -c $id &&
- check_entries A "newfile1.txt/1.2/" &&
- check_entries B "" &&
- check_entries C "" &&
- check_entries D "newfile4.png/1.2/-kb" &&
- check_entries E "newfile5.txt/1.1/" &&
- check_entries F "newfile6.png/1.1/-kb" &&
- test_cmp A/newfile1.txt ../A/newfile1.txt &&
- test_cmp D/newfile4.png ../D/newfile4.png &&
- test_cmp E/newfile5.txt ../E/newfile5.txt &&
- test_cmp F/newfile6.png ../F/newfile6.png
- )'
+test_expect_success 'Remove two files, add two and update two' '
+ echo Hello1 >>A/newfile1.txt &&
+ rm -f B/newfile2.txt &&
+ rm -f C/newfile3.png &&
+ echo Hello5 >E/newfile5.txt &&
+ cp "$TEST_DIRECTORY"/test-binary-2.png D/newfile4.png &&
+ cp "$TEST_DIRECTORY"/test-binary-1.png F/newfile6.png &&
+ git add E/newfile5.txt &&
+ git add F/newfile6.png &&
+ git commit -a -m "Test: Remove, add and update" &&
+ id=$(git rev-list --max-count=1 HEAD) &&
+ (cd "$CVSWORK" &&
+ git cvsexportcommit -c $id &&
+ check_entries A "newfile1.txt/1.2/" &&
+ check_entries B "" &&
+ check_entries C "" &&
+ check_entries D "newfile4.png/1.2/-kb" &&
+ check_entries E "newfile5.txt/1.1/" &&
+ check_entries F "newfile6.png/1.1/-kb" &&
+ test_cmp A/newfile1.txt ../A/newfile1.txt &&
+ test_cmp D/newfile4.png ../D/newfile4.png &&
+ test_cmp E/newfile5.txt ../E/newfile5.txt &&
+ test_cmp F/newfile6.png ../F/newfile6.png
+ )
+'
# Should fail (but only on the git cvsexportcommit stage)
test_expect_success \
@@ -129,67 +129,67 @@ test_expect_success \
# This test is here because a patch for only binary files will
# fail with gnu patch, so cvsexportcommit must handle that.
-test_expect_success \
- 'Remove only binary files' \
- 'git reset --hard HEAD^^ &&
- rm -f D/newfile4.png &&
- git commit -a -m "test: remove only a binary file" &&
- id=$(git rev-list --max-count=1 HEAD) &&
- (cd "$CVSWORK" &&
- git cvsexportcommit -c $id &&
- check_entries A "newfile1.txt/1.2/" &&
- check_entries B "" &&
- check_entries C "" &&
- check_entries D "" &&
- check_entries E "newfile5.txt/1.1/" &&
- check_entries F "newfile6.png/1.1/-kb" &&
- test_cmp A/newfile1.txt ../A/newfile1.txt &&
- test_cmp E/newfile5.txt ../E/newfile5.txt &&
- test_cmp F/newfile6.png ../F/newfile6.png
- )'
+test_expect_success 'Remove only binary files' '
+ git reset --hard HEAD^^ &&
+ rm -f D/newfile4.png &&
+ git commit -a -m "test: remove only a binary file" &&
+ id=$(git rev-list --max-count=1 HEAD) &&
+ (cd "$CVSWORK" &&
+ git cvsexportcommit -c $id &&
+ check_entries A "newfile1.txt/1.2/" &&
+ check_entries B "" &&
+ check_entries C "" &&
+ check_entries D "" &&
+ check_entries E "newfile5.txt/1.1/" &&
+ check_entries F "newfile6.png/1.1/-kb" &&
+ test_cmp A/newfile1.txt ../A/newfile1.txt &&
+ test_cmp E/newfile5.txt ../E/newfile5.txt &&
+ test_cmp F/newfile6.png ../F/newfile6.png
+ )
+'
-test_expect_success \
- 'Remove only a text file' \
- 'rm -f A/newfile1.txt &&
- git commit -a -m "test: remove only a binary file" &&
- id=$(git rev-list --max-count=1 HEAD) &&
- (cd "$CVSWORK" &&
- git cvsexportcommit -c $id &&
- check_entries A "" &&
- check_entries B "" &&
- check_entries C "" &&
- check_entries D "" &&
- check_entries E "newfile5.txt/1.1/" &&
- check_entries F "newfile6.png/1.1/-kb" &&
- test_cmp E/newfile5.txt ../E/newfile5.txt &&
- test_cmp F/newfile6.png ../F/newfile6.png
- )'
+test_expect_success 'Remove only a text file' '
+ rm -f A/newfile1.txt &&
+ git commit -a -m "test: remove only a binary file" &&
+ id=$(git rev-list --max-count=1 HEAD) &&
+ (cd "$CVSWORK" &&
+ git cvsexportcommit -c $id &&
+ check_entries A "" &&
+ check_entries B "" &&
+ check_entries C "" &&
+ check_entries D "" &&
+ check_entries E "newfile5.txt/1.1/" &&
+ check_entries F "newfile6.png/1.1/-kb" &&
+ test_cmp E/newfile5.txt ../E/newfile5.txt &&
+ test_cmp F/newfile6.png ../F/newfile6.png
+ )
+'
-test_expect_success \
- 'New file with spaces in file name' \
- 'mkdir "G g" &&
- echo ok then >"G g/with spaces.txt" &&
- git add "G g/with spaces.txt" && \
- cp "$TEST_DIRECTORY"/test-binary-1.png "G g/with spaces.png" && \
- git add "G g/with spaces.png" &&
- git commit -a -m "With spaces" &&
- id=$(git rev-list --max-count=1 HEAD) &&
- (cd "$CVSWORK" &&
- git cvsexportcommit -c $id &&
- check_entries "G g" "with spaces.png/1.1/-kb|with spaces.txt/1.1/"
- )'
+test_expect_success 'New file with spaces in file name' '
+ mkdir "G g" &&
+ echo ok then >"G g/with spaces.txt" &&
+ git add "G g/with spaces.txt" && \
+ cp "$TEST_DIRECTORY"/test-binary-1.png "G g/with spaces.png" && \
+ git add "G g/with spaces.png" &&
+ git commit -a -m "With spaces" &&
+ id=$(git rev-list --max-count=1 HEAD) &&
+ (cd "$CVSWORK" &&
+ git cvsexportcommit -c $id &&
+ check_entries "G g" "with spaces.png/1.1/-kb|with spaces.txt/1.1/"
+ )
+'
-test_expect_success \
- 'Update file with spaces in file name' \
- 'echo Ok then >>"G g/with spaces.txt" &&
- cat "$TEST_DIRECTORY"/test-binary-1.png >>"G g/with spaces.png" && \
- git add "G g/with spaces.png" &&
- git commit -a -m "Update with spaces" &&
- id=$(git rev-list --max-count=1 HEAD) &&
- (cd "$CVSWORK" &&
- git cvsexportcommit -c $id &&
- check_entries "G g" "with spaces.png/1.2/-kb|with spaces.txt/1.2/"
- )'
+test_expect_success 'Update file with spaces in file name' '
+ echo Ok then >>"G g/with spaces.txt" &&
+ cat "$TEST_DIRECTORY"/test-binary-1.png >>"G g/with spaces.png" && \
+ git add "G g/with spaces.png" &&
+ git commit -a -m "Update with spaces" &&
+ id=$(git rev-list --max-count=1 HEAD) &&
+ (cd "$CVSWORK" &&
+ git cvsexportcommit -c $id &&
+ check_entries "G g" "with spaces.png/1.2/-kb|with spaces.txt/1.2/"
+ )
+'
# Some filesystems mangle pathnames with UTF-8 characters --
# check and skip
@@ -202,68 +202,68 @@ if p="Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö" &&
then
# This test contains UTF-8 characters
-test_expect_success !MINGW \
- 'File with non-ascii file name' \
- 'mkdir -p Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö &&
- echo Foo >Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
- git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
- cp "$TEST_DIRECTORY"/test-binary-1.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
- git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
- git commit -a -m "Går det så går det" && \
- id=$(git rev-list --max-count=1 HEAD) &&
- (cd "$CVSWORK" &&
- git cvsexportcommit -v -c $id &&
- check_entries \
- "Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö" \
- "gårdetsågårdet.png/1.1/-kb|gårdetsågårdet.txt/1.1/"
- )'
+test_expect_success !MINGW 'File with non-ascii file name' '
+ mkdir -p Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö &&
+ echo Foo >Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
+ git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
+ cp "$TEST_DIRECTORY"/test-binary-1.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
+ git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
+ git commit -a -m "Går det så går det" && \
+ id=$(git rev-list --max-count=1 HEAD) &&
+ (cd "$CVSWORK" &&
+ git cvsexportcommit -v -c $id &&
+ check_entries \
+ "Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö" \
+ "gårdetsågårdet.png/1.1/-kb|gårdetsågårdet.txt/1.1/"
+ )
+'
fi
rm -fr tst
-test_expect_success \
- 'Mismatching patch should fail' \
- 'date >>"E/newfile5.txt" &&
- git add "E/newfile5.txt" &&
- git commit -a -m "Update one" &&
- date >>"E/newfile5.txt" &&
- git add "E/newfile5.txt" &&
- git commit -a -m "Update two" &&
- id=$(git rev-list --max-count=1 HEAD) &&
- (cd "$CVSWORK" &&
- test_must_fail git cvsexportcommit -c $id
- )'
-
-test_expect_success FILEMODE \
- 'Retain execute bit' \
- 'mkdir G &&
- echo executeon >G/on &&
- chmod +x G/on &&
- echo executeoff >G/off &&
- git add G/on &&
- git add G/off &&
- git commit -a -m "Execute test" &&
- (cd "$CVSWORK" &&
- git cvsexportcommit -c HEAD &&
- test -x G/on &&
- ! test -x G/off
- )'
+test_expect_success 'Mismatching patch should fail' '
+ date >>"E/newfile5.txt" &&
+ git add "E/newfile5.txt" &&
+ git commit -a -m "Update one" &&
+ date >>"E/newfile5.txt" &&
+ git add "E/newfile5.txt" &&
+ git commit -a -m "Update two" &&
+ id=$(git rev-list --max-count=1 HEAD) &&
+ (cd "$CVSWORK" &&
+ test_must_fail git cvsexportcommit -c $id
+ )
+'
+
+test_expect_success FILEMODE 'Retain execute bit' '
+ mkdir G &&
+ echo executeon >G/on &&
+ chmod +x G/on &&
+ echo executeoff >G/off &&
+ git add G/on &&
+ git add G/off &&
+ git commit -a -m "Execute test" &&
+ (cd "$CVSWORK" &&
+ git cvsexportcommit -c HEAD &&
+ test -x G/on &&
+ ! test -x G/off
+ )
+'
test_expect_success '-w option should work with relative GIT_DIR' '
- mkdir W &&
- echo foobar >W/file1.txt &&
- echo bazzle >W/file2.txt &&
- git add W/file1.txt &&
- git add W/file2.txt &&
- git commit -m "More updates" &&
- id=$(git rev-list --max-count=1 HEAD) &&
- (cd "$GIT_DIR" &&
- GIT_DIR=. git cvsexportcommit -w "$CVSWORK" -c $id &&
- check_entries "$CVSWORK/W" "file1.txt/1.1/|file2.txt/1.1/" &&
- test_cmp "$CVSWORK/W/file1.txt" ../W/file1.txt &&
- test_cmp "$CVSWORK/W/file2.txt" ../W/file2.txt
- )
+ mkdir W &&
+ echo foobar >W/file1.txt &&
+ echo bazzle >W/file2.txt &&
+ git add W/file1.txt &&
+ git add W/file2.txt &&
+ git commit -m "More updates" &&
+ id=$(git rev-list --max-count=1 HEAD) &&
+ (cd "$GIT_DIR" &&
+ GIT_DIR=. git cvsexportcommit -w "$CVSWORK" -c $id &&
+ check_entries "$CVSWORK/W" "file1.txt/1.1/|file2.txt/1.1/" &&
+ test_cmp "$CVSWORK/W/file1.txt" ../W/file1.txt &&
+ test_cmp "$CVSWORK/W/file2.txt" ../W/file2.txt
+ )
'
test_expect_success 'check files before directories' '
@@ -290,21 +290,20 @@ test_expect_success 'check files before directories' '
'
test_expect_success 're-commit a removed filename which remains in CVS attic' '
-
- (cd "$CVSWORK" &&
- echo >attic_gremlin &&
- cvs -Q add attic_gremlin &&
- cvs -Q ci -m "added attic_gremlin" &&
- rm attic_gremlin &&
- cvs -Q rm attic_gremlin &&
- cvs -Q ci -m "removed attic_gremlin") &&
-
- echo > attic_gremlin &&
- git add attic_gremlin &&
- git commit -m "Added attic_gremlin" &&
+ (cd "$CVSWORK" &&
+ echo >attic_gremlin &&
+ cvs -Q add attic_gremlin &&
+ cvs -Q ci -m "added attic_gremlin" &&
+ rm attic_gremlin &&
+ cvs -Q rm attic_gremlin &&
+ cvs -Q ci -m "removed attic_gremlin") &&
+
+ echo > attic_gremlin &&
+ git add attic_gremlin &&
+ git commit -m "Added attic_gremlin" &&
git cvsexportcommit -w "$CVSWORK" -c HEAD &&
- (cd "$CVSWORK" && cvs -Q update -d) &&
- test -f "$CVSWORK/attic_gremlin"
+ (cd "$CVSWORK" && cvs -Q update -d) &&
+ test -f "$CVSWORK/attic_gremlin"
'
# the state of the CVS sandbox may be indeterminate for ' space'
diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh
index 14ca575a21..4432a30d10 100755
--- a/t/t9210-scalar.sh
+++ b/t/t9210-scalar.sh
@@ -104,6 +104,13 @@ test_expect_success FSMONITOR_DAEMON 'scalar register starts fsmon daemon' '
test_cmp_config -C test/src true core.fsmonitor
'
+test_expect_success 'scalar register warns when background maintenance fails' '
+ git init register-repo &&
+ GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \
+ scalar register register-repo 2>err &&
+ grep "could not turn on maintenance" err
+'
+
test_expect_success 'scalar unregister' '
git init vanish/src &&
scalar register vanish/src &&
@@ -116,7 +123,10 @@ test_expect_success 'scalar unregister' '
test_must_fail git config --get --global --fixed-value \
maintenance.repo "$(pwd)/vanish/src" &&
scalar list >scalar.repos &&
- ! grep -F "$(pwd)/vanish/src" scalar.repos
+ ! grep -F "$(pwd)/vanish/src" scalar.repos &&
+
+ # scalar unregister should be idempotent
+ scalar unregister vanish
'
test_expect_success 'set up repository to clone' '
@@ -163,6 +173,20 @@ test_expect_success 'scalar reconfigure' '
test true = "$(git -C one/src config core.preloadIndex)"
'
+test_expect_success '`reconfigure -a` removes stale config entries' '
+ git init stale/src &&
+ scalar register stale &&
+ scalar list >scalar.repos &&
+ grep stale scalar.repos &&
+
+ grep -v stale scalar.repos >expect &&
+
+ rm -rf stale &&
+ scalar reconfigure -a &&
+ scalar list >scalar.repos &&
+ test_cmp expect scalar.repos
+'
+
test_expect_success 'scalar delete without enlistment shows a usage' '
test_expect_code 129 scalar delete
'
diff --git a/t/t9211-scalar-clone.sh b/t/t9211-scalar-clone.sh
index dd33d87e9b..7869f45ee6 100755
--- a/t/t9211-scalar-clone.sh
+++ b/t/t9211-scalar-clone.sh
@@ -3,6 +3,7 @@
test_description='test the `scalar clone` subcommand'
. ./test-lib.sh
+. "${TEST_DIRECTORY}/lib-terminal.sh"
GIT_TEST_MAINT_SCHEDULER="crontab:test-tool crontab cron.txt,launchctl:true,schtasks:true"
export GIT_TEST_MAINT_SCHEDULER
@@ -148,4 +149,47 @@ test_expect_success '--no-single-branch clones all branches' '
cleanup_clone $enlistment
'
+test_expect_success TTY 'progress with tty' '
+ enlistment=progress1 &&
+
+ test_config -C to-clone uploadpack.allowfilter true &&
+ test_config -C to-clone uploadpack.allowanysha1inwant true &&
+
+ test_terminal env GIT_PROGRESS_DELAY=0 \
+ scalar clone "file://$(pwd)/to-clone" "$enlistment" 2>stderr &&
+ grep "Enumerating objects" stderr >actual &&
+ test_line_count = 2 actual &&
+ cleanup_clone $enlistment
+'
+
+test_expect_success 'progress without tty' '
+ enlistment=progress2 &&
+
+ test_config -C to-clone uploadpack.allowfilter true &&
+ test_config -C to-clone uploadpack.allowanysha1inwant true &&
+
+ GIT_PROGRESS_DELAY=0 scalar clone "file://$(pwd)/to-clone" "$enlistment" 2>stderr &&
+ ! grep "Enumerating objects" stderr &&
+ ! grep "Updating files" stderr &&
+ cleanup_clone $enlistment
+'
+
+test_expect_success 'scalar clone warns when background maintenance fails' '
+ GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \
+ scalar clone "file://$(pwd)/to-clone" maint-fail 2>err &&
+ grep "could not turn on maintenance" err
+'
+
+test_expect_success '`scalar clone --no-src`' '
+ scalar clone --src "file://$(pwd)/to-clone" with-src &&
+ scalar clone --no-src "file://$(pwd)/to-clone" without-src &&
+
+ test_path_is_dir with-src/src &&
+ test_path_is_missing without-src/src &&
+
+ (cd with-src/src && ls ?*) >with &&
+ (cd without-src && ls ?*) >without &&
+ test_cmp with without
+'
+
test_done
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index aa55b41b9a..ac237a1f90 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -388,9 +388,7 @@ test_expect_success 'B: accept branch name "TEMP_TAG"' '
INPUT_END
- test_when_finished "rm -f .git/TEMP_TAG
- git gc
- git prune" &&
+ test_when_finished "rm -f .git/TEMP_TAG && git gc --prune=now" &&
git fast-import <input &&
test $(test-tool ref-store main resolve-ref TEMP_TAG 0 | cut -f1 -d " " ) != "$ZERO_OID" &&
test $(git rev-parse main) = $(git rev-parse TEMP_TAG^)
@@ -406,8 +404,7 @@ test_expect_success 'B: accept empty committer' '
INPUT_END
test_when_finished "git update-ref -d refs/heads/empty-committer-1
- git gc
- git prune" &&
+ git gc --prune=now" &&
git fast-import <input &&
out=$(git fsck) &&
echo "$out" &&
@@ -452,8 +449,7 @@ test_expect_success 'B: accept and fixup committer with no name' '
INPUT_END
test_when_finished "git update-ref -d refs/heads/empty-committer-2
- git gc
- git prune" &&
+ git gc --prune=now" &&
git fast-import <input &&
out=$(git fsck) &&
echo "$out" &&
@@ -1778,8 +1774,7 @@ test_expect_success 'P: verbatim SHA gitlinks' '
INPUT_END
git branch -D sub &&
- git gc &&
- git prune &&
+ git gc --prune=now &&
git fast-import <input &&
test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)
'
diff --git a/t/t9304-fast-import-marks.sh b/t/t9304-fast-import-marks.sh
index a98ef032d9..410a871c52 100755
--- a/t/t9304-fast-import-marks.sh
+++ b/t/t9304-fast-import-marks.sh
@@ -49,4 +49,33 @@ test_expect_success 'import with submodule mapping' '
test_cmp expect actual
'
+test_expect_success 'paths adjusted for relative subdir' '
+ git init deep-dst &&
+ mkdir deep-dst/subdir &&
+ >deep-dst/subdir/empty-marks &&
+ git -C deep-dst/subdir fast-import \
+ --rewrite-submodules-from=sub:../../from \
+ --rewrite-submodules-to=sub:../../to \
+ --import-marks=empty-marks \
+ --export-marks=exported-marks \
+ --export-pack-edges=exported-edges \
+ <dump &&
+ # we do not bother checking resulting repo; we just care that nothing
+ # complained about failing to open files for reading, and that files
+ # for writing were created in the expected spot
+ test_path_is_file deep-dst/subdir/exported-marks &&
+ test_path_is_file deep-dst/subdir/exported-edges
+'
+
+test_expect_success 'relative marks are not affected by subdir' '
+ git init deep-relative &&
+ mkdir deep-relative/subdir &&
+ git -C deep-relative/subdir fast-import \
+ --relative-marks \
+ --export-marks=exported-marks \
+ <dump &&
+ test_path_is_missing deep-relative/subdir/exported-marks &&
+ test_path_is_file deep-relative/.git/info/fast-import/exported-marks
+'
+
test_done
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index ff21a12ee6..26c25c0eb2 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -373,7 +373,7 @@ EOF
test_expect_success 'cope with tagger-less tags' '
- TAG=$(git hash-object -t tag -w tag-content) &&
+ TAG=$(git hash-object --literally -t tag -w tag-content) &&
git update-ref refs/tags/sonnenschein $TAG &&
git fast-export -C -C --signed-tags=strip --all > output &&
test $(grep -c "^tag " output) = 4 &&
diff --git a/t/t9351-fast-export-anonymize.sh b/t/t9351-fast-export-anonymize.sh
index 77047e250d..156a647484 100755
--- a/t/t9351-fast-export-anonymize.sh
+++ b/t/t9351-fast-export-anonymize.sh
@@ -25,6 +25,7 @@ test_expect_success 'setup simple repo' '
test_expect_success 'export anonymized stream' '
git fast-export --anonymize --all \
--anonymize-map=retain-me \
+ --anonymize-map=xyzzy:should-not-appear \
--anonymize-map=xyzzy:custom-name \
--anonymize-map=other \
>stream
@@ -41,6 +42,7 @@ test_expect_success 'stream omits path names' '
test_expect_success 'stream contains user-specified names' '
grep retain-me stream &&
+ ! grep should-not-appear stream &&
grep custom-name stream
'
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index 379b19f2f8..003c0b61d0 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -66,10 +66,11 @@ test_expect_success 'setup' '
# note that cvs doesn't accept absolute pathnames
# as argument to co -d
-test_expect_success 'basic checkout' \
- 'GIT_CONFIG="$git_config" cvs -Q co -d cvswork main &&
- test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | head -n 1))" = "empty/1.1/" &&
- test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | sed -ne \$p))" = "secondrootfile/1.1/"'
+test_expect_success 'basic checkout' '
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork main &&
+ test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | head -n 1))" = "empty/1.1/" &&
+ test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | sed -ne \$p))" = "secondrootfile/1.1/"
+'
#------------------------
# PSERVER AUTHENTICATION
@@ -115,35 +116,40 @@ Ah<Z:yZZ30 e
END VERIFICATION REQUEST
EOF
-test_expect_success 'pserver authentication' \
- 'cat request-anonymous | git-cvsserver pserver >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU\$"'
+test_expect_success 'pserver authentication' '
+ cat request-anonymous | git-cvsserver pserver >log 2>&1 &&
+ sed -ne \$p log | grep "^I LOVE YOU\$"
+'
-test_expect_success 'pserver authentication failure (non-anonymous user)' \
- 'if cat request-git | git-cvsserver pserver >log 2>&1
- then
- false
- else
- true
- fi &&
- sed -ne \$p log | grep "^I HATE YOU\$"'
+test_expect_success 'pserver authentication failure (non-anonymous user)' '
+ if cat request-git | git-cvsserver pserver >log 2>&1
+ then
+ false
+ else
+ true
+ fi &&
+ sed -ne \$p log | grep "^I HATE YOU\$"
+'
-test_expect_success 'pserver authentication success (non-anonymous user with password)' \
- 'cat login-git-ok | git-cvsserver pserver >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU\$"'
+test_expect_success 'pserver authentication success (non-anonymous user with password)' '
+ cat login-git-ok | git-cvsserver pserver >log 2>&1 &&
+ sed -ne \$p log | grep "^I LOVE YOU\$"
+'
-test_expect_success 'pserver authentication (login)' \
- 'cat login-anonymous | git-cvsserver pserver >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU\$"'
+test_expect_success 'pserver authentication (login)' '
+ cat login-anonymous | git-cvsserver pserver >log 2>&1 &&
+ sed -ne \$p log | grep "^I LOVE YOU\$"
+'
-test_expect_success 'pserver authentication failure (login/non-anonymous user)' \
- 'if cat login-git | git-cvsserver pserver >log 2>&1
- then
- false
- else
- true
- fi &&
- sed -ne \$p log | grep "^I HATE YOU\$"'
+test_expect_success 'pserver authentication failure (login/non-anonymous user)' '
+ if cat login-git | git-cvsserver pserver >log 2>&1
+ then
+ false
+ else
+ true
+ fi &&
+ sed -ne \$p log | grep "^I HATE YOU\$"
+'
# misuse pserver authentication for testing of req_Root
@@ -165,36 +171,40 @@ END AUTH REQUEST
Root $WORKDIR
EOF
-test_expect_success 'req_Root failure (relative pathname)' \
- 'if cat request-relative | git-cvsserver pserver >log 2>&1
- then
- echo unexpected success
- false
- else
- true
- fi &&
- tail log | grep "^error 1 Root must be an absolute pathname$"'
+test_expect_success 'req_Root failure (relative pathname)' '
+ if cat request-relative | git-cvsserver pserver >log 2>&1
+ then
+ echo unexpected success
+ false
+ else
+ true
+ fi &&
+ tail log | grep "^error 1 Root must be an absolute pathname$"
+'
-test_expect_success 'req_Root failure (conflicting roots)' \
- 'cat request-conflict | git-cvsserver pserver >log 2>&1 &&
- tail log | grep "^error 1 Conflicting roots specified$"'
+test_expect_success 'req_Root failure (conflicting roots)' '
+ cat request-conflict | git-cvsserver pserver >log 2>&1 &&
+ tail log | grep "^error 1 Conflicting roots specified$"
+'
-test_expect_success 'req_Root (strict paths)' \
- 'cat request-anonymous | git-cvsserver --strict-paths pserver "$SERVERDIR" >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU\$"'
+test_expect_success 'req_Root (strict paths)' '
+ cat request-anonymous | git-cvsserver --strict-paths pserver "$SERVERDIR" >log 2>&1 &&
+ sed -ne \$p log | grep "^I LOVE YOU\$"
+'
test_expect_success 'req_Root failure (strict-paths)' '
- ! cat request-anonymous |
- git-cvsserver --strict-paths pserver "$WORKDIR" >log 2>&1
+ ! cat request-anonymous |
+ git-cvsserver --strict-paths pserver "$WORKDIR" >log 2>&1
'
-test_expect_success 'req_Root (w/o strict-paths)' \
- 'cat request-anonymous | git-cvsserver pserver "$WORKDIR/" >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU\$"'
+test_expect_success 'req_Root (w/o strict-paths)' '
+ cat request-anonymous | git-cvsserver pserver "$WORKDIR/" >log 2>&1 &&
+ sed -ne \$p log | grep "^I LOVE YOU\$"
+'
test_expect_success 'req_Root failure (w/o strict-paths)' '
- ! cat request-anonymous |
- git-cvsserver pserver "$WORKDIR/gitcvs" >log 2>&1
+ ! cat request-anonymous |
+ git-cvsserver pserver "$WORKDIR/gitcvs" >log 2>&1
'
cat >request-base <<EOF
@@ -206,27 +216,30 @@ END AUTH REQUEST
Root /gitcvs.git
EOF
-test_expect_success 'req_Root (base-path)' \
- 'cat request-base | git-cvsserver --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU\$"'
+test_expect_success 'req_Root (base-path)' '
+ cat request-base | git-cvsserver --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 &&
+ sed -ne \$p log | grep "^I LOVE YOU\$"
+'
test_expect_success 'req_Root failure (base-path)' '
- ! cat request-anonymous |
- git-cvsserver --strict-paths --base-path "$WORKDIR" pserver "$SERVERDIR" >log 2>&1
+ ! cat request-anonymous |
+ git-cvsserver --strict-paths --base-path "$WORKDIR" pserver "$SERVERDIR" >log 2>&1
'
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false || exit 1
-test_expect_success 'req_Root (export-all)' \
- 'cat request-anonymous | git-cvsserver --export-all pserver "$WORKDIR" >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU\$"'
+test_expect_success 'req_Root (export-all)' '
+ cat request-anonymous | git-cvsserver --export-all pserver "$WORKDIR" >log 2>&1 &&
+ sed -ne \$p log | grep "^I LOVE YOU\$"
+'
-test_expect_success 'req_Root failure (export-all w/o directory list)' \
- '! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)'
+test_expect_success 'req_Root failure (export-all w/o directory list)' '
+ ! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)'
-test_expect_success 'req_Root (everything together)' \
- 'cat request-base | git-cvsserver --export-all --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU\$"'
+test_expect_success 'req_Root (everything together)' '
+ cat request-base | git-cvsserver --export-all --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 &&
+ sed -ne \$p log | grep "^I LOVE YOU\$"
+'
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true || exit 1
@@ -247,45 +260,49 @@ test_expect_success 'gitcvs.enabled = false' \
test ! -d cvswork2'
rm -fr cvswork2
-test_expect_success 'gitcvs.ext.enabled = true' \
- 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true &&
- GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false &&
- GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 &&
- test_cmp cvswork cvswork2'
+test_expect_success 'gitcvs.ext.enabled = true' '
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true &&
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false &&
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 &&
+ test_cmp cvswork cvswork2
+'
rm -fr cvswork2
-test_expect_success 'gitcvs.ext.enabled = false' \
- 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled false &&
- GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
- if GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1
- then
- echo unexpected cvs success
- false
- else
- true
- fi &&
- grep "GITCVS emulation disabled" cvs.log &&
- test ! -d cvswork2'
+test_expect_success 'gitcvs.ext.enabled = false' '
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled false &&
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
+ if GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1
+ then
+ echo unexpected cvs success
+ false
+ else
+ true
+ fi &&
+ grep "GITCVS emulation disabled" cvs.log &&
+ test ! -d cvswork2
+'
rm -fr cvswork2
-test_expect_success 'gitcvs.dbname' \
- 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true &&
- GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs.%a.%m.sqlite &&
- GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 &&
- test_cmp cvswork cvswork2 &&
- test -f "$SERVERDIR/gitcvs.ext.main.sqlite" &&
- cmp "$SERVERDIR/gitcvs.main.sqlite" "$SERVERDIR/gitcvs.ext.main.sqlite"'
+test_expect_success 'gitcvs.dbname' '
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true &&
+ GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs.%a.%m.sqlite &&
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 &&
+ test_cmp cvswork cvswork2 &&
+ test -f "$SERVERDIR/gitcvs.ext.main.sqlite" &&
+ cmp "$SERVERDIR/gitcvs.main.sqlite" "$SERVERDIR/gitcvs.ext.main.sqlite"
+'
rm -fr cvswork2
-test_expect_success 'gitcvs.ext.dbname' \
- 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true &&
- GIT_DIR="$SERVERDIR" git config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite &&
- GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite &&
- GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 &&
- test_cmp cvswork cvswork2 &&
- test -f "$SERVERDIR/gitcvs1.ext.main.sqlite" &&
- test ! -f "$SERVERDIR/gitcvs2.ext.main.sqlite" &&
- cmp "$SERVERDIR/gitcvs.main.sqlite" "$SERVERDIR/gitcvs1.ext.main.sqlite"'
+test_expect_success 'gitcvs.ext.dbname' '
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true &&
+ GIT_DIR="$SERVERDIR" git config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite &&
+ GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite &&
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 &&
+ test_cmp cvswork cvswork2 &&
+ test -f "$SERVERDIR/gitcvs1.ext.main.sqlite" &&
+ test ! -f "$SERVERDIR/gitcvs2.ext.main.sqlite" &&
+ cmp "$SERVERDIR/gitcvs.main.sqlite" "$SERVERDIR/gitcvs1.ext.main.sqlite"
+'
#------------
@@ -299,109 +316,115 @@ GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" ||
exit 1
-test_expect_success 'cvs update (create new file)' \
- 'echo testfile1 >testfile1 &&
- git add testfile1 &&
- git commit -q -m "Add testfile1" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs -Q update &&
- test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.1/" &&
- test_cmp testfile1 ../testfile1'
+test_expect_success 'cvs update (create new file)' '
+ echo testfile1 >testfile1 &&
+ git add testfile1 &&
+ git commit -q -m "Add testfile1" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.1/" &&
+ test_cmp testfile1 ../testfile1
+'
cd "$WORKDIR"
-test_expect_success 'cvs update (update existing file)' \
- 'echo line 2 >>testfile1 &&
- git add testfile1 &&
- git commit -q -m "Append to testfile1" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs -Q update &&
- test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.2/" &&
- test_cmp testfile1 ../testfile1'
+test_expect_success 'cvs update (update existing file)' '
+ echo line 2 >>testfile1 &&
+ git add testfile1 &&
+ git commit -q -m "Append to testfile1" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.2/" &&
+ test_cmp testfile1 ../testfile1
+'
cd "$WORKDIR"
#TODO: cvsserver doesn't support update w/o -d
test_expect_failure "cvs update w/o -d doesn't create subdir (TODO)" '
- mkdir test &&
- echo >test/empty &&
- git add test &&
- git commit -q -m "Single Subdirectory" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs -Q update &&
- test ! -d test
+ mkdir test &&
+ echo >test/empty &&
+ git add test &&
+ git commit -q -m "Single Subdirectory" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ test ! -d test
'
cd "$WORKDIR"
-test_expect_success 'cvs update (subdirectories)' \
- '(for dir in A A/B A/B/C A/D E; do
- mkdir $dir &&
- echo "test file in $dir" >"$dir/file_in_$(echo $dir|sed -e "s#/# #g")" &&
- git add $dir || exit 1
- done) &&
- git commit -q -m "deep sub directory structure" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs -Q update -d &&
- (for dir in A A/B A/B/C A/D E; do
- filename="file_in_$(echo $dir|sed -e "s#/# #g")" &&
- if test "$(echo $(grep -v ^D $dir/CVS/Entries|cut -d/ -f2,3,5))" = "$filename/1.1/" &&
- test_cmp "$dir/$filename" "../$dir/$filename"; then
- :
- else
- exit 1
- fi
- done)'
+test_expect_success 'cvs update (subdirectories)' '
+ (for dir in A A/B A/B/C A/D E; do
+ mkdir $dir &&
+ echo "test file in $dir" >"$dir/file_in_$(echo $dir|sed -e "s#/# #g")" &&
+ git add $dir || exit 1
+ done) &&
+ git commit -q -m "deep sub directory structure" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q update -d &&
+ (for dir in A A/B A/B/C A/D E; do
+ filename="file_in_$(echo $dir|sed -e "s#/# #g")" &&
+ if test "$(echo $(grep -v ^D $dir/CVS/Entries|cut -d/ -f2,3,5))" = "$filename/1.1/" &&
+ test_cmp "$dir/$filename" "../$dir/$filename"; then
+ :
+ else
+ exit 1
+ fi
+ done)
+'
cd "$WORKDIR"
-test_expect_success 'cvs update (delete file)' \
- 'git rm testfile1 &&
- git commit -q -m "Remove testfile1" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs -Q update &&
- test -z "$(grep testfile1 CVS/Entries)" &&
- test ! -f testfile1'
+test_expect_success 'cvs update (delete file)' '
+ git rm testfile1 &&
+ git commit -q -m "Remove testfile1" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ test -z "$(grep testfile1 CVS/Entries)" &&
+ test ! -f testfile1
+'
cd "$WORKDIR"
-test_expect_success 'cvs update (re-add deleted file)' \
- 'echo readded testfile >testfile1 &&
- git add testfile1 &&
- git commit -q -m "Re-Add testfile1" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs -Q update &&
- test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.4/" &&
- test_cmp testfile1 ../testfile1'
+test_expect_success 'cvs update (re-add deleted file)' '
+ echo readded testfile >testfile1 &&
+ git add testfile1 &&
+ git commit -q -m "Re-Add testfile1" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.4/" &&
+ test_cmp testfile1 ../testfile1
+'
cd "$WORKDIR"
-test_expect_success 'cvs update (merge)' \
- 'echo Line 0 >expected &&
- for i in 1 2 3 4 5 6 7
- do
- echo Line $i >>merge &&
- echo Line $i >>expected || return 1
- done &&
- echo Line 8 >>expected &&
- git add merge &&
- git commit -q -m "Merge test (pre-merge)" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs -Q update &&
- test "$(echo $(grep merge CVS/Entries|cut -d/ -f2,3,5))" = "merge/1.1/" &&
- test_cmp merge ../merge &&
- ( echo Line 0 && cat merge ) >merge.tmp &&
- mv merge.tmp merge &&
- cd "$WORKDIR" &&
- echo Line 8 >>merge &&
- git add merge &&
- git commit -q -m "Merge test (merge)" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- sleep 1 && touch merge &&
- GIT_CONFIG="$git_config" cvs -Q update &&
- test_cmp merge ../expected'
+test_expect_success 'cvs update (merge)' '
+ echo Line 0 >expected &&
+ for i in 1 2 3 4 5 6 7
+ do
+ echo Line $i >>merge &&
+ echo Line $i >>expected || return 1
+ done &&
+ echo Line 8 >>expected &&
+ git add merge &&
+ git commit -q -m "Merge test (pre-merge)" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ test "$(echo $(grep merge CVS/Entries|cut -d/ -f2,3,5))" = "merge/1.1/" &&
+ test_cmp merge ../merge &&
+ ( echo Line 0 && cat merge ) >merge.tmp &&
+ mv merge.tmp merge &&
+ cd "$WORKDIR" &&
+ echo Line 8 >>merge &&
+ git add merge &&
+ git commit -q -m "Merge test (merge)" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ sleep 1 && touch merge &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ test_cmp merge ../expected
+'
cd "$WORKDIR"
@@ -418,55 +441,58 @@ do
echo Line $i >>expected.C
done
-test_expect_success 'cvs update (conflict merge)' \
- '( echo LINE 0 && cat merge ) >merge.tmp &&
- mv merge.tmp merge &&
- git add merge &&
- git commit -q -m "Merge test (conflict)" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs -Q update &&
- test_cmp merge ../expected.C'
+test_expect_success 'cvs update (conflict merge)' '
+ ( echo LINE 0 && cat merge ) >merge.tmp &&
+ mv merge.tmp merge &&
+ git add merge &&
+ git commit -q -m "Merge test (conflict)" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ test_cmp merge ../expected.C
+'
cd "$WORKDIR"
-test_expect_success 'cvs update (-C)' \
- 'cd cvswork &&
- GIT_CONFIG="$git_config" cvs -Q update -C &&
- test_cmp merge ../merge'
+test_expect_success 'cvs update (-C)' '
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q update -C &&
+ test_cmp merge ../merge
+'
cd "$WORKDIR"
-test_expect_success 'cvs update (merge no-op)' \
- 'echo Line 9 >>merge &&
- cp merge cvswork/merge &&
- git add merge &&
- git commit -q -m "Merge test (no-op)" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- sleep 1 && touch merge &&
- GIT_CONFIG="$git_config" cvs -Q update &&
- test_cmp merge ../merge'
+test_expect_success 'cvs update (merge no-op)' '
+ echo Line 9 >>merge &&
+ cp merge cvswork/merge &&
+ git add merge &&
+ git commit -q -m "Merge test (no-op)" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ sleep 1 && touch merge &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ test_cmp merge ../merge
+'
cd "$WORKDIR"
test_expect_success 'cvs update (-p)' '
- touch really-empty &&
- echo Line 1 > no-lf &&
- printf "Line 2" >> no-lf &&
- git add really-empty no-lf &&
- git commit -q -m "Update -p test" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs update &&
- for i in merge no-lf empty really-empty; do
- GIT_CONFIG="$git_config" cvs update -p "$i" >$i.out &&
- test_cmp $i.out ../$i || return 1
- done
+ touch really-empty &&
+ echo Line 1 > no-lf &&
+ printf "Line 2" >> no-lf &&
+ git add really-empty no-lf &&
+ git commit -q -m "Update -p test" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs update &&
+ for i in merge no-lf empty really-empty; do
+ GIT_CONFIG="$git_config" cvs update -p "$i" >$i.out &&
+ test_cmp $i.out ../$i || return 1
+ done
'
cd "$WORKDIR"
test_expect_success 'cvs update (module list supports packed refs)' '
- GIT_DIR="$SERVERDIR" git pack-refs --all &&
- GIT_CONFIG="$git_config" cvs -n up -d 2> out &&
- grep "cvs update: New directory \`main'\''" < out
+ GIT_DIR="$SERVERDIR" git pack-refs --all &&
+ GIT_CONFIG="$git_config" cvs -n up -d 2> out &&
+ grep "cvs update: New directory \`main'\''" < out
'
#------------
@@ -475,30 +501,30 @@ test_expect_success 'cvs update (module list supports packed refs)' '
cd "$WORKDIR"
test_expect_success 'cvs status' '
- mkdir status.dir &&
- echo Line > status.dir/status.file &&
- echo Line > status.file &&
- git add status.dir status.file &&
- git commit -q -m "Status test" &&
- git push gitcvs.git >/dev/null &&
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs update &&
- GIT_CONFIG="$git_config" cvs status | grep "^File: status.file" >../out &&
- test_line_count = 2 ../out
+ mkdir status.dir &&
+ echo Line > status.dir/status.file &&
+ echo Line > status.file &&
+ git add status.dir status.file &&
+ git commit -q -m "Status test" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs update &&
+ GIT_CONFIG="$git_config" cvs status | grep "^File: status.file" >../out &&
+ test_line_count = 2 ../out
'
cd "$WORKDIR"
test_expect_success 'cvs status (nonrecursive)' '
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs status -l | grep "^File: status.file" >../out &&
- test_line_count = 1 ../out
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs status -l | grep "^File: status.file" >../out &&
+ test_line_count = 1 ../out
'
cd "$WORKDIR"
test_expect_success 'cvs status (no subdirs in header)' '
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs status | grep ^File: >../out &&
- ! grep / <../out
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs status | grep ^File: >../out &&
+ ! grep / <../out
'
#------------
@@ -507,9 +533,9 @@ test_expect_success 'cvs status (no subdirs in header)' '
cd "$WORKDIR"
test_expect_success 'cvs co -c (shows module database)' '
- GIT_CONFIG="$git_config" cvs co -c > out &&
- grep "^main[ ][ ]*main$" <out &&
- ! grep -v "^main[ ][ ]*main$" <out
+ GIT_CONFIG="$git_config" cvs co -c > out &&
+ grep "^main[ ][ ]*main$" <out &&
+ ! grep -v "^main[ ][ ]*main$" <out
'
#------------
@@ -575,11 +601,11 @@ expectStat="$?"
cd "$WORKDIR"
test_expect_success 'cvs log' '
- cd cvswork &&
- test x"$expectStat" = x"0" &&
- GIT_CONFIG="$git_config" cvs log merge >../out &&
- sed -e "s%2[0-9][0-9][0-9]/[01][0-9]/[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]%__DATE__%" ../out > ../actual &&
- test_cmp ../expect ../actual
+ cd cvswork &&
+ test x"$expectStat" = x"0" &&
+ GIT_CONFIG="$git_config" cvs log merge >../out &&
+sed -e "s%2[0-9][0-9][0-9]/[01][0-9]/[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]%__DATE__%" ../out > ../actual &&
+ test_cmp ../expect ../actual
'
#------------
@@ -588,11 +614,11 @@ test_expect_success 'cvs log' '
cd "$WORKDIR"
test_expect_success 'cvs annotate' '
- cd cvswork &&
- GIT_CONFIG="$git_config" cvs annotate merge >../out &&
- sed -e "s/ .*//" ../out >../actual &&
- printf "1.%d\n" 3 1 1 1 1 1 1 1 2 4 >../expect &&
- test_cmp ../expect ../actual
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs annotate merge >../out &&
+ sed -e "s/ .*//" ../out >../actual &&
+ printf "1.%d\n" 3 1 1 1 1 1 1 1 2 4 >../expect &&
+ test_cmp ../expect ../actual
'
#------------
diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh
index 4aa5d90d32..ccc8212d73 100755
--- a/t/t9700-perl-git.sh
+++ b/t/t9700-perl-git.sh
@@ -13,37 +13,40 @@ skip_all_if_no_Test_More
# set up test repository
-test_expect_success \
- 'set up test repository' \
- 'echo "test file 1" > file1 &&
- echo "test file 2" > file2 &&
- mkdir directory1 &&
- echo "in directory1" >> directory1/file &&
- mkdir directory2 &&
- echo "in directory2" >> directory2/file &&
- git add . &&
- git commit -m "first commit" &&
-
- echo "new file in subdir 2" > directory2/file2 &&
- git add . &&
- git commit -m "commit in directory2" &&
-
- echo "changed file 1" > file1 &&
- git commit -a -m "second commit" &&
-
- git config --add color.test.slot1 green &&
- git config --add test.string value &&
- git config --add test.dupstring value1 &&
- git config --add test.dupstring value2 &&
- git config --add test.booltrue true &&
- git config --add test.boolfalse no &&
- git config --add test.boolother other &&
- git config --add test.int 2k &&
- git config --add test.path "~/foo" &&
- git config --add test.pathexpanded "$HOME/foo" &&
- git config --add test.pathmulti foo &&
- git config --add test.pathmulti bar
- '
+test_expect_success 'set up test repository' '
+ echo "test file 1" >file1 &&
+ echo "test file 2" >file2 &&
+ mkdir directory1 &&
+ echo "in directory1" >>directory1/file &&
+ mkdir directory2 &&
+ echo "in directory2" >>directory2/file &&
+ git add . &&
+ git commit -m "first commit" &&
+
+ echo "new file in subdir 2" >directory2/file2 &&
+ git add . &&
+ git commit -m "commit in directory2" &&
+
+ echo "changed file 1" >file1 &&
+ git commit -a -m "second commit" &&
+
+ git config --add color.test.slot1 green &&
+ git config --add test.string value &&
+ git config --add test.dupstring value1 &&
+ git config --add test.dupstring value2 &&
+ git config --add test.booltrue true &&
+ git config --add test.boolfalse no &&
+ git config --add test.boolother other &&
+ git config --add test.int 2k &&
+ git config --add test.path "~/foo" &&
+ git config --add test.pathexpanded "$HOME/foo" &&
+ git config --add test.pathmulti foo &&
+ git config --add test.pathmulti bar
+'
+
+test_expect_success 'set up bare repository' '
+ git init --bare bare.git
+'
test_expect_success 'use t9700/test.pl to test Git.pm' '
"$PERL_PATH" "$TEST_DIRECTORY"/t9700/test.pl 2>stderr &&
diff --git a/t/t9700/test.pl b/t/t9700/test.pl
index e046f7db76..6d753708d2 100755
--- a/t/t9700/test.pl
+++ b/t/t9700/test.pl
@@ -30,6 +30,18 @@ BEGIN { use_ok('Git') }
# set up
our $abs_repo_dir = cwd();
ok(our $r = Git->repository(Directory => "."), "open repository");
+{
+ local $ENV{GIT_TEST_ASSUME_DIFFERENT_OWNER} = 1;
+ my $failed;
+
+ $failed = eval { Git->repository(Directory => $abs_repo_dir) };
+ ok(!$failed, "reject unsafe non-bare repository");
+ like($@, qr/not a git repository/i, "unsafe error message");
+
+ $failed = eval { Git->repository(Directory => "$abs_repo_dir/bare.git") };
+ ok(!$failed, "reject unsafe bare repository");
+ like($@, qr/not a git repository/i, "unsafe error message");
+}
# config
is($r->config("test.string"), "value", "config scalar: string");
diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh
index dc88d0e064..a4b3cb9492 100755
--- a/t/t9800-git-p4-basic.sh
+++ b/t/t9800-git-p4-basic.sh
@@ -330,7 +330,7 @@ test_expect_success 'initial import time from top change time' '
test_when_finished cleanup_git &&
(
cd "$git" &&
- gittime=$(git show -s --raw --pretty=format:%at HEAD) &&
+ gittime=$(git show -s --pretty=format:%at HEAD) &&
echo $p4time $gittime &&
test $p4time = $gittime
)
diff --git a/t/t9814-git-p4-rename.sh b/t/t9814-git-p4-rename.sh
index 468767cbf4..2a9838f37f 100755
--- a/t/t9814-git-p4-rename.sh
+++ b/t/t9814-git-p4-rename.sh
@@ -216,7 +216,7 @@ test_expect_success 'detect copies' '
# variable exists, which allows admins to disable the "p4 move" command.
test_lazy_prereq P4D_HAVE_CONFIGURABLE_RUN_MOVE_ALLOW '
p4 configure show run.move.allow >out &&
- egrep ^run.move.allow: out
+ grep -E ^run.move.allow: out
'
# If move can be disabled, turn it off and test p4 move handling
diff --git a/t/t9815-git-p4-submit-fail.sh b/t/t9815-git-p4-submit-fail.sh
index 9779dc0d11..0ca9937de6 100755
--- a/t/t9815-git-p4-submit-fail.sh
+++ b/t/t9815-git-p4-submit-fail.sh
@@ -417,8 +417,8 @@ test_expect_success 'cleanup chmod after submit cancel' '
! p4 fstat -T action text &&
test_path_is_file text+x &&
! p4 fstat -T action text+x &&
- ls -l text | egrep ^-r-- &&
- ls -l text+x | egrep ^-r-x
+ ls -l text | grep -E ^-r-- &&
+ ls -l text+x | grep -E ^-r-x
)
'
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 43de868b80..47e20fb8b1 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -405,40 +405,40 @@ test_expect_success '__gitdir - remote as argument' '
test_expect_success '__git_dequote - plain unquoted word' '
__git_dequote unquoted-word &&
- verbose test unquoted-word = "$dequoted_word"
+ test unquoted-word = "$dequoted_word"
'
# input: b\a\c\k\'\\\"s\l\a\s\h\es
# expected: back'\"slashes
test_expect_success '__git_dequote - backslash escaped' '
__git_dequote "b\a\c\k\\'\''\\\\\\\"s\l\a\s\h\es" &&
- verbose test "back'\''\\\"slashes" = "$dequoted_word"
+ test "back'\''\\\"slashes" = "$dequoted_word"
'
# input: sin'gle\' '"quo'ted
# expected: single\ "quoted
test_expect_success '__git_dequote - single quoted' '
__git_dequote "'"sin'gle\\\\' '\\\"quo'ted"'" &&
- verbose test '\''single\ "quoted'\'' = "$dequoted_word"
+ test '\''single\ "quoted'\'' = "$dequoted_word"
'
# input: dou"ble\\" "\"\quot"ed
# expected: double\ "\quoted
test_expect_success '__git_dequote - double quoted' '
__git_dequote '\''dou"ble\\" "\"\quot"ed'\'' &&
- verbose test '\''double\ "\quoted'\'' = "$dequoted_word"
+ test '\''double\ "\quoted'\'' = "$dequoted_word"
'
# input: 'open single quote
test_expect_success '__git_dequote - open single quote' '
__git_dequote "'\''open single quote" &&
- verbose test "open single quote" = "$dequoted_word"
+ test "open single quote" = "$dequoted_word"
'
# input: "open double quote
test_expect_success '__git_dequote - open double quote' '
__git_dequote "\"open double quote" &&
- verbose test "open double quote" = "$dequoted_word"
+ test "open double quote" = "$dequoted_word"
'
@@ -616,7 +616,7 @@ test_expect_success '__git_is_configured_remote' '
test_when_finished "git remote remove remote_2" &&
git remote add remote_2 git://remote_2 &&
(
- verbose __git_is_configured_remote remote_2 &&
+ __git_is_configured_remote remote_2 &&
test_must_fail __git_is_configured_remote non-existent
)
'
@@ -1622,14 +1622,22 @@ test_expect_success 'git checkout - with -d, complete only references' '
'
test_expect_success 'git switch - with --track, complete only remote branches' '
- test_completion "git switch --track " <<-\EOF
+ test_completion "git switch --track " <<-\EOF &&
+ other/branch-in-other Z
+ other/main-in-other Z
+ EOF
+ test_completion "git switch -t " <<-\EOF
other/branch-in-other Z
other/main-in-other Z
EOF
'
test_expect_success 'git checkout - with --track, complete only remote branches' '
- test_completion "git checkout --track " <<-\EOF
+ test_completion "git checkout --track " <<-\EOF &&
+ other/branch-in-other Z
+ other/main-in-other Z
+ EOF
+ test_completion "git checkout -t " <<-\EOF
other/branch-in-other Z
other/main-in-other Z
EOF
@@ -2255,6 +2263,36 @@ test_expect_success 'checkout completes ref names' '
EOF
'
+test_expect_success 'checkout does not match ref names of a different case' '
+ test_completion "git checkout M" ""
+'
+
+test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGNORE_CASE' '
+ (
+ GIT_COMPLETION_IGNORE_CASE=1 &&
+ test_completion "git checkout M" <<-\EOF
+ main Z
+ mybranch Z
+ mytag Z
+ EOF
+ )
+'
+
+test_expect_success 'checkout completes pseudo refs' '
+ test_completion "git checkout H" <<-\EOF
+ HEAD Z
+ EOF
+'
+
+test_expect_success 'checkout completes pseudo refs case insensitively with GIT_COMPLETION_IGNORE_CASE' '
+ (
+ GIT_COMPLETION_IGNORE_CASE=1 &&
+ test_completion "git checkout h" <<-\EOF
+ HEAD Z
+ EOF
+ )
+'
+
test_expect_success 'git -C <path> checkout uses the right repo' '
test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
branch-in-other Z
@@ -2566,30 +2604,30 @@ test_expect_success 'options with value' '
test_expect_success 'sourcing the completion script clears cached commands' '
(
__git_compute_all_commands &&
- verbose test -n "$__git_all_commands" &&
+ test -n "$__git_all_commands" &&
. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
- verbose test -z "$__git_all_commands"
+ test -z "$__git_all_commands"
)
'
test_expect_success 'sourcing the completion script clears cached merge strategies' '
(
__git_compute_merge_strategies &&
- verbose test -n "$__git_merge_strategies" &&
+ test -n "$__git_merge_strategies" &&
. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
- verbose test -z "$__git_merge_strategies"
+ test -z "$__git_merge_strategies"
)
'
test_expect_success 'sourcing the completion script clears cached --options' '
(
__gitcomp_builtin checkout &&
- verbose test -n "$__gitcomp_builtin_checkout" &&
+ test -n "$__gitcomp_builtin_checkout" &&
__gitcomp_builtin notes_edit &&
- verbose test -n "$__gitcomp_builtin_notes_edit" &&
+ test -n "$__gitcomp_builtin_notes_edit" &&
. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
- verbose test -z "$__gitcomp_builtin_checkout" &&
- verbose test -z "$__gitcomp_builtin_notes_edit"
+ test -z "$__gitcomp_builtin_checkout" &&
+ test -z "$__gitcomp_builtin_notes_edit"
)
'
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index d459fae655..d667dda654 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -13,10 +13,10 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. "$GIT_BUILD_DIR/contrib/completion/git-prompt.sh"
actual="$TRASH_DIRECTORY/actual"
-c_red='\\[\\e[31m\\]'
-c_green='\\[\\e[32m\\]'
-c_lblue='\\[\\e[1;34m\\]'
-c_clear='\\[\\e[0m\\]'
+c_red='\001\e[31m\002'
+c_green='\001\e[32m\002'
+c_lblue='\001\e[1;34m\002'
+c_clear='\001\e[0m\002'
test_expect_success 'setup for prompt tests' '
git init otherrepo &&
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index c6479f24eb..2f8868caa1 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -32,6 +32,14 @@ test_set_editor () {
export EDITOR
}
+# Like test_set_editor but sets GIT_SEQUENCE_EDITOR instead of EDITOR
+test_set_sequence_editor () {
+ FAKE_SEQUENCE_EDITOR="$1"
+ export FAKE_SEQUENCE_EDITOR
+ GIT_SEQUENCE_EDITOR='"$FAKE_SEQUENCE_EDITOR"'
+ export GIT_SEQUENCE_EDITOR
+}
+
test_decode_color () {
awk '
function name(n) {
@@ -273,13 +281,13 @@ debug () {
# <file>, <contents>, and <tag> all default to <message>.
test_commit () {
- notick= &&
- echo=echo &&
- append= &&
- author= &&
- signoff= &&
- indir= &&
- tag=light &&
+ local notick= &&
+ local echo=echo &&
+ local append= &&
+ local author= &&
+ local signoff= &&
+ local indir= &&
+ local tag=light &&
while test $# != 0
do
case "$1" in
@@ -322,7 +330,7 @@ test_commit () {
shift
done &&
indir=${indir:+"$indir"/} &&
- file=${2:-"$1.t"} &&
+ local file=${2:-"$1.t"} &&
if test -n "$append"
then
$echo "${3-$1}" >>"$indir$file"
@@ -534,8 +542,17 @@ test_config () {
config_dir=$1
shift
fi
- test_when_finished "test_unconfig ${config_dir:+-C '$config_dir'} '$1'" &&
- git ${config_dir:+-C "$config_dir"} config "$@"
+
+ # If --worktree is provided, use it to configure/unconfigure
+ is_worktree=
+ if test "$1" = --worktree
+ then
+ is_worktree=1
+ shift
+ fi
+
+ test_when_finished "test_unconfig ${config_dir:+-C '$config_dir'} ${is_worktree:+--worktree} '$1'" &&
+ git ${config_dir:+-C "$config_dir"} config ${is_worktree:+--worktree} "$@"
}
test_config_global () {
@@ -893,11 +910,20 @@ test_path_is_symlink () {
fi
}
+test_path_is_executable () {
+ test "$#" -ne 1 && BUG "1 param"
+ if ! test -x "$1"
+ then
+ echo "$1 is not executable"
+ false
+ fi
+}
+
# Check if the directory exists and is empty as expected, barf otherwise.
test_dir_is_empty () {
test "$#" -ne 1 && BUG "1 param"
test_path_is_dir "$1" &&
- if test -n "$(ls -a1 "$1" | egrep -v '^\.\.?$')"
+ if test -n "$(ls -a1 "$1" | grep -E -v '^\.\.?$')"
then
echo "Directory '$1' is not empty, it contains:"
ls -la "$1"
@@ -921,10 +947,6 @@ test_path_is_missing () {
then
echo "Path exists:"
ls -ld "$1"
- if test $# -ge 1
- then
- echo "$*"
- fi
false
fi
}
@@ -1020,7 +1042,7 @@ test_must_fail_acceptable () {
fi
case "$1" in
- git|__git*|test-tool|test_terminal)
+ git|__git*|scalar|test-tool|test_terminal)
return 0
;;
*)
@@ -1223,15 +1245,6 @@ test_i18ngrep () {
return 1
}
-# Call any command "$@" but be more verbose about its
-# failure. This is handy for commands like "test" which do
-# not output anything when they fail.
-verbose () {
- "$@" && return 0
- echo >&4 "command failed: $(git rev-parse --sq-quote "$@")"
- return 1
-}
-
# Check if the file expected to be empty is indeed empty, and barfs
# otherwise.
@@ -1278,6 +1291,39 @@ test_cmp_rev () {
fi
}
+# Tests that a commit message matches the expected text
+#
+# Usage: test_commit_message <rev> [-m <msg> | <file>]
+#
+# When using "-m" <msg> will have a line feed appended. If the second
+# argument is omitted then the expected message is read from stdin.
+
+test_commit_message () {
+ local msg_file=expect.msg
+
+ case $# in
+ 3)
+ if test "$2" = "-m"
+ then
+ printf "%s\n" "$3" >"$msg_file"
+ else
+ BUG "Usage: test_commit_message <rev> [-m <message> | <file>]"
+ fi
+ ;;
+ 2)
+ msg_file="$2"
+ ;;
+ 1)
+ cat >"$msg_file"
+ ;;
+ *)
+ BUG "Usage: test_commit_message <rev> [-m <message> | <file>]"
+ ;;
+ esac
+ git show --no-patch --pretty=format:%B "$1" -- >actual.msg &&
+ test_cmp "$msg_file" actual.msg
+}
+
# Compare paths respecting core.ignoreCase
test_cmp_fspath () {
if test "x$1" = "x$2"
@@ -1426,7 +1472,7 @@ test_bool_env () {
BUG "test_bool_env requires two parameters (variable name and default value)"
fi
- git env--helper --type=bool --default="$2" --exit-code "$1"
+ test-tool env-helper --type=bool --default="$2" --exit-code "$1"
ret=$?
case $ret in
0|1) # unset or valid bool value
@@ -1454,72 +1500,6 @@ test_skip_or_die () {
error "$2"
}
-# The following mingw_* functions obey POSIX shell syntax, but are actually
-# bash scripts, and are meant to be used only with bash on Windows.
-
-# A test_cmp function that treats LF and CRLF equal and avoids to fork
-# diff when possible.
-mingw_test_cmp () {
- # Read text into shell variables and compare them. If the results
- # are different, use regular diff to report the difference.
- local test_cmp_a= test_cmp_b=
-
- # When text came from stdin (one argument is '-') we must feed it
- # to diff.
- local stdin_for_diff=
-
- # Since it is difficult to detect the difference between an
- # empty input file and a failure to read the files, we go straight
- # to diff if one of the inputs is empty.
- if test -s "$1" && test -s "$2"
- then
- # regular case: both files non-empty
- mingw_read_file_strip_cr_ test_cmp_a <"$1"
- mingw_read_file_strip_cr_ test_cmp_b <"$2"
- elif test -s "$1" && test "$2" = -
- then
- # read 2nd file from stdin
- mingw_read_file_strip_cr_ test_cmp_a <"$1"
- mingw_read_file_strip_cr_ test_cmp_b
- stdin_for_diff='<<<"$test_cmp_b"'
- elif test "$1" = - && test -s "$2"
- then
- # read 1st file from stdin
- mingw_read_file_strip_cr_ test_cmp_a
- mingw_read_file_strip_cr_ test_cmp_b <"$2"
- stdin_for_diff='<<<"$test_cmp_a"'
- fi
- test -n "$test_cmp_a" &&
- test -n "$test_cmp_b" &&
- test "$test_cmp_a" = "$test_cmp_b" ||
- eval "diff -u \"\$@\" $stdin_for_diff"
-}
-
-# $1 is the name of the shell variable to fill in
-mingw_read_file_strip_cr_ () {
- # Read line-wise using LF as the line separator
- # and use IFS to strip CR.
- local line
- while :
- do
- if IFS=$'\r' read -r -d $'\n' line
- then
- # good
- line=$line$'\n'
- else
- # we get here at EOF, but also if the last line
- # was not terminated by LF; in the latter case,
- # some text was read
- if test -z "$line"
- then
- # EOF, really
- break
- fi
- fi
- eval "$1=\$$1\$line"
- done
-}
-
# Like "env FOO=BAR some-program", but run inside a subshell, which means
# it also works for shell functions (though those functions cannot impact
# the environment outside of the test_env invocation).
@@ -1686,7 +1666,7 @@ test_oid () {
then
BUG "undefined key '$1'"
fi &&
- eval "printf '%s' \"\${$var}\""
+ eval "printf '%s\n' \"\${$var}\""
}
# Insert a slash into an object ID so it can be used to reference a location
@@ -1755,6 +1735,13 @@ test_path_is_hidden () {
return 1
}
+# Poor man's URI escaping. Good enough for the test suite whose trash
+# directory has a space in it. See 93c3fcbe4d4 (git-svn: attempt to
+# mimic SVN 1.7 URL canonicalization, 2012-07-28) for prior art.
+test_uri_escape() {
+ sed 's/ /%20/g'
+}
+
# Check that the given command was invoked as part of the
# trace2-format trace on stdin.
#
@@ -1830,6 +1817,14 @@ test_region () {
return 0
}
+# Given a GIT_TRACE2_EVENT log over stdin, writes to stdout a list of URLs
+# sent to git-remote-https child processes.
+test_remote_https_urls() {
+ grep -e '"event":"child_start".*"argv":\["git-remote-https",".*"\]' |
+ sed -e 's/{"event":"child_start".*"argv":\["git-remote-https","//g' \
+ -e 's/"\]}//g'
+}
+
# Print the destination of symlink(s) provided as arguments. Basically
# the same as the readlink command, but it's not available everywhere.
test_readlink () {
@@ -1868,3 +1863,22 @@ test_is_magic_mtime () {
rm -f .git/test-mtime-actual
return $ret
}
+
+# Given two filenames, parse both using 'git config --list --file'
+# and compare the sorted output of those commands. Useful when
+# wanting to ignore whitespace differences and sorting concerns.
+test_cmp_config_output () {
+ git config --list --file="$1" >config-expect &&
+ git config --list --file="$2" >config-actual &&
+ sort config-expect >sorted-expect &&
+ sort config-actual >sorted-actual &&
+ test_cmp sorted-expect sorted-actual
+}
+
+# Given a filename, extract its trailing hash as a hex string
+test_trailing_hash () {
+ local file="$1" &&
+ tail -c $(test_oid rawsz) "$file" |
+ test-tool hexdump |
+ sed "s/ //g"
+}
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 6ca68311eb..5ea5d1d62a 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -47,6 +47,16 @@ then
echo "PANIC: Running in a $TEST_DIRECTORY that doesn't end in '/t'?" >&2
exit 1
fi
+if test -f "$GIT_BUILD_DIR/GIT-BUILD-DIR"
+then
+ GIT_BUILD_DIR="$(cat "$GIT_BUILD_DIR/GIT-BUILD-DIR")" || exit 1
+ # On Windows, we must convert Windows paths lest they contain a colon
+ case "$(uname -s)" in
+ *MINGW*)
+ GIT_BUILD_DIR="$(cygpath -au "$GIT_BUILD_DIR")"
+ ;;
+ esac
+fi
# Prepend a string to a VAR using an arbitrary ":" delimiter, not
# adding the delimiter if VAR or VALUE is empty. I.e. a generalized:
@@ -324,6 +334,7 @@ nr_san_dir_leaks_ () {
find "$TEST_RESULTS_SAN_DIR" \
-type f \
-name "$TEST_RESULTS_SAN_FILE_PFX.*" 2>/dev/null |
+ xargs grep -lv "Unable to get registers from thread" |
wc -l
}
@@ -635,12 +646,6 @@ u200c=$(printf '\342\200\214')
export _x05 _x35 LF u200c EMPTY_TREE EMPTY_BLOB ZERO_OID OID_REGEX
-# Each test should start with something like this, after copyright notices:
-#
-# test_description='Description of this test...
-# This test checks if command xyzzy does the right thing...
-# '
-# . ./test-lib.sh
test "x$TERM" != "xdumb" && (
test -t 1 &&
tput bold >/dev/null 2>&1 &&
@@ -1037,10 +1042,7 @@ want_trace () {
# (and we want to make sure we run any cleanup like
# "set +x").
test_eval_inner_ () {
- # Do not add anything extra (including LF) after '$*'
- eval "
- want_trace && trace_level_=$(($trace_level_+1)) && set -x
- $*"
+ eval "$*"
}
test_eval_ () {
@@ -1065,7 +1067,10 @@ test_eval_ () {
# be _inside_ the block to avoid polluting the "set -x" output
#
- test_eval_inner_ "$@" </dev/null >&3 2>&4
+ # Do not add anything extra (including LF) after '$*'
+ test_eval_inner_ </dev/null >&3 2>&4 "
+ want_trace && trace_level_=$(($trace_level_+1)) && set -x
+ $*"
{
test_eval_ret_=$?
if want_trace
@@ -1082,22 +1087,22 @@ test_eval_ () {
return $test_eval_ret_
}
+fail_117 () {
+ return 117
+}
+
test_run_ () {
test_cleanup=:
expecting_failure=$2
if test "${GIT_TEST_CHAIN_LINT:-1}" != 0; then
- # turn off tracing for this test-eval, as it simply creates
- # confusing noise in the "-x" output
- trace_tmp=$trace
- trace=
# 117 is magic because it is unlikely to match the exit
# code of other programs
- if test "OK-117" != "$(test_eval_ "(exit 117) && $1${LF}${LF}echo OK-\$?" 3>&1)"
+ test_eval_inner_ "fail_117 && $1" </dev/null >&3 2>&4
+ if test $? != 117
then
- BUG "broken &&-chain or run-away HERE-DOC: $1"
+ BUG "broken &&-chain: $1"
fi
- trace=$trace_tmp
fi
setup_malloc_check
@@ -1532,8 +1537,8 @@ then
# Normalize with test_bool_env
passes_sanitize_leak=
- # We need to see TEST_PASSES_SANITIZE_LEAK in "git
- # env--helper" (via test_bool_env)
+ # We need to see TEST_PASSES_SANITIZE_LEAK in "test-tool
+ # env-helper" (via test_bool_env)
export TEST_PASSES_SANITIZE_LEAK
if test_bool_env TEST_PASSES_SANITIZE_LEAK false
then
@@ -1589,7 +1594,8 @@ then
BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_SANITIZE_LEAK_LOG=true"
fi
-if test "${GIT_TEST_CHAIN_LINT:-1}" != 0
+if test "${GIT_TEST_CHAIN_LINT:-1}" != 0 &&
+ test "${GIT_TEST_EXT_CHAIN_LINT:-1}" != 0
then
"$PERL_PATH" "$TEST_DIRECTORY/chainlint.pl" "$0" ||
BUG "lint error (see '?!...!? annotations above)"
@@ -1672,7 +1678,7 @@ yes () {
# The GIT_TEST_FAIL_PREREQS code hooks into test_set_prereq(), and
# thus needs to be set up really early, and set an internal variable
# for convenience so the hot test_set_prereq() codepath doesn't need
-# to call "git env--helper" (via test_bool_env). Only do that work
+# to call "test-tool env-helper" (via test_bool_env). Only do that work
# if needed by seeing if GIT_TEST_FAIL_PREREQS is set at all.
GIT_TEST_FAIL_PREREQS_INTERNAL=
if test -n "$GIT_TEST_FAIL_PREREQS"
@@ -1711,7 +1717,7 @@ case $uname_s in
test_set_prereq SED_STRIPS_CR
test_set_prereq GREP_STRIPS_CR
test_set_prereq WINDOWS
- GIT_TEST_CMP=mingw_test_cmp
+ GIT_TEST_CMP="GIT_DIR=/dev/null git diff --no-index --ignore-cr-at-eol --"
;;
*CYGWIN*)
test_set_prereq POSIXPERM
@@ -1927,10 +1933,6 @@ test_lazy_prereq SHA1 '
esac
'
-test_lazy_prereq ADD_I_USE_BUILTIN '
- test_bool_env GIT_TEST_ADD_I_USE_BUILTIN true
-'
-
# Ensure that no test accidentally triggers a Git command
# that runs the actual maintenance scheduler, affecting a user's
# system permanently.