summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/Makefile15
-rw-r--r--t/README4
-rw-r--r--t/for-each-ref-tests.sh2141
-rw-r--r--t/helper/test-advise.c3
-rw-r--r--t/helper/test-bitmap.c8
-rw-r--r--t/helper/test-bloom.c8
-rw-r--r--t/helper/test-config.c20
-rw-r--r--t/helper/test-delta.c77
-rw-r--r--t/helper/test-find-pack.c2
-rw-r--r--t/helper/test-hashmap.c9
-rw-r--r--t/helper/test-json-writer.c4
-rw-r--r--t/helper/test-pack-mtimes.c2
-rw-r--r--t/helper/test-parse-options.c17
-rw-r--r--t/helper/test-partial-clone.c4
-rw-r--r--t/helper/test-path-utils.c3
-rw-r--r--t/helper/test-path-walk.c2
-rw-r--r--t/helper/test-read-cache.c3
-rw-r--r--t/helper/test-read-graph.c8
-rw-r--r--t/helper/test-read-midx.c33
-rw-r--r--t/helper/test-ref-store.c9
-rw-r--r--t/helper/test-string-list.c96
-rw-r--r--t/helper/test-truncate.c3
-rw-r--r--t/helper/test-userdiff.c2
-rw-r--r--t/meson.build60
-rwxr-xr-xt/perf/p1501-rev-parse-oneline.sh71
-rwxr-xr-xt/perf/p5313-pack-objects.sh37
-rwxr-xr-xt/perf/p8020-last-modified.sh22
-rw-r--r--t/show-ref-exists-tests.sh77
-rwxr-xr-xt/t0000-basic.sh39
-rwxr-xr-xt/t0001-init.sh45
-rwxr-xr-xt/t0021-conversion.sh4
-rwxr-xr-xt/t0050-filesystem.sh30
-rwxr-xr-xt/t0063-string-list.sh142
-rwxr-xr-xt/t0411-clone-from-partial.sh6
-rwxr-xr-xt/t0450-txt-doc-vs-help.sh15
-rw-r--r--t/t0450/adoc-help-mismatches2
-rw-r--r--t/t0450/adoc-missing9
-rwxr-xr-xt/t0610-reftable-basics.sh6
-rwxr-xr-xt/t0612-reftable-jgit-compatibility.sh13
-rwxr-xr-xt/t0613-reftable-write-options.sh24
-rwxr-xr-xt/t1006-cat-file.sh111
-rwxr-xr-xt/t1007-hash-object.sh6
-rwxr-xr-xt/t1021-rerere-in-workdir.sh58
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh13
-rwxr-xr-xt/t1400-update-ref.sh95
-rwxr-xr-xt/t1403-show-ref.sh65
-rwxr-xr-xt/t1410-reflog.sh28
-rwxr-xr-xt/t1416-ref-transaction-hooks.sh2
-rwxr-xr-xt/t1421-reflog-write.sh126
-rwxr-xr-xt/t1422-show-ref-exists.sh9
-rwxr-xr-xt/t1460-refs-migrate.sh22
-rwxr-xr-xt/t1461-refs-list.sh8
-rwxr-xr-xt/t1462-refs-exists.sh10
-rwxr-xr-xt/t1517-outside-repo.sh45
-rwxr-xr-xt/t1900-repo.sh113
-rwxr-xr-xt/t2400-worktree-add.sh20
-rwxr-xr-xt/t3000-ls-files-others.sh19
-rwxr-xr-xt/t3404-rebase-interactive.sh20
-rwxr-xr-xt/t3415-rebase-autosquash.sh10
-rwxr-xr-xt/t3418-rebase-continue.sh13
-rwxr-xr-xt/t3600-rm.sh5
-rwxr-xr-xt/t3701-add-interactive.sh119
-rwxr-xr-xt/t3903-stash.sh173
-rwxr-xr-xt/t4000-diff-format.sh2
-rwxr-xr-xt/t4013-diff-various.sh40
-rwxr-xr-xt/t4015-diff-whitespace.sh8
-rw-r--r--t/t4018/r-indent6
-rw-r--r--t/t4018/r-indent-nested10
-rw-r--r--t/t4018/r-noindent6
-rwxr-xr-xt/t4041-diff-submodule-option.sh22
-rwxr-xr-xt/t4042-diff-textconv-caching.sh12
-rwxr-xr-xt/t4053-diff-no-index.sh92
-rwxr-xr-xt/t4055-diff-context.sh42
-rwxr-xr-xt/t4060-diff-submodule-option-diff-format.sh9
-rwxr-xr-xt/t4072-diff-max-depth.sh116
-rwxr-xr-xt/t4140-apply-ita.sh31
-rwxr-xr-xt/t4150-am.sh2
-rwxr-xr-xt/t4202-log.sh40
-rwxr-xr-xt/t4203-mailmap.sh33
-rwxr-xr-xt/t4211-line-log.sh2
-rw-r--r--t/t4211/sha1/expect.multiple6
-rw-r--r--t/t4211/sha1/expect.no-assertion-error90
-rw-r--r--t/t4211/sha1/expect.two-ranges6
-rw-r--r--t/t4211/sha256/expect.multiple6
-rw-r--r--t/t4211/sha256/expect.no-assertion-error90
-rw-r--r--t/t4211/sha256/expect.two-ranges6
-rwxr-xr-xt/t4216-log-bloom.sh46
-rw-r--r--t/t4256/1/mailinfo.c2
-rw-r--r--t/t4256/1/mailinfo.c.orig2
-rwxr-xr-xt/t5004-archive-corner-cases.sh5
-rwxr-xr-xt/t5200-update-server-info.sh5
-rwxr-xr-xt/t5300-pack-object.sh25
-rwxr-xr-xt/t5304-prune.sh5
-rwxr-xr-xt/t5306-pack-nobase.sh5
-rwxr-xr-xt/t5310-pack-bitmaps.sh43
-rwxr-xr-xt/t5316-pack-delta-depth.sh9
-rwxr-xr-xt/t5319-multi-pack-index.sh30
-rwxr-xr-xt/t5323-pack-redundant.sh5
-rwxr-xr-xt/t5331-pack-objects-stdin.sh122
-rwxr-xr-xt/t5332-multi-pack-reuse.sh7
-rwxr-xr-xt/t5333-pseudo-merge-bitmaps.sh21
-rwxr-xr-xt/t5408-send-pack-stdin.sh15
-rwxr-xr-xt/t5505-remote.sh87
-rwxr-xr-xt/t5510-fetch.sh543
-rwxr-xr-xt/t5516-fetch-push.sh81
-rwxr-xr-xt/t5520-pull.sh60
-rwxr-xr-xt/t5530-upload-pack-error.sh68
-rwxr-xr-xt/t5538-push-shallow.sh41
-rwxr-xr-xt/t6120-describe.sh30
-rwxr-xr-xt/t6137-pathspec-wildcards-literal.sh12
-rwxr-xr-xt/t6300-for-each-ref.sh2140
-rwxr-xr-xt/t6302-for-each-ref-filter.sh213
-rwxr-xr-xt/t6422-merge-rename-corner-cases.sh10
-rwxr-xr-xt/t6423-merge-rename-directories.sh519
-rwxr-xr-xt/t6601-path-walk.sh20
-rwxr-xr-xt/t7005-editor.sh145
-rwxr-xr-xt/t7007-show.sh24
-rwxr-xr-xt/t7400-submodule-basic.sh23
-rwxr-xr-xt/t7401-submodule-summary.sh18
-rwxr-xr-xt/t7406-submodule-update.sh64
-rwxr-xr-xt/t7413-submodule-is-active.sh15
-rwxr-xr-xt/t7422-submodule-output.sh9
-rwxr-xr-xt/t7450-bad-git-dotfiles.sh2
-rwxr-xr-xt/t7502-commit-porcelain.sh52
-rwxr-xr-xt/t7510-signed-commit.sh12
-rwxr-xr-xt/t7528-signed-commit-ssh.sh32
-rwxr-xr-xt/t7600-merge.sh74
-rwxr-xr-xt/t7700-repack.sh63
-rwxr-xr-xt/t7704-repack-cruft.sh145
-rwxr-xr-xt/t7815-grep-binary.sh2
-rwxr-xr-xt/t7900-maintenance.sh19
-rwxr-xr-xt/t8020-last-modified.sh210
-rwxr-xr-xt/t9001-send-email.sh7
-rwxr-xr-xt/t9300-fast-import.sh12
-rwxr-xr-xt/t9301-fast-import-notes.sh2
-rwxr-xr-xt/t9350-fast-export.sh255
-rwxr-xr-xt/t9500-gitweb-standalone-no-errors.sh16
-rwxr-xr-xt/t9822-git-p4-path-encoding.sh13
-rwxr-xr-xt/t9835-git-p4-metadata-encoding-python2.sh24
-rwxr-xr-xt/t9836-git-p4-metadata-encoding-python3.sh24
-rwxr-xr-xt/t9902-completion.sh2
-rwxr-xr-xt/t9903-bash-prompt.sh4
-rw-r--r--t/test-lib-functions.sh21
-rw-r--r--t/test-lib.sh31
-rw-r--r--t/unit-tests/clar/clar.c2
-rw-r--r--t/unit-tests/lib-reftable.c35
-rw-r--r--t/unit-tests/lib-reftable.h15
-rw-r--r--t/unit-tests/t-reftable-basics.c219
-rw-r--r--t/unit-tests/u-dir.c47
-rw-r--r--t/unit-tests/u-prio-queue.c23
-rw-r--r--t/unit-tests/u-reftable-basics.c227
-rw-r--r--t/unit-tests/u-reftable-block.c (renamed from t/unit-tests/t-reftable-block.c)164
-rw-r--r--t/unit-tests/u-reftable-merged.c (renamed from t/unit-tests/t-reftable-merged.c)160
-rw-r--r--t/unit-tests/u-reftable-pq.c (renamed from t/unit-tests/t-reftable-pq.c)59
-rw-r--r--t/unit-tests/u-reftable-readwrite.c (renamed from t/unit-tests/t-reftable-readwrite.c)403
-rw-r--r--t/unit-tests/u-reftable-record.c (renamed from t/unit-tests/t-reftable-record.c)250
-rw-r--r--t/unit-tests/u-reftable-stack.c (renamed from t/unit-tests/t-reftable-stack.c)789
-rw-r--r--t/unit-tests/u-reftable-table.c (renamed from t/unit-tests/t-reftable-table.c)73
-rw-r--r--t/unit-tests/u-string-list.c306
-rw-r--r--t/unit-tests/unit-test.h7
160 files changed, 8167 insertions, 4945 deletions
diff --git a/t/Makefile b/t/Makefile
index 791e0a0978..ab8a5b54aa 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -125,7 +125,6 @@ check-meson:
@mkdir -p mesontmp && \
printf "%s\n" \
"integration_tests t[0-9][0-9][0-9][0-9]-*.sh" \
- "unit_test_programs unit-tests/t-*.c" \
"clar_test_suites unit-tests/u-*.c" | \
while read -r variable pattern; do \
awk "/^$$variable = \[\$$/ {flag=1 ; next } /^]$$/ { flag=0 } flag { gsub(/^ \047/, \"\"); gsub(/\047,\$$/, \"\"); print }" meson.build >mesontmp/meson.txt && \
@@ -190,15 +189,9 @@ perf:
.PHONY: libgit-sys-test libgit-rs-test
libgit-sys-test:
- $(QUIET)(\
- cd ../contrib/libgit-sys && \
- cargo test \
- )
-libgit-rs-test:
- $(QUIET)(\
- cd ../contrib/libgit-rs && \
- cargo test \
- )
+ $(QUIET)cargo test --manifest-path ../contrib/libgit-sys/Cargo.toml
+libgit-rs-test: libgit-sys-test
+ $(QUIET)cargo test --manifest-path ../contrib/libgit-rs/Cargo.toml
ifdef INCLUDE_LIBGIT_RS
-all:: libgit-sys-test libgit-rs-test
+all:: libgit-rs-test
endif
diff --git a/t/README b/t/README
index e9ffd9a81c..adbbd9acf4 100644
--- a/t/README
+++ b/t/README
@@ -415,6 +415,10 @@ 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.
+GIT_TEST_PACK_PATH_WALK=<boolean> if enabled will default the pack-objects
+builtin to use the path-walk API for the object walk. This can still be
+overridden by the --no-path-walk 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.
diff --git a/t/for-each-ref-tests.sh b/t/for-each-ref-tests.sh
new file mode 100644
index 0000000000..e3ad19298a
--- /dev/null
+++ b/t/for-each-ref-tests.sh
@@ -0,0 +1,2141 @@
+git_for_each_ref=${git_for_each_ref:-git for-each-ref}
+GNUPGHOME_NOT_USED=$GNUPGHOME
+. "$TEST_DIRECTORY"/lib-gpg.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
+
+# Mon Jul 3 23:18:43 2006 +0000
+datestamp=1151968723
+setdate_and_increment () {
+ GIT_COMMITTER_DATE="$datestamp +0200"
+ datestamp=$(expr "$datestamp" + 1)
+ GIT_AUTHOR_DATE="$datestamp +0200"
+ datestamp=$(expr "$datestamp" + 1)
+ export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
+}
+
+test_object_file_size () {
+ oid=$(git rev-parse "$1")
+ path=".git/objects/$(test_oid_to_path $oid)"
+ test_file_size "$path"
+}
+
+test_expect_success setup '
+ # setup .mailmap
+ cat >.mailmap <<-EOF &&
+ A Thor <athor@example.com> A U Thor <author@example.com>
+ C Mitter <cmitter@example.com> C O Mitter <committer@example.com>
+ EOF
+
+ setdate_and_increment &&
+ echo "Using $datestamp" > one &&
+ git add one &&
+ git commit -m "Initial" &&
+ git branch -M main &&
+ setdate_and_increment &&
+ git tag -a -m "Tagging at $datestamp" testtag &&
+ git update-ref refs/remotes/origin/main main &&
+ git remote add origin nowhere &&
+ git config branch.main.remote origin &&
+ git config branch.main.merge refs/heads/main &&
+ git remote add myfork elsewhere &&
+ git config remote.pushdefault myfork &&
+ git config push.default current
+'
+
+test_atom () {
+ case "$1" in
+ head) ref=refs/heads/main ;;
+ tag) ref=refs/tags/testtag ;;
+ sym) ref=refs/heads/sym ;;
+ *) ref=$1 ;;
+ esac
+ format=$2
+ test_do=test_expect_${4:-success}
+
+ printf '%s\n' "$3" >expected
+ $test_do $PREREQ "basic atom: $ref $format" '
+ ${git_for_each_ref} --format="%($format)" "$ref" >actual &&
+ sanitize_pgp <actual >actual.clean &&
+ test_cmp expected actual.clean
+ '
+
+ # Automatically test "contents:size" atom after testing "contents"
+ if test "$format" = "contents"
+ then
+ # for commit leg, $3 is changed there
+ expect=$(printf '%s' "$3" | wc -c)
+ $test_do $PREREQ "basic atom: $ref contents:size" '
+ type=$(git cat-file -t "$ref") &&
+ case $type in
+ tag)
+ # We cannot use $3 as it expects sanitize_pgp to run
+ git cat-file tag $ref >out &&
+ expect=$(tail -n +6 out | wc -c) &&
+ rm -f out ;;
+ tree | blob)
+ expect="" ;;
+ commit)
+ : "use the calculated expect" ;;
+ *)
+ BUG "unknown object type" ;;
+ esac &&
+ # Leave $expect unquoted to lose possible leading whitespaces
+ echo $expect >expected &&
+ ${git_for_each_ref} --format="%(contents:size)" "$ref" >actual &&
+ test_cmp expected actual
+ '
+ fi
+}
+
+hexlen=$(test_oid hexsz)
+
+test_atom head refname refs/heads/main
+test_atom head refname: refs/heads/main
+test_atom head refname:short main
+test_atom head refname:lstrip=1 heads/main
+test_atom head refname:lstrip=2 main
+test_atom head refname:lstrip=-1 main
+test_atom head refname:lstrip=-2 heads/main
+test_atom head refname:rstrip=1 refs/heads
+test_atom head refname:rstrip=2 refs
+test_atom head refname:rstrip=-1 refs
+test_atom head refname:rstrip=-2 refs/heads
+test_atom head refname:strip=1 heads/main
+test_atom head refname:strip=2 main
+test_atom head refname:strip=-1 main
+test_atom head refname:strip=-2 heads/main
+test_atom head upstream refs/remotes/origin/main
+test_atom head upstream:short origin/main
+test_atom head upstream:lstrip=2 origin/main
+test_atom head upstream:lstrip=-2 origin/main
+test_atom head upstream:rstrip=2 refs/remotes
+test_atom head upstream:rstrip=-2 refs/remotes
+test_atom head upstream:strip=2 origin/main
+test_atom head upstream:strip=-2 origin/main
+test_atom head push refs/remotes/myfork/main
+test_atom head push:short myfork/main
+test_atom head push:lstrip=1 remotes/myfork/main
+test_atom head push:lstrip=-1 main
+test_atom head push:rstrip=1 refs/remotes/myfork
+test_atom head push:rstrip=-1 refs
+test_atom head push:strip=1 remotes/myfork/main
+test_atom head push:strip=-1 main
+test_atom head objecttype commit
+test_atom head objectsize $((131 + hexlen))
+test_atom head objectsize:disk $(test_object_file_size refs/heads/main)
+test_atom head deltabase $ZERO_OID
+test_atom head objectname $(git rev-parse refs/heads/main)
+test_atom head objectname:short $(git rev-parse --short refs/heads/main)
+test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/main)
+test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/main)
+test_atom head tree $(git rev-parse refs/heads/main^{tree})
+test_atom head tree:short $(git rev-parse --short refs/heads/main^{tree})
+test_atom head tree:short=1 $(git rev-parse --short=1 refs/heads/main^{tree})
+test_atom head tree:short=10 $(git rev-parse --short=10 refs/heads/main^{tree})
+test_atom head parent ''
+test_atom head parent:short ''
+test_atom head parent:short=1 ''
+test_atom head parent:short=10 ''
+test_atom head numparent 0
+test_atom head object ''
+test_atom head type ''
+test_atom head raw "$(git cat-file commit refs/heads/main)
+"
+test_atom head '*objectname' ''
+test_atom head '*objecttype' ''
+test_atom head author 'A U Thor <author@example.com> 1151968724 +0200'
+test_atom head authorname 'A U Thor'
+test_atom head authorname:mailmap 'A Thor'
+test_atom head authoremail '<author@example.com>'
+test_atom head authoremail:trim 'author@example.com'
+test_atom head authoremail:localpart 'author'
+test_atom head authoremail:trim,localpart 'author'
+test_atom head authoremail:mailmap '<athor@example.com>'
+test_atom head authoremail:mailmap,trim 'athor@example.com'
+test_atom head authoremail:trim,mailmap 'athor@example.com'
+test_atom head authoremail:mailmap,localpart 'athor'
+test_atom head authoremail:localpart,mailmap 'athor'
+test_atom head authoremail:mailmap,trim,localpart,mailmap,trim 'athor'
+test_atom head authordate 'Tue Jul 4 01:18:44 2006 +0200'
+test_atom head committer 'C O Mitter <committer@example.com> 1151968723 +0200'
+test_atom head committername 'C O Mitter'
+test_atom head committername:mailmap 'C Mitter'
+test_atom head committeremail '<committer@example.com>'
+test_atom head committeremail:trim 'committer@example.com'
+test_atom head committeremail:localpart 'committer'
+test_atom head committeremail:localpart,trim 'committer'
+test_atom head committeremail:mailmap '<cmitter@example.com>'
+test_atom head committeremail:mailmap,trim 'cmitter@example.com'
+test_atom head committeremail:trim,mailmap 'cmitter@example.com'
+test_atom head committeremail:mailmap,localpart 'cmitter'
+test_atom head committeremail:localpart,mailmap 'cmitter'
+test_atom head committeremail:trim,mailmap,trim,trim,localpart 'cmitter'
+test_atom head committerdate 'Tue Jul 4 01:18:43 2006 +0200'
+test_atom head tag ''
+test_atom head tagger ''
+test_atom head taggername ''
+test_atom head taggeremail ''
+test_atom head taggeremail:trim ''
+test_atom head taggeremail:localpart ''
+test_atom head taggerdate ''
+test_atom head creator 'C O Mitter <committer@example.com> 1151968723 +0200'
+test_atom head creatordate 'Tue Jul 4 01:18:43 2006 +0200'
+test_atom head subject 'Initial'
+test_atom head subject:sanitize 'Initial'
+test_atom head contents:subject 'Initial'
+test_atom head body ''
+test_atom head contents:body ''
+test_atom head contents:signature ''
+test_atom head contents 'Initial
+'
+test_atom head HEAD '*'
+
+test_atom tag refname refs/tags/testtag
+test_atom tag refname:short testtag
+test_atom tag upstream ''
+test_atom tag push ''
+test_atom tag objecttype tag
+test_atom tag objectsize $((114 + hexlen))
+test_atom tag objectsize:disk $(test_object_file_size refs/tags/testtag)
+test_atom tag '*objectsize:disk' $(test_object_file_size refs/heads/main)
+test_atom tag deltabase $ZERO_OID
+test_atom tag '*deltabase' $ZERO_OID
+test_atom tag objectname $(git rev-parse refs/tags/testtag)
+test_atom tag objectname:short $(git rev-parse --short refs/tags/testtag)
+test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/main)
+test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/main)
+test_atom tag tree ''
+test_atom tag tree:short ''
+test_atom tag tree:short=1 ''
+test_atom tag tree:short=10 ''
+test_atom tag parent ''
+test_atom tag parent:short ''
+test_atom tag parent:short=1 ''
+test_atom tag parent:short=10 ''
+test_atom tag numparent ''
+test_atom tag object $(git rev-parse refs/tags/testtag^0)
+test_atom tag type 'commit'
+test_atom tag '*objectname' $(git rev-parse refs/tags/testtag^{})
+test_atom tag '*objecttype' 'commit'
+test_atom tag author ''
+test_atom tag authorname ''
+test_atom tag authorname:mailmap ''
+test_atom tag authoremail ''
+test_atom tag authoremail:trim ''
+test_atom tag authoremail:localpart ''
+test_atom tag authoremail:trim,localpart ''
+test_atom tag authoremail:mailmap ''
+test_atom tag authoremail:mailmap,trim ''
+test_atom tag authoremail:trim,mailmap ''
+test_atom tag authoremail:mailmap,localpart ''
+test_atom tag authoremail:localpart,mailmap ''
+test_atom tag authoremail:mailmap,trim,localpart,mailmap,trim ''
+test_atom tag authordate ''
+test_atom tag committer ''
+test_atom tag committername ''
+test_atom tag committername:mailmap ''
+test_atom tag committeremail ''
+test_atom tag committeremail:trim ''
+test_atom tag committeremail:localpart ''
+test_atom tag committeremail:localpart,trim ''
+test_atom tag committeremail:mailmap ''
+test_atom tag committeremail:mailmap,trim ''
+test_atom tag committeremail:trim,mailmap ''
+test_atom tag committeremail:mailmap,localpart ''
+test_atom tag committeremail:localpart,mailmap ''
+test_atom tag committeremail:trim,mailmap,trim,trim,localpart ''
+test_atom tag committerdate ''
+test_atom tag tag 'testtag'
+test_atom tag tagger 'C O Mitter <committer@example.com> 1151968725 +0200'
+test_atom tag taggername 'C O Mitter'
+test_atom tag taggername:mailmap 'C Mitter'
+test_atom tag taggeremail '<committer@example.com>'
+test_atom tag taggeremail:trim 'committer@example.com'
+test_atom tag taggeremail:localpart 'committer'
+test_atom tag taggeremail:trim,localpart 'committer'
+test_atom tag taggeremail:mailmap '<cmitter@example.com>'
+test_atom tag taggeremail:mailmap,trim 'cmitter@example.com'
+test_atom tag taggeremail:trim,mailmap 'cmitter@example.com'
+test_atom tag taggeremail:mailmap,localpart 'cmitter'
+test_atom tag taggeremail:localpart,mailmap 'cmitter'
+test_atom tag taggeremail:trim,mailmap,trim,localpart,localpart 'cmitter'
+test_atom tag taggerdate 'Tue Jul 4 01:18:45 2006 +0200'
+test_atom tag creator 'C O Mitter <committer@example.com> 1151968725 +0200'
+test_atom tag creatordate 'Tue Jul 4 01:18:45 2006 +0200'
+test_atom tag subject 'Tagging at 1151968727'
+test_atom tag subject:sanitize 'Tagging-at-1151968727'
+test_atom tag contents:subject 'Tagging at 1151968727'
+test_atom tag body ''
+test_atom tag contents:body ''
+test_atom tag contents:signature ''
+test_atom tag contents 'Tagging at 1151968727
+'
+test_atom tag HEAD ' '
+
+test_expect_success 'basic atom: refs/tags/testtag *raw' '
+ git cat-file commit refs/tags/testtag^{} >expected &&
+ ${git_for_each_ref} --format="%(*raw)" refs/tags/testtag >actual &&
+ sanitize_pgp <expected >expected.clean &&
+ echo >>expected.clean &&
+ sanitize_pgp <actual >actual.clean &&
+ test_cmp expected.clean actual.clean
+'
+
+test_expect_success 'Check invalid atoms names are errors' '
+ test_must_fail ${git_for_each_ref} --format="%(INVALID)" refs/heads
+'
+
+test_expect_success 'Check format specifiers are ignored in naming date atoms' '
+ ${git_for_each_ref} --format="%(authordate)" refs/heads &&
+ ${git_for_each_ref} --format="%(authordate:default) %(authordate)" refs/heads &&
+ ${git_for_each_ref} --format="%(authordate) %(authordate:default)" refs/heads &&
+ ${git_for_each_ref} --format="%(authordate:default) %(authordate:default)" refs/heads
+'
+
+test_expect_success 'Check valid format specifiers for date fields' '
+ ${git_for_each_ref} --format="%(authordate:default)" refs/heads &&
+ ${git_for_each_ref} --format="%(authordate:relative)" refs/heads &&
+ ${git_for_each_ref} --format="%(authordate:short)" refs/heads &&
+ ${git_for_each_ref} --format="%(authordate:local)" refs/heads &&
+ ${git_for_each_ref} --format="%(authordate:iso8601)" refs/heads &&
+ ${git_for_each_ref} --format="%(authordate:rfc2822)" refs/heads
+'
+
+test_expect_success 'Check invalid format specifiers are errors' '
+ test_must_fail ${git_for_each_ref} --format="%(authordate:INVALID)" refs/heads
+'
+
+test_expect_success 'arguments to %(objectname:short=) must be positive integers' '
+ test_must_fail ${git_for_each_ref} --format="%(objectname:short=0)" &&
+ test_must_fail ${git_for_each_ref} --format="%(objectname:short=-1)" &&
+ test_must_fail ${git_for_each_ref} --format="%(objectname:short=foo)"
+'
+
+test_bad_atom () {
+ case "$1" in
+ head) ref=refs/heads/main ;;
+ tag) ref=refs/tags/testtag ;;
+ sym) ref=refs/heads/sym ;;
+ *) ref=$1 ;;
+ esac
+ format=$2
+ test_do=test_expect_${4:-success}
+
+ printf '%s\n' "$3" >expect
+ $test_do $PREREQ "err basic atom: $ref $format" '
+ test_must_fail ${git_for_each_ref} \
+ --format="%($format)" "$ref" 2>error &&
+ test_cmp expect error
+ '
+}
+
+test_bad_atom head 'authoremail:foo' \
+ 'fatal: unrecognized %(authoremail) argument: foo'
+
+test_bad_atom head 'authoremail:mailmap,trim,bar' \
+ 'fatal: unrecognized %(authoremail) argument: bar'
+
+test_bad_atom head 'authoremail:trim,' \
+ 'fatal: unrecognized %(authoremail) argument: '
+
+test_bad_atom head 'authoremail:mailmaptrim' \
+ 'fatal: unrecognized %(authoremail) argument: trim'
+
+test_bad_atom head 'committeremail: ' \
+ 'fatal: unrecognized %(committeremail) argument: '
+
+test_bad_atom head 'committeremail: trim,foo' \
+ 'fatal: unrecognized %(committeremail) argument: trim,foo'
+
+test_bad_atom head 'committeremail:mailmap,localpart ' \
+ 'fatal: unrecognized %(committeremail) argument: '
+
+test_bad_atom head 'committeremail:trim_localpart' \
+ 'fatal: unrecognized %(committeremail) argument: _localpart'
+
+test_bad_atom head 'committeremail:localpart,,,trim' \
+ 'fatal: unrecognized %(committeremail) argument: ,,trim'
+
+test_bad_atom tag 'taggeremail:mailmap,trim, foo ' \
+ 'fatal: unrecognized %(taggeremail) argument: foo '
+
+test_bad_atom tag 'taggeremail:trim,localpart,' \
+ 'fatal: unrecognized %(taggeremail) argument: '
+
+test_bad_atom tag 'taggeremail:mailmap;localpart trim' \
+ 'fatal: unrecognized %(taggeremail) argument: ;localpart trim'
+
+test_bad_atom tag 'taggeremail:localpart trim' \
+ 'fatal: unrecognized %(taggeremail) argument: trim'
+
+test_bad_atom tag 'taggeremail:mailmap,mailmap,trim,qux,localpart,trim' \
+ 'fatal: unrecognized %(taggeremail) argument: qux,localpart,trim'
+
+test_date () {
+ f=$1 &&
+ committer_date=$2 &&
+ author_date=$3 &&
+ tagger_date=$4 &&
+ cat >expected <<-EOF &&
+ 'refs/heads/main' '$committer_date' '$author_date'
+ 'refs/tags/testtag' '$tagger_date'
+ EOF
+ (
+ ${git_for_each_ref} --shell \
+ --format="%(refname) %(committerdate${f:+:$f}) %(authordate${f:+:$f})" \
+ refs/heads &&
+ ${git_for_each_ref} --shell \
+ --format="%(refname) %(taggerdate${f:+:$f})" \
+ refs/tags
+ ) >actual &&
+ test_cmp expected actual
+}
+
+test_expect_success 'Check unformatted date fields output' '
+ test_date "" \
+ "Tue Jul 4 01:18:43 2006 +0200" \
+ "Tue Jul 4 01:18:44 2006 +0200" \
+ "Tue Jul 4 01:18:45 2006 +0200"
+'
+
+test_expect_success 'Check format "default" formatted date fields output' '
+ test_date default \
+ "Tue Jul 4 01:18:43 2006 +0200" \
+ "Tue Jul 4 01:18:44 2006 +0200" \
+ "Tue Jul 4 01:18:45 2006 +0200"
+'
+
+test_expect_success 'Check format "default-local" date fields output' '
+ test_date default-local "Mon Jul 3 23:18:43 2006" "Mon Jul 3 23:18:44 2006" "Mon Jul 3 23:18:45 2006"
+'
+
+# Don't know how to do relative check because I can't know when this script
+# is going to be run and can't fake the current time to git, and hence can't
+# provide expected output. Instead, I'll just make sure that "relative"
+# doesn't exit in error
+test_expect_success 'Check format "relative" date fields output' '
+ f=relative &&
+ (${git_for_each_ref} --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
+ ${git_for_each_ref} --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual
+'
+
+# We just check that this is the same as "relative" for now.
+test_expect_success 'Check format "relative-local" date fields output' '
+ test_date relative-local \
+ "$(${git_for_each_ref} --format="%(committerdate:relative)" refs/heads)" \
+ "$(${git_for_each_ref} --format="%(authordate:relative)" refs/heads)" \
+ "$(${git_for_each_ref} --format="%(taggerdate:relative)" refs/tags)"
+'
+
+test_expect_success 'Check format "short" date fields output' '
+ test_date short 2006-07-04 2006-07-04 2006-07-04
+'
+
+test_expect_success 'Check format "short-local" date fields output' '
+ test_date short-local 2006-07-03 2006-07-03 2006-07-03
+'
+
+test_expect_success 'Check format "local" date fields output' '
+ test_date local \
+ "Mon Jul 3 23:18:43 2006" \
+ "Mon Jul 3 23:18:44 2006" \
+ "Mon Jul 3 23:18:45 2006"
+'
+
+test_expect_success 'Check format "iso8601" date fields output' '
+ test_date iso8601 \
+ "2006-07-04 01:18:43 +0200" \
+ "2006-07-04 01:18:44 +0200" \
+ "2006-07-04 01:18:45 +0200"
+'
+
+test_expect_success 'Check format "iso8601-local" date fields output' '
+ test_date iso8601-local "2006-07-03 23:18:43 +0000" "2006-07-03 23:18:44 +0000" "2006-07-03 23:18:45 +0000"
+'
+
+test_expect_success 'Check format "rfc2822" date fields output' '
+ test_date rfc2822 \
+ "Tue, 4 Jul 2006 01:18:43 +0200" \
+ "Tue, 4 Jul 2006 01:18:44 +0200" \
+ "Tue, 4 Jul 2006 01:18:45 +0200"
+'
+
+test_expect_success 'Check format "rfc2822-local" date fields output' '
+ test_date rfc2822-local "Mon, 3 Jul 2006 23:18:43 +0000" "Mon, 3 Jul 2006 23:18:44 +0000" "Mon, 3 Jul 2006 23:18:45 +0000"
+'
+
+test_expect_success 'Check format "raw" date fields output' '
+ test_date raw "1151968723 +0200" "1151968724 +0200" "1151968725 +0200"
+'
+
+test_expect_success 'Check format "raw-local" date fields output' '
+ test_date raw-local "1151968723 +0000" "1151968724 +0000" "1151968725 +0000"
+'
+
+test_expect_success 'Check format of strftime date fields' '
+ echo "my date is 2006-07-04" >expected &&
+ ${git_for_each_ref} \
+ --format="%(authordate:format:my date is %Y-%m-%d)" \
+ refs/heads >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'Check format of strftime-local date fields' '
+ echo "my date is 2006-07-03" >expected &&
+ ${git_for_each_ref} \
+ --format="%(authordate:format-local:my date is %Y-%m-%d)" \
+ refs/heads >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'exercise strftime with odd fields' '
+ echo >expected &&
+ ${git_for_each_ref} --format="%(authordate:format:)" refs/heads >actual &&
+ test_cmp expected actual &&
+ long="long format -- $ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID" &&
+ echo $long >expected &&
+ ${git_for_each_ref} --format="%(authordate:format:$long)" refs/heads >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+refs/heads/main
+refs/remotes/origin/main
+refs/tags/testtag
+EOF
+
+test_expect_success 'Verify ascending sort' '
+ ${git_for_each_ref} --format="%(refname)" --sort=refname >actual &&
+ test_cmp expected actual
+'
+
+
+cat >expected <<\EOF
+refs/tags/testtag
+refs/remotes/origin/main
+refs/heads/main
+EOF
+
+test_expect_success 'Verify descending sort' '
+ ${git_for_each_ref} --format="%(refname)" --sort=-refname >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'Give help even with invalid sort atoms' '
+ test_expect_code 129 ${git_for_each_ref} --sort=bogus -h >actual 2>&1 &&
+ grep "^usage: ${git_for_each_ref}" actual
+'
+
+cat >expected <<\EOF
+refs/tags/testtag
+refs/tags/testtag-2
+EOF
+
+test_expect_success 'exercise patterns with prefixes' '
+ git tag testtag-2 &&
+ test_when_finished "git tag -d testtag-2" &&
+ ${git_for_each_ref} --format="%(refname)" \
+ refs/tags/testtag refs/tags/testtag-2 >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+refs/tags/testtag
+refs/tags/testtag-2
+EOF
+
+test_expect_success 'exercise glob patterns with prefixes' '
+ git tag testtag-2 &&
+ test_when_finished "git tag -d testtag-2" &&
+ ${git_for_each_ref} --format="%(refname)" \
+ refs/tags/testtag "refs/tags/testtag-*" >actual &&
+ test_cmp expected actual
+'
+
+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'
+EOF
+
+test_expect_success 'Quoting style: shell' '
+ ${git_for_each_ref} --shell --format="%(refname)" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'Quoting style: perl' '
+ ${git_for_each_ref} --perl --format="%(refname)" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'Quoting style: python' '
+ ${git_for_each_ref} --python --format="%(refname)" >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+"refs/heads/main"
+"refs/remotes/origin/main"
+"refs/tags/testtag"
+EOF
+
+test_expect_success 'Quoting style: tcl' '
+ ${git_for_each_ref} --tcl --format="%(refname)" >actual &&
+ test_cmp expected actual
+'
+
+for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do
+ test_expect_success "more than one quoting style: $i" "
+ test_must_fail ${git_for_each_ref} $i 2>err &&
+ grep '^error: more than one quoting style' err
+ "
+done
+
+test_expect_success 'setup for upstream:track[short]' '
+ test_commit two
+'
+
+test_atom head upstream:track '[ahead 1]'
+test_atom head upstream:trackshort '>'
+test_atom head upstream:track,nobracket 'ahead 1'
+test_atom head upstream:nobracket,track 'ahead 1'
+
+test_expect_success 'setup for push:track[short]' '
+ test_commit third &&
+ git update-ref refs/remotes/myfork/main main &&
+ git reset main~1
+'
+
+test_atom head push:track '[behind 1]'
+test_atom head push:trackshort '<'
+
+test_expect_success 'Check that :track[short] cannot be used with other atoms' '
+ test_must_fail ${git_for_each_ref} --format="%(refname:track)" 2>/dev/null &&
+ test_must_fail ${git_for_each_ref} --format="%(refname:trackshort)" 2>/dev/null
+'
+
+test_expect_success 'Check that :track[short] works when upstream is invalid' '
+ cat >expected <<-\EOF &&
+ [gone]
+
+ EOF
+ test_when_finished "git config branch.main.merge refs/heads/main" &&
+ git config branch.main.merge refs/heads/does-not-exist &&
+ ${git_for_each_ref} \
+ --format="%(upstream:track)$LF%(upstream:trackshort)" \
+ refs/heads >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'Check for invalid refname format' '
+ test_must_fail ${git_for_each_ref} --format="%(refname:INVALID)"
+'
+
+test_expect_success 'set up color tests' '
+ cat >expected.color <<-EOF &&
+ $(git rev-parse --short refs/heads/main) <GREEN>main<RESET>
+ $(git rev-parse --short refs/remotes/myfork/main) <GREEN>myfork/main<RESET>
+ $(git rev-parse --short refs/remotes/origin/main) <GREEN>origin/main<RESET>
+ $(git rev-parse --short refs/tags/testtag) <GREEN>testtag<RESET>
+ $(git rev-parse --short refs/tags/third) <GREEN>third<RESET>
+ $(git rev-parse --short refs/tags/two) <GREEN>two<RESET>
+ EOF
+ sed "s/<[^>]*>//g" <expected.color >expected.bare &&
+ color_format="%(objectname:short) %(color:green)%(refname:short)"
+'
+
+test_expect_success TTY '%(color) shows color with a tty' '
+ test_terminal ${git_for_each_ref} --format="$color_format" >actual.raw &&
+ test_decode_color <actual.raw >actual &&
+ test_cmp expected.color actual
+'
+
+test_expect_success '%(color) does not show color without tty' '
+ TERM=vt100 ${git_for_each_ref} --format="$color_format" >actual &&
+ test_cmp expected.bare actual
+'
+
+test_expect_success '--color can override tty check' '
+ ${git_for_each_ref} --color --format="$color_format" >actual.raw &&
+ test_decode_color <actual.raw >actual &&
+ test_cmp expected.color actual
+'
+
+test_expect_success 'color.ui=always does not override tty check' '
+ git -c color.ui=always ${git_for_each_ref#git} --format="$color_format" >actual &&
+ 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 at least 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
+EOF
+
+test_expect_success 'Check ambiguous head and tag refs (strict)' '
+ git config --bool core.warnambiguousrefs true &&
+ git checkout -b newtag &&
+ echo "Using $datestamp" > one &&
+ git add one &&
+ git commit -m "Branch" &&
+ setdate_and_increment &&
+ git tag -m "Tagging at $datestamp" main &&
+ ${git_for_each_ref} --format "%(refname:short)" refs/heads/main refs/tags/main >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+heads/main
+main
+EOF
+
+test_expect_success 'Check ambiguous head and tag refs (loose)' '
+ git config --bool core.warnambiguousrefs false &&
+ ${git_for_each_ref} --format "%(refname:short)" refs/heads/main refs/tags/main >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+heads/ambiguous
+ambiguous
+EOF
+
+test_expect_success 'Check ambiguous head and tag refs II (loose)' '
+ git checkout main &&
+ git tag ambiguous testtag^0 &&
+ git branch ambiguous testtag^0 &&
+ ${git_for_each_ref} --format "%(refname:short)" refs/heads/ambiguous refs/tags/ambiguous >actual &&
+ test_cmp expected actual
+'
+
+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 --literally --stdin -w -t tag)
+'
+
+test_atom refs/tags/taggerless type 'commit'
+test_atom refs/tags/taggerless tag 'taggerless'
+test_atom refs/tags/taggerless tagger ''
+test_atom refs/tags/taggerless taggername ''
+test_atom refs/tags/taggerless taggeremail ''
+test_atom refs/tags/taggerless taggeremail:trim ''
+test_atom refs/tags/taggerless taggeremail:localpart ''
+test_atom refs/tags/taggerless taggerdate ''
+test_atom refs/tags/taggerless committer ''
+test_atom refs/tags/taggerless committername ''
+test_atom refs/tags/taggerless committeremail ''
+test_atom refs/tags/taggerless committeremail:trim ''
+test_atom refs/tags/taggerless committeremail:localpart ''
+test_atom refs/tags/taggerless committerdate ''
+test_atom refs/tags/taggerless subject 'Broken tag'
+
+test_expect_success 'an unusual tag with an incomplete line' '
+
+ git tag -m "bogo" bogo &&
+ bogo=$(git cat-file tag bogo) &&
+ bogo=$(printf "%s" "$bogo" | git mktag) &&
+ git tag -f bogo "$bogo" &&
+ ${git_for_each_ref} --format "%(body)" refs/tags/bogo
+
+'
+
+test_expect_success 'create tag with subject and body content' '
+ cat >>msg <<-\EOF &&
+ the subject line
+
+ first body line
+ second body line
+ EOF
+ git tag -F msg subject-body
+'
+test_atom refs/tags/subject-body subject 'the subject line'
+test_atom refs/tags/subject-body subject:sanitize 'the-subject-line'
+test_atom refs/tags/subject-body body 'first body line
+second body line
+'
+test_atom refs/tags/subject-body contents 'the subject line
+
+first body line
+second body line
+'
+
+test_expect_success 'create tag with multiline subject' '
+ cat >msg <<-\EOF &&
+ first subject line
+ second subject line
+
+ first body line
+ second body line
+ EOF
+ git tag -F msg multiline
+'
+test_atom refs/tags/multiline subject 'first subject line second subject line'
+test_atom refs/tags/multiline subject:sanitize 'first-subject-line-second-subject-line'
+test_atom refs/tags/multiline contents:subject 'first subject line second subject line'
+test_atom refs/tags/multiline body 'first body line
+second body line
+'
+test_atom refs/tags/multiline contents:body 'first body line
+second body line
+'
+test_atom refs/tags/multiline contents:signature ''
+test_atom refs/tags/multiline contents 'first subject line
+second subject line
+
+first body line
+second body line
+'
+
+test_expect_success GPG 'create signed tags' '
+ git tag -s -m "" signed-empty &&
+ git tag -s -m "subject line" signed-short &&
+ cat >msg <<-\EOF &&
+ subject line
+
+ body contents
+ EOF
+ git tag -s -F msg signed-long
+'
+
+sig='-----BEGIN PGP SIGNATURE-----
+-----END PGP SIGNATURE-----
+'
+
+PREREQ=GPG
+test_atom refs/tags/signed-empty subject ''
+test_atom refs/tags/signed-empty subject:sanitize ''
+test_atom refs/tags/signed-empty contents:subject ''
+test_atom refs/tags/signed-empty body "$sig"
+test_atom refs/tags/signed-empty contents:body ''
+test_atom refs/tags/signed-empty contents:signature "$sig"
+test_atom refs/tags/signed-empty contents "$sig"
+
+test_expect_success GPG 'basic atom: refs/tags/signed-empty raw' '
+ git cat-file tag refs/tags/signed-empty >expected &&
+ ${git_for_each_ref} --format="%(raw)" refs/tags/signed-empty >actual &&
+ sanitize_pgp <expected >expected.clean &&
+ echo >>expected.clean &&
+ sanitize_pgp <actual >actual.clean &&
+ test_cmp expected.clean actual.clean
+'
+
+test_atom refs/tags/signed-short subject 'subject line'
+test_atom refs/tags/signed-short subject:sanitize 'subject-line'
+test_atom refs/tags/signed-short contents:subject 'subject line'
+test_atom refs/tags/signed-short body "$sig"
+test_atom refs/tags/signed-short contents:body ''
+test_atom refs/tags/signed-short contents:signature "$sig"
+test_atom refs/tags/signed-short contents "subject line
+$sig"
+
+test_expect_success GPG 'basic atom: refs/tags/signed-short raw' '
+ git cat-file tag refs/tags/signed-short >expected &&
+ ${git_for_each_ref} --format="%(raw)" refs/tags/signed-short >actual &&
+ sanitize_pgp <expected >expected.clean &&
+ echo >>expected.clean &&
+ sanitize_pgp <actual >actual.clean &&
+ test_cmp expected.clean actual.clean
+'
+
+test_atom refs/tags/signed-long subject 'subject line'
+test_atom refs/tags/signed-long subject:sanitize 'subject-line'
+test_atom refs/tags/signed-long contents:subject 'subject line'
+test_atom refs/tags/signed-long body "body contents
+$sig"
+test_atom refs/tags/signed-long contents:body 'body contents
+'
+test_atom refs/tags/signed-long contents:signature "$sig"
+test_atom refs/tags/signed-long contents "subject line
+
+body contents
+$sig"
+
+test_expect_success GPG 'basic atom: refs/tags/signed-long raw' '
+ git cat-file tag refs/tags/signed-long >expected &&
+ ${git_for_each_ref} --format="%(raw)" refs/tags/signed-long >actual &&
+ sanitize_pgp <expected >expected.clean &&
+ echo >>expected.clean &&
+ sanitize_pgp <actual >actual.clean &&
+ test_cmp expected.clean actual.clean
+'
+
+test_expect_success 'set up refs pointing to tree and blob' '
+ git update-ref refs/mytrees/first refs/heads/main^{tree} &&
+ git update-ref refs/myblobs/first refs/heads/main:one
+'
+
+test_atom refs/mytrees/first subject ""
+test_atom refs/mytrees/first contents:subject ""
+test_atom refs/mytrees/first body ""
+test_atom refs/mytrees/first contents:body ""
+test_atom refs/mytrees/first contents:signature ""
+test_atom refs/mytrees/first contents ""
+
+test_expect_success 'basic atom: refs/mytrees/first raw' '
+ git cat-file tree refs/mytrees/first >expected &&
+ echo >>expected &&
+ ${git_for_each_ref} --format="%(raw)" refs/mytrees/first >actual &&
+ test_cmp expected actual &&
+ git cat-file -s refs/mytrees/first >expected &&
+ ${git_for_each_ref} --format="%(raw:size)" refs/mytrees/first >actual &&
+ test_cmp expected actual
+'
+
+test_atom refs/myblobs/first subject ""
+test_atom refs/myblobs/first contents:subject ""
+test_atom refs/myblobs/first body ""
+test_atom refs/myblobs/first contents:body ""
+test_atom refs/myblobs/first contents:signature ""
+test_atom refs/myblobs/first contents ""
+
+test_expect_success 'basic atom: refs/myblobs/first raw' '
+ git cat-file blob refs/myblobs/first >expected &&
+ echo >>expected &&
+ ${git_for_each_ref} --format="%(raw)" refs/myblobs/first >actual &&
+ test_cmp expected actual &&
+ git cat-file -s refs/myblobs/first >expected &&
+ ${git_for_each_ref} --format="%(raw:size)" refs/myblobs/first >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'set up refs pointing to binary blob' '
+ printf "a\0b\0c" >blob1 &&
+ printf "a\0c\0b" >blob2 &&
+ printf "\0a\0b\0c" >blob3 &&
+ printf "abc" >blob4 &&
+ printf "\0 \0 \0 " >blob5 &&
+ printf "\0 \0a\0 " >blob6 &&
+ printf " " >blob7 &&
+ >blob8 &&
+ obj=$(git hash-object -w blob1) &&
+ git update-ref refs/myblobs/blob1 "$obj" &&
+ obj=$(git hash-object -w blob2) &&
+ git update-ref refs/myblobs/blob2 "$obj" &&
+ obj=$(git hash-object -w blob3) &&
+ git update-ref refs/myblobs/blob3 "$obj" &&
+ obj=$(git hash-object -w blob4) &&
+ git update-ref refs/myblobs/blob4 "$obj" &&
+ obj=$(git hash-object -w blob5) &&
+ git update-ref refs/myblobs/blob5 "$obj" &&
+ obj=$(git hash-object -w blob6) &&
+ git update-ref refs/myblobs/blob6 "$obj" &&
+ obj=$(git hash-object -w blob7) &&
+ git update-ref refs/myblobs/blob7 "$obj" &&
+ obj=$(git hash-object -w blob8) &&
+ git update-ref refs/myblobs/blob8 "$obj"
+'
+
+test_expect_success 'Verify sorts with raw' '
+ cat >expected <<-EOF &&
+ refs/myblobs/blob8
+ refs/myblobs/blob5
+ refs/myblobs/blob6
+ refs/myblobs/blob3
+ refs/myblobs/blob7
+ refs/mytrees/first
+ refs/myblobs/first
+ refs/myblobs/blob1
+ refs/myblobs/blob2
+ refs/myblobs/blob4
+ refs/heads/main
+ EOF
+ ${git_for_each_ref} --format="%(refname)" --sort=raw \
+ refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'Verify sorts with raw:size' '
+ cat >expected <<-EOF &&
+ refs/myblobs/blob8
+ refs/myblobs/blob7
+ 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 &&
+ test_cmp expected actual
+'
+
+test_expect_success 'validate raw atom with %(if:equals)' '
+ cat >expected <<-EOF &&
+ not equals
+ not equals
+ not equals
+ not equals
+ not equals
+ not equals
+ refs/myblobs/blob4
+ not equals
+ not equals
+ not equals
+ not equals
+ not equals
+ EOF
+ ${git_for_each_ref} --format="%(if:equals=abc)%(raw)%(then)%(refname)%(else)not equals%(end)" \
+ refs/myblobs/ refs/heads/ >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'validate raw atom with %(if:notequals)' '
+ cat >expected <<-EOF &&
+ refs/heads/ambiguous
+ refs/heads/main
+ refs/heads/newtag
+ refs/myblobs/blob1
+ refs/myblobs/blob2
+ refs/myblobs/blob3
+ equals
+ refs/myblobs/blob5
+ refs/myblobs/blob6
+ refs/myblobs/blob7
+ refs/myblobs/blob8
+ refs/myblobs/first
+ EOF
+ ${git_for_each_ref} --format="%(if:notequals=abc)%(raw)%(then)%(refname)%(else)equals%(end)" \
+ refs/myblobs/ refs/heads/ >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'empty raw refs with %(if)' '
+ cat >expected <<-EOF &&
+ refs/myblobs/blob1 not empty
+ refs/myblobs/blob2 not empty
+ refs/myblobs/blob3 not empty
+ refs/myblobs/blob4 not empty
+ refs/myblobs/blob5 not empty
+ refs/myblobs/blob6 not empty
+ refs/myblobs/blob7 empty
+ refs/myblobs/blob8 empty
+ refs/myblobs/first not empty
+ EOF
+ ${git_for_each_ref} --format="%(refname) %(if)%(raw)%(then)not empty%(else)empty%(end)" \
+ refs/myblobs/ >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '%(raw) with --python must fail' '
+ test_must_fail ${git_for_each_ref} --format="%(raw)" --python
+'
+
+test_expect_success '%(raw) with --tcl must fail' '
+ test_must_fail ${git_for_each_ref} --format="%(raw)" --tcl
+'
+
+test_expect_success PERL_TEST_HELPERS '%(raw) with --perl' '
+ ${git_for_each_ref} --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/blob1 --perl | perl >actual &&
+ cmp blob1 actual &&
+ ${git_for_each_ref} --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/blob3 --perl | perl >actual &&
+ cmp blob3 actual &&
+ ${git_for_each_ref} --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/blob8 --perl | perl >actual &&
+ cmp blob8 actual &&
+ ${git_for_each_ref} --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/first --perl | perl >actual &&
+ cmp one actual &&
+ git cat-file tree refs/mytrees/first > expected &&
+ ${git_for_each_ref} --format="\$name= %(raw);
+print \"\$name\"" refs/mytrees/first --perl | perl >actual &&
+ cmp expected actual
+'
+
+test_expect_success '%(raw) with --shell must fail' '
+ test_must_fail ${git_for_each_ref} --format="%(raw)" --shell
+'
+
+test_expect_success '%(raw) with --shell and --sort=raw must fail' '
+ test_must_fail ${git_for_each_ref} --format="%(raw)" --sort=raw --shell
+'
+
+test_expect_success '%(raw:size) with --shell' '
+ ${git_for_each_ref} --format="%(raw:size)" | sed "s/^/$SQ/;s/$/$SQ/" >expect &&
+ ${git_for_each_ref} --format="%(raw:size)" --shell >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success "${git_for_each_ref} --format compare with cat-file --batch" '
+ git rev-parse refs/mytrees/first | git cat-file --batch >expected &&
+ ${git_for_each_ref} --format="%(objectname) %(objecttype) %(objectsize)
+%(raw)" refs/mytrees/first >actual &&
+ 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
+ for email in user1 user2
+ do
+ for ref in ref1 ref2
+ do
+ GIT_COMMITTER_DATE="@$when +0000" \
+ GIT_COMMITTER_EMAIL="$email@example.com" \
+ git tag -m "tag $ref-$when-$email" \
+ multi-$ref-$when-$email || return 1
+ done
+ done
+ done
+'
+
+test_expect_success 'Verify sort with multiple keys' '
+ cat >expected <<-\EOF &&
+ 100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
+ 100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
+ 100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
+ 100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
+ 200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
+ 200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
+ 200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
+ 200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
+ EOF
+ ${git_for_each_ref} \
+ --format="%(taggerdate:unix) %(taggeremail) %(refname)" \
+ --sort=-refname \
+ --sort=taggeremail \
+ --sort=taggerdate \
+ "refs/tags/multi-*" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'equivalent sorts fall back on refname' '
+ cat >expected <<-\EOF &&
+ 100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
+ 100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
+ 100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
+ 100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
+ 200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
+ 200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
+ 200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
+ 200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
+ EOF
+ ${git_for_each_ref} \
+ --format="%(taggerdate:unix) %(taggeremail) %(refname)" \
+ --sort=taggerdate \
+ "refs/tags/multi-*" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '--no-sort cancels the previous sort keys' '
+ cat >expected <<-\EOF &&
+ 100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
+ 100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
+ 100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
+ 100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
+ 200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
+ 200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
+ 200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
+ 200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
+ EOF
+ ${git_for_each_ref} \
+ --format="%(taggerdate:unix) %(taggeremail) %(refname)" \
+ --sort=-refname \
+ --sort=taggeremail \
+ --no-sort \
+ --sort=taggerdate \
+ "refs/tags/multi-*" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '--no-sort without subsequent --sort prints expected refs' '
+ cat >expected <<-\EOF &&
+ 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
+ EOF
+
+ # Sort the results with `sort` for a consistent comparison against
+ # expected
+ ${git_for_each_ref} \
+ --format="%(refname)" \
+ --no-sort \
+ "refs/tags/multi-*" | sort >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'set up custom date sorting' '
+ # Dates:
+ # - Wed Feb 07 2024 21:34:20 +0000
+ # - Tue Dec 14 1999 00:05:22 +0000
+ # - Fri Jun 04 2021 11:26:51 +0000
+ # - Mon Jan 22 2007 16:44:01 GMT+0000
+ i=1 &&
+ for when in 1707341660 945129922 1622806011 1169484241
+ do
+ GIT_COMMITTER_DATE="@$when +0000" \
+ GIT_COMMITTER_EMAIL="user@example.com" \
+ git tag -m "tag $when" custom-dates-$i &&
+ i=$(($i+1)) || return 1
+ done
+'
+
+test_expect_success 'sort by date defaults to full timestamp' '
+ cat >expected <<-\EOF &&
+ 945129922 refs/tags/custom-dates-2
+ 1169484241 refs/tags/custom-dates-4
+ 1622806011 refs/tags/custom-dates-3
+ 1707341660 refs/tags/custom-dates-1
+ EOF
+
+ ${git_for_each_ref} \
+ --format="%(creatordate:unix) %(refname)" \
+ --sort=creatordate \
+ "refs/tags/custom-dates-*" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'sort by custom date format' '
+ cat >expected <<-\EOF &&
+ 00:05:22 refs/tags/custom-dates-2
+ 11:26:51 refs/tags/custom-dates-3
+ 16:44:01 refs/tags/custom-dates-4
+ 21:34:20 refs/tags/custom-dates-1
+ EOF
+
+ ${git_for_each_ref} \
+ --format="%(creatordate:format:%H:%M:%S) %(refname)" \
+ --sort="creatordate:format:%H:%M:%S" \
+ "refs/tags/custom-dates-*" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' '
+ test_when_finished "git checkout main" &&
+ ${git_for_each_ref} --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
+ sed -e "s/^\* / /" actual >expect &&
+ git checkout --orphan orphaned-branch &&
+ ${git_for_each_ref} --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
+ test_cmp expect actual
+'
+
+cat >trailers <<EOF
+Reviewed-by: A U Thor <author@example.com>
+Signed-off-by: A U Thor <author@example.com>
+[ v2 updated patch description ]
+Acked-by: A U Thor
+ <author@example.com>
+EOF
+
+unfold () {
+ perl -0pe 's/\n\s+/ /g'
+}
+
+test_expect_success 'set up trailers for next test' '
+ echo "Some contents" > two &&
+ git add two &&
+ git commit -F - <<-EOF
+ trailers: this commit message has trailers
+
+ Some message contents
+
+ $(cat trailers)
+ EOF
+'
+
+test_trailer_option () {
+ if test "$#" -eq 3
+ then
+ prereq="$1"
+ shift
+ fi &&
+ title=$1 option=$2
+ cat >expect
+ test_expect_success $prereq "$title" '
+ ${git_for_each_ref} --format="%($option)" refs/heads/main >actual &&
+ test_cmp expect actual &&
+ ${git_for_each_ref} --format="%(contents:$option)" refs/heads/main >actual &&
+ test_cmp expect actual
+ '
+}
+
+test_trailer_option PERL_TEST_HELPERS '%(trailers:unfold) unfolds trailers' \
+ 'trailers:unfold' <<-EOF
+ $(unfold <trailers)
+
+ EOF
+
+test_trailer_option '%(trailers:only) shows only "key: value" trailers' \
+ 'trailers:only' <<-EOF
+ $(grep -v patch.description <trailers)
+
+ EOF
+
+test_trailer_option '%(trailers:only=no,only=true) shows only "key: value" trailers' \
+ 'trailers:only=no,only=true' <<-EOF
+ $(grep -v patch.description <trailers)
+
+ EOF
+
+test_trailer_option '%(trailers:only=yes) shows only "key: value" trailers' \
+ 'trailers:only=yes' <<-EOF
+ $(grep -v patch.description <trailers)
+
+ EOF
+
+test_trailer_option '%(trailers:only=no) shows all trailers' \
+ 'trailers:only=no' <<-EOF
+ $(cat trailers)
+
+ EOF
+
+test_trailer_option PERL_TEST_HELPERS '%(trailers:only) and %(trailers:unfold) work together' \
+ 'trailers:only,unfold' <<-EOF
+ $(grep -v patch.description <trailers | unfold)
+
+ EOF
+
+test_trailer_option PERL_TEST_HELPERS '%(trailers:unfold) and %(trailers:only) work together' \
+ 'trailers:unfold,only' <<-EOF
+ $(grep -v patch.description <trailers | unfold)
+
+ EOF
+
+test_trailer_option '%(trailers:key=foo) shows that trailer' \
+ 'trailers:key=Signed-off-by' <<-EOF
+ Signed-off-by: A U Thor <author@example.com>
+
+ EOF
+
+test_trailer_option '%(trailers:key=foo) is case insensitive' \
+ 'trailers:key=SiGned-oFf-bY' <<-EOF
+ Signed-off-by: A U Thor <author@example.com>
+
+ EOF
+
+test_trailer_option '%(trailers:key=foo:) trailing colon also works' \
+ 'trailers:key=Signed-off-by:' <<-EOF
+ Signed-off-by: A U Thor <author@example.com>
+
+ EOF
+
+test_trailer_option '%(trailers:key=foo) multiple keys' \
+ 'trailers:key=Reviewed-by:,key=Signed-off-by' <<-EOF
+ Reviewed-by: A U Thor <author@example.com>
+ Signed-off-by: A U Thor <author@example.com>
+
+ EOF
+
+test_trailer_option '%(trailers:key=nonexistent) becomes empty' \
+ 'trailers:key=Shined-off-by:' <<-EOF
+
+ EOF
+
+test_trailer_option '%(trailers:key=foo) handles multiple lines even if folded' \
+ 'trailers:key=Acked-by' <<-EOF
+ $(grep -v patch.description <trailers | grep -v Signed-off-by | grep -v Reviewed-by)
+
+ EOF
+
+test_trailer_option '%(trailers:key=foo,unfold) properly unfolds' \
+ 'trailers:key=Signed-Off-by,unfold' <<-EOF
+ $(unfold <trailers | grep Signed-off-by)
+
+ EOF
+
+test_trailer_option '%(trailers:key=foo,only=no) also includes nontrailer lines' \
+ 'trailers:key=Signed-off-by,only=no' <<-EOF
+ Signed-off-by: A U Thor <author@example.com>
+ $(grep patch.description <trailers)
+
+ EOF
+
+test_trailer_option '%(trailers:key=foo,valueonly) shows only value' \
+ 'trailers:key=Signed-off-by,valueonly' <<-EOF
+ A U Thor <author@example.com>
+
+ EOF
+
+test_trailer_option '%(trailers:separator) changes separator' \
+ 'trailers:separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
+ Reviewed-by: A U Thor <author@example.com>,Signed-off-by: A U Thor <author@example.com>
+ EOF
+
+test_trailer_option '%(trailers:key_value_separator) changes key-value separator' \
+ 'trailers:key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
+ Reviewed-by,A U Thor <author@example.com>
+ Signed-off-by,A U Thor <author@example.com>
+
+ EOF
+
+test_trailer_option '%(trailers:separator,key_value_separator) changes both separators' \
+ 'trailers:separator=%x2C,key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
+ Reviewed-by,A U Thor <author@example.com>,Signed-off-by,A U Thor <author@example.com>
+ EOF
+
+test_expect_success 'multiple %(trailers) use their own options' '
+ git tag -F - tag-with-trailers <<-\EOF &&
+ body
+
+ one: foo
+ one: bar
+ two: baz
+ two: qux
+ EOF
+ t1="%(trailers:key=one,key_value_separator=W,separator=X)" &&
+ t2="%(trailers:key=two,key_value_separator=Y,separator=Z)" &&
+ ${git_for_each_ref} --format="$t1%0a$t2" refs/tags/tag-with-trailers >actual &&
+ cat >expect <<-\EOF &&
+ oneWfooXoneWbar
+ twoYbazZtwoYqux
+ EOF
+ test_cmp expect actual
+'
+
+test_failing_trailer_option () {
+ title=$1 option=$2
+ cat >expect
+ test_expect_success "$title" '
+ # error message cannot be checked under i18n
+ test_must_fail ${git_for_each_ref} --format="%($option)" refs/heads/main 2>actual &&
+ test_cmp expect actual &&
+ test_must_fail ${git_for_each_ref} --format="%(contents:$option)" refs/heads/main 2>actual &&
+ test_cmp expect actual
+ '
+}
+
+test_failing_trailer_option '%(trailers) rejects unknown trailers arguments' \
+ 'trailers:unsupported' <<-\EOF
+ fatal: unknown %(trailers) argument: unsupported
+ EOF
+
+test_failing_trailer_option '%(trailers:key) without value is error' \
+ 'trailers:key' <<-\EOF
+ fatal: expected %(trailers:key=<value>)
+ EOF
+
+test_expect_success 'if arguments, %(contents:trailers) shows error if colon is missing' '
+ cat >expect <<-EOF &&
+ fatal: unrecognized %(contents) argument: trailersonly
+ EOF
+ test_must_fail ${git_for_each_ref} --format="%(contents:trailersonly)" 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'basic atom: head contents:trailers' '
+ ${git_for_each_ref} --format="%(contents:trailers)" refs/heads/main >actual &&
+ sanitize_pgp <actual >actual.clean &&
+ # ${git_for_each_ref} ends with a blank line
+ cat >expect <<-EOF &&
+ $(cat trailers)
+
+ EOF
+ test_cmp expect actual.clean
+'
+
+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
+
+ This is the body. The message has a "---" line which would confuse a
+ message+patch parser. But here we know we have only a commit message,
+ so we get it right.
+
+ trailer: wrong
+ ---
+ This is more body.
+
+ trailer: right
+ EOF
+
+ {
+ echo "trailer: right" &&
+ echo
+ } >expect &&
+ ${git_for_each_ref} --format="%(trailers)" refs/heads/main >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Add symbolic ref for the following tests' '
+ git symbolic-ref refs/heads/sym refs/heads/main
+'
+
+cat >expected <<EOF
+refs/heads/main
+EOF
+
+test_expect_success 'Verify usage of %(symref) atom' '
+ ${git_for_each_ref} --format="%(symref)" refs/heads/sym >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+heads/main
+EOF
+
+test_expect_success 'Verify usage of %(symref:short) atom' '
+ ${git_for_each_ref} --format="%(symref:short)" refs/heads/sym >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+main
+heads/main
+EOF
+
+test_expect_success 'Verify usage of %(symref:lstrip) atom' '
+ ${git_for_each_ref} --format="%(symref:lstrip=2)" refs/heads/sym > actual &&
+ ${git_for_each_ref} --format="%(symref:lstrip=-2)" refs/heads/sym >> actual &&
+ test_cmp expected actual &&
+
+ ${git_for_each_ref} --format="%(symref:strip=2)" refs/heads/sym > actual &&
+ ${git_for_each_ref} --format="%(symref:strip=-2)" refs/heads/sym >> actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+refs
+refs/heads
+EOF
+
+test_expect_success 'Verify usage of %(symref:rstrip) atom' '
+ ${git_for_each_ref} --format="%(symref:rstrip=2)" refs/heads/sym > actual &&
+ ${git_for_each_ref} --format="%(symref:rstrip=-2)" refs/heads/sym >> actual &&
+ test_cmp expected actual
+'
+
+test_expect_success ':remotename and :remoteref' '
+ git init remote-tests &&
+ (
+ cd remote-tests &&
+ test_commit initial &&
+ git branch -M main &&
+ git remote add from fifth.coffee:blub &&
+ git config branch.main.remote from &&
+ git config branch.main.merge refs/heads/stable &&
+ git remote add to southridge.audio:repo &&
+ git config remote.to.push "refs/heads/*:refs/heads/pushed/*" &&
+ git config branch.main.pushRemote to &&
+ for pair in "%(upstream)=refs/remotes/from/stable" \
+ "%(upstream:remotename)=from" \
+ "%(upstream:remoteref)=refs/heads/stable" \
+ "%(push)=refs/remotes/to/pushed/main" \
+ "%(push:remotename)=to" \
+ "%(push:remoteref)=refs/heads/pushed/main"
+ do
+ echo "${pair#*=}" >expect &&
+ ${git_for_each_ref} --format="${pair%=*}" \
+ refs/heads/main >actual &&
+ test_cmp expect actual || exit 1
+ done &&
+ git branch push-simple &&
+ git config branch.push-simple.pushRemote from &&
+ actual="$(${git_for_each_ref} \
+ --format="%(push:remotename),%(push:remoteref)" \
+ refs/heads/push-simple)" &&
+ test from, = "$actual"
+ )
+'
+
+test_expect_success "${git_for_each_ref} --ignore-case ignores case" '
+ ${git_for_each_ref} --format="%(refname)" refs/heads/MAIN >actual &&
+ test_must_be_empty actual &&
+
+ echo refs/heads/main >expect &&
+ ${git_for_each_ref} --format="%(refname)" --ignore-case \
+ refs/heads/MAIN >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success "${git_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 "${git_for_each_ref} --ignore-case works on multiple sort keys" '
+ # name refs numerically to avoid case-insensitive filesystem conflicts
+ nr=0 &&
+ for email in a A b B
+ do
+ for subject in a A b B
+ do
+ GIT_COMMITTER_EMAIL="$email@example.com" \
+ git tag -m "tag $subject" icase-$(printf %02d $nr) &&
+ nr=$((nr+1))||
+ return 1
+ done
+ done &&
+ ${git_for_each_ref} --ignore-case \
+ --format="%(taggeremail) %(subject) %(refname)" \
+ --sort=refname \
+ --sort=subject \
+ --sort=taggeremail \
+ refs/tags/icase-* >actual &&
+ cat >expect <<-\EOF &&
+ <a@example.com> tag a refs/tags/icase-00
+ <a@example.com> tag A refs/tags/icase-01
+ <A@example.com> tag a refs/tags/icase-04
+ <A@example.com> tag A refs/tags/icase-05
+ <a@example.com> tag b refs/tags/icase-02
+ <a@example.com> tag B refs/tags/icase-03
+ <A@example.com> tag b refs/tags/icase-06
+ <A@example.com> tag B refs/tags/icase-07
+ <b@example.com> tag a refs/tags/icase-08
+ <b@example.com> tag A refs/tags/icase-09
+ <B@example.com> tag a refs/tags/icase-12
+ <B@example.com> tag A refs/tags/icase-13
+ <b@example.com> tag b refs/tags/icase-10
+ <b@example.com> tag B refs/tags/icase-11
+ <B@example.com> tag b refs/tags/icase-14
+ <B@example.com> tag B refs/tags/icase-15
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success "${git_for_each_ref} reports broken tags" '
+ git tag -m "good tag" broken-tag-good HEAD &&
+ git cat-file tag broken-tag-good >good &&
+ sed s/commit/blob/ <good >bad &&
+ bad=$(git hash-object -w -t tag bad) &&
+ git update-ref refs/tags/broken-tag-bad $bad &&
+ test_must_fail ${git_for_each_ref} --format="%(*objectname)" \
+ 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 'set up tag with signature and trailers' '
+ git tag -F - fake-sig-trailer <<-\EOF
+ this is the subject
+
+ this is the body
+
+ My-Trailer: foo
+ -----BEGIN PGP SIGNATURE-----
+
+ not a real signature, but we just care about the
+ subject/body/trailer parsing.
+ -----END PGP SIGNATURE-----
+ EOF
+'
+
+# use "separator=" here to suppress the terminating newline
+test_atom refs/tags/fake-sig-trailer trailers:separator= 'My-Trailer: foo'
+
+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
+'
+
+test_expect_success "${git_for_each_ref} with nested tags" '
+ git tag -am "Normal tag" nested/base HEAD &&
+ git tag -am "Nested tag" nested/nest1 refs/tags/nested/base &&
+ git tag -am "Double nested tag" nested/nest2 refs/tags/nested/nest1 &&
+
+ head_oid="$(git rev-parse HEAD)" &&
+ base_tag_oid="$(git rev-parse refs/tags/nested/base)" &&
+ nest1_tag_oid="$(git rev-parse refs/tags/nested/nest1)" &&
+ nest2_tag_oid="$(git rev-parse refs/tags/nested/nest2)" &&
+
+ cat >expect <<-EOF &&
+ refs/tags/nested/base $base_tag_oid tag $head_oid commit
+ refs/tags/nested/nest1 $nest1_tag_oid tag $head_oid commit
+ refs/tags/nested/nest2 $nest2_tag_oid tag $head_oid commit
+ EOF
+
+ ${git_for_each_ref} \
+ --format="%(refname) %(objectname) %(objecttype) %(*objectname) %(*objecttype)" \
+ refs/tags/nested/ >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'is-base atom with non-commits' '
+ ${git_for_each_ref} --format="%(is-base:HEAD) %(refname)" >out 2>err &&
+ grep "(HEAD) refs/heads/main" out &&
+
+ test_line_count = 2 err &&
+ grep "error: object .* is a commit, not a blob" err &&
+ grep "error: bad tag pointer to" err
+'
+
+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/helper/test-advise.c b/t/helper/test-advise.c
index 6967c8e25c..81ed93a05c 100644
--- a/t/helper/test-advise.c
+++ b/t/helper/test-advise.c
@@ -3,6 +3,7 @@
#include "test-tool.h"
#include "advice.h"
#include "config.h"
+#include "environment.h"
#include "setup.h"
int cmd__advise_if_enabled(int argc, const char **argv)
@@ -11,7 +12,7 @@ int cmd__advise_if_enabled(int argc, const char **argv)
die("usage: %s <advice>", argv[0]);
setup_git_directory();
- git_config(git_default_config, NULL);
+ repo_config(the_repository, git_default_config, NULL);
/*
* Any advice type can be used for testing, but NESTED_TAG was
diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c
index 3f23f21072..16a01669e4 100644
--- a/t/helper/test-bitmap.c
+++ b/t/helper/test-bitmap.c
@@ -10,6 +10,11 @@ static int bitmap_list_commits(void)
return test_bitmap_commits(the_repository);
}
+static int bitmap_list_commits_with_offset(void)
+{
+ return test_bitmap_commits_with_offset(the_repository);
+}
+
static int bitmap_dump_hashes(void)
{
return test_bitmap_hashes(the_repository);
@@ -36,6 +41,8 @@ int cmd__bitmap(int argc, const char **argv)
if (argc == 2 && !strcmp(argv[1], "list-commits"))
return bitmap_list_commits();
+ if (argc == 2 && !strcmp(argv[1], "list-commits-with-offset"))
+ return bitmap_list_commits_with_offset();
if (argc == 2 && !strcmp(argv[1], "dump-hashes"))
return bitmap_dump_hashes();
if (argc == 2 && !strcmp(argv[1], "dump-pseudo-merges"))
@@ -46,6 +53,7 @@ int cmd__bitmap(int argc, const char **argv)
return bitmap_dump_pseudo_merge_objects(atoi(argv[2]));
usage("\ttest-tool bitmap list-commits\n"
+ "\ttest-tool bitmap list-commits-with-offset\n"
"\ttest-tool bitmap dump-hashes\n"
"\ttest-tool bitmap dump-pseudo-merges\n"
"\ttest-tool bitmap dump-pseudo-merge-commits <n>\n"
diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c
index 9aa2c5a592..3283544bd3 100644
--- a/t/helper/test-bloom.c
+++ b/t/helper/test-bloom.c
@@ -12,13 +12,13 @@ static struct bloom_filter_settings settings = DEFAULT_BLOOM_FILTER_SETTINGS;
static void add_string_to_filter(const char *data, struct bloom_filter *filter) {
struct bloom_key key;
- fill_bloom_key(data, strlen(data), &key, &settings);
+ bloom_key_fill(&key, data, strlen(data), &settings);
printf("Hashes:");
for (size_t i = 0; i < settings.num_hashes; i++)
printf("0x%08x|", key.hashes[i]);
printf("\n");
add_key_to_filter(&key, filter, &settings);
- clear_bloom_key(&key);
+ bloom_key_clear(&key);
}
static void print_bloom_filter(struct bloom_filter *filter) {
@@ -61,13 +61,13 @@ int cmd__bloom(int argc, const char **argv)
uint32_t hashed;
if (argc < 3)
usage(bloom_usage);
- hashed = murmur3_seeded_v2(0, argv[2], strlen(argv[2]));
+ hashed = test_bloom_murmur3_seeded(0, argv[2], strlen(argv[2]), 2);
printf("Murmur3 Hash with seed=0:0x%08x\n", hashed);
}
if (!strcmp(argv[1], "get_murmur3_seven_highbit")) {
uint32_t hashed;
- hashed = murmur3_seeded_v2(0, "\x99\xaa\xbb\xcc\xdd\xee\xff", 7);
+ hashed = test_bloom_murmur3_seeded(0, "\x99\xaa\xbb\xcc\xdd\xee\xff", 7, 2);
printf("Murmur3 Hash with seed=0:0x%08x\n", hashed);
}
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 75e028ab2a..9f8cca7c48 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -32,10 +32,10 @@
* ascending order of priority from a config_set
* constructed from files entered as arguments.
*
- * iterate -> iterate over all values using git_config(), and print some
+ * iterate -> iterate over all values using repo_config(), and print some
* data for each
*
- * git_config_int -> iterate over all values using git_config() and print the
+ * git_config_int -> iterate over all values using repo_config() and print the
* integer value for the entered key or die
*
* Examples:
@@ -110,7 +110,7 @@ int cmd__config(int argc, const char **argv)
fprintf(stderr, "Please, provide a command name on the command-line\n");
goto exit1;
} else if (argc == 3 && !strcmp(argv[1], "get_value")) {
- if (!git_config_get_value(argv[2], &v)) {
+ if (!repo_config_get_value(the_repository, argv[2], &v)) {
if (!v)
printf("(NULL)\n");
else
@@ -121,7 +121,7 @@ int cmd__config(int argc, const char **argv)
goto exit1;
}
} else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
- if (!git_config_get_value_multi(argv[2], &strptr)) {
+ if (!repo_config_get_value_multi(the_repository, argv[2], &strptr)) {
for (i = 0; i < strptr->nr; i++) {
v = strptr->items[i].string;
if (!v)
@@ -137,7 +137,7 @@ int cmd__config(int argc, const char **argv)
} else if (argc == 3 && !strcmp(argv[1], "get")) {
int ret;
- if (!(ret = git_config_get(argv[2])))
+ if (!(ret = repo_config_get(the_repository, argv[2])))
goto exit0;
else if (ret == 1)
printf("Value not found for \"%s\"\n", argv[2]);
@@ -155,7 +155,7 @@ int cmd__config(int argc, const char **argv)
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)) {
+ if (!repo_config_get_int(the_repository, argv[2], &val)) {
printf("%d\n", val);
goto exit0;
} else {
@@ -163,7 +163,7 @@ int cmd__config(int argc, const char **argv)
goto exit1;
}
} else if (argc == 3 && !strcmp(argv[1], "get_bool")) {
- if (!git_config_get_bool(argv[2], &val)) {
+ if (!repo_config_get_bool(the_repository, argv[2], &val)) {
printf("%d\n", val);
goto exit0;
} else {
@@ -171,7 +171,7 @@ int cmd__config(int argc, const char **argv)
goto exit1;
}
} else if (argc == 3 && !strcmp(argv[1], "get_string")) {
- if (!git_config_get_string_tmp(argv[2], &v)) {
+ if (!repo_config_get_string_tmp(the_repository, argv[2], &v)) {
printf("%s\n", v);
goto exit0;
} else {
@@ -218,10 +218,10 @@ int cmd__config(int argc, const char **argv)
goto exit1;
}
} else if (!strcmp(argv[1], "iterate")) {
- git_config(iterate_cb, NULL);
+ repo_config(the_repository, iterate_cb, NULL);
goto exit0;
} else if (argc == 3 && !strcmp(argv[1], "git_config_int")) {
- git_config(parse_int_cb, (void *) argv[2]);
+ repo_config(the_repository, parse_int_cb, (void *) argv[2]);
goto exit0;
}
diff --git a/t/helper/test-delta.c b/t/helper/test-delta.c
index 6bc787a474..52ea00c937 100644
--- a/t/helper/test-delta.c
+++ b/t/helper/test-delta.c
@@ -11,6 +11,7 @@
#include "test-tool.h"
#include "git-compat-util.h"
#include "delta.h"
+#include "strbuf.h"
static const char usage_str[] =
"test-tool delta (-d|-p) <from_file> <data_file> <out_file>";
@@ -18,68 +19,38 @@ static const char usage_str[] =
int cmd__delta(int argc, const char **argv)
{
int fd;
- struct stat st;
- void *from_buf = NULL, *data_buf = NULL, *out_buf = NULL;
- unsigned long from_size, data_size, out_size;
- int ret = 1;
+ struct strbuf from = STRBUF_INIT, data = STRBUF_INIT;
+ char *out_buf;
+ unsigned long out_size;
- if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) {
- fprintf(stderr, "usage: %s\n", usage_str);
- return 1;
- }
+ if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p")))
+ usage(usage_str);
- fd = open(argv[2], O_RDONLY);
- if (fd < 0 || fstat(fd, &st)) {
- perror(argv[2]);
- return 1;
- }
- from_size = st.st_size;
- from_buf = xmalloc(from_size);
- if (read_in_full(fd, from_buf, from_size) < 0) {
- perror(argv[2]);
- close(fd);
- goto cleanup;
- }
- close(fd);
-
- fd = open(argv[3], O_RDONLY);
- if (fd < 0 || fstat(fd, &st)) {
- perror(argv[3]);
- goto cleanup;
- }
- data_size = st.st_size;
- data_buf = xmalloc(data_size);
- if (read_in_full(fd, data_buf, data_size) < 0) {
- perror(argv[3]);
- close(fd);
- goto cleanup;
- }
- close(fd);
+ if (strbuf_read_file(&from, argv[2], 0) < 0)
+ die_errno("unable to read '%s'", argv[2]);
+ if (strbuf_read_file(&data, argv[3], 0) < 0)
+ die_errno("unable to read '%s'", argv[3]);
if (argv[1][1] == 'd')
- out_buf = diff_delta(from_buf, from_size,
- data_buf, data_size,
+ out_buf = diff_delta(from.buf, from.len,
+ data.buf, data.len,
&out_size, 0);
else
- out_buf = patch_delta(from_buf, from_size,
- data_buf, data_size,
+ out_buf = patch_delta(from.buf, from.len,
+ data.buf, data.len,
&out_size);
- if (!out_buf) {
- fprintf(stderr, "delta operation failed (returned NULL)\n");
- goto cleanup;
- }
+ if (!out_buf)
+ die("delta operation failed (returned NULL)");
- fd = open (argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666);
- if (fd < 0 || write_in_full(fd, out_buf, out_size) < 0) {
- perror(argv[4]);
- goto cleanup;
- }
+ fd = xopen(argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ if (write_in_full(fd, out_buf, out_size) < 0)
+ die_errno("write(%s)", argv[4]);
+ if (close(fd) < 0)
+ die_errno("close(%s)", argv[4]);
- ret = 0;
-cleanup:
- free(from_buf);
- free(data_buf);
+ strbuf_release(&from);
+ strbuf_release(&data);
free(out_buf);
- return ret;
+ return 0;
}
diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c
index 76c2f4eba8..611a13a326 100644
--- a/t/helper/test-find-pack.c
+++ b/t/helper/test-find-pack.c
@@ -2,7 +2,7 @@
#include "test-tool.h"
#include "object-name.h"
-#include "object-store.h"
+#include "odb.h"
#include "packfile.h"
#include "parse-options.h"
#include "setup.h"
diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c
index 7782ae585e..56d223a283 100644
--- a/t/helper/test-hashmap.c
+++ b/t/helper/test-hashmap.c
@@ -137,6 +137,11 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
* Read stdin line by line and print result of commands to stdout:
*
* perfhashmap method rounds -> test hashmap.[ch] performance
+ *
+ * NOTE: this is not used by any of our mechanized build & test
+ * procedure, after 3469a236 (t: port helper/test-hashmap.c to
+ * unit-tests/t-hashmap.c, 2024-08-03). See the log message of that
+ * commit for the reason why this is still here.
*/
int cmd__hashmap(int argc UNUSED, const char **argv UNUSED)
{
@@ -149,8 +154,8 @@ int cmd__hashmap(int argc UNUSED, const char **argv UNUSED)
/* break line into command and up to two parameters */
string_list_setlen(&parts, 0);
- string_list_split_in_place(&parts, line.buf, DELIM, 2);
- string_list_remove_empty_items(&parts, 0);
+ string_list_split_in_place_f(&parts, line.buf, DELIM, 2,
+ STRING_LIST_SPLIT_NONEMPTY);
/* ignore empty lines */
if (!parts.nr)
diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c
index a288069b04..f8316a7d29 100644
--- a/t/helper/test-json-writer.c
+++ b/t/helper/test-json-writer.c
@@ -492,8 +492,8 @@ static int scripted(void)
/* 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);
+ string_list_split_in_place_f(&parts, line, " ", -1,
+ STRING_LIST_SPLIT_NONEMPTY);
/* ignore empty lines */
if (!parts.nr || !*parts.items[0].string)
diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c
index fdf1b13437..d51aaa3dc4 100644
--- a/t/helper/test-pack-mtimes.c
+++ b/t/helper/test-pack-mtimes.c
@@ -3,7 +3,7 @@
#include "test-tool.h"
#include "hex.h"
#include "strbuf.h"
-#include "object-store.h"
+#include "odb.h"
#include "packfile.h"
#include "pack-mtimes.h"
#include "setup.h"
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index f2663dd0c0..68579d83f3 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -131,6 +131,7 @@ int cmd__parse_options(int argc, const char **argv)
.short_name = 'B',
.long_name = "no-fear",
.value = &boolean,
+ .precision = sizeof(boolean),
.help = "be brave",
.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
.defval = 1,
@@ -148,9 +149,16 @@ int cmd__parse_options(int argc, const char **argv)
OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1),
OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2),
- OPT_CALLBACK_F(0, "mode34", &integer, "(3|4)",
- "set integer to 3 or 4 (cmdmode option)",
- PARSE_OPT_CMDMODE, mode34_callback),
+ {
+ .type = OPTION_CALLBACK,
+ .long_name = "mode34",
+ .value = &integer,
+ .precision = sizeof(integer),
+ .argh = "(3|4)",
+ .help = "set integer to 3 or 4 (cmdmode option)",
+ .flags = PARSE_OPT_CMDMODE,
+ .callback = mode34_callback,
+ },
OPT_CALLBACK('L', "length", &integer, "str",
"get length of <str>", length_callback),
OPT_FILENAME('F', "file", &file, "set file to <file>"),
@@ -170,6 +178,7 @@ int cmd__parse_options(int argc, const char **argv)
.type = OPTION_COUNTUP,
.short_name = '+',
.value = &boolean,
+ .precision = sizeof(boolean),
.help = "same as -b",
.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
},
@@ -177,6 +186,7 @@ int cmd__parse_options(int argc, const char **argv)
.type = OPTION_COUNTUP,
.long_name = "ambiguous",
.value = &ambiguous,
+ .precision = sizeof(ambiguous),
.help = "positive ambiguity",
.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
},
@@ -184,6 +194,7 @@ int cmd__parse_options(int argc, const char **argv)
.type = OPTION_COUNTUP,
.long_name = "no-ambiguous",
.value = &ambiguous,
+ .precision = sizeof(ambiguous),
.help = "negative ambiguity",
.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
},
diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c
index 34f1aee558..d848800749 100644
--- a/t/helper/test-partial-clone.c
+++ b/t/helper/test-partial-clone.c
@@ -1,7 +1,7 @@
#include "test-tool.h"
#include "hex.h"
#include "repository.h"
-#include "object-store.h"
+#include "odb.h"
#include "setup.h"
/*
@@ -23,7 +23,7 @@ static void object_info(const char *gitdir, const char *oid_hex)
die("could not init repo");
if (parse_oid_hex_algop(oid_hex, &oid, &p, r.hash_algo))
die("could not parse oid");
- if (oid_object_info_extended(&r, &oid, &oi, 0))
+ if (odb_read_object_info_extended(r.objects, &oid, &oi, 0))
die("could not obtain object info");
printf("%d\n", (int) size);
diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c
index 086238c826..f5f33751da 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -348,6 +348,7 @@ int cmd__path_utils(int argc, const char **argv)
if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
int len;
struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
+ const char path_sep[] = { PATH_SEP, '\0' };
char *path = xstrdup(argv[2]);
/*
@@ -362,7 +363,7 @@ int cmd__path_utils(int argc, const char **argv)
*/
if (normalize_path_copy(path, path))
die("Path \"%s\" could not be normalized", argv[2]);
- string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1);
+ string_list_split(&ceiling_dirs, argv[3], path_sep, -1);
filter_string_list(&ceiling_dirs, 0,
normalize_ceiling_entry, NULL);
len = longest_ancestor_length(path, &ceiling_dirs);
diff --git a/t/helper/test-path-walk.c b/t/helper/test-path-walk.c
index 61e845e5ec..fe63002c2b 100644
--- a/t/helper/test-path-walk.c
+++ b/t/helper/test-path-walk.c
@@ -82,6 +82,8 @@ int cmd__path_walk(int argc, const char **argv)
N_("toggle inclusion of tree objects")),
OPT_BOOL(0, "prune", &info.prune_all_uninteresting,
N_("toggle pruning of uninteresting paths")),
+ OPT_BOOL(0, "edge-aggressive", &info.edge_aggressive,
+ N_("toggle aggressive edge walk")),
OPT_BOOL(0, "stdin-pl", &stdin_pl,
N_("read a pattern list over stdin")),
OPT_END(),
diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index e277dde8e7..9ae71cefb3 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -2,6 +2,7 @@
#include "test-tool.h"
#include "config.h"
+#include "environment.h"
#include "read-cache-ll.h"
#include "repository.h"
#include "setup.h"
@@ -19,7 +20,7 @@ int cmd__read_cache(int argc, const char **argv)
if (argc == 2)
cnt = strtol(argv[1], NULL, 0);
setup_git_directory();
- git_config(git_default_config, NULL);
+ repo_config(the_repository, git_default_config, NULL);
for (i = 0; i < cnt; i++) {
repo_read_index(the_repository);
diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c
index 8b413b644b..6a5f64e473 100644
--- a/t/helper/test-read-graph.c
+++ b/t/helper/test-read-graph.c
@@ -3,7 +3,7 @@
#include "test-tool.h"
#include "commit-graph.h"
#include "repository.h"
-#include "object-store.h"
+#include "odb.h"
#include "bloom.h"
#include "setup.h"
@@ -73,15 +73,15 @@ static void dump_graph_bloom_filters(struct commit_graph *graph)
int cmd__read_graph(int argc, const char **argv)
{
struct commit_graph *graph = NULL;
- struct object_directory *odb;
+ struct odb_source *source;
int ret = 0;
setup_git_directory();
- odb = the_repository->objects->odb;
+ source = the_repository->objects->sources;
prepare_repo_settings(the_repository);
- graph = read_commit_graph_one(the_repository, odb);
+ graph = read_commit_graph_one(source);
if (!graph) {
ret = 1;
goto done;
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
index ac81390899..6de5d1665a 100644
--- a/t/helper/test-read-midx.c
+++ b/t/helper/test-read-midx.c
@@ -4,21 +4,31 @@
#include "hex.h"
#include "midx.h"
#include "repository.h"
-#include "object-store.h"
+#include "odb.h"
#include "pack-bitmap.h"
#include "packfile.h"
#include "setup.h"
#include "gettext.h"
#include "pack-revindex.h"
+static struct multi_pack_index *setup_midx(const char *object_dir)
+{
+ struct odb_source *source;
+ setup_git_directory();
+ source = odb_find_source(the_repository->objects, object_dir);
+ if (!source)
+ source = odb_add_to_alternates_memory(the_repository->objects,
+ object_dir);
+ return load_multi_pack_index(source);
+}
+
static int read_midx_file(const char *object_dir, const char *checksum,
int show_objects)
{
uint32_t i;
struct multi_pack_index *m;
- setup_git_directory();
- m = load_multi_pack_index(the_repository, object_dir, 1);
+ m = setup_midx(object_dir);
if (!m)
return 1;
@@ -56,7 +66,7 @@ static int read_midx_file(const char *object_dir, const char *checksum,
for (i = 0; i < m->num_packs; i++)
printf("%s\n", m->pack_names[i]);
- printf("object-dir: %s\n", m->object_dir);
+ printf("object-dir: %s\n", m->source->path);
if (show_objects) {
struct object_id oid;
@@ -65,7 +75,7 @@ static int read_midx_file(const char *object_dir, const char *checksum,
for (i = 0; i < m->num_objects; i++) {
nth_midxed_object_oid(&oid, m,
i + m->num_objects_in_base);
- fill_midx_entry(the_repository, &oid, &e, m);
+ fill_midx_entry(m, &oid, &e);
printf("%s %"PRIu64"\t%s\n",
oid_to_hex(&oid), e.offset, e.p->pack_name);
@@ -81,8 +91,7 @@ static int read_midx_checksum(const char *object_dir)
{
struct multi_pack_index *m;
- setup_git_directory();
- m = load_multi_pack_index(the_repository, object_dir, 1);
+ m = setup_midx(object_dir);
if (!m)
return 1;
printf("%s\n", hash_to_hex(get_midx_checksum(m)));
@@ -96,9 +105,7 @@ static int read_midx_preferred_pack(const char *object_dir)
struct multi_pack_index *midx = NULL;
uint32_t preferred_pack;
- setup_git_directory();
-
- midx = load_multi_pack_index(the_repository, object_dir, 1);
+ midx = setup_midx(object_dir);
if (!midx)
return 1;
@@ -119,14 +126,12 @@ static int read_midx_bitmapped_packs(const char *object_dir)
struct bitmapped_pack pack;
uint32_t i;
- setup_git_directory();
-
- midx = load_multi_pack_index(the_repository, object_dir, 1);
+ midx = setup_midx(object_dir);
if (!midx)
return 1;
for (i = 0; i < midx->num_packs + midx->num_packs_in_base; i++) {
- if (nth_bitmapped_pack(the_repository, midx, &pack, i) < 0) {
+ if (nth_bitmapped_pack(midx, &pack, i) < 0) {
close_midx(midx);
return 1;
}
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 4cfc7c90b5..83b06d39a3 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -5,7 +5,7 @@
#include "refs.h"
#include "setup.h"
#include "worktree.h"
-#include "object-store.h"
+#include "odb.h"
#include "path.h"
#include "repository.h"
#include "strbuf.h"
@@ -29,7 +29,7 @@ static unsigned int parse_flags(const char *str, struct flag_definition *defs)
if (!strcmp(str, "0"))
return 0;
- string_list_split(&masks, str, ',', 64);
+ string_list_split(&masks, str, ",", 64);
for (size_t i = 0; i < masks.nr; i++) {
const char *name = masks.items[i].string;
struct flag_definition *def = defs;
@@ -79,7 +79,7 @@ static const char **get_store(const char **argv, struct ref_store **refs)
if (!repo_submodule_path_append(the_repository,
&sb, gitdir, "objects/"))
die("computing submodule path failed");
- add_to_alternates_memory(sb.buf);
+ odb_add_to_alternates_memory(the_repository->objects, sb.buf);
strbuf_release(&sb);
*refs = repo_get_submodule_ref_store(the_repository, gitdir);
@@ -215,7 +215,8 @@ static int cmd_for_each_reflog(struct ref_store *refs,
return refs_for_each_reflog(refs, each_reflog, NULL);
}
-static int each_reflog_ent(struct object_id *old_oid, struct object_id *new_oid,
+static int each_reflog_ent(const char *refname UNUSED,
+ struct object_id *old_oid, struct object_id *new_oid,
const char *committer, timestamp_t timestamp,
int tz, const char *msg, void *cb_data UNUSED)
{
diff --git a/t/helper/test-string-list.c b/t/helper/test-string-list.c
index 6f10c5a435..6be0cdb8e2 100644
--- a/t/helper/test-string-list.c
+++ b/t/helper/test-string-list.c
@@ -1,105 +1,9 @@
-#define DISABLE_SIGN_COMPARE_WARNINGS
-
#include "test-tool.h"
#include "strbuf.h"
#include "string-list.h"
-/*
- * Parse an argument into a string list. arg should either be a
- * ':'-separated list of strings, or "-" to indicate an empty string
- * list (as opposed to "", which indicates a string list containing a
- * single empty string). list->strdup_strings must be set.
- */
-static void parse_string_list(struct string_list *list, const char *arg)
-{
- if (!strcmp(arg, "-"))
- return;
-
- (void)string_list_split(list, arg, ':', -1);
-}
-
-static void write_list(const struct string_list *list)
-{
- int i;
- for (i = 0; i < list->nr; i++)
- printf("[%d]: \"%s\"\n", i, list->items[i].string);
-}
-
-static void write_list_compact(const struct string_list *list)
-{
- int i;
- if (!list->nr)
- printf("-\n");
- else {
- printf("%s", list->items[0].string);
- for (i = 1; i < list->nr; i++)
- printf(":%s", list->items[i].string);
- printf("\n");
- }
-}
-
-static int prefix_cb(struct string_list_item *item, void *cb_data)
-{
- const char *prefix = (const char *)cb_data;
- return starts_with(item->string, prefix);
-}
-
int cmd__string_list(int argc, const char **argv)
{
- if (argc == 5 && !strcmp(argv[1], "split")) {
- struct string_list list = STRING_LIST_INIT_DUP;
- int i;
- const char *s = argv[2];
- int delim = *argv[3];
- int maxsplit = atoi(argv[4]);
-
- i = string_list_split(&list, s, delim, maxsplit);
- printf("%d\n", i);
- write_list(&list);
- string_list_clear(&list, 0);
- return 0;
- }
-
- if (argc == 5 && !strcmp(argv[1], "split_in_place")) {
- struct string_list list = STRING_LIST_INIT_NODUP;
- int i;
- char *s = xstrdup(argv[2]);
- const char *delim = argv[3];
- int maxsplit = atoi(argv[4]);
-
- i = string_list_split_in_place(&list, s, delim, maxsplit);
- printf("%d\n", i);
- write_list(&list);
- string_list_clear(&list, 0);
- free(s);
- return 0;
- }
-
- if (argc == 4 && !strcmp(argv[1], "filter")) {
- /*
- * Retain only the items that have the specified prefix.
- * Arguments: list|- prefix
- */
- struct string_list list = STRING_LIST_INIT_DUP;
- const char *prefix = argv[3];
-
- parse_string_list(&list, argv[2]);
- filter_string_list(&list, 0, prefix_cb, (void *)prefix);
- write_list_compact(&list);
- string_list_clear(&list, 0);
- return 0;
- }
-
- if (argc == 3 && !strcmp(argv[1], "remove_duplicates")) {
- struct string_list list = STRING_LIST_INIT_DUP;
-
- parse_string_list(&list, argv[2]);
- string_list_remove_duplicates(&list, 0);
- write_list_compact(&list);
- string_list_clear(&list, 0);
- return 0;
- }
-
if (argc == 2 && !strcmp(argv[1], "sort")) {
struct string_list list = STRING_LIST_INIT_NODUP;
struct strbuf sb = STRBUF_INIT;
diff --git a/t/helper/test-truncate.c b/t/helper/test-truncate.c
index 3931deaec7..2820cc7ed7 100644
--- a/t/helper/test-truncate.c
+++ b/t/helper/test-truncate.c
@@ -21,5 +21,8 @@ int cmd__truncate(int argc, const char **argv)
if (ftruncate(fd, (off_t) sz) < 0)
die_errno("failed to truncate file");
+
+ close(fd);
+
return 0;
}
diff --git a/t/helper/test-userdiff.c b/t/helper/test-userdiff.c
index 94c48ababb..aa3a9894d2 100644
--- a/t/helper/test-userdiff.c
+++ b/t/helper/test-userdiff.c
@@ -41,7 +41,7 @@ int cmd__userdiff(int argc, const char **argv)
if (want & USERDIFF_DRIVER_TYPE_CUSTOM) {
setup_git_directory();
- git_config(cmd__userdiff_config, NULL);
+ repo_config(the_repository, cmd__userdiff_config, NULL);
}
for_each_userdiff_driver(driver_cb, &want);
diff --git a/t/meson.build b/t/meson.build
index d052fc3e23..7974795fe4 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -1,5 +1,6 @@
clar_test_suites = [
'unit-tests/u-ctype.c',
+ 'unit-tests/u-dir.c',
'unit-tests/u-example-decorate.c',
'unit-tests/u-hash.c',
'unit-tests/u-hashmap.c',
@@ -8,9 +9,18 @@ clar_test_suites = [
'unit-tests/u-oidmap.c',
'unit-tests/u-oidtree.c',
'unit-tests/u-prio-queue.c',
+ 'unit-tests/u-reftable-basics.c',
+ 'unit-tests/u-reftable-block.c',
+ 'unit-tests/u-reftable-merged.c',
+ 'unit-tests/u-reftable-pq.c',
+ 'unit-tests/u-reftable-readwrite.c',
+ 'unit-tests/u-reftable-record.c',
+ 'unit-tests/u-reftable-stack.c',
+ 'unit-tests/u-reftable-table.c',
'unit-tests/u-reftable-tree.c',
'unit-tests/u-strbuf.c',
'unit-tests/u-strcmp-offset.c',
+ 'unit-tests/u-string-list.c',
'unit-tests/u-strvec.c',
'unit-tests/u-trailer.c',
'unit-tests/u-urlmatch-normalization.c',
@@ -19,7 +29,8 @@ clar_test_suites = [
clar_sources = [
'unit-tests/clar/clar.c',
'unit-tests/unit-test.c',
- 'unit-tests/lib-oid.c'
+ 'unit-tests/lib-oid.c',
+ 'unit-tests/lib-reftable.c'
]
clar_decls_h = custom_target(
@@ -49,36 +60,12 @@ clar_sources += custom_target(
clar_unit_tests = executable('unit-tests',
sources: clar_sources + clar_test_suites,
+ c_args: [
+ '-DGIT_CLAR_DECLS_H="' + clar_decls_h.full_path() + '"',
+ ],
dependencies: [libgit_commonmain],
)
-test('unit-tests', clar_unit_tests)
-
-unit_test_programs = [
- 'unit-tests/t-reftable-basics.c',
- 'unit-tests/t-reftable-block.c',
- 'unit-tests/t-reftable-merged.c',
- 'unit-tests/t-reftable-pq.c',
- 'unit-tests/t-reftable-readwrite.c',
- 'unit-tests/t-reftable-record.c',
- 'unit-tests/t-reftable-stack.c',
- 'unit-tests/t-reftable-table.c',
-]
-
-foreach unit_test_program : unit_test_programs
- unit_test_name = fs.stem(unit_test_program)
- unit_test = executable(unit_test_name,
- sources: [
- 'unit-tests/test-lib.c',
- 'unit-tests/lib-reftable.c',
- unit_test_program,
- ],
- dependencies: [libgit_commonmain],
- )
- test(unit_test_name, unit_test,
- workdir: meson.current_source_dir(),
- timeout: 0,
- )
-endforeach
+test('unit-tests', clar_unit_tests, kwargs: test_kwargs)
subdir('helper')
@@ -123,7 +110,6 @@ integration_tests = [
't0060-path-utils.sh',
't0061-run-command.sh',
't0062-revision-walking.sh',
- 't0063-string-list.sh',
't0066-dir-iterator.sh',
't0067-parse_pathspec_file.sh',
't0068-for-each-repo.sh',
@@ -178,7 +164,6 @@ integration_tests = [
't1015-read-index-unmerged.sh',
't1016-compatObjectFormat.sh',
't1020-subdirectory.sh',
- 't1021-rerere-in-workdir.sh',
't1022-read-tree-partial-clone.sh',
't1050-large.sh',
't1051-large-conversion.sh',
@@ -220,10 +205,14 @@ integration_tests = [
't1418-reflog-exists.sh',
't1419-exclude-refs.sh',
't1420-lost-found.sh',
+ 't1421-reflog-write.sh',
+ 't1422-show-ref-exists.sh',
't1430-bad-ref-name.sh',
't1450-fsck.sh',
't1451-fsck-buffer.sh',
't1460-refs-migrate.sh',
+ 't1461-refs-list.sh',
+ 't1462-refs-exists.sh',
't1500-rev-parse.sh',
't1501-work-tree.sh',
't1502-rev-parse-parseopt.sh',
@@ -246,6 +235,7 @@ integration_tests = [
't1700-split-index.sh',
't1701-racy-split-index.sh',
't1800-hook.sh',
+ 't1900-repo.sh',
't2000-conflict-when-checking-files-out.sh',
't2002-checkout-cache-u.sh',
't2003-checkout-cache-mkdir.sh',
@@ -502,6 +492,7 @@ integration_tests = [
't4069-remerge-diff.sh',
't4070-diff-pairs.sh',
't4071-diff-minimal.sh',
+ 't4072-diff-max-depth.sh',
't4100-apply-stat.sh',
't4101-apply-nonl.sh',
't4102-apply-rename.sh',
@@ -962,6 +953,7 @@ integration_tests = [
't8012-blame-colors.sh',
't8013-blame-ignore-revs.sh',
't8014-blame-ignore-fuzzy.sh',
+ 't8020-last-modified.sh',
't9001-send-email.sh',
't9002-column.sh',
't9003-help-autocorrect.sh',
@@ -1117,6 +1109,7 @@ benchmarks = [
'perf/p1450-fsck.sh',
'perf/p1451-fsck-skip-list.sh',
'perf/p1500-graph-walks.sh',
+ 'perf/p1501-rev-parse-oneline.sh',
'perf/p2000-sparse-operations.sh',
'perf/p3400-rebase.sh',
'perf/p3404-rebase-interactive.sh',
@@ -1154,6 +1147,7 @@ benchmarks = [
'perf/p7820-grep-engines.sh',
'perf/p7821-grep-engines-fixed.sh',
'perf/p7822-grep-perl-character.sh',
+ 'perf/p8020-last-modified.sh',
'perf/p9210-scalar.sh',
'perf/p9300-fast-import-export.sh',
]
@@ -1163,8 +1157,6 @@ benchmarks = [
# sufficient to catch missing test suites in our CI though.
foreach glob, tests : {
't[0-9][0-9][0-9][0-9]-*.sh': integration_tests,
- 'perf/p[0-9][0-9][0-9][0-9]-*.sh': benchmarks,
- 'unit-tests/t-*.c': unit_test_programs,
'unit-tests/u-*.c': clar_test_suites,
}
actual_tests = run_command(shell, '-c', 'ls ' + glob,
@@ -1212,7 +1204,7 @@ foreach integration_test : integration_tests
workdir: meson.current_source_dir(),
env: test_environment,
depends: test_dependencies + bin_wrappers,
- timeout: 0,
+ kwargs: test_kwargs,
)
endforeach
diff --git a/t/perf/p1501-rev-parse-oneline.sh b/t/perf/p1501-rev-parse-oneline.sh
new file mode 100755
index 0000000000..538fa9c404
--- /dev/null
+++ b/t/perf/p1501-rev-parse-oneline.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+test_description='Test :/ object name notation'
+
+. ./perf-lib.sh
+
+test_perf_fresh_repo
+
+#
+# Creates lots of merges to make history traversal costly. In
+# particular it creates 2^($max_level-1)-1 2-way merges on top of
+# 2^($max_level-1) root commits. E.g., the commit history looks like
+# this for a $max_level of 3:
+#
+# _1_
+# / \
+# 2 3
+# / \ / \
+# 4 5 6 7
+#
+# The numbers are the fast-import marks, which also are the commit
+# messages. 1 is the HEAD commit and a merge, 2 and 3 are also merges,
+# 4-7 are the root commits.
+#
+build_history () {
+ local max_level="$1" &&
+ local level="${2:-1}" &&
+ local mark="${3:-1}" &&
+ if test $level -eq $max_level
+ then
+ echo "reset refs/heads/master" &&
+ echo "from $ZERO_OID" &&
+ echo "commit refs/heads/master" &&
+ echo "mark :$mark" &&
+ echo "committer C <c@example.com> 1234567890 +0000" &&
+ echo "data <<EOF" &&
+ echo "$mark" &&
+ echo "EOF"
+ else
+ local level1=$((level+1)) &&
+ local mark1=$((2*mark)) &&
+ local mark2=$((2*mark+1)) &&
+ build_history $max_level $level1 $mark1 &&
+ build_history $max_level $level1 $mark2 &&
+ echo "commit refs/heads/master" &&
+ echo "mark :$mark" &&
+ echo "committer C <c@example.com> 1234567890 +0000" &&
+ echo "data <<EOF" &&
+ echo "$mark" &&
+ echo "EOF" &&
+ echo "from :$mark1" &&
+ echo "merge :$mark2"
+ fi
+}
+
+test_expect_success 'setup' '
+ build_history 16 | git fast-import &&
+ git log --format="%H %s" --reverse >commits &&
+ sed -n -e "s/ .*$//p" -e "q" <commits >expect &&
+ sed -n -e "s/^.* //p" -e "q" <commits >needle
+'
+
+test_perf "rev-parse :/$(cat needle)" '
+ git rev-parse :/$(cat needle) >actual
+'
+
+test_expect_success 'verify result' '
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/perf/p5313-pack-objects.sh b/t/perf/p5313-pack-objects.sh
index 786a2c1c6f..46a6cd32d2 100755
--- a/t/perf/p5313-pack-objects.sh
+++ b/t/perf/p5313-pack-objects.sh
@@ -22,46 +22,53 @@ test_expect_success 'create rev input' '
EOF
'
-for version in 1 2
-do
- export version
+test_all_with_args () {
+ parameter=$1
+ export parameter
- test_perf "thin pack with version $version" '
+ test_perf "thin pack with $parameter" '
git pack-objects --thin --stdout --revs --sparse \
- --name-hash-version=$version <in-thin >out
+ $parameter <in-thin >out
'
- test_size "thin pack size with version $version" '
+ test_size "thin pack size with $parameter" '
test_file_size out
'
- test_perf "big pack with version $version" '
+ test_perf "big pack with $parameter" '
git pack-objects --stdout --revs --sparse \
- --name-hash-version=$version <in-big >out
+ $parameter <in-big >out
'
- test_size "big pack size with version $version" '
+ test_size "big pack size with $parameter" '
test_file_size out
'
- test_perf "shallow fetch pack with version $version" '
+ test_perf "shallow fetch pack with $parameter" '
git pack-objects --stdout --revs --sparse --shallow \
- --name-hash-version=$version <in-shallow >out
+ $parameter <in-shallow >out
'
- test_size "shallow pack size with version $version" '
+ test_size "shallow pack size with $parameter" '
test_file_size out
'
- test_perf "repack with version $version" '
- git repack -adf --name-hash-version=$version
+ test_perf "repack with $parameter" '
+ git repack -adf $parameter
'
- test_size "repack size with version $version" '
+ test_size "repack size with $parameter" '
gitdir=$(git rev-parse --git-dir) &&
pack=$(ls $gitdir/objects/pack/pack-*.pack) &&
test_file_size "$pack"
'
+}
+
+for version in 1 2
+do
+ test_all_with_args --name-hash-version=$version
done
+test_all_with_args --path-walk
+
test_done
diff --git a/t/perf/p8020-last-modified.sh b/t/perf/p8020-last-modified.sh
new file mode 100755
index 0000000000..cb1f98d3db
--- /dev/null
+++ b/t/perf/p8020-last-modified.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description='last-modified perf tests'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_perf 'top-level last-modified' '
+ git last-modified HEAD
+'
+
+test_perf 'top-level recursive last-modified' '
+ git last-modified -r HEAD
+'
+
+test_perf 'subdir last-modified' '
+ git ls-tree -d HEAD >subtrees &&
+ path="$(head -n 1 subtrees | cut -f2)" &&
+ git last-modified -r HEAD -- "$path"
+'
+
+test_done
diff --git a/t/show-ref-exists-tests.sh b/t/show-ref-exists-tests.sh
new file mode 100644
index 0000000000..36e8e9df33
--- /dev/null
+++ b/t/show-ref-exists-tests.sh
@@ -0,0 +1,77 @@
+git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
+
+test_expect_success setup '
+ test_commit --annotate A &&
+ git checkout -b side &&
+ test_commit --annotate B &&
+ git checkout main &&
+ test_commit C &&
+ git branch B A^0
+'
+
+test_expect_success '--exists with existing reference' '
+ ${git_show_ref_exists} refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+ test_expect_code 2 ${git_show_ref_exists} refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+ test_expect_code 2 ${git_show_ref_exists} $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+ grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+ ${git_show_ref_exists} HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+ test_when_finished "git update-ref -d refs/heads/bad...name" &&
+ new_oid=$(git rev-parse HEAD) &&
+ test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+ test_when_finished "git symbolic-ref -d refs/symref" &&
+ git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+ ${git_show_ref_exists} refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+ test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+ git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+ ${git_show_ref_exists} refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+ test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+ tree_oid=$(git rev-parse HEAD^{tree}) &&
+ test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+ ${git_show_ref_exists} refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+ cat >expect <<-EOF &&
+ error: reference does not exist
+ EOF
+ test_expect_code 2 ${git_show_ref_exists} refs/heads 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+ test_expect_code 2 ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+ test_when_finished "rm .git/FETCH_HEAD" &&
+ git rev-parse HEAD >.git/FETCH_HEAD &&
+ ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_done
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 35c5c2b4f9..2b63e1c86c 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -130,7 +130,7 @@ test_expect_success 'subtest: a failing TODO test' '
'
test_expect_success 'subtest: a passing TODO test' '
- write_and_run_sub_test_lib_test passing-todo <<-\EOF &&
+ write_and_run_sub_test_lib_test_err passing-todo <<-\EOF &&
test_expect_failure "pretend we have fixed a known breakage" "true"
test_done
EOF
@@ -142,7 +142,7 @@ test_expect_success 'subtest: a passing TODO test' '
'
test_expect_success 'subtest: 2 TODO tests, one passin' '
- write_and_run_sub_test_lib_test partially-passing-todos <<-\EOF &&
+ write_and_run_sub_test_lib_test_err partially-passing-todos <<-\EOF &&
test_expect_failure "pretend we have a known breakage" "false"
test_expect_success "pretend we have a passing test" "true"
test_expect_failure "pretend we have fixed another known breakage" "true"
@@ -219,41 +219,44 @@ test_expect_success 'subtest: --verbose option' '
test_expect_success "failing test" false
test_done
EOF
- mv t1234-verbose/out t1234-verbose/out+ &&
- grep -v "^Initialized empty" t1234-verbose/out+ >t1234-verbose/out &&
- check_sub_test_lib_test t1234-verbose <<-\EOF
- > expecting success of 1234.1 '\''passing test'\'': true
+ mv t1234-verbose/err t1234-verbose/err+ &&
+ grep -v "^Initialized empty" t1234-verbose/err+ >t1234-verbose/err &&
+ check_sub_test_lib_test_err t1234-verbose \
+ <<-\EOF_OUT 3<<-\EOF_ERR
> ok 1 - passing test
+ > ok 2 - test with output
+ > not ok 3 - failing test
+ > # false
+ > # failed 1 among 3 test(s)
+ > 1..3
+ EOF_OUT
+ > expecting success of 1234.1 '\''passing test'\'': true
> Z
> expecting success of 1234.2 '\''test with output'\'': echo foo
> foo
- > ok 2 - test with output
> Z
> expecting success of 1234.3 '\''failing test'\'': false
- > not ok 3 - failing test
- > # false
> Z
- > # failed 1 among 3 test(s)
- > 1..3
- EOF
+ EOF_ERR
'
test_expect_success 'subtest: --verbose-only option' '
run_sub_test_lib_test_err \
t1234-verbose \
--verbose-only=2 &&
- check_sub_test_lib_test t1234-verbose <<-\EOF
+ check_sub_test_lib_test_err t1234-verbose <<-\EOF_OUT 3<<-\EOF_ERR
> ok 1 - passing test
- > Z
- > expecting success of 1234.2 '\''test with output'\'': echo foo
- > foo
> ok 2 - test with output
- > Z
> not ok 3 - failing test
> # false
> # failed 1 among 3 test(s)
> 1..3
- EOF
+ EOF_OUT
+ > Z
+ > expecting success of 1234.2 '\''test with output'\'': echo foo
+ > foo
+ > Z
+ EOF_ERR
'
test_expect_success 'subtest: skip one with GIT_SKIP_TESTS' '
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index f11a40811f..f593c53687 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -658,6 +658,17 @@ test_expect_success 'init warns about invalid init.defaultRefFormat' '
test_cmp expected actual
'
+test_expect_success 'default ref format' '
+ test_when_finished "rm -rf refformat" &&
+ (
+ sane_unset GIT_DEFAULT_REF_FORMAT &&
+ git init refformat
+ ) &&
+ git version --build-options | sed -ne "s/^default-ref-format: //p" >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
backends="files reftable"
for format in $backends
do
@@ -738,6 +749,40 @@ test_expect_success "GIT_DEFAULT_REF_FORMAT= overrides init.defaultRefFormat" '
test_cmp expect actual
'
+test_expect_success "init with feature.experimental=true" '
+ test_when_finished "rm -rf refformat" &&
+ test_config_global feature.experimental true &&
+ (
+ sane_unset GIT_DEFAULT_REF_FORMAT &&
+ git init refformat
+ ) &&
+ echo reftable >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success "init.defaultRefFormat overrides feature.experimental=true" '
+ test_when_finished "rm -rf refformat" &&
+ test_config_global feature.experimental true &&
+ test_config_global init.defaultRefFormat files &&
+ (
+ sane_unset GIT_DEFAULT_REF_FORMAT &&
+ git init refformat
+ ) &&
+ echo files >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success "GIT_DEFAULT_REF_FORMAT= overrides feature.experimental=true" '
+ test_when_finished "rm -rf refformat" &&
+ test_config_global feature.experimental true &&
+ GIT_DEFAULT_REF_FORMAT=files git init refformat &&
+ echo files >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
for from_format in $backends
do
test_expect_success "re-init with same format ($from_format)" '
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index bf10d253ec..f0d50d769e 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -281,7 +281,7 @@ test_expect_success 'required filter with absent smudge field' '
test_expect_success 'filtering large input to small output should use little memory' '
test_config filter.devnull.clean "cat >/dev/null" &&
test_config filter.devnull.required true &&
- for i in $(test_seq 1 30); do printf "%1048576d" 1 || return 1; done >30MB &&
+ test_seq -f "%1048576d" 1 30 >30MB &&
echo "30MB filter=devnull" >.gitattributes &&
GIT_MMAP_LIMIT=1m GIT_ALLOC_LIMIT=1m git add 30MB
'
@@ -299,7 +299,7 @@ test_expect_success 'filter that does not read is fine' '
test_expect_success EXPENSIVE 'filter large file' '
test_config filter.largefile.smudge cat &&
test_config filter.largefile.clean cat &&
- for i in $(test_seq 1 2048); do printf "%1048576d" 1 || return 1; done >2GB &&
+ test_seq -f "%1048576d" 1 2048 >2GB &&
echo "2GB filter=largefile" >.gitattributes &&
git add 2GB 2>err &&
test_must_be_empty err &&
diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh
index 5c9dc90d0b..ca8568067d 100755
--- a/t/t0050-filesystem.sh
+++ b/t/t0050-filesystem.sh
@@ -10,53 +10,35 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
auml=$(printf '\303\244')
aumlcdiar=$(printf '\141\314\210')
-if test_have_prereq CASE_INSENSITIVE_FS
-then
- say "will test on a case insensitive filesystem"
- test_case=test_expect_failure
-else
- test_case=test_expect_success
-fi
-
if test_have_prereq UTF8_NFD_TO_NFC
then
- say "will test on a unicode corrupting filesystem"
test_unicode=test_expect_failure
else
test_unicode=test_expect_success
fi
-test_have_prereq SYMLINKS ||
- say "will test on a filesystem lacking symbolic links"
-
-if test_have_prereq CASE_INSENSITIVE_FS
-then
-test_expect_success "detection of case insensitive filesystem during repo init" '
+test_expect_success CASE_INSENSITIVE_FS "detection of case insensitive filesystem during repo init" '
test $(git config --bool core.ignorecase) = true
'
-else
-test_expect_success "detection of case insensitive filesystem during repo init" '
+
+test_expect_success !CASE_INSENSITIVE_FS "detection of case insensitive filesystem during repo init" '
{
test_must_fail git config --bool core.ignorecase >/dev/null ||
test $(git config --bool core.ignorecase) = false
}
'
-fi
-if test_have_prereq SYMLINKS
-then
-test_expect_success "detection of filesystem w/o symlink support during repo init" '
+test_expect_success SYMLINKS "detection of filesystem w/o symlink support during repo init" '
{
test_must_fail git config --bool core.symlinks ||
test "$(git config --bool core.symlinks)" = true
}
'
-else
-test_expect_success "detection of filesystem w/o symlink support during repo init" '
+
+test_expect_success !SYMLINKS "detection of filesystem w/o symlink support during repo init" '
v=$(git config --bool core.symlinks) &&
test "$v" = false
'
-fi
test_expect_success "setup case tests" '
git config core.ignorecase true &&
diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh
deleted file mode 100755
index aac63ba506..0000000000
--- a/t/t0063-string-list.sh
+++ /dev/null
@@ -1,142 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2012 Michael Haggerty
-#
-
-test_description='Test string list functionality'
-
-. ./test-lib.sh
-
-test_split () {
- cat >expected &&
- test_expect_success "split $1 at $2, max $3" "
- test-tool string-list split '$1' '$2' '$3' >actual &&
- test_cmp expected actual &&
- test-tool string-list split_in_place '$1' '$2' '$3' >actual &&
- test_cmp expected actual
- "
-}
-
-test_split_in_place() {
- cat >expected &&
- test_expect_success "split (in place) $1 at $2, max $3" "
- test-tool string-list split_in_place '$1' '$2' '$3' >actual &&
- test_cmp expected actual
- "
-}
-
-test_split "foo:bar:baz" ":" "-1" <<EOF
-3
-[0]: "foo"
-[1]: "bar"
-[2]: "baz"
-EOF
-
-test_split "foo:bar:baz" ":" "0" <<EOF
-1
-[0]: "foo:bar:baz"
-EOF
-
-test_split "foo:bar:baz" ":" "1" <<EOF
-2
-[0]: "foo"
-[1]: "bar:baz"
-EOF
-
-test_split "foo:bar:baz" ":" "2" <<EOF
-3
-[0]: "foo"
-[1]: "bar"
-[2]: "baz"
-EOF
-
-test_split "foo:bar:" ":" "-1" <<EOF
-3
-[0]: "foo"
-[1]: "bar"
-[2]: ""
-EOF
-
-test_split "" ":" "-1" <<EOF
-1
-[0]: ""
-EOF
-
-test_split ":" ":" "-1" <<EOF
-2
-[0]: ""
-[1]: ""
-EOF
-
-test_split_in_place "foo:;:bar:;:baz:;:" ":;" "-1" <<EOF
-10
-[0]: "foo"
-[1]: ""
-[2]: ""
-[3]: "bar"
-[4]: ""
-[5]: ""
-[6]: "baz"
-[7]: ""
-[8]: ""
-[9]: ""
-EOF
-
-test_split_in_place "foo:;:bar:;:baz" ":;" "0" <<EOF
-1
-[0]: "foo:;:bar:;:baz"
-EOF
-
-test_split_in_place "foo:;:bar:;:baz" ":;" "1" <<EOF
-2
-[0]: "foo"
-[1]: ";:bar:;:baz"
-EOF
-
-test_split_in_place "foo:;:bar:;:baz" ":;" "2" <<EOF
-3
-[0]: "foo"
-[1]: ""
-[2]: ":bar:;:baz"
-EOF
-
-test_split_in_place "foo:;:bar:;:" ":;" "-1" <<EOF
-7
-[0]: "foo"
-[1]: ""
-[2]: ""
-[3]: "bar"
-[4]: ""
-[5]: ""
-[6]: ""
-EOF
-
-test_expect_success "test filter_string_list" '
- test "x-" = "x$(test-tool string-list filter - y)" &&
- test "x-" = "x$(test-tool string-list filter no y)" &&
- test yes = "$(test-tool string-list filter yes y)" &&
- test yes = "$(test-tool string-list filter no:yes y)" &&
- test yes = "$(test-tool string-list filter yes:no y)" &&
- test y1:y2 = "$(test-tool string-list filter y1:y2 y)" &&
- test y2:y1 = "$(test-tool string-list filter y2:y1 y)" &&
- test "x-" = "x$(test-tool string-list filter x1:x2 y)"
-'
-
-test_expect_success "test remove_duplicates" '
- test "x-" = "x$(test-tool string-list remove_duplicates -)" &&
- test "x" = "x$(test-tool string-list remove_duplicates "")" &&
- test a = "$(test-tool string-list remove_duplicates a)" &&
- test a = "$(test-tool string-list remove_duplicates a:a)" &&
- test a = "$(test-tool string-list remove_duplicates a:a:a:a:a)" &&
- test a:b = "$(test-tool string-list remove_duplicates a:b)" &&
- test a:b = "$(test-tool string-list remove_duplicates a:a:b)" &&
- test a:b = "$(test-tool string-list remove_duplicates a:b:b)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:b:c)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:a:b:c)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:b:b:c)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:b:c:c)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:a:b:b:c:c)" &&
- test a:b:c = "$(test-tool string-list remove_duplicates a:a:a:b:b:b:c:c:c)"
-'
-
-test_done
diff --git a/t/t0411-clone-from-partial.sh b/t/t0411-clone-from-partial.sh
index 196fc61784..9e6bca5625 100755
--- a/t/t0411-clone-from-partial.sh
+++ b/t/t0411-clone-from-partial.sh
@@ -59,6 +59,12 @@ test_expect_success 'pack-objects should fetch from promisor remote and execute
test_expect_success 'clone from promisor remote does not lazy-fetch by default' '
rm -f script-executed &&
+
+ # The --path-walk feature of "git pack-objects" is not
+ # compatible with this kind of fetch from an incomplete repo.
+ GIT_TEST_PACK_PATH_WALK=0 &&
+ export GIT_TEST_PACK_PATH_WALK &&
+
test_must_fail git clone evil no-lazy 2>err &&
test_grep "lazy fetching disabled" err &&
test_path_is_missing script-executed
diff --git a/t/t0450-txt-doc-vs-help.sh b/t/t0450-txt-doc-vs-help.sh
index 2f7504ae7e..e12e18f97f 100755
--- a/t/t0450-txt-doc-vs-help.sh
+++ b/t/t0450-txt-doc-vs-help.sh
@@ -41,7 +41,7 @@ help_to_synopsis () {
}
builtin_to_adoc () {
- echo "$GIT_BUILD_DIR/Documentation/git-$1.adoc"
+ echo "$GIT_SOURCE_DIR/Documentation/git-$1.adoc"
}
adoc_to_synopsis () {
@@ -112,10 +112,19 @@ do
adoc="$(builtin_to_adoc "$builtin")" &&
preq="$(echo BUILTIN_ADOC_$builtin | tr '[:lower:]-' '[:upper:]_')" &&
- if test -f "$adoc"
+ # If and only if *.adoc is missing, builtin shall be listed in t0450/adoc-missing.
+ if grep -q "^$builtin$" "$TEST_DIRECTORY"/t0450/adoc-missing
then
+ test_expect_success "$builtin appropriately marked as not having .adoc" '
+ ! test -f "$adoc"
+ '
+ else
test_set_prereq "$preq"
- fi &&
+
+ test_expect_success "$builtin appropriately marked as having .adoc" '
+ test -f "$adoc"
+ '
+ fi
# *.adoc output assertions
test_expect_success "$preq" "$builtin *.adoc SYNOPSIS has dashed labels" '
diff --git a/t/t0450/adoc-help-mismatches b/t/t0450/adoc-help-mismatches
index c4a15fd0cb..2c6ecd5fc8 100644
--- a/t/t0450/adoc-help-mismatches
+++ b/t/t0450/adoc-help-mismatches
@@ -17,7 +17,6 @@ fast-export
fast-import
fetch-pack
fmt-merge-msg
-for-each-ref
format-patch
fsck-objects
fsmonitor--daemon
@@ -38,7 +37,6 @@ merge-one-file
multi-pack-index
name-rev
notes
-pack-objects
push
range-diff
rebase
diff --git a/t/t0450/adoc-missing b/t/t0450/adoc-missing
new file mode 100644
index 0000000000..1ec9f8dcf3
--- /dev/null
+++ b/t/t0450/adoc-missing
@@ -0,0 +1,9 @@
+checkout--worker
+merge-ours
+merge-recursive
+merge-recursive-ours
+merge-recursive-theirs
+merge-subtree
+pickaxe
+submodule--helper
+upload-archive--writer
diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh
index 1be534a895..3ea5d51532 100755
--- a/t/t0610-reftable-basics.sh
+++ b/t/t0610-reftable-basics.sh
@@ -477,11 +477,7 @@ test_expect_success !CYGWIN 'ref transaction: many concurrent writers' '
test_commit --no-tag initial &&
head=$(git rev-parse HEAD) &&
- for i in $(test_seq 100)
- do
- printf "%s commit\trefs/heads/branch-%s\n" "$head" "$i" ||
- return 1
- done >expect &&
+ test_seq -f "$head commit\trefs/heads/branch-%d" 100 >expect &&
printf "%s commit\trefs/heads/main\n" "$head" >>expect &&
for i in $(test_seq 100)
diff --git a/t/t0612-reftable-jgit-compatibility.sh b/t/t0612-reftable-jgit-compatibility.sh
index d0d7e80b49..7df2ad5817 100755
--- a/t/t0612-reftable-jgit-compatibility.sh
+++ b/t/t0612-reftable-jgit-compatibility.sh
@@ -112,14 +112,11 @@ test_expect_success 'JGit can read multi-level index' '
cd repo &&
test_commit A &&
- awk "
- BEGIN {
- print \"start\";
- for (i = 0; i < 10000; i++)
- printf \"create refs/heads/branch-%d HEAD\n\", i;
- print \"commit\";
- }
- " >input &&
+ {
+ echo start &&
+ test_seq -f "create refs/heads/branch-%d HEAD" 10000 &&
+ echo commit
+ } >input &&
git update-ref --stdin <input &&
test_same_refs &&
diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh
index 6447920c9b..d77e601111 100755
--- a/t/t0613-reftable-write-options.sh
+++ b/t/t0613-reftable-write-options.sh
@@ -66,11 +66,7 @@ test_expect_success 'many refs results in multiple blocks' '
(
cd repo &&
test_commit initial &&
- for i in $(test_seq 200)
- do
- printf "update refs/heads/branch-%d HEAD\n" "$i" ||
- return 1
- done >input &&
+ test_seq -f "update refs/heads/branch-%d HEAD" 200 >input &&
git update-ref --stdin <input &&
git pack-refs &&
@@ -180,11 +176,7 @@ test_expect_success 'restart interval at every single record' '
(
cd repo &&
test_commit initial &&
- for i in $(test_seq 10)
- do
- printf "update refs/heads/branch-%d HEAD\n" "$i" ||
- return 1
- done >input &&
+ test_seq -f "update refs/heads/branch-%d HEAD" 10 >input &&
git update-ref --stdin <input &&
git -c reftable.restartInterval=1 pack-refs &&
@@ -224,11 +216,7 @@ test_expect_success 'object index gets written by default with ref index' '
(
cd repo &&
test_commit initial &&
- for i in $(test_seq 5)
- do
- printf "update refs/heads/branch-%d HEAD\n" "$i" ||
- return 1
- done >input &&
+ test_seq -f "update refs/heads/branch-%d HEAD" 5 >input &&
git update-ref --stdin <input &&
git -c reftable.blockSize=100 pack-refs &&
@@ -263,11 +251,7 @@ test_expect_success 'object index can be disabled' '
(
cd repo &&
test_commit initial &&
- for i in $(test_seq 5)
- do
- printf "update refs/heads/branch-%d HEAD\n" "$i" ||
- return 1
- done >input &&
+ test_seq -f "update refs/heads/branch-%d HEAD" 5 >input &&
git update-ref --stdin <input &&
git -c reftable.blockSize=100 -c reftable.indexObjects=false pack-refs &&
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 317da6869c..1f61b666a7 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -113,53 +113,55 @@ strlen () {
run_tests () {
type=$1
- oid=$2
- size=$3
- content=$4
- pretty_content=$5
+ object_name="$2"
+ mode=$3
+ size=$4
+ content=$5
+ pretty_content=$6
+ oid=${7:-"$object_name"}
batch_output="$oid $type $size
$content"
test_expect_success "$type exists" '
- git cat-file -e $oid
+ git cat-file -e "$object_name"
'
test_expect_success "Type of $type is correct" '
echo $type >expect &&
- git cat-file -t $oid >actual &&
+ git cat-file -t "$object_name" >actual &&
test_cmp expect actual
'
test_expect_success "Size of $type is correct" '
echo $size >expect &&
- git cat-file -s $oid >actual &&
+ git cat-file -s "$object_name" >actual &&
test_cmp expect actual
'
test -z "$content" ||
test_expect_success "Content of $type is correct" '
echo_without_newline "$content" >expect &&
- git cat-file $type $oid >actual &&
+ git cat-file $type "$object_name" >actual &&
test_cmp expect actual
'
test_expect_success "Pretty content of $type is correct" '
echo_without_newline "$pretty_content" >expect &&
- git cat-file -p $oid >actual &&
+ git cat-file -p "$object_name" >actual &&
test_cmp expect actual
'
test -z "$content" ||
test_expect_success "--batch output of $type is correct" '
echo "$batch_output" >expect &&
- echo $oid | git cat-file --batch >actual &&
+ echo "$object_name" | git cat-file --batch >actual &&
test_cmp expect actual
'
test_expect_success "--batch-check output of $type is correct" '
echo "$oid $type $size" >expect &&
- echo_without_newline $oid | git cat-file --batch-check >actual &&
+ echo_without_newline "$object_name" | git cat-file --batch-check >actual &&
test_cmp expect actual
'
@@ -168,13 +170,13 @@ $content"
test -z "$content" ||
test_expect_success "--batch-command $opt output of $type content is correct" '
echo "$batch_output" >expect &&
- test_write_lines "contents $oid" | git cat-file --batch-command $opt >actual &&
+ test_write_lines "contents $object_name" | git cat-file --batch-command $opt >actual &&
test_cmp expect actual
'
test_expect_success "--batch-command $opt output of $type info is correct" '
echo "$oid $type $size" >expect &&
- test_write_lines "info $oid" |
+ test_write_lines "info $object_name" |
git cat-file --batch-command $opt >actual &&
test_cmp expect actual
'
@@ -182,30 +184,45 @@ $content"
test_expect_success "custom --batch-check format" '
echo "$type $oid" >expect &&
- echo $oid | git cat-file --batch-check="%(objecttype) %(objectname)" >actual &&
+ echo "$object_name" | git cat-file --batch-check="%(objecttype) %(objectname)" >actual &&
test_cmp expect actual
'
test_expect_success "custom --batch-command format" '
echo "$type $oid" >expect &&
- echo "info $oid" | git cat-file --batch-command="%(objecttype) %(objectname)" >actual &&
+ echo "info $object_name" | git cat-file --batch-command="%(objecttype) %(objectname)" >actual &&
test_cmp expect actual
'
- test_expect_success '--batch-check with %(rest)' '
+ # FIXME: %(rest) is incompatible with object names that include whitespace,
+ # e.g. HEAD:path/to/a/file with spaces. Use the resolved OID as input to
+ # test this instead of the raw object name.
+ if echo "$object_name" | grep -q " "; then
+ test_rest=test_expect_failure
+ else
+ test_rest=test_expect_success
+ fi
+
+ $test_rest '--batch-check with %(rest)' '
echo "$type this is some extra content" >expect &&
- echo "$oid this is some extra content" |
+ echo "$object_name this is some extra content" |
git cat-file --batch-check="%(objecttype) %(rest)" >actual &&
test_cmp expect actual
'
+ test_expect_success '--batch-check with %(objectmode)' '
+ echo "$mode $oid" >expect &&
+ echo $object_name | git cat-file --batch-check="%(objectmode) %(objectname)" >actual &&
+ test_cmp expect actual
+ '
+
test -z "$content" ||
test_expect_success "--batch without type ($type)" '
{
echo "$size" &&
echo "$content"
} >expect &&
- echo $oid | git cat-file --batch="%(objectsize)" >actual &&
+ echo "$object_name" | git cat-file --batch="%(objectsize)" >actual &&
test_cmp expect actual
'
@@ -215,7 +232,7 @@ $content"
echo "$type" &&
echo "$content"
} >expect &&
- echo $oid | git cat-file --batch="%(objecttype)" >actual &&
+ echo "$object_name" | git cat-file --batch="%(objecttype)" >actual &&
test_cmp expect actual
'
}
@@ -230,13 +247,14 @@ test_expect_success "setup" '
git config extensions.compatobjectformat $test_compat_hash_algo &&
echo_without_newline "$hello_content" > hello &&
git update-index --add hello &&
+ echo_without_newline "$hello_content" > "path with spaces" &&
+ git update-index --add --chmod=+x "path with spaces" &&
git commit -m "add hello file"
'
run_blob_tests () {
oid=$1
-
- run_tests 'blob' $oid $hello_size "$hello_content" "$hello_content"
+ run_tests 'blob' $oid "" $hello_size "$hello_content" "$hello_content"
test_expect_success '--batch-command --buffer with flush for blob info' '
echo "$oid blob $hello_size" >expect &&
@@ -269,13 +287,17 @@ test_expect_success '--batch-check without %(rest) considers whole line' '
tree_oid=$(git write-tree)
tree_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $tree_oid)
-tree_size=$(($(test_oid rawsz) + 13))
-tree_compat_size=$(($(test_oid --hash=compat rawsz) + 13))
-tree_pretty_content="100644 blob $hello_oid hello${LF}"
-tree_compat_pretty_content="100644 blob $hello_compat_oid hello${LF}"
-
-run_tests 'tree' $tree_oid $tree_size "" "$tree_pretty_content"
-run_tests 'tree' $tree_compat_oid $tree_compat_size "" "$tree_compat_pretty_content"
+tree_size=$((2 * $(test_oid rawsz) + 13 + 24))
+tree_compat_size=$((2 * $(test_oid --hash=compat rawsz) + 13 + 24))
+tree_pretty_content="100644 blob $hello_oid hello${LF}100755 blob $hello_oid path with spaces${LF}"
+tree_compat_pretty_content="100644 blob $hello_compat_oid hello${LF}100755 blob $hello_compat_oid path with spaces${LF}"
+
+run_tests 'tree' $tree_oid "" $tree_size "" "$tree_pretty_content"
+run_tests 'tree' $tree_compat_oid "" $tree_compat_size "" "$tree_compat_pretty_content"
+run_tests 'blob' "$tree_oid:hello" "100644" $hello_size "" "$hello_content" $hello_oid
+run_tests 'blob' "$tree_compat_oid:hello" "100644" $hello_size "" "$hello_content" $hello_compat_oid
+run_tests 'blob' "$tree_oid:path with spaces" "100755" $hello_size "" "$hello_content" $hello_oid
+run_tests 'blob' "$tree_compat_oid:path with spaces" "100755" $hello_size "" "$hello_content" $hello_compat_oid
commit_message="Initial commit"
commit_oid=$(echo_without_newline "$commit_message" | git commit-tree $tree_oid)
@@ -294,8 +316,8 @@ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
$commit_message"
-run_tests 'commit' $commit_oid $commit_size "$commit_content" "$commit_content"
-run_tests 'commit' $commit_compat_oid $commit_compat_size "$commit_compat_content" "$commit_compat_content"
+run_tests 'commit' $commit_oid "" $commit_size "$commit_content" "$commit_content"
+run_tests 'commit' $commit_compat_oid "" $commit_compat_size "$commit_compat_content" "$commit_compat_content"
tag_header_without_oid="type blob
tag hellotag
@@ -318,8 +340,8 @@ tag_size=$(strlen "$tag_content")
tag_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $tag_oid)
tag_compat_size=$(strlen "$tag_compat_content")
-run_tests 'tag' $tag_oid $tag_size "$tag_content" "$tag_content"
-run_tests 'tag' $tag_compat_oid $tag_compat_size "$tag_compat_content" "$tag_compat_content"
+run_tests 'tag' $tag_oid "" $tag_size "$tag_content" "$tag_content"
+run_tests 'tag' $tag_compat_oid "" $tag_compat_size "$tag_compat_content" "$tag_compat_content"
test_expect_success "Reach a blob from a tag pointing to it" '
echo_without_newline "$hello_content" >expect &&
@@ -1198,6 +1220,31 @@ test_expect_success 'cat-file --batch-check respects replace objects' '
test_cmp expect actual
'
+test_expect_success 'batch-check with a submodule' '
+ # FIXME: this call to mktree is incompatible with compatObjectFormat
+ # because the submodule OID cannot be mapped to the compat hash algo.
+ test_unconfig extensions.compatobjectformat &&
+ printf "160000 commit $(test_oid deadbeef)\tsub\n" >tree-with-sub &&
+ tree=$(git mktree <tree-with-sub) &&
+ test_config extensions.compatobjectformat $test_compat_hash_algo &&
+
+ git cat-file --batch-check >actual <<-EOF &&
+ $tree:sub
+ EOF
+ printf "$(test_oid deadbeef) submodule\n" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'batch-check with a submodule, object exists' '
+ printf "160000 commit $commit_oid\tsub\n" >tree-with-sub &&
+ tree=$(git mktree <tree-with-sub) &&
+ git cat-file --batch-check >actual <<-EOF &&
+ $tree:sub
+ EOF
+ printf "$commit_oid commit $commit_size\n" >expect &&
+ test_cmp expect actual
+'
+
# Pull the entry for object with oid "$1" out of the output of
# "cat-file --batch", including its object content (which requires
# parsing and reading a set amount of bytes, hence perl).
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index dbbe9fb0d4..de076293b6 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -30,7 +30,7 @@ setup_repo() {
test_repo=test
push_repo() {
- test_create_repo $test_repo
+ git init --quiet $test_repo
cd $test_repo
setup_repo
@@ -252,9 +252,9 @@ test_expect_success '--literally complains about non-standard types' '
test_must_fail git hash-object -t bogus --literally --stdin
'
-test_expect_success '--stdin outside of repository (uses SHA-1)' '
+test_expect_success '--stdin outside of repository (uses default hash)' '
nongit git hash-object --stdin <hello >actual &&
- echo "$(test_oid --hash=sha1 hello)" >expect &&
+ echo "$(test_oid --hash=builtin hello)" >expect &&
test_cmp expect actual
'
diff --git a/t/t1021-rerere-in-workdir.sh b/t/t1021-rerere-in-workdir.sh
deleted file mode 100755
index 0b892894eb..0000000000
--- a/t/t1021-rerere-in-workdir.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/sh
-
-test_description='rerere run in a workdir'
-GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
-export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-
-. ./test-lib.sh
-
-test_expect_success SYMLINKS setup '
- git config rerere.enabled true &&
- >world &&
- git add world &&
- test_tick &&
- git commit -m initial &&
-
- echo hello >world &&
- test_tick &&
- git commit -a -m hello &&
-
- git checkout -b side HEAD^ &&
- echo goodbye >world &&
- test_tick &&
- git commit -a -m goodbye &&
-
- git checkout main
-'
-
-test_expect_success SYMLINKS 'rerere in workdir' '
- rm -rf .git/rr-cache &&
- "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" . work &&
- (
- cd work &&
- test_must_fail git merge side &&
- git rerere status >actual &&
- echo world >expect &&
- test_cmp expect actual
- )
-'
-
-# This fails because we don't resolve relative symlink in mkdir_in_gitdir()
-# For the purpose of helping contrib/workdir/git-new-workdir users, we do not
-# have to support relative symlinks, but it might be nicer to make this work
-# with a relative symbolic link someday.
-test_expect_failure SYMLINKS 'rerere in workdir (relative)' '
- rm -rf .git/rr-cache &&
- "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" . krow &&
- (
- cd krow &&
- rm -f .git/rr-cache &&
- ln -s ../.git/rr-cache .git/rr-cache &&
- test_must_fail git merge side &&
- git rerere status >actual &&
- echo world >expect &&
- test_cmp expect actual
- )
-'
-
-test_done
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index d8101139b4..b0f691c151 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -1506,6 +1506,8 @@ test_expect_success 'sparse-index is not expanded' '
ensure_not_expanded reset --hard &&
ensure_not_expanded restore -s rename-out-to-out -- deep/deeper1 &&
+ ensure_not_expanded ls-files deep/deeper1 &&
+
echo >>sparse-index/README.md &&
ensure_not_expanded add -A &&
echo >>sparse-index/extra.txt &&
@@ -1607,6 +1609,17 @@ test_expect_success 'describe tested on all' '
test_all_match git describe --dirty
'
+test_expect_success 'ls-files filtering and expansion' '
+ init_repos &&
+
+ # This filtering will hit a sparse directory midway
+ # through the iteration.
+ test_all_match git ls-files deep &&
+
+ # This pathspec will filter the index to only a sparse
+ # directory.
+ test_all_match git ls-files folder1
+'
test_expect_success 'sparse-index is not expanded: describe' '
init_repos &&
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index d29d23cb89..b7415ec9d5 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -1380,10 +1380,7 @@ test_expect_success 'fails with duplicate ref update via symref' '
test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction creating branches does not burst open file limit' '
(
- for i in $(test_seq 33)
- do
- echo "create refs/heads/$i HEAD" || exit 1
- done >large_input &&
+ test_seq -f "create refs/heads/%d HEAD" 33 >large_input &&
run_with_limited_open_files git update-ref --stdin <large_input &&
git rev-parse --verify -q refs/heads/33
)
@@ -1391,10 +1388,7 @@ test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction creating branches
test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction deleting branches does not burst open file limit' '
(
- for i in $(test_seq 33)
- do
- echo "delete refs/heads/$i HEAD" || exit 1
- done >large_input &&
+ test_seq -f "delete refs/heads/%d HEAD" 33 >large_input &&
run_with_limited_open_files git update-ref --stdin <large_input &&
test_must_fail git rev-parse --verify -q refs/heads/33
)
@@ -2299,6 +2293,51 @@ do
test_grep -q "refname conflict" stdout
)
'
+
+ test_expect_success "stdin $type batch-updates delete incorrect symbolic ref" '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit c1 &&
+ head=$(git rev-parse HEAD) &&
+ git symbolic-ref refs/heads/symbolic refs/heads/non-existent &&
+
+ format_command $type "delete refs/heads/symbolic" "$head" >stdin &&
+ git update-ref $type --stdin --batch-updates <stdin >stdout &&
+ test_grep "reference does not exist" stdout
+ )
+ '
+
+ test_expect_success "stdin $type batch-updates delete with incorrect old_oid" '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit c1 &&
+ git branch new-branch &&
+ test_commit c2 &&
+ head=$(git rev-parse HEAD) &&
+
+ format_command $type "delete refs/heads/new-branch" "$head" >stdin &&
+ git update-ref $type --stdin --batch-updates <stdin >stdout &&
+ test_grep "incorrect old value provided" stdout
+ )
+ '
+
+ test_expect_success "stdin $type batch-updates delete non-existent ref" '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit commit &&
+ head=$(git rev-parse HEAD) &&
+
+ format_command $type "delete refs/heads/non-existent" "$head" >stdin &&
+ git update-ref $type --stdin --batch-updates <stdin >stdout &&
+ test_grep "reference does not exist" stdout
+ )
+ '
done
test_expect_success 'update-ref should also create reflog for HEAD' '
@@ -2310,4 +2349,44 @@ test_expect_success 'update-ref should also create reflog for HEAD' '
test_cmp expect actual
'
+test_expect_success REFFILES 'empty directories are pruned when aborting a transaction' '
+ test_path_is_missing .git/refs/heads/nested &&
+ git update-ref --stdin <<-EOF &&
+ create refs/heads/nested/something HEAD
+ prepare
+ abort
+ EOF
+ test_path_is_missing .git/refs/heads/nested
+'
+
+test_expect_success REFFILES 'empty directories are pruned when not committing' '
+ test_path_is_missing .git/refs/heads/nested &&
+ git update-ref --stdin <<-EOF &&
+ create refs/heads/nested/something HEAD
+ prepare
+ EOF
+ test_path_is_missing .git/refs/heads/nested
+'
+
+test_expect_success 'dangling symref not overwritten by creation' '
+ test_when_finished "git update-ref -d refs/heads/dangling" &&
+ git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+ test_must_fail git update-ref --no-deref --stdin 2>err <<-\EOF &&
+ create refs/heads/dangling HEAD
+ EOF
+ test_grep "cannot lock.*dangling symref already exists" err &&
+ test_must_fail git rev-parse --verify refs/heads/dangling &&
+ test_must_fail git rev-parse --verify refs/heads/does-not-exist
+'
+
+test_expect_success 'dangling symref overwritten without old oid' '
+ test_when_finished "git update-ref -d refs/heads/dangling" &&
+ git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+ git update-ref --no-deref --stdin <<-\EOF &&
+ update refs/heads/dangling HEAD
+ EOF
+ git rev-parse --verify refs/heads/dangling &&
+ test_must_fail git rev-parse --verify refs/heads/does-not-exist
+'
+
test_done
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
index 9da3650e91..36c903ca19 100755
--- a/t/t1403-show-ref.sh
+++ b/t/t1403-show-ref.sh
@@ -228,69 +228,4 @@ test_expect_success 'show-ref sub-modes are mutually exclusive' '
grep "cannot be used together" err
'
-test_expect_success '--exists with existing reference' '
- git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
- test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
- test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
- grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
- git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
- test_when_finished "git update-ref -d refs/heads/bad...name" &&
- new_oid=$(git rev-parse HEAD) &&
- test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
- git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
- test_when_finished "git symbolic-ref -d refs/symref" &&
- git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
- git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
- test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
- git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
- git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
- test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
- tree_oid=$(git rev-parse HEAD^{tree}) &&
- test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
- git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
- cat >expect <<-EOF &&
- error: reference does not exist
- EOF
- test_expect_code 2 git show-ref --exists refs/heads 2>err &&
- test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
- test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
- test_when_finished "rm .git/FETCH_HEAD" &&
- git rev-parse HEAD >.git/FETCH_HEAD &&
- git show-ref --exists FETCH_HEAD
-'
-
test_done
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 42b501f163..e30f87a358 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -673,4 +673,32 @@ test_expect_success 'reflog drop --all with reference' '
)
'
+test_expect_success 'expire with pattern config' '
+ # Split refs/heads/ into two roots so we can apply config to each. Make
+ # two branches per root to verify that config is applied correctly
+ # multiple times.
+ git branch root1/branch1 &&
+ git branch root1/branch2 &&
+ git branch root2/branch1 &&
+ git branch root2/branch2 &&
+
+ test_config "gc.reflogexpire" "never" &&
+ test_config "gc.refs/heads/root2/*.reflogExpire" "now" &&
+ git reflog expire \
+ root1/branch1 root1/branch2 \
+ root2/branch1 root2/branch2 &&
+
+ cat >expect <<-\EOF &&
+ root1/branch1@{0}
+ root1/branch2@{0}
+ EOF
+ git log -g --branches="root*" --format=%gD >actual.raw &&
+ # The sole reflog entry of each branch points to the same commit, so
+ # the order in which they are shown is nondeterministic. We just care
+ # about the what was expired (and what was not), so sort to get a known
+ # order.
+ sort <actual.raw >actual.sorted &&
+ test_cmp expect actual.sorted
+'
+
test_done
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 8c777f7cf8..d91dd3a3b5 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -120,8 +120,6 @@ test_expect_success 'interleaving hook calls succeed' '
cat >expect <<-EOF &&
hooks/update refs/tags/PRE $ZERO_OID $PRE_OID
- hooks/reference-transaction prepared
- hooks/reference-transaction committed
hooks/update refs/tags/POST $ZERO_OID $POST_OID
hooks/reference-transaction prepared
hooks/reference-transaction committed
diff --git a/t/t1421-reflog-write.sh b/t/t1421-reflog-write.sh
new file mode 100755
index 0000000000..46df64c176
--- /dev/null
+++ b/t/t1421-reflog-write.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+test_description='Manually write reflog entries'
+
+. ./test-lib.sh
+
+SIGNATURE="C O Mitter <committer@example.com> 1112911993 -0700"
+
+test_reflog_matches () {
+ repo="$1" &&
+ refname="$2" &&
+ cat >actual &&
+ test-tool -C "$repo" ref-store main for-each-reflog-ent "$refname" >expected &&
+ test_cmp expected actual
+}
+
+test_expect_success 'invalid number of arguments' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ for args in "" "1" "1 2" "1 2 3" "1 2 3 4 5"
+ do
+ test_must_fail git reflog write $args 2>err &&
+ test_grep "usage: git reflog write" err || return 1
+ done
+ )
+'
+
+test_expect_success 'invalid refname' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_must_fail git reflog write "refs/heads/ invalid" $ZERO_OID $ZERO_OID first 2>err &&
+ test_grep "invalid reference name: " err
+ )
+'
+
+test_expect_success 'unqualified refname is rejected' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_must_fail git reflog write unqualified $ZERO_OID $ZERO_OID first 2>err &&
+ test_grep "invalid reference name: " err
+ )
+'
+
+test_expect_success 'nonexistent object IDs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_must_fail git reflog write refs/heads/something $(test_oid deadbeef) $ZERO_OID old-object-id 2>err &&
+ test_grep "old object .* does not exist" err &&
+ test_must_fail git reflog write refs/heads/something $ZERO_OID $(test_oid deadbeef) new-object-id 2>err &&
+ test_grep "new object .* does not exist" err
+ )
+'
+
+test_expect_success 'abbreviated object IDs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ abbreviated_oid=$(git rev-parse HEAD | test_copy_bytes 8) &&
+ test_must_fail git reflog write refs/heads/something $abbreviated_oid $ZERO_OID old-object-id 2>err &&
+ test_grep "invalid old object ID" err &&
+ test_must_fail git reflog write refs/heads/something $ZERO_OID $abbreviated_oid new-object-id 2>err &&
+ test_grep "invalid new object ID" err
+ )
+'
+
+test_expect_success 'reflog message gets normalized' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ COMMIT_OID=$(git rev-parse HEAD) &&
+ git reflog write HEAD $COMMIT_OID $COMMIT_OID "$(printf "message\nwith\nnewlines")" &&
+ git reflog show -1 --format=%gs HEAD >actual &&
+ echo "message with newlines" >expected &&
+ test_cmp expected actual
+ )
+'
+
+test_expect_success 'simple writes' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ COMMIT_OID=$(git rev-parse HEAD) &&
+
+ git reflog write refs/heads/something $ZERO_OID $COMMIT_OID first &&
+ test_reflog_matches . refs/heads/something <<-EOF &&
+ $ZERO_OID $COMMIT_OID $SIGNATURE first
+ EOF
+
+ git reflog write refs/heads/something $COMMIT_OID $COMMIT_OID second &&
+ test_reflog_matches . refs/heads/something <<-EOF
+ $ZERO_OID $COMMIT_OID $SIGNATURE first
+ $COMMIT_OID $COMMIT_OID $SIGNATURE second
+ EOF
+ )
+'
+
+test_expect_success 'can write to root ref' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ COMMIT_OID=$(git rev-parse HEAD) &&
+
+ git reflog write ROOT_REF_HEAD $ZERO_OID $COMMIT_OID first &&
+ test_reflog_matches . ROOT_REF_HEAD <<-EOF
+ $ZERO_OID $COMMIT_OID $SIGNATURE first
+ EOF
+ )
+'
+
+test_done
diff --git a/t/t1422-show-ref-exists.sh b/t/t1422-show-ref-exists.sh
new file mode 100755
index 0000000000..fdca3f16c8
--- /dev/null
+++ b/t/t1422-show-ref-exists.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+test_description='show-ref --exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh
index 2ab97e1b7d..0e1116a319 100755
--- a/t/t1460-refs-migrate.sh
+++ b/t/t1460-refs-migrate.sh
@@ -7,6 +7,17 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
+print_all_reflog_entries () {
+ repo=$1 &&
+ test-tool -C "$repo" ref-store main for-each-reflog >reflogs &&
+ while read reflog
+ do
+ echo "REFLOG: $reflog" &&
+ test-tool -C "$repo" ref-store main for-each-reflog-ent "$reflog" ||
+ return 1
+ done <reflogs
+}
+
# Migrate the provided repository from one format to the other and
# verify that the references and logs are migrated over correctly.
# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]]
@@ -28,8 +39,7 @@ test_migration () {
--format='%(refname) %(objectname) %(symref)' >expect &&
if ! $skip_reflog_verify
then
- git -C "$repo" reflog --all >expect_logs &&
- git -C "$repo" reflog list >expect_log_list
+ print_all_reflog_entries "$repo" >expect_logs
fi &&
git -C "$repo" refs migrate --ref-format="$format" "$@" &&
@@ -39,10 +49,8 @@ test_migration () {
test_cmp expect actual &&
if ! $skip_reflog_verify
then
- git -C "$repo" reflog --all >actual_logs &&
- git -C "$repo" reflog list >actual_log_list &&
- test_cmp expect_logs actual_logs &&
- test_cmp expect_log_list actual_log_list
+ print_all_reflog_entries "$repo" >actual_logs &&
+ test_cmp expect_logs actual_logs
fi &&
git -C "$repo" rev-parse --show-ref-format >actual &&
@@ -273,7 +281,7 @@ test_expect_success 'multiple reftable blocks with multiple entries' '
test_commit -C repo second &&
printf "update refs/heads/ref-%d HEAD\n" $(test_seq 3000) >stdin &&
git -C repo update-ref --stdin <stdin &&
- test_migration repo reftable
+ test_migration repo reftable true
'
test_expect_success 'migrating from files format deletes backend files' '
diff --git a/t/t1461-refs-list.sh b/t/t1461-refs-list.sh
new file mode 100755
index 0000000000..36e3d81e59
--- /dev/null
+++ b/t/t1461-refs-list.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+test_description='git refs list tests'
+
+. ./test-lib.sh
+
+git_for_each_ref='git refs list'
+. "$TEST_DIRECTORY"/for-each-ref-tests.sh
diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
new file mode 100755
index 0000000000..349453c4ca
--- /dev/null
+++ b/t/t1462-refs-exists.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+test_description='refs exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+git_show_ref_exists='git refs exists'
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh
index 6824581317..c824c1a25c 100755
--- a/t/t1517-outside-repo.sh
+++ b/t/t1517-outside-repo.sh
@@ -107,11 +107,46 @@ test_expect_success LIBCURL 'remote-http outside repository' '
test_grep "^error: remote-curl" actual
'
-test_expect_success 'update-server-info does not crash with -h' '
- test_expect_code 129 git update-server-info -h >usage &&
- test_grep "[Uu]sage: git update-server-info " usage &&
- test_expect_code 129 nongit git update-server-info -h >usage &&
- test_grep "[Uu]sage: git update-server-info " usage
+for cmd in $(git --list-cmds=main)
+do
+ cmd=${cmd%.*} # strip .sh, .perl, etc.
+ case "$cmd" in
+ archimport | citool | credential-netrc | credential-libsecret | \
+ credential-osxkeychain | cvsexportcommit | cvsimport | cvsserver | \
+ daemon | \
+ difftool--helper | filter-branch | fsck-objects | get-tar-commit-id | \
+ gui | gui--askpass | \
+ http-backend | http-fetch | http-push | init-db | \
+ merge-octopus | merge-one-file | merge-resolve | mergetool | \
+ mktag | p4 | p4.py | pickaxe | remote-ftp | remote-ftps | \
+ remote-http | remote-https | replay | send-email | \
+ sh-i18n--envsubst | shell | show | stage | submodule | svn | \
+ upload-archive--writer | upload-pack | web--browse | whatchanged)
+ expect_outcome=expect_failure ;;
+ *)
+ expect_outcome=expect_success ;;
+ esac
+ case "$cmd" in
+ instaweb)
+ prereq=PERL ;;
+ *)
+ prereq= ;;
+ esac
+ test_$expect_outcome $prereq "'git $cmd -h' outside a repository" '
+ test_expect_code 129 nongit git $cmd -h >usage &&
+ test_grep "[Uu]sage: git $cmd " usage
+ '
+ test_$expect_outcome $prereq "'git $cmd --help-all' outside a repository" '
+ test_expect_code 129 nongit git $cmd --help-all >usage &&
+ test_grep "[Uu]sage: git $cmd " usage
+ '
+done
+
+test_expect_success 'fmt-merge-msg does not crash with -h' '
+ test_expect_code 129 git fmt-merge-msg -h >usage &&
+ test_grep "[Uu]sage: git fmt-merge-msg " usage &&
+ test_expect_code 129 nongit git fmt-merge-msg -h >usage &&
+ test_grep "[Uu]sage: git fmt-merge-msg " usage
'
test_done
diff --git a/t/t1900-repo.sh b/t/t1900-repo.sh
new file mode 100755
index 0000000000..2beba67889
--- /dev/null
+++ b/t/t1900-repo.sh
@@ -0,0 +1,113 @@
+#!/bin/sh
+
+test_description='test git repo-info'
+
+. ./test-lib.sh
+
+# Test whether a key-value pair is correctly returned
+#
+# Usage: test_repo_info <label> <init command> <repo_name> <key> <expected value>
+#
+# Arguments:
+# label: the label of the test
+# init_command: a command which creates a repository
+# repo_name: the name of the repository that will be created in init_command
+# key: the key of the field that is being tested
+# expected_value: the value that the field should contain
+test_repo_info () {
+ label=$1
+ init_command=$2
+ repo_name=$3
+ key=$4
+ expected_value=$5
+
+ test_expect_success "setup: $label" '
+ eval "$init_command $repo_name"
+ '
+
+ test_expect_success "keyvalue: $label" '
+ echo "$key=$expected_value" > expect &&
+ git -C "$repo_name" repo info "$key" >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "nul: $label" '
+ printf "%s\n%s\0" "$key" "$expected_value" >expect &&
+ git -C "$repo_name" repo info --format=nul "$key" >actual &&
+ test_cmp_bin expect actual
+ '
+}
+
+test_repo_info 'ref format files is retrieved correctly' \
+ 'git init --ref-format=files' 'format-files' 'references.format' 'files'
+
+test_repo_info 'ref format reftable is retrieved correctly' \
+ 'git init --ref-format=reftable' 'format-reftable' 'references.format' 'reftable'
+
+test_repo_info 'bare repository = false is retrieved correctly' \
+ 'git init' 'nonbare' 'layout.bare' 'false'
+
+test_repo_info 'bare repository = true is retrieved correctly' \
+ 'git init --bare' 'bare' 'layout.bare' 'true'
+
+test_repo_info 'shallow repository = false is retrieved correctly' \
+ 'git init' 'nonshallow' 'layout.shallow' 'false'
+
+test_expect_success 'setup remote' '
+ git init remote &&
+ echo x >remote/x &&
+ git -C remote add x &&
+ git -C remote commit -m x
+'
+
+test_repo_info 'shallow repository = true is retrieved correctly' \
+ 'git clone --depth 1 "file://$PWD/remote"' 'shallow' 'layout.shallow' 'true'
+
+test_repo_info 'object.format = sha1 is retrieved correctly' \
+ 'git init --object-format=sha1' 'sha1' 'object.format' 'sha1'
+
+test_repo_info 'object.format = sha256 is retrieved correctly' \
+ 'git init --object-format=sha256' 'sha256' 'object.format' 'sha256'
+
+test_expect_success 'values returned in order requested' '
+ cat >expect <<-\EOF &&
+ layout.bare=false
+ references.format=files
+ layout.bare=false
+ EOF
+ git init --ref-format=files ordered &&
+ git -C ordered repo info layout.bare references.format layout.bare >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git-repo-info fails if an invalid key is requested' '
+ echo "error: key ${SQ}foo${SQ} not found" >expect &&
+ test_must_fail git repo info foo 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git-repo-info outputs data even if there is an invalid field' '
+ echo "references.format=$(test_detect_ref_format)" >expect &&
+ test_must_fail git repo info foo references.format bar >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git-repo-info aborts when requesting an invalid format' '
+ echo "fatal: invalid format ${SQ}foo${SQ}" >expect &&
+ test_must_fail git repo info --format=foo 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '-z uses nul-terminated format' '
+ printf "layout.bare\nfalse\0layout.shallow\nfalse\0" >expected &&
+ git repo info -z layout.bare layout.shallow >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'git repo info uses the last requested format' '
+ echo "layout.bare=false" >expected &&
+ git repo info --format=nul -z --format=keyvalue layout.bare >actual &&
+ test_cmp expected actual
+'
+
+test_done
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index 90638fa886..023e1301c8 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -42,8 +42,8 @@ test_expect_success '"add" using - shorthand' '
test_expect_success '"add" refuses to checkout locked branch' '
test_must_fail git worktree add zere main &&
- ! test -d zere &&
- ! test -d .git/worktrees/zere
+ test_path_is_missing zere &&
+ test_path_is_missing .git/worktrees/zere
'
test_expect_success 'checking out paths not complaining about linked checkouts' '
@@ -70,14 +70,14 @@ test_expect_success '"add" worktree' '
test_expect_success '"add" worktree with lock' '
git worktree add --detach --lock here-with-lock main &&
test_when_finished "git worktree unlock here-with-lock || :" &&
- test -f .git/worktrees/here-with-lock/locked
+ test_path_is_file .git/worktrees/here-with-lock/locked
'
test_expect_success '"add" worktree with lock and reason' '
lock_reason="why not" &&
git worktree add --detach --lock --reason "$lock_reason" here-with-lock-reason main &&
test_when_finished "git worktree unlock here-with-lock-reason || :" &&
- test -f .git/worktrees/here-with-lock-reason/locked &&
+ test_path_is_file .git/worktrees/here-with-lock-reason/locked &&
echo "$lock_reason" >expect &&
test_cmp expect .git/worktrees/here-with-lock-reason/locked
'
@@ -412,14 +412,14 @@ test_expect_success '"add --orphan" with empty repository' '
test_expect_success '"add" worktree with orphan branch and lock' '
git worktree add --lock --orphan -b orphanbr orphan-with-lock &&
test_when_finished "git worktree unlock orphan-with-lock || :" &&
- test -f .git/worktrees/orphan-with-lock/locked
+ test_path_is_file .git/worktrees/orphan-with-lock/locked
'
test_expect_success '"add" worktree with orphan branch, lock, and reason' '
lock_reason="why not" &&
git worktree add --detach --lock --reason "$lock_reason" orphan-with-lock-reason main &&
test_when_finished "git worktree unlock orphan-with-lock-reason || :" &&
- test -f .git/worktrees/orphan-with-lock-reason/locked &&
+ test_path_is_file .git/worktrees/orphan-with-lock-reason/locked &&
echo "$lock_reason" >expect &&
test_cmp expect .git/worktrees/orphan-with-lock-reason/locked
'
@@ -474,7 +474,7 @@ test_expect_success 'local clone --shared from linked checkout' '
test_expect_success '"add" worktree with --no-checkout' '
git worktree add --no-checkout -b swamp swamp &&
- ! test -e swamp/init.t &&
+ test_path_is_missing swamp/init.t &&
git -C swamp reset --hard &&
test_cmp init.t swamp/init.t
'
@@ -497,7 +497,7 @@ test_expect_success 'put a worktree under rebase' '
test_expect_success 'add a worktree, checking out a rebased branch' '
test_must_fail git worktree add new-rebase under-rebase &&
- ! test -d new-rebase
+ test_path_is_missing new-rebase
'
test_expect_success 'checking out a rebased branch from another worktree' '
@@ -535,7 +535,7 @@ test_expect_success 'checkout a branch under bisect' '
git worktree list >actual &&
grep "under-bisect.*detached HEAD" actual &&
test_must_fail git worktree add new-bisect under-bisect &&
- ! test -d new-bisect
+ test_path_is_missing new-bisect
)
'
@@ -1165,7 +1165,7 @@ test_expect_success '"add" not tripped up by magic worktree matching"' '
test_expect_success FUNNYNAMES 'sanitize generated worktree name' '
git worktree add --detach ". weird*..?.lock.lock" &&
- test -d .git/worktrees/---weird-.-
+ test_path_is_dir .git/worktrees/---weird-.-
'
test_expect_success '"add" should not fail because of another bad worktree' '
diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh
index 13f66fd649..b41e7f0daa 100755
--- a/t/t3000-ls-files-others.sh
+++ b/t/t3000-ls-files-others.sh
@@ -73,25 +73,6 @@ test_expect_success 'ls-files --others handles non-submodule .git' '
test_cmp expected1 output
'
-test_expect_success SYMLINKS 'ls-files --others with symlinked submodule' '
- git init super &&
- git init sub &&
- (
- cd sub &&
- >a &&
- git add a &&
- git commit -m sub &&
- git pack-refs --all
- ) &&
- (
- cd super &&
- "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" ../sub sub &&
- git ls-files --others --exclude-standard >../actual
- ) &&
- echo sub/ >expect &&
- test_cmp expect actual
-'
-
test_expect_success 'setup nested pathspec search' '
test_create_repo nested &&
(
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 6bac217ed3..e778dd8ae4 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1176,7 +1176,7 @@ test_expect_success 'rebase -i respects core.commentchar' '
test B = $(git cat-file commit HEAD^ | sed -ne \$p)
'
-test_expect_success 'rebase -i respects core.commentchar=auto' '
+test_expect_success !WITH_BREAKING_CHANGES 'rebase -i respects core.commentchar=auto' '
test_config core.commentchar auto &&
write_script copy-edit-script.sh <<-\EOF &&
cp "$1" edit-script
@@ -1184,8 +1184,23 @@ test_expect_success 'rebase -i respects core.commentchar=auto' '
test_when_finished "git rebase --abort || :" &&
(
test_set_editor "$(pwd)/copy-edit-script.sh" &&
- git rebase -i HEAD^
+ git rebase -i HEAD^ 2>err
) &&
+ sed -n "s/^hint: *\$//p; s/^hint: //p; s/^warning: //p" err >actual &&
+ cat >expect <<-EOF &&
+ Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0
+
+ To use the default comment string (#) please run
+
+ git config unset core.commentChar
+
+ To set a custom comment string please run
+
+ git config set core.commentChar <comment string>
+
+ where ${SQ}<comment string>${SQ} is the string you wish to use.
+ EOF
+ test_cmp expect actual &&
test -z "$(grep -ve "^#" -e "^\$" -e "^pick" edit-script)"
'
@@ -2263,6 +2278,7 @@ test_expect_success 'non-merge commands reject merge commits' '
edit $oid
fixup $oid
squash $oid
+ drop $oid # acceptable, no advice
EOF
(
set_replace_editor todo &&
diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
index 26b42a526a..5d093e3a7a 100755
--- a/t/t3415-rebase-autosquash.sh
+++ b/t/t3415-rebase-autosquash.sh
@@ -394,6 +394,16 @@ test_expect_success 'autosquash with empty custom instructionFormat' '
)
'
+test_expect_success 'autosquash with invalid custom instructionFormat' '
+ git reset --hard base &&
+ test_commit invalid-instructionFormat-test &&
+ (
+ test_must_fail git -c rebase.instructionFormat=blah \
+ rebase --autosquash --force-rebase -i HEAD^ &&
+ test_path_is_missing .git/rebase-merge
+ )
+'
+
set_backup_editor () {
write_script backup-editor.sh <<-\EOF
cp "$1" .git/backup-"$(basename "$1")"
diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index 127216f722..f9b8999db5 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -328,6 +328,19 @@ test_expect_success 'there is no --no-reschedule-failed-exec in an ongoing rebas
test_expect_code 129 git rebase --edit-todo --no-reschedule-failed-exec
'
+test_expect_success !WITH_BREAKING_CHANGES 'no change in comment character due to conflicts markers with core.commentChar=auto' '
+ git checkout -b branch-a &&
+ test_commit A F1 &&
+ git checkout -b branch-b HEAD^ &&
+ test_commit B F1 &&
+ test_must_fail git rebase branch-a &&
+ printf "B\nA\n" >F1 &&
+ git add F1 &&
+ GIT_EDITOR="cat >actual" git -c core.commentChar=auto rebase --continue &&
+ # Check that "#" is still the comment character.
+ test_grep "^# Changes to be committed" actual
+'
+
test_orig_head_helper () {
test_when_finished 'git rebase --abort &&
git checkout topic &&
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 98259e2ada..1f16e6b522 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -17,11 +17,6 @@ test_expect_success 'Initialize test directory' '
git commit -m "add normal files"
'
-if test_have_prereq !FUNNYNAMES
-then
- say 'Your filesystem does not allow tabs in filenames.'
-fi
-
test_expect_success FUNNYNAMES 'add files with funny names' '
touch -- "tab embedded" "newline${LF}embedded" &&
git add -- "tab embedded" "newline${LF}embedded" &&
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index b8a05d95f3..04d2a19835 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -63,7 +63,7 @@ test_expect_success 'setup (initial)' '
'
test_expect_success 'status works (initial)' '
git add -i </dev/null >output &&
- grep "+1/-0 *+2/-0 file" output
+ test_grep "+1/-0 *+2/-0 file" output
'
test_expect_success 'setup expected' '
@@ -86,7 +86,7 @@ test_expect_success 'revert works (initial)' '
git add file &&
test_write_lines r 1 | git add -i &&
git ls-files >output &&
- ! grep . output
+ test_grep ! . output
'
test_expect_success 'add untracked (multiple)' '
@@ -109,7 +109,7 @@ test_expect_success 'setup (commit)' '
'
test_expect_success 'status works (commit)' '
git add -i </dev/null >output &&
- grep "+1/-0 *+2/-0 file" output
+ test_grep "+1/-0 *+2/-0 file" output
'
test_expect_success 'update can stage deletions' '
@@ -141,7 +141,7 @@ test_expect_success 'revert works (commit)' '
git add file &&
test_write_lines r 1 | git add -i &&
git add -i </dev/null >output &&
- grep "unchanged *+3/-0 file" output
+ test_grep "unchanged *+3/-0 file" output
'
test_expect_success 'reject multi-key input' '
@@ -185,7 +185,7 @@ test_expect_success 'setup fake editor' '
test_expect_success 'bad edit rejected' '
git reset &&
test_write_lines e n d | git add -p >output &&
- grep "hunk does not apply" output
+ test_grep "hunk does not apply" output
'
test_expect_success 'setup patch' '
@@ -198,7 +198,7 @@ test_expect_success 'setup patch' '
test_expect_success 'garbage edit rejected' '
git reset &&
test_write_lines e n d | git add -p >output &&
- grep "hunk does not apply" output
+ test_grep "hunk does not apply" output
'
test_expect_success 'setup patch' '
@@ -313,8 +313,8 @@ test_expect_success FILEMODE 'stage mode and hunk' '
chmod +x file &&
printf "y\\ny\\n" | git add -p &&
git diff --cached file >out &&
- grep "new mode" out &&
- grep "+content" out &&
+ test_grep "new mode" out &&
+ test_grep "+content" out &&
git diff file >out &&
test_must_be_empty out
'
@@ -636,7 +636,7 @@ test_expect_success 'split hunk "add -p (edit)"' '
printf "%s\n" s e q n q q |
EDITOR=: git add -p &&
git diff >actual &&
- ! grep "^+15" actual
+ test_grep ! "^+15" actual
'
test_expect_success 'split hunk "add -p (no, yes, edit)"' '
@@ -648,7 +648,7 @@ test_expect_success 'split hunk "add -p (no, yes, edit)"' '
EDITOR=: git add -p 2>error &&
test_must_be_empty error &&
git diff >actual &&
- ! grep "^+31" actual
+ test_grep ! "^+31" actual
'
test_expect_success 'split hunk with incomplete line at end' '
@@ -682,7 +682,7 @@ test_expect_success 'edit, adding lines to the first hunk' '
EDITOR=./fake_editor.sh git add -p 2>error &&
test_must_be_empty error &&
git diff --cached >actual &&
- grep "^+22" actual
+ test_grep "^+22" actual
'
test_expect_success 'patch mode ignores unmerged entries' '
@@ -696,7 +696,7 @@ test_expect_success 'patch mode ignores unmerged entries' '
test_must_fail git merge side &&
echo changed >non-conflict.t &&
echo y | git add -p >output &&
- ! grep a/conflict.t output &&
+ test_grep ! a/conflict.t output &&
cat >expected <<-\EOF &&
* Unmerged path conflict.t
diff --git a/non-conflict.t b/non-conflict.t
@@ -728,7 +728,7 @@ test_expect_success 'diffs can be colorized' '
# We do not want to depend on the exact coloring scheme
# git uses for diffs, so just check that we saw some kind of color.
- grep "$(printf "\\033")" output
+ test_grep "$(printf "\\033")" output
'
test_expect_success 'colors can be overridden' '
@@ -743,7 +743,7 @@ test_expect_success 'colors can be overridden' '
-c color.interactive.error=blue \
add -i 2>err.raw <input &&
test_decode_color <err.raw >err &&
- grep "<BLUE>Huh (trigger)?<RESET>" err &&
+ test_grep "<BLUE>Huh (trigger)?<RESET>" err &&
test_write_lines help quit >input &&
force_color git \
@@ -863,7 +863,7 @@ test_expect_success 'colorized diffs respect diff.wsErrorHighlight' '
printf y >y &&
force_color git -c diff.wsErrorHighlight=all add -p >output.raw 2>&1 <y &&
test_decode_color <output.raw >output &&
- grep "old<" output
+ test_grep "old<" output
'
test_expect_success 'diffFilter filters diff' '
@@ -876,7 +876,7 @@ test_expect_success 'diffFilter filters diff' '
# avoid depending on the exact coloring or content of the prompts,
# and just make sure we saw our diff prefixed
- grep foo:.*content output
+ test_grep foo:.*content output
'
test_expect_success 'detect bogus diffFilter output' '
@@ -886,7 +886,7 @@ test_expect_success 'detect bogus diffFilter output' '
test_config interactive.diffFilter "sed 6d" &&
printf y >y &&
force_color test_must_fail git add -p <y >output 2>&1 &&
- grep "mismatched output" output
+ test_grep "mismatched output" output
'
test_expect_success 'handle iffy colored hunk headers' '
@@ -896,7 +896,7 @@ test_expect_success 'handle iffy colored hunk headers' '
printf n >n &&
force_color git -c interactive.diffFilter="sed s/.*@@.*/XX/" \
add -p >output 2>&1 <n &&
- grep "^XX$" output
+ test_grep "^XX$" output
'
test_expect_success 'handle very large filtered diff' '
@@ -1002,7 +1002,7 @@ test_expect_success 'add -p does not expand argument lists' '
# update it, but we want to be sure that our "." pathspec
# was not expanded into the argument list of any command.
# So look only for "not-changed".
- ! grep -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out
+ test_grep ! -E "^trace: (built-in|exec|run_command): .*not-changed" trace.out
'
test_expect_success 'hunk-editing handles custom comment char' '
@@ -1072,21 +1072,21 @@ test_expect_success 'setup different kinds of dirty submodules' '
test_expect_success 'status ignores dirty submodules (except HEAD)' '
git -C for-submodules add -i </dev/null >output &&
- grep dirty-head output &&
- grep dirty-both-ways output &&
- ! grep dirty-otherwise output
+ test_grep dirty-head output &&
+ test_grep dirty-both-ways output &&
+ test_grep ! dirty-otherwise output
'
test_expect_success 'handle submodules' '
echo 123 >>for-submodules/dirty-otherwise/initial.t &&
force_color git -C for-submodules add -p dirty-otherwise >output 2>&1 &&
- grep "No changes" output &&
+ test_grep "No changes" output &&
force_color git -C for-submodules add -p dirty-head >output 2>&1 <y &&
git -C for-submodules ls-files --stage dirty-head >actual &&
rev="$(git -C for-submodules/dirty-head rev-parse HEAD)" &&
- grep "$rev" actual
+ test_grep "$rev" actual
'
test_expect_success 'set up pathological context' '
@@ -1230,4 +1230,75 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' '
test_cmp expect actual
'
+test_expect_success 'add -p respects diff.context' '
+ test_write_lines a b c d e f g h i j k l m >file &&
+ git add file &&
+ test_write_lines a b c d e f G h i j k l m >file &&
+ echo y | git -c diff.context=5 add -p >actual &&
+ test_grep "@@ -2,11 +2,11 @@" actual
+'
+
+test_expect_success 'add -p respects diff.interHunkContext' '
+ test_write_lines a b c d e f g h i j k l m n o p q r s >file &&
+ git add file &&
+ test_write_lines a b c d E f g i i j k l m N o p q r s >file &&
+ echo y | git -c diff.interhunkcontext=2 add -p >actual &&
+ test_grep "@@ -2,16 +2,16 @@" actual
+'
+
+test_expect_success 'add -p rejects negative diff.context' '
+ test_config diff.context -1 &&
+ test_must_fail git add -p 2>output &&
+ test_grep "diff.context cannot be negative" output
+'
+
+for cmd in add checkout restore 'commit -m file'
+do
+ test_expect_success "${cmd%% *} accepts -U and --inter-hunk-context" '
+ test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
+ git add file &&
+ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
+ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
+ $cmd -p -U 4 --inter-hunk-context 2 >actual &&
+ test_grep "@@ -2,20 +2,20 @@" actual
+ '
+done
+
+test_expect_success 'reset accepts -U and --inter-hunk-context' '
+ test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
+ git commit -m file file &&
+ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
+ git add file &&
+ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
+ reset -p -U 4 --inter-hunk-context 2 >actual &&
+ test_grep "@@ -2,20 +2,20 @@" actual
+'
+
+test_expect_success 'stash accepts -U and --inter-hunk-context' '
+ test_write_lines a b c d e F g h i j k l m n o p Q r s t u v >file &&
+ git commit -m file file &&
+ test_write_lines a b c d e f g h i j k l m n o p q r s t u v >file &&
+ echo y | git -c diff.context=5 -c diff.interhunkcontext=1 \
+ stash -p -U 4 --inter-hunk-context 2 >actual &&
+ test_grep "@@ -2,20 +2,20 @@" actual
+'
+
+for cmd in add checkout commit reset restore "stash save" "stash push"
+do
+ test_expect_success "$cmd rejects invalid context options" '
+ test_must_fail git $cmd -p -U -3 2>actual &&
+ cat actual | echo &&
+ test_grep -e ".--unified. cannot be negative" actual &&
+
+ test_must_fail git $cmd -p --inter-hunk-context -3 2>actual &&
+ test_grep -e ".--inter-hunk-context. cannot be negative" actual &&
+
+ test_must_fail git $cmd -U 7 2>actual &&
+ test_grep -E ".--unified. requires .(--interactive/)?--patch." actual &&
+
+ test_must_fail git $cmd --inter-hunk-context 2 2>actual &&
+ test_grep -E ".--inter-hunk-context. requires .(--interactive/)?--patch." actual
+ '
+done
+
test_done
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 74666ff3e4..0bb4648e36 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -11,6 +11,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-unique-files.sh
+test_expect_success 'setup' '
+ test_oid_cache <<-EOF
+ export_base sha1:73c9bab443d1f88ac61aa533d2eeaaa15451239c
+ export_base sha256:f210fa6346e3e2ce047bdb570426b17075980c1ac01fec8fc4b75bd3ab4bcfe4
+ EOF
+'
+
test_expect_success 'usage on cmd and subcommand invalid option' '
test_expect_code 129 git stash --invalid-option 2>usage &&
grep "or: git stash" usage &&
@@ -1177,6 +1184,28 @@ test_expect_success 'stash -- <pathspec> stashes and restores the file' '
test_path_is_file bar
'
+test_expect_success 'stash --patch <pathspec> stash and restores the file' '
+ test_write_lines b c >file &&
+ git commit -m "add a few lines" file &&
+ test_write_lines a b c d >file &&
+ test_write_lines b c d >expect-file &&
+ echo changed-other-file >other-file &&
+ test_write_lines s y n | git stash -m "stash bar" --patch file &&
+ test_cmp expect-file file &&
+ echo changed-other-file >expect &&
+ test_cmp expect other-file &&
+ git checkout HEAD -- file &&
+ git stash pop &&
+ test_cmp expect other-file &&
+ test_write_lines a b c >expect &&
+ test_cmp expect file
+'
+
+test_expect_success 'stash <pathspec> -p is rejected' '
+ test_must_fail git stash file -p 2>err &&
+ test_grep "subcommand wasn${SQ}t specified; ${SQ}push${SQ} can${SQ}t be assumed due to unexpected token ${SQ}file${SQ}" err
+'
+
test_expect_success 'stash -- <pathspec> stashes in subdirectory' '
mkdir sub &&
>foo &&
@@ -1412,6 +1441,100 @@ test_expect_success 'stash --keep-index --include-untracked with empty tree' '
)
'
+test_expect_success 'stash export and import round-trip stashes' '
+ git reset &&
+ >untracked &&
+ >tracked1 &&
+ >tracked2 &&
+ git add tracked* &&
+ git stash -- &&
+ >subdir/untracked &&
+ >subdir/tracked1 &&
+ >subdir/tracked2 &&
+ git add subdir/tracked* &&
+ git stash --include-untracked -- subdir/ &&
+ git tag t-stash0 stash@{0} &&
+ git tag t-stash1 stash@{1} &&
+ simple=$(git stash export --print) &&
+ git stash clear &&
+ git stash import "$simple" &&
+ test_cmp_rev stash@{0} t-stash0 &&
+ test_cmp_rev stash@{1} t-stash1 &&
+ git stash export --to-ref refs/heads/foo &&
+ test_cmp_rev "$(test_oid empty_tree)" foo: &&
+ test_cmp_rev "$(test_oid empty_tree)" foo^: &&
+ test_cmp_rev t-stash0 foo^2 &&
+ test_cmp_rev t-stash1 foo^^2 &&
+ git log --first-parent --format="%s" refs/heads/foo >log &&
+ grep "^git stash: " log >log2 &&
+ test_line_count = 13 log2 &&
+ git stash clear &&
+ git stash import foo &&
+ test_cmp_rev stash@{0} t-stash0 &&
+ test_cmp_rev stash@{1} t-stash1
+'
+
+test_expect_success 'stash import appends commits' '
+ git log --format=oneline -g refs/stash >out &&
+ cat out out >out2 &&
+ git stash import refs/heads/foo &&
+ git log --format=oneline -g refs/stash >actual &&
+ test_line_count = $(wc -l <out2) actual
+'
+
+test_expect_success 'stash export can accept specified stashes' '
+ git stash clear &&
+ git stash import foo &&
+ git stash export --to-ref refs/heads/bar stash@{1} stash@{0} &&
+ git stash clear &&
+ git stash import refs/heads/bar &&
+ test_cmp_rev stash@{1} t-stash0 &&
+ test_cmp_rev stash@{0} t-stash1 &&
+ git log --format=oneline -g refs/stash >actual &&
+ test_line_count = 2 actual
+'
+
+test_expect_success 'stash export rejects invalid arguments' '
+ test_must_fail git stash export --print --to-ref refs/heads/invalid 2>err &&
+ grep "exactly one of --print and --to-ref is required" err &&
+ test_must_fail git stash export 2>err2 &&
+ grep "exactly one of --print and --to-ref is required" err2
+'
+
+test_expect_success 'stash can import and export zero stashes' '
+ git stash clear &&
+ git stash export --to-ref refs/heads/baz &&
+ test_cmp_rev "$(test_oid empty_tree)" baz: &&
+ test_cmp_rev "$(test_oid export_base)" baz &&
+ test_must_fail git rev-parse baz^1 &&
+ git stash import baz &&
+ test_must_fail git rev-parse refs/stash
+'
+
+test_expect_success 'stash rejects invalid attempts to import commits' '
+ git stash import foo &&
+ test_must_fail git stash import HEAD 2>output &&
+ oid=$(git rev-parse HEAD) &&
+ grep "$oid is not a valid exported stash commit" output &&
+ test_cmp_rev stash@{0} t-stash0 &&
+
+ git checkout --orphan orphan &&
+ git commit-tree $(test_oid empty_tree) -p "$oid" -p "$oid^" -m "" >fake-commit &&
+ git update-ref refs/heads/orphan "$(cat fake-commit)" &&
+ oid=$(git rev-parse HEAD) &&
+ test_must_fail git stash import orphan 2>output &&
+ grep "found stash commit $oid without expected prefix" output &&
+ test_cmp_rev stash@{0} t-stash0 &&
+
+ git checkout --orphan orphan2 &&
+ git commit-tree $(test_oid empty_tree) -m "" >fake-commit &&
+ git update-ref refs/heads/orphan2 "$(cat fake-commit)" &&
+ oid=$(git rev-parse HEAD) &&
+ test_must_fail git stash import orphan2 2>output &&
+ grep "found root commit $oid with invalid data" output &&
+ test_cmp_rev stash@{0} t-stash0
+'
+
test_expect_success 'stash apply should succeed with unmodified file' '
echo base >file &&
git add file &&
@@ -1549,11 +1672,9 @@ test_expect_success 'stash create reports a locked index' '
echo change >A.file &&
touch .git/index.lock &&
- cat >expect <<-EOF &&
- error: could not write index
- EOF
test_must_fail git stash create 2>err &&
- test_cmp expect err
+ test_grep "error: could not write index" err &&
+ test_grep "error: Unable to create '.*index.lock'" err
)
'
@@ -1566,11 +1687,9 @@ test_expect_success 'stash push reports a locked index' '
echo change >A.file &&
touch .git/index.lock &&
- cat >expect <<-EOF &&
- error: could not write index
- EOF
test_must_fail git stash push 2>err &&
- test_cmp expect err
+ test_grep "error: could not write index" err &&
+ test_grep "error: Unable to create '.*index.lock'" err
)
'
@@ -1584,11 +1703,41 @@ test_expect_success 'stash apply reports a locked index' '
git stash push &&
touch .git/index.lock &&
- cat >expect <<-EOF &&
- error: could not write index
- EOF
test_must_fail git stash apply 2>err &&
- test_cmp expect err
+ test_grep "error: could not write index" err &&
+ test_grep "error: Unable to create '.*index.lock'" err
+ )
+'
+
+test_expect_success 'submodules does not affect the branch recorded in stash message' '
+ git init sub_project &&
+ (
+ cd sub_project &&
+ echo "Initial content in sub_project" >sub_file.txt &&
+ git add sub_file.txt &&
+ git commit -m "Initial commit in sub_project"
+ ) &&
+
+ git init main_project &&
+ (
+ cd main_project &&
+ echo "Initial content in main_project" >main_file.txt &&
+ git add main_file.txt &&
+ git commit -m "Initial commit in main_project" &&
+
+ git -c protocol.file.allow=always submodule add ../sub_project sub &&
+ git commit -m "Added submodule sub_project" &&
+
+ git checkout -b feature_main &&
+ git -C sub checkout -b feature_sub &&
+
+ git checkout -b work_branch &&
+ echo "Important work to be stashed" >work_item.txt &&
+ git add work_item.txt &&
+ git stash push -m "custom stash for work_branch" &&
+
+ git stash list >../actual_stash_list.txt &&
+ grep "On work_branch: custom stash for work_branch" ../actual_stash_list.txt
)
'
diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh
index a51f881b1c..32b14e3a71 100755
--- a/t/t4000-diff-format.sh
+++ b/t/t4000-diff-format.sh
@@ -36,7 +36,7 @@ test_expect_success 'git diff-files -p after editing work tree.' '
# that's as far as it comes
if [ "$(git config --get core.filemode)" = false ]
then
- say 'filemode disabled on the filesystem'
+ skip_all='filemode disabled on the filesystem'
test_done
fi
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 782d97fb7d..cfeec239e0 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -206,14 +206,30 @@ do
expect="$TEST_DIRECTORY/t4013/diff.$test"
actual="$pfx-diff.$test"
- test_expect_success "git $cmd # magic is ${magic:-(not used)}" '
+ case "$cmd" in
+ whatchanged | whatchanged" "*)
+ prereq=!WITH_BREAKING_CHANGES
+ ;;
+ *)
+ prereq=;;
+ esac
+
+ test_expect_success $prereq "git $cmd # magic is ${magic:-(not used)}" '
{
echo "$ git $cmd"
+
+ case "$cmd" in
+ whatchanged | whatchanged" "*)
+ run="whatchanged --i-still-use-this"
+ run="$run ${cmd#whatchanged}" ;;
+ *)
+ run=$cmd ;;
+ esac &&
case "$magic" in
"")
- GIT_PRINT_SHA1_ELLIPSIS=yes git $cmd ;;
+ GIT_PRINT_SHA1_ELLIPSIS=yes git $run ;;
noellipses)
- git $cmd ;;
+ git $run ;;
esac |
sed -e "s/^\\(-*\\)$V\\(-*\\)\$/\\1g-i-t--v-e-r-s-i-o-n\2/" \
-e "s/^\\(.*mixed; boundary=\"-*\\)$V\\(-*\\)\"\$/\\1g-i-t--v-e-r-s-i-o-n\2\"/"
@@ -460,6 +476,11 @@ diff-tree --stat --compact-summary initial mode
diff-tree -R --stat --compact-summary initial mode
EOF
+test_expect_success !WITH_BREAKING_CHANGES 'whatchanged needs --i-still-use-this' '
+ test_must_fail git whatchanged >message 2>&1 &&
+ test_grep "nominated for removal" message
+'
+
test_expect_success 'log -m matches pure log' '
git log master >result &&
process_diffs result >expected &&
@@ -627,6 +648,19 @@ test_expect_success 'diff -I<regex>: detect malformed regex' '
test_grep "invalid regex given to -I: " error
'
+test_expect_success 'diff -I<regex>: ignore matching file' '
+ test_when_finished "git rm -f file1" &&
+ test_seq 50 >file1 &&
+ git add file1 &&
+ test_seq 50 | sed -e "s/13/ten and three/" -e "s/^[124-9].*/& /" >file1 &&
+
+ : >actual &&
+ git diff --raw --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
+ git diff --name-only --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
+ git diff --name-status --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
+ test_grep ! "file1" actual
+'
+
# check_prefix <patch> <src> <dst>
# check only lines with paths to avoid dependency on exact oid/contents
check_prefix () {
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index 52e3e476ff..9de7f73f42 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -11,12 +11,8 @@ test_description='Test special whitespace in diff engine.
. "$TEST_DIRECTORY"/lib-diff.sh
for opt_res in --patch --quiet -s --stat --shortstat --dirstat=lines \
- --raw! --name-only! --name-status!
+ --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 &&
@@ -43,7 +39,7 @@ do
echo foo >x &&
git add x &&
echo " foo" >x &&
- $expect_failure git diff -w $opts --exit-code x
+ git diff -w $opts --exit-code x
'
done
diff --git a/t/t4018/r-indent b/t/t4018/r-indent
new file mode 100644
index 0000000000..9df440f2a4
--- /dev/null
+++ b/t/t4018/r-indent
@@ -0,0 +1,6 @@
+RIGHT <- function(a, b) {
+ c = mean(a, b)
+ d = c + 2
+ ChangeMe()
+ return (d)
+}
diff --git a/t/t4018/r-indent-nested b/t/t4018/r-indent-nested
new file mode 100644
index 0000000000..30412e6c79
--- /dev/null
+++ b/t/t4018/r-indent-nested
@@ -0,0 +1,10 @@
+LEFT = function(a, b) {
+ c = mean(a, b)
+ RIGHT = function(d, e) {
+ f = var(d, e)
+ g = f + 1
+ ChangeMe()
+ return (g)
+ }
+ return (RIGHT(2, 3))
+}
diff --git a/t/t4018/r-noindent b/t/t4018/r-noindent
new file mode 100644
index 0000000000..6d9b01ffe3
--- /dev/null
+++ b/t/t4018/r-noindent
@@ -0,0 +1,6 @@
+RIGHT <- function(a, b) {
+c = mean(a, b)
+d = c + 2
+ChangeMe()
+return (c)
+}
diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh
index 28f9d83d4c..4d4aa1650f 100755
--- a/t/t4041-diff-submodule-option.sh
+++ b/t/t4041-diff-submodule-option.sh
@@ -48,11 +48,12 @@ commit_file () {
git commit "$@" -m "Commit $*" >/dev/null
}
-test_create_repo sm1 &&
-add_file . foo >/dev/null
-
-head1=$(add_file sm1 foo1 foo2)
-fullhead1=$(cd sm1; git rev-parse --verify HEAD)
+test_expect_success 'setup submodule' '
+ git init sm1 &&
+ add_file . foo &&
+ head1=$(add_file sm1 foo1 foo2) &&
+ fullhead1=$(cd sm1 && git rev-parse --verify HEAD)
+'
test_expect_success 'added submodule' '
git add sm1 &&
@@ -235,10 +236,13 @@ test_expect_success 'typechanged submodule(submodule->blob)' '
test_cmp expected actual
'
-rm -f sm1 &&
-test_create_repo sm1 &&
-head6=$(add_file sm1 foo6 foo7)
-fullhead6=$(cd sm1; git rev-parse --verify HEAD)
+test_expect_success 'setup submodule anew' '
+ rm -f sm1 &&
+ git init sm1 &&
+ head6=$(add_file sm1 foo6 foo7) &&
+ fullhead6=$(cd sm1 && git rev-parse --verify HEAD)
+'
+
test_expect_success 'nonexistent commit' '
git diff-index -p --submodule=log HEAD >actual &&
cat >expected <<-EOF &&
diff --git a/t/t4042-diff-textconv-caching.sh b/t/t4042-diff-textconv-caching.sh
index ff0e73531b..31018ceba2 100755
--- a/t/t4042-diff-textconv-caching.sh
+++ b/t/t4042-diff-textconv-caching.sh
@@ -120,6 +120,14 @@ test_expect_success 'log notes cache and still use cache for -p' '
'
test_expect_success 'caching is silently ignored outside repo' '
+ test_oid_cache <<-\EOM &&
+ oid1 sha1:5626abf
+ oid1 sha256:a4ed1f3
+ oid2 sha1:f719efd
+ oid2 sha256:aa9e7dc
+ EOM
+ oid1=$(test_oid --hash=builtin oid1) &&
+ oid2=$(test_oid --hash=builtin oid2) &&
mkdir -p non-repo &&
echo one >non-repo/one &&
echo two >non-repo/two &&
@@ -129,9 +137,9 @@ test_expect_success 'caching is silently ignored outside repo' '
-c diff.test.textconv="tr a-z A-Z <" \
-c diff.test.cachetextconv=true \
diff --no-index one two >actual &&
- cat >expect <<-\EOF &&
+ cat >expect <<-EOF &&
diff --git a/one b/two
- index 5626abf..f719efd 100644
+ index $oid1..$oid2 100644
--- a/one
+++ b/two
@@ -1 +1 @@
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
index 5e5bad61ca..44b4b13f5d 100755
--- a/t/t4053-diff-no-index.sh
+++ b/t/t4053-diff-no-index.sh
@@ -26,6 +26,23 @@ test_expect_success 'git diff --no-index directories' '
test_line_count = 14 cnt
'
+test_expect_success 'git diff --no-index with -' '
+ cat >expect <<-\EOF &&
+ diff --git a/- b/-
+ new file mode 100644
+ --- /dev/null
+ +++ b/-
+ @@ -0,0 +1 @@
+ +frotz
+ EOF
+ (
+ cd a &&
+ echo frotz |
+ test_expect_code 1 git diff --no-index /dev/null - >../actual
+ ) &&
+ test_cmp expect actual
+'
+
test_expect_success 'git diff --no-index relative path outside repo' '
(
cd repo &&
@@ -295,4 +312,79 @@ test_expect_success PIPE,SYMLINKS 'diff --no-index reads from pipes' '
test_cmp expect actual
'
+test_expect_success 'diff --no-index F F rejects pathspecs' '
+ test_must_fail git diff --no-index -- a/1 a/2 a 2>actual.err &&
+ test_grep "usage: git diff --no-index" actual.err
+'
+
+test_expect_success 'diff --no-index D F rejects pathspecs' '
+ test_must_fail git diff --no-index -- a a/2 a 2>actual.err &&
+ test_grep "usage: git diff --no-index" actual.err
+'
+
+test_expect_success 'diff --no-index F D rejects pathspecs' '
+ test_must_fail git diff --no-index -- a/1 b b 2>actual.err &&
+ test_grep "usage: git diff --no-index" actual.err
+'
+
+test_expect_success 'diff --no-index rejects absolute pathspec' '
+ test_must_fail git diff --no-index -- a b $(pwd)/a/1
+'
+
+test_expect_success 'diff --no-index with pathspec' '
+ test_expect_code 1 git diff --name-status --no-index a b 1 >actual &&
+ cat >expect <<-EOF &&
+ D a/1
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'diff --no-index with pathspec no matches' '
+ test_expect_code 0 git diff --name-status --no-index a b missing
+'
+
+test_expect_success 'diff --no-index with negative pathspec' '
+ test_expect_code 1 git diff --name-status --no-index a b ":!2" >actual &&
+ cat >expect <<-EOF &&
+ D a/1
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'setup nested' '
+ mkdir -p c/1/2 &&
+ mkdir -p d/1/2 &&
+ echo 1 >c/1/2/a &&
+ echo 2 >c/1/2/b
+'
+
+test_expect_success 'diff --no-index with pathspec nested negative pathspec' '
+ test_expect_code 0 git diff --no-index c d ":!1"
+'
+
+test_expect_success 'diff --no-index with pathspec nested pathspec' '
+ test_expect_code 1 git diff --name-status --no-index c d 1/2 >actual &&
+ cat >expect <<-EOF &&
+ D c/1/2/a
+ D c/1/2/b
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'diff --no-index with pathspec glob' '
+ test_expect_code 1 git diff --name-status --no-index c d ":(glob)**/a" >actual &&
+ cat >expect <<-EOF &&
+ D c/1/2/a
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'diff --no-index with pathspec glob and exclude' '
+ test_expect_code 1 git diff --name-status --no-index c d ":(glob,exclude)**/a" >actual &&
+ cat >expect <<-EOF &&
+ D c/1/2/b
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4055-diff-context.sh b/t/t4055-diff-context.sh
index ec2804eea6..1384a81957 100755
--- a/t/t4055-diff-context.sh
+++ b/t/t4055-diff-context.sh
@@ -38,55 +38,55 @@ test_expect_success 'setup' '
test_expect_success 'the default number of context lines is 3' '
git diff >output &&
- ! grep "^ d" output &&
- grep "^ e" output &&
- grep "^ j" output &&
- ! grep "^ k" output
+ test_grep ! "^ d" output &&
+ test_grep "^ e" output &&
+ test_grep "^ j" output &&
+ test_grep ! "^ k" output
'
test_expect_success 'diff.context honored by "log"' '
git log -1 -p >output &&
- ! grep firstline output &&
- git config diff.context 8 &&
+ test_grep ! firstline output &&
+ test_config diff.context 8 &&
git log -1 -p >output &&
- grep "^ firstline" output
+ test_grep "^ firstline" output
'
test_expect_success 'The -U option overrides diff.context' '
- git config diff.context 8 &&
+ test_config diff.context 8 &&
git log -U4 -1 >output &&
- ! grep "^ firstline" output
+ test_grep ! "^ firstline" output
'
test_expect_success 'diff.context honored by "diff"' '
- git config diff.context 8 &&
+ test_config diff.context 8 &&
git diff >output &&
- grep "^ firstline" output
+ test_grep "^ firstline" output
'
test_expect_success 'plumbing not affected' '
- git config diff.context 8 &&
+ test_config diff.context 8 &&
git diff-files -p >output &&
- ! grep "^ firstline" output
+ test_grep ! "^ firstline" output
'
test_expect_success 'non-integer config parsing' '
- git config diff.context no &&
+ test_config diff.context no &&
test_must_fail git diff 2>output &&
test_grep "bad numeric config value" output
'
test_expect_success 'negative integer config parsing' '
- git config diff.context -1 &&
+ test_config diff.context -1 &&
test_must_fail git diff 2>output &&
test_grep "bad config variable" output
'
test_expect_success '-U0 is valid, so is diff.context=0' '
- git config diff.context 0 &&
+ test_config diff.context 0 &&
git diff >output &&
- grep "^-ADDED" output &&
- grep "^+MODIFIED" output
+ test_grep "^-ADDED" output &&
+ test_grep "^+MODIFIED" output
'
test_expect_success '-U2147483647 works' '
@@ -94,9 +94,9 @@ test_expect_success '-U2147483647 works' '
test_line_count = 16 x &&
git diff -U2147483647 >output &&
test_line_count = 22 output &&
- grep "^-ADDED" output &&
- grep "^+MODIFIED" output &&
- grep "^+APPENDED" output
+ test_grep "^-ADDED" output &&
+ test_grep "^+MODIFIED" output &&
+ test_grep "^+APPENDED" output
'
test_done
diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh
index 76b83101d3..dbfeb7470b 100755
--- a/t/t4060-diff-submodule-option-diff-format.sh
+++ b/t/t4060-diff-submodule-option-diff-format.sh
@@ -363,9 +363,12 @@ test_expect_success 'typechanged submodule(submodule->blob)' '
diff_cmp expected actual
'
-rm -f sm1 &&
-test_create_repo sm1 &&
-head6=$(add_file sm1 foo6 foo7)
+test_expect_success 'setup' '
+ rm -f sm1 &&
+ git init sm1 &&
+ head6=$(add_file sm1 foo6 foo7)
+'
+
test_expect_success 'nonexistent commit' '
git diff-index -p --submodule=diff HEAD >actual &&
cat >expected <<-EOF &&
diff --git a/t/t4072-diff-max-depth.sh b/t/t4072-diff-max-depth.sh
new file mode 100755
index 0000000000..0fbf1321f7
--- /dev/null
+++ b/t/t4072-diff-max-depth.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+test_description='check that diff --max-depth will limit recursion'
+. ./test-lib.sh
+
+make_dir() {
+ mkdir -p "$1" &&
+ echo "$2" >"$1/file"
+}
+
+make_files() {
+ echo "$1" >file &&
+ make_dir one "$1" &&
+ make_dir one/two "$1" &&
+ make_dir one/two/three "$1"
+}
+
+test_expect_success 'setup' '
+ git commit --allow-empty -m empty &&
+ git tag empty &&
+ make_files added &&
+ git add . &&
+ git commit -m added &&
+ make_files modified &&
+ git add . &&
+ git commit -m modified &&
+ make_files index &&
+ git add . &&
+ make_files worktree
+'
+
+test_expect_success '--max-depth is disallowed with wildcard pathspecs' '
+ test_must_fail git diff-tree --max-depth=0 HEAD^ HEAD -- "f*"
+'
+
+check_one() {
+ type=$1; shift
+ args=$1; shift
+ path=$1; shift
+ depth=$1; shift
+ test_expect_${expect:-success} "diff-$type $args, path=$path, depth=$depth" "
+ for i in $*; do echo \$i; done >expect &&
+ git diff-$type --max-depth=$depth --name-only $args -- $path >actual &&
+ test_cmp expect actual
+ "
+}
+
+# For tree comparisons, we expect to see subtrees at the boundary
+# get their own entry.
+check_trees() {
+ check_one tree "$*" '' 0 file one
+ check_one tree "$*" '' 1 file one/file one/two
+ check_one tree "$*" '' 2 file one/file one/two/file one/two/three
+ check_one tree "$*" '' 3 file one/file one/two/file one/two/three/file
+ check_one tree "$*" '' -1 file one/file one/two/file one/two/three/file
+ check_one tree "$*" one 0 one
+ check_one tree "$*" one 1 one/file one/two
+ check_one tree "$*" one 2 one/file one/two/file one/two/three
+ check_one tree "$*" one 3 one/file one/two/file one/two/three/file
+ check_one tree "$*" one/two 0 one/two
+ check_one tree "$*" one/two 1 one/two/file one/two/three
+ check_one tree "$*" one/two 2 one/two/file one/two/three/file
+ check_one tree "$*" one/two 2 one/two/file one/two/three/file
+ check_one tree "$*" one/two/three 0 one/two/three
+ check_one tree "$*" one/two/three 1 one/two/three/file
+}
+
+# But for index comparisons, we do not store subtrees at all, so we do not
+# expect them.
+check_index() {
+ check_one "$@" '' 0 file
+ check_one "$@" '' 1 file one/file
+ check_one "$@" '' 2 file one/file one/two/file
+ check_one "$@" '' 3 file one/file one/two/file one/two/three/file
+ check_one "$@" one 0
+ check_one "$@" one 1 one/file
+ check_one "$@" one 2 one/file one/two/file
+ check_one "$@" one 3 one/file one/two/file one/two/three/file
+ check_one "$@" one/two 0
+ check_one "$@" one/two 1 one/two/file
+ check_one "$@" one/two 2 one/two/file one/two/three/file
+ check_one "$@" one/two/three 0
+ check_one "$@" one/two/three 1 one/two/three/file
+
+ # Value '-1' for '--max-depth is the same as recursion without limit,
+ # and thus should always succeed.
+ local expect=
+ check_one "$@" '' -1 file one/file one/two/file one/two/three/file
+}
+
+# Check as a modification...
+check_trees HEAD^ HEAD
+# ...and as an addition...
+check_trees empty HEAD
+# ...and as a deletion.
+check_trees HEAD empty
+
+# We currently only implement max-depth for trees.
+expect=failure
+# Check index against a tree
+check_index index "--cached HEAD"
+# and index against the worktree
+check_index files ""
+expect=
+
+test_expect_success 'find shortest path within embedded pathspecs' '
+ cat >expect <<-\EOF &&
+ one/file
+ one/two/file
+ one/two/three/file
+ EOF
+ git diff-tree --max-depth=2 --name-only HEAD^ HEAD -- one one/two >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t4140-apply-ita.sh b/t/t4140-apply-ita.sh
index c614eaf04c..0b11a8aef4 100755
--- a/t/t4140-apply-ita.sh
+++ b/t/t4140-apply-ita.sh
@@ -7,6 +7,10 @@ test_description='git apply of i-t-a file'
test_expect_success setup '
test_write_lines 1 2 3 4 5 >blueprint &&
+ cat blueprint >committed-file &&
+ git add committed-file &&
+ git commit -m "commit" &&
+
cat blueprint >test-file &&
git add -N test-file &&
git diff >creation-patch &&
@@ -14,7 +18,14 @@ test_expect_success setup '
rm -f test-file &&
git diff >deletion-patch &&
- grep "deleted file mode 100644" deletion-patch
+ grep "deleted file mode 100644" deletion-patch &&
+
+ git rm -f test-file &&
+ test_write_lines 6 >>committed-file &&
+ cat blueprint >test-file &&
+ git add -N test-file &&
+ git diff >complex-patch &&
+ git restore committed-file
'
test_expect_success 'apply creation patch to ita path (--cached)' '
@@ -53,4 +64,22 @@ test_expect_success 'apply deletion patch to ita path (--index)' '
git ls-files --stage --error-unmatch test-file
'
+test_expect_success 'apply creation patch to existing index with -N' '
+ git rm -f test-file &&
+ cat blueprint >index-file &&
+ git add index-file &&
+ git apply -N creation-patch &&
+
+ git ls-files --stage --error-unmatch index-file &&
+ git ls-files --stage --error-unmatch test-file
+'
+
+test_expect_success 'apply complex patch with -N' '
+ git rm -f test-file index-file &&
+ git apply -N complex-patch &&
+
+ git ls-files --stage --error-unmatch test-file &&
+ git diff | grep "a/committed-file"
+'
+
test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 2ae93d3c96..699a81ab5c 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -1086,7 +1086,7 @@ test_expect_success 'am works with multi-line in-body headers' '
# bump from, date, and subject down to in-body header
awk "
/^From:/{
- print \"From: x <x\@example.com>\";
+ print \"From: x <x@example.com>\";
print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\";
print \"Subject: x\n\";
}; 1
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 51f7beb59f..05cee9e41b 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -134,6 +134,12 @@ test_expect_success 'diff-filter=D' '
'
+test_expect_success 'all-negative filter' '
+ git log --no-renames --format=%s --diff-filter=d HEAD >actual &&
+ printf "%s\n" fifth fourth third second initial >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'diff-filter=R' '
git log -M --pretty="format:%s" --diff-filter=R HEAD >actual &&
@@ -486,10 +492,16 @@ test_expect_success !FAIL_PREREQS 'log with various grep.patternType configurati
)
'
-for cmd in show whatchanged reflog format-patch
+cmds="show reflog format-patch"
+if test_have_prereq !WITH_BREAKING_CHANGES
+then
+ cmds="$cmds whatchanged"
+fi
+for cmd in $cmds
do
case "$cmd" in
format-patch) myarg="HEAD~.." ;;
+ whatchanged) myarg=--i-still-use-this ;;
*) myarg= ;;
esac
@@ -1201,20 +1213,27 @@ test_expect_success 'reflog is expected format' '
test_cmp expect actual
'
-test_expect_success 'whatchanged is expected format' '
+test_expect_success !WITH_BREAKING_CHANGES 'whatchanged is expected format' '
+ whatchanged="whatchanged --i-still-use-this" &&
git log --no-merges --raw >expect &&
- git whatchanged >actual &&
+ git $whatchanged >actual &&
test_cmp expect actual
'
test_expect_success 'log.abbrevCommit configuration' '
+ whatchanged="whatchanged --i-still-use-this" &&
+
git log --abbrev-commit >expect.log.abbrev &&
git log --no-abbrev-commit >expect.log.full &&
git log --pretty=raw >expect.log.raw &&
git reflog --abbrev-commit >expect.reflog.abbrev &&
git reflog --no-abbrev-commit >expect.reflog.full &&
- git whatchanged --abbrev-commit >expect.whatchanged.abbrev &&
- git whatchanged --no-abbrev-commit >expect.whatchanged.full &&
+
+ if test_have_prereq !WITH_BREAKING_CHANGES
+ then
+ git $whatchanged --abbrev-commit >expect.whatchanged.abbrev &&
+ git $whatchanged --no-abbrev-commit >expect.whatchanged.full
+ fi &&
test_config log.abbrevCommit true &&
@@ -1231,10 +1250,13 @@ test_expect_success 'log.abbrevCommit configuration' '
git reflog --no-abbrev-commit >actual &&
test_cmp expect.reflog.full actual &&
- git whatchanged >actual &&
- test_cmp expect.whatchanged.abbrev actual &&
- git whatchanged --no-abbrev-commit >actual &&
- test_cmp expect.whatchanged.full actual
+ if test_have_prereq !WITH_BREAKING_CHANGES
+ then
+ git $whatchanged >actual &&
+ test_cmp expect.whatchanged.abbrev actual &&
+ git $whatchanged --no-abbrev-commit >actual &&
+ test_cmp expect.whatchanged.full actual
+ fi
'
test_expect_success '--abbrev-commit with core.abbrev=false' '
diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh
index 4a6242ff99..74b7ddccb2 100755
--- a/t/t4203-mailmap.sh
+++ b/t/t4203-mailmap.sh
@@ -1133,4 +1133,37 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us
test_cmp expect actual
'
+test_expect_success 'git cat-file --mailmap works with different author and committer' '
+ test_when_finished "rm .mailmap" &&
+ cat >.mailmap <<-\EOF &&
+ Mailmapped User <mailmapped-user@gitlab.com> C O Mitter <committer@example.com>
+ EOF
+ git commit --allow-empty -m "different author/committer" \
+ --author="Different Author <different@example.com>" &&
+ cat >expect <<-\EOF &&
+ author Different Author <different@example.com>
+ committer Mailmapped User <mailmapped-user@gitlab.com>
+ EOF
+ git cat-file --mailmap commit HEAD >log &&
+ sed -n -e "/^author /s/>.*/>/p" -e "/^committer /s/>.*/>/p" log >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git cat-file --mailmap maps both author and committer when both need mapping' '
+ test_when_finished "rm .mailmap" &&
+ cat >.mailmap <<-\EOF &&
+ Mapped Author <mapped-author@example.com> <different@example.com>
+ Mapped Committer <mapped-committer@example.com> C O Mitter <committer@example.com>
+ EOF
+ git commit --allow-empty -m "both author and committer mapped" \
+ --author="Different Author <different@example.com>" &&
+ cat >expect <<-\EOF &&
+ author Mapped Author <mapped-author@example.com>
+ committer Mapped Committer <mapped-committer@example.com>
+ EOF
+ git cat-file --mailmap commit HEAD >log &&
+ sed -n -e "/^author /s/>.*/>/p" -e "/^committer /s/>.*/>/p" log >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index 950451cf6a..0a7c3ca42f 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -78,6 +78,8 @@ canned_test "-L :main:a.c -L 4,18:a.c simple" multiple-overlapping
canned_test "-L 4:a.c -L 8,12:a.c simple" multiple-superset
canned_test "-L 8,12:a.c -L 4:a.c simple" multiple-superset
+canned_test "-L 10,16:b.c -L 18,26:b.c main" no-assertion-error
+
test_bad_opts "-L" "switch.*requires a value"
test_bad_opts "-L b.c" "argument not .start,end:file"
test_bad_opts "-L 1:" "argument not .start,end:file"
diff --git a/t/t4211/sha1/expect.multiple b/t/t4211/sha1/expect.multiple
index 76ad5b598c..1eee8a7801 100644
--- a/t/t4211/sha1/expect.multiple
+++ b/t/t4211/sha1/expect.multiple
@@ -102,3 +102,9 @@ diff --git a/a.c b/a.c
+ s++;
+ }
+}
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4211/sha1/expect.no-assertion-error b/t/t4211/sha1/expect.no-assertion-error
new file mode 100644
index 0000000000..994c37db1e
--- /dev/null
+++ b/t/t4211/sha1/expect.no-assertion-error
@@ -0,0 +1,90 @@
+commit 0d8dcfc6b968e06a27d5215bad1fdde3de9d6235
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:50:24 2013 +0100
+
+ move within the file
+
+diff --git a/b.c b/b.c
+--- a/b.c
++++ b/b.c
+@@ -25,0 +18,9 @@
++long f(long x)
++{
++ int s = 0;
++ while (x) {
++ x /= 2;
++ s++;
++ }
++ return s;
++}
+
+commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:48:43 2013 +0100
+
+ change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,7 @@
+ int main ()
+ {
+ printf("%ld\n", f(15));
+ return 0;
+-}
+\ No newline at end of file
++}
++
++/* incomplete lines are bad! */
+
+commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:48:10 2013 +0100
+
+ change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,5 @@
+ int main ()
+ {
+ printf("%ld\n", f(15));
+ return 0;
+-}
++}
+\ No newline at end of file
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:45:16 2013 +0100
+
+ touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -17,5 +17,5 @@
+ int main ()
+ {
+- printf("%d\n", f(15));
++ printf("%ld\n", f(15));
+ return 0;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:44:48 2013 +0100
+
+ initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4211/sha1/expect.two-ranges b/t/t4211/sha1/expect.two-ranges
index 6109aa0dce..c5164f3be3 100644
--- a/t/t4211/sha1/expect.two-ranges
+++ b/t/t4211/sha1/expect.two-ranges
@@ -100,3 +100,9 @@ diff --git a/a.c b/a.c
+ s++;
+ }
+}
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4211/sha256/expect.multiple b/t/t4211/sha256/expect.multiple
index ca00409b9a..dbd987b74a 100644
--- a/t/t4211/sha256/expect.multiple
+++ b/t/t4211/sha256/expect.multiple
@@ -102,3 +102,9 @@ diff --git a/a.c b/a.c
+ s++;
+ }
+}
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4211/sha256/expect.no-assertion-error b/t/t4211/sha256/expect.no-assertion-error
new file mode 100644
index 0000000000..36ed12aa9c
--- /dev/null
+++ b/t/t4211/sha256/expect.no-assertion-error
@@ -0,0 +1,90 @@
+commit eb871b8aa9aff323e484723039c9a92ab0266e060bc0ef2afb08fadda25c5ace
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:50:24 2013 +0100
+
+ move within the file
+
+diff --git a/b.c b/b.c
+--- a/b.c
++++ b/b.c
+@@ -25,0 +18,9 @@
++long f(long x)
++{
++ int s = 0;
++ while (x) {
++ x /= 2;
++ s++;
++ }
++ return s;
++}
+
+commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:48:43 2013 +0100
+
+ change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,7 @@
+ int main ()
+ {
+ printf("%ld\n", f(15));
+ return 0;
+-}
+\ No newline at end of file
++}
++
++/* incomplete lines are bad! */
+
+commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:48:10 2013 +0100
+
+ change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,5 @@
+ int main ()
+ {
+ printf("%ld\n", f(15));
+ return 0;
+-}
++}
+\ No newline at end of file
+
+commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:45:16 2013 +0100
+
+ touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -17,5 +17,5 @@
+ int main ()
+ {
+- printf("%d\n", f(15));
++ printf("%ld\n", f(15));
+ return 0;
+ }
+
+commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:44:48 2013 +0100
+
+ initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4211/sha256/expect.two-ranges b/t/t4211/sha256/expect.two-ranges
index af57c8b997..6a94d3b9cb 100644
--- a/t/t4211/sha256/expect.two-ranges
+++ b/t/t4211/sha256/expect.two-ranges
@@ -100,3 +100,9 @@ diff --git a/a.c b/a.c
+ s++;
+ }
+}
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index 8910d53cac..1064990de3 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -66,8 +66,9 @@ sane_unset GIT_TRACE2_CONFIG_PARAMS
setup () {
rm -f "$TRASH_DIRECTORY/trace.perf" &&
- git -c core.commitGraph=false log --pretty="format:%s" $1 >log_wo_bloom &&
- GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.perf" git -c core.commitGraph=true log --pretty="format:%s" $1 >log_w_bloom
+ eval git -c core.commitGraph=false log --pretty="format:%s" "$1" >log_wo_bloom &&
+ eval "GIT_TRACE2_PERF=\"$TRASH_DIRECTORY/trace.perf\"" \
+ git -c core.commitGraph=true log --pretty="format:%s" "$1" >log_w_bloom
}
test_bloom_filters_used () {
@@ -138,10 +139,6 @@ test_expect_success 'git log with --walk-reflogs does not use Bloom filters' '
test_bloom_filters_not_used "--walk-reflogs -- A"
'
-test_expect_success 'git log -- multiple path specs does not use Bloom filters' '
- test_bloom_filters_not_used "-- file4 A/file1"
-'
-
test_expect_success 'git log -- "." pathspec at root does not use Bloom filters' '
test_bloom_filters_not_used "-- ."
'
@@ -151,9 +148,40 @@ test_expect_success 'git log with wildcard that resolves to a single path uses B
test_bloom_filters_used "-- *renamed"
'
-test_expect_success 'git log with wildcard that resolves to a multiple paths does not uses Bloom filters' '
- test_bloom_filters_not_used "-- *" &&
- test_bloom_filters_not_used "-- file*"
+test_expect_success 'git log with multiple literal paths uses Bloom filter' '
+ test_bloom_filters_used "-- file4 A/file1" &&
+ test_bloom_filters_used "-- *" &&
+ test_bloom_filters_used "-- file*"
+'
+
+test_expect_success 'git log with paths all contain non-wildcard part uses Bloom filter' '
+ test_bloom_filters_used "-- A/\* file4" &&
+ test_bloom_filters_used "-- A/file\*" &&
+ test_bloom_filters_used "-- * A/\*"
+'
+
+test_expect_success 'git log with path only contains wildcard part does not use Bloom filter' '
+ test_bloom_filters_not_used "-- file\*" &&
+ test_bloom_filters_not_used "-- file\* A/\*" &&
+ test_bloom_filters_not_used "-- file\* *" &&
+ test_bloom_filters_not_used "-- \*"
+'
+
+test_expect_success 'git log with path contains various magic signatures' '
+ cd A &&
+ test_bloom_filters_used "-- \:\(top\)B" &&
+ cd .. &&
+
+ test_bloom_filters_used "-- \:\(glob\)A/\*\*/C" &&
+ test_bloom_filters_not_used "-- \:\(icase\)FILE4" &&
+ test_bloom_filters_not_used "-- \:\(exclude\)A/B/C" &&
+
+ test_when_finished "rm -f .gitattributes" &&
+ cat >.gitattributes <<-EOF &&
+ A/file1 text
+ A/B/file2 -text
+ EOF
+ test_bloom_filters_used "-- \:\(attr\:text\)A"
'
test_expect_success 'setup - add commit-graph to the chain without Bloom filters' '
diff --git a/t/t4256/1/mailinfo.c b/t/t4256/1/mailinfo.c
index b395adbdf2..39caeba865 100644
--- a/t/t4256/1/mailinfo.c
+++ b/t/t4256/1/mailinfo.c
@@ -1214,7 +1214,7 @@ void setup_mailinfo(struct mailinfo *mi)
mi->header_stage = 1;
mi->use_inbody_headers = 1;
mi->content_top = mi->content;
- git_config(git_mailinfo_config, mi);
+ repo_config(the_repository, git_mailinfo_config, mi);
}
void clear_mailinfo(struct mailinfo *mi)
diff --git a/t/t4256/1/mailinfo.c.orig b/t/t4256/1/mailinfo.c.orig
index 3281a37d51..b76eb866aa 100644
--- a/t/t4256/1/mailinfo.c.orig
+++ b/t/t4256/1/mailinfo.c.orig
@@ -1154,7 +1154,7 @@ void setup_mailinfo(struct mailinfo *mi)
mi->header_stage = 1;
mi->use_inbody_headers = 1;
mi->content_top = mi->content;
- git_config(git_mailinfo_config, mi);
+ repo_config(the_repository, git_mailinfo_config, mi);
}
void clear_mailinfo(struct mailinfo *mi)
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index 5174995191..027dedd976 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -176,10 +176,7 @@ test_expect_success EXPENSIVE,UNZIP,UNZIP_ZIP64_SUPPORT \
blob=$(echo $s | git hash-object -w --stdin) &&
# create tree containing 65500 entries of that blob
- for i in $(test_seq 1 65500)
- do
- echo "100644 blob $blob $i" || return 1
- done >tree &&
+ test_seq -f "100644 blob $blob\t%d" 1 65500 >tree &&
tree=$(git mktree <tree) &&
# zip it, creating an archive a bit bigger than 4GB
diff --git a/t/t5200-update-server-info.sh b/t/t5200-update-server-info.sh
index 8365907055..a551e955b5 100755
--- a/t/t5200-update-server-info.sh
+++ b/t/t5200-update-server-info.sh
@@ -46,4 +46,9 @@ test_expect_success 'midx does not create duplicate pack entries' '
test_must_be_empty dups
'
+test_expect_success 'update-server-info does not crash with -h' '
+ test_expect_code 129 git update-server-info -h >usage &&
+ test_grep "[Uu]sage: git update-server-info " usage
+'
+
test_done
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index a5932b6a8b..73445782e7 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -525,7 +525,7 @@ test_expect_success 'index-pack --strict <pack> works in non-repo' '
test_path_is_file foo.idx
'
-test_expect_success SHA1 'show-index works OK outside a repository' '
+test_expect_success DEFAULT_HASH_ALGORITHM 'show-index works OK outside a repository' '
nongit git show-index <foo.idx
'
@@ -658,7 +658,7 @@ do
test_commit -C repo initial &&
git -C repo repack -ad &&
git -C repo verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx &&
- if test $hash = sha1
+ if test $hash = $GIT_TEST_BUILTIN_HASH
then
nongit git verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx
else
@@ -676,7 +676,7 @@ do
test_commit -C repo initial &&
git -C repo repack -ad &&
git -C repo index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack &&
- if test $hash = sha1
+ if test $hash = $GIT_TEST_BUILTIN_HASH
then
nongit git index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack
else
@@ -723,4 +723,23 @@ test_expect_success '--name-hash-version=2 and --write-bitmap-index are incompat
! test_grep "currently, --write-bitmap-index requires --name-hash-version=1" err
'
+test_expect_success '--path-walk pack everything' '
+ git -C server rev-parse HEAD >in &&
+ GIT_PROGRESS_DELAY=0 git -C server pack-objects \
+ --stdout --revs --path-walk --progress <in >out.pack 2>err &&
+ grep "Compressing objects by path" err &&
+ git -C server index-pack --stdin <out.pack
+'
+
+test_expect_success '--path-walk thin pack' '
+ cat >in <<-EOF &&
+ $(git -C server rev-parse HEAD)
+ ^$(git -C server rev-parse HEAD~2)
+ EOF
+ GIT_PROGRESS_DELAY=0 git -C server pack-objects \
+ --thin --stdout --revs --path-walk --progress <in >out.pack 2>err &&
+ grep "Compressing objects by path" err &&
+ git -C server index-pack --fix-thin --stdin <out.pack
+'
+
test_done
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index 1f1f664871..2be7cd30de 100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -364,4 +364,9 @@ test_expect_success 'gc.recentObjectsHook' '
git cat-file -p $BLOB
'
+test_expect_success 'prune does not crash with -h' '
+ test_expect_code 129 git prune -h >usage &&
+ test_grep "[Uu]sage: git prune " usage
+'
+
test_done
diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh
index 805d60ff31..609399d54f 100755
--- a/t/t5306-pack-nobase.sh
+++ b/t/t5306-pack-nobase.sh
@@ -59,6 +59,11 @@ test_expect_success 'indirectly clone patch_clone' '
git pull ../.git &&
test $(git rev-parse HEAD) = $B &&
+ # The --path-walk feature of "git pack-objects" is not
+ # compatible with this kind of fetch from an incomplete repo.
+ GIT_TEST_PACK_PATH_WALK=0 &&
+ export GIT_TEST_PACK_PATH_WALK &&
+
git pull ../patch_clone/.git &&
test $(git rev-parse HEAD) = $C
)
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index a62b463eaf..6718fb98c0 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -158,8 +158,9 @@ test_bitmap_cases () {
ls .git/objects/pack/ | grep bitmap >output &&
test_line_count = 1 output &&
# verify equivalent packs are generated with/without using bitmap index
- packasha1=$(git pack-objects --no-use-bitmap-index --all packa </dev/null) &&
- packbsha1=$(git pack-objects --use-bitmap-index --all packb </dev/null) &&
+ # Be careful to not use the path-walk option in either case.
+ packasha1=$(git pack-objects --no-use-bitmap-index --no-path-walk --all packa </dev/null) &&
+ packbsha1=$(git pack-objects --use-bitmap-index --no-path-walk --all packb </dev/null) &&
list_packed_objects packa-$packasha1.idx >packa.objects &&
list_packed_objects packb-$packbsha1.idx >packb.objects &&
test_cmp packa.objects packb.objects
@@ -388,6 +389,14 @@ test_bitmap_cases () {
git init --bare client.git &&
(
cd client.git &&
+
+ # This test relies on reusing a delta, but if the
+ # path-walk machinery is engaged, the base object
+ # is considered too small to use during the
+ # dynamic computation, so is not used.
+ GIT_TEST_PACK_PATH_WALK=0 &&
+ export GIT_TEST_PACK_PATH_WALK &&
+
git config transfer.unpackLimit 1 &&
git fetch .. delta-reuse-old:delta-reuse-old &&
git fetch .. delta-reuse-new:delta-reuse-new &&
@@ -486,6 +495,36 @@ test_bitmap_cases () {
grep "ignoring extra bitmap" trace2.txt
)
'
+
+ test_expect_success 'load corrupt bitmap' '
+ rm -fr repo &&
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
+
+ test_commit base &&
+
+ git repack -adb &&
+ bitmap="$(ls .git/objects/pack/pack-*.bitmap)" &&
+ chmod +w $bitmap &&
+
+ test-tool bitmap list-commits-with-offset >offsets &&
+ xor_off=$(head -n1 offsets | awk "{print \$3}") &&
+ printf '\161' |
+ dd of=$bitmap count=1 bs=1 conv=notrunc seek=$xor_off &&
+
+ git rev-list --objects --no-object-names HEAD >expect.raw &&
+ git rev-list --objects --use-bitmap-index --no-object-names HEAD \
+ >actual.raw &&
+
+ sort expect.raw >expect &&
+ sort actual.raw >actual &&
+
+ test_cmp expect actual
+ )
+ '
}
test_bitmap_cases
diff --git a/t/t5316-pack-delta-depth.sh b/t/t5316-pack-delta-depth.sh
index defaa06d65..03dfb7a61e 100755
--- a/t/t5316-pack-delta-depth.sh
+++ b/t/t5316-pack-delta-depth.sh
@@ -89,15 +89,18 @@ max_chain() {
# adjusted (or scrapped if the heuristics have become too unreliable)
test_expect_success 'packing produces a long delta' '
# Use --window=0 to make sure we are seeing reused deltas,
- # not computing a new long chain.
- pack=$(git pack-objects --all --window=0 </dev/null pack) &&
+ # not computing a new long chain. (Also avoid the --path-walk
+ # option as it may break delta chains.)
+ pack=$(git pack-objects --all --window=0 --no-path-walk </dev/null pack) &&
echo 9 >expect &&
max_chain pack-$pack.pack >actual &&
test_cmp expect actual
'
test_expect_success '--depth limits depth' '
- pack=$(git pack-objects --all --depth=5 </dev/null pack) &&
+ # Avoid --path-walk to avoid breaking delta chains across path
+ # boundaries.
+ pack=$(git pack-objects --all --depth=5 --no-path-walk </dev/null pack) &&
echo 5 >expect &&
max_chain pack-$pack.pack >actual &&
test_cmp expect actual
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index bd75dea950..93f319a4b2 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -28,11 +28,11 @@ midx_read_expect () {
EOF
if test $NUM_PACKS -ge 1
then
- ls $OBJECT_DIR/pack/ | grep idx | sort
+ ls "$OBJECT_DIR"/pack/ | grep idx | sort
fi &&
printf "object-dir: $OBJECT_DIR\n"
} >expect &&
- test-tool read-midx $OBJECT_DIR >actual &&
+ test-tool read-midx "$OBJECT_DIR" >actual &&
test_cmp expect actual
}
@@ -305,7 +305,7 @@ test_expect_success 'midx picks objects from preferred pack' '
ofs=$(git show-index <objects/pack/test-BC-$bc.idx | grep $b |
cut -d" " -f1) &&
- printf "%s %s\tobjects/pack/test-BC-%s.pack\n" \
+ printf "%s %s\t./objects/pack/test-BC-%s.pack\n" \
"$b" "$ofs" "$bc" >expect &&
grep ^$b out >actual &&
@@ -639,7 +639,7 @@ test_expect_success 'force some 64-bit offsets with pack-objects' '
( cd ../objects64 && pwd ) >.git/objects/info/alternates &&
midx64=$(git multi-pack-index --object-dir=../objects64 write)
) &&
- midx_read_expect 1 63 5 objects64 " large-offsets"
+ midx_read_expect 1 63 5 "$(pwd)/objects64" " large-offsets"
'
test_expect_success 'verify multi-pack-index with 64-bit offsets' '
@@ -989,6 +989,23 @@ test_expect_success 'repack --batch-size=0 repacks everything' '
)
'
+test_expect_success EXPENSIVE 'repack/expire with many packs' '
+ cp -r dup many &&
+ (
+ cd many &&
+
+ for i in $(test_seq 1 100)
+ do
+ test_commit extra$i &&
+ git maintenance run --task=loose-objects || return 1
+ done &&
+
+ git multi-pack-index write &&
+ git multi-pack-index repack &&
+ git multi-pack-index expire
+ )
+'
+
test_expect_success 'repack --batch-size=<large> repacks everything' '
(
cd dup2 &&
@@ -1083,7 +1100,10 @@ test_expect_success 'load reverse index when missing .idx, .pack' '
mv $idx.bak $idx &&
mv $pack $pack.bak &&
- git cat-file --batch-check="%(objectsize:disk)" <tip
+ git cat-file --batch-check="%(objectsize:disk)" <tip &&
+
+ test_must_fail git multi-pack-index write 2>err &&
+ test_grep "could not load pack" err
)
'
diff --git a/t/t5323-pack-redundant.sh b/t/t5323-pack-redundant.sh
index bc30bc9652..2d96afd6f7 100755
--- a/t/t5323-pack-redundant.sh
+++ b/t/t5323-pack-redundant.sh
@@ -45,6 +45,11 @@ fi
main_repo=main.git
shared_repo=shared.git
+test_expect_success 'pack-redundant needs --i-still-use-this' '
+ test_must_fail git pack-redundant >message 2>&1 &&
+ test_grep "nominated for removal" message
+'
+
git_pack_redundant='git pack-redundant --i-still-use-this'
# Create commits in <repo> and assign each commit's oid to shell variables
diff --git a/t/t5331-pack-objects-stdin.sh b/t/t5331-pack-objects-stdin.sh
index b48c0cbe8f..4a8df5a389 100755
--- a/t/t5331-pack-objects-stdin.sh
+++ b/t/t5331-pack-objects-stdin.sh
@@ -64,7 +64,7 @@ test_expect_success '--stdin-packs is incompatible with --filter' '
cd stdin-packs &&
test_must_fail git pack-objects --stdin-packs --stdout \
--filter=blob:none </dev/null 2>err &&
- test_grep "cannot use --filter with --stdin-packs" err
+ test_grep "options .--stdin-packs. and .--filter. cannot be used together" err
)
'
@@ -236,4 +236,124 @@ test_expect_success 'pack-objects --stdin with packfiles from main and alternate
test_cmp expected-objects actual-objects
'
+objdir=.git/objects
+packdir=$objdir/pack
+
+objects_in_packs () {
+ for p in "$@"
+ do
+ git show-index <"$packdir/pack-$p.idx" || return 1
+ done >objects.raw &&
+
+ cut -d' ' -f2 objects.raw | sort &&
+ rm -f objects.raw
+}
+
+test_expect_success '--stdin-packs=follow walks into unknown packs' '
+ test_when_finished "rm -fr repo" &&
+
+ git init repo &&
+ (
+ cd repo &&
+
+ for c in A B C D
+ do
+ test_commit "$c" || return 1
+ done &&
+
+ A="$(echo A | git pack-objects --revs $packdir/pack)" &&
+ B="$(echo A..B | git pack-objects --revs $packdir/pack)" &&
+ C="$(echo B..C | git pack-objects --revs $packdir/pack)" &&
+ D="$(echo C..D | git pack-objects --revs $packdir/pack)" &&
+ test_commit E &&
+
+ git prune-packed &&
+
+ cat >in <<-EOF &&
+ pack-$B.pack
+ ^pack-$C.pack
+ pack-$D.pack
+ EOF
+
+ # With just --stdin-packs, pack "A" is unknown to us, so
+ # only objects from packs "B" and "D" are included in
+ # the output pack.
+ P=$(git pack-objects --stdin-packs $packdir/pack <in) &&
+ objects_in_packs $B $D >expect &&
+ objects_in_packs $P >actual &&
+ test_cmp expect actual &&
+
+ # But with --stdin-packs=follow, objects from both
+ # included packs reach objects from the unknown pack, so
+ # objects from pack "A" is included in the output pack
+ # in addition to the above.
+ P=$(git pack-objects --stdin-packs=follow $packdir/pack <in) &&
+ objects_in_packs $A $B $D >expect &&
+ objects_in_packs $P >actual &&
+ test_cmp expect actual &&
+
+ # And with --unpacked, we will pick up objects from unknown
+ # packs that are reachable from loose objects. Loose object E
+ # reaches objects in pack A, but there are three excluded packs
+ # in between.
+ #
+ # The resulting pack should include objects reachable from E
+ # that are not present in packs B, C, or D, along with those
+ # present in pack A.
+ cat >in <<-EOF &&
+ ^pack-$B.pack
+ ^pack-$C.pack
+ ^pack-$D.pack
+ EOF
+
+ P=$(git pack-objects --stdin-packs=follow --unpacked \
+ $packdir/pack <in) &&
+
+ {
+ objects_in_packs $A &&
+ git rev-list --objects --no-object-names D..E
+ }>expect.raw &&
+ sort expect.raw >expect &&
+ objects_in_packs $P >actual &&
+ test_cmp expect actual
+ )
+'
+
+stdin_packs__follow_with_only () {
+ rm -fr stdin_packs__follow_with_only &&
+ git init stdin_packs__follow_with_only &&
+ (
+ cd stdin_packs__follow_with_only &&
+
+ test_commit A &&
+ test_commit B &&
+
+ git rev-parse "$@" >B.objects &&
+
+ echo A | git pack-objects --revs $packdir/pack &&
+ B="$(git pack-objects $packdir/pack <B.objects)" &&
+
+ git cat-file --batch-check="%(objectname)" --batch-all-objects >objs &&
+ for obj in $(cat objs)
+ do
+ rm -f $objdir/$(test_oid_to_path $obj) || return 1
+ done &&
+
+ ( cd $packdir && ls pack-*.pack ) >in &&
+ git pack-objects --stdin-packs=follow --stdout >/dev/null <in
+ )
+}
+
+test_expect_success '--stdin-packs=follow tolerates missing blobs' '
+ stdin_packs__follow_with_only HEAD HEAD^{tree}
+'
+
+test_expect_success '--stdin-packs=follow tolerates missing trees' '
+ stdin_packs__follow_with_only HEAD HEAD:B.t
+'
+
+test_expect_success '--stdin-packs=follow tolerates missing commits' '
+ stdin_packs__follow_with_only HEAD HEAD^{tree}
+'
+
test_done
diff --git a/t/t5332-multi-pack-reuse.sh b/t/t5332-multi-pack-reuse.sh
index 57cad7708f..395d09444c 100755
--- a/t/t5332-multi-pack-reuse.sh
+++ b/t/t5332-multi-pack-reuse.sh
@@ -7,6 +7,13 @@ test_description='pack-objects multi-pack reuse'
GIT_TEST_MULTI_PACK_INDEX=0
GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0
+
+# The --path-walk option does not consider the preferred pack
+# at all for reusing deltas, so this variable changes the
+# behavior of this test, if enabled.
+GIT_TEST_PACK_PATH_WALK=0
+export GIT_TEST_PACK_PATH_WALK
+
objdir=.git/objects
packdir=$objdir/pack
diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh
index 56674db562..1f7a5d82ee 100755
--- a/t/t5333-pseudo-merge-bitmaps.sh
+++ b/t/t5333-pseudo-merge-bitmaps.sh
@@ -234,8 +234,8 @@ test_expect_success 'pseudo-merge pattern with capture groups' '
test_commit_bulk 16 &&
git rev-list HEAD~16.. >in &&
- sed "s|\(.*\)|create refs/remotes/$r/tags/\1 \1" in |
- git update-ref --stdin || return 1
+ sed "s|\(.*\)|create refs/remotes/$r/tags/\1 \1|" in >refs &&
+ git update-ref --stdin <refs || return 1
done &&
git \
@@ -445,4 +445,21 @@ test_expect_success 'pseudo-merge closure' '
)
'
+test_expect_success 'use pseudo-merge in boundary traversal' '
+ git init pseudo-merge-boundary-traversal &&
+ (
+ cd pseudo-merge-boundary-traversal &&
+
+ git config bitmapPseudoMerge.test.pattern refs/ &&
+ git config pack.useBitmapBoundaryTraversal true &&
+
+ test_commit A &&
+ git repack -adb &&
+ test_commit B &&
+
+ nr=$(git rev-list --count --use-bitmap-index HEAD~1..HEAD) &&
+ test 1 -eq "$nr"
+ )
+'
+
test_done
diff --git a/t/t5408-send-pack-stdin.sh b/t/t5408-send-pack-stdin.sh
index 526a675045..ec339761c2 100755
--- a/t/t5408-send-pack-stdin.sh
+++ b/t/t5408-send-pack-stdin.sh
@@ -69,15 +69,24 @@ test_expect_success 'stdin mixed with cmdline' '
test_expect_success 'cmdline refs written in order' '
clear_remote &&
- test_must_fail git send-pack remote.git A:foo B:foo &&
- verify_push A foo
+ test_must_fail git send-pack remote.git A:foo B:foo 2>err &&
+ test_grep "multiple updates for ref ${SQ}refs/heads/foo${SQ} not allowed" err &&
+ test_must_fail git --git-dir=remote.git rev-parse foo
+'
+
+test_expect_success 'cmdline refs with multiple duplicates' '
+ clear_remote &&
+ test_must_fail git send-pack remote.git A:foo B:foo C:foo 2>err &&
+ test_grep "multiple updates for ref ${SQ}refs/heads/foo${SQ} not allowed" err &&
+ test_must_fail git --git-dir=remote.git rev-parse foo
'
test_expect_success '--stdin refs come after cmdline' '
clear_remote &&
echo A:foo >input &&
test_must_fail git send-pack remote.git --stdin B:foo <input &&
- verify_push B foo
+ test_grep "multiple updates for ref ${SQ}refs/heads/foo${SQ} not allowed" err &&
+ test_must_fail git --git-dir=remote.git rev-parse foo
'
test_expect_success 'refspecs and --mirror do not mix (cmdline)' '
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index bef0250e89..e592c0bcde 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -1644,4 +1644,91 @@ test_expect_success 'empty config clears remote.*.pushurl list' '
test_cmp expect actual
'
+test_expect_success 'forbid adding subset of existing remote' '
+ test_when_finished "git remote rm outer" &&
+ git remote add outer url &&
+ test_must_fail git remote add outer/inner url 2>err &&
+ test_grep ".outer/inner. is a subset of existing remote .outer." err
+'
+
+test_expect_success 'forbid adding superset of existing remote' '
+ test_when_finished "git remote rm outer/inner" &&
+ git remote add outer/inner url &&
+ test_must_fail git remote add outer url 2>err &&
+ test_grep ".outer. is a superset of existing remote .outer/inner." err
+'
+
+test_expect_success 'rename handles unborn HEAD' '
+ test_when_finished "git remote remove unborn-renamed" &&
+ git remote add unborn url &&
+ git symbolic-ref refs/remotes/unborn/HEAD refs/remotes/unborn/nonexistent &&
+ git remote rename unborn unborn-renamed &&
+ git symbolic-ref refs/remotes/unborn-renamed/HEAD >actual &&
+ echo refs/remotes/unborn-renamed/nonexistent >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'rename can nest a remote into itself' '
+ test_commit parent-commit &&
+ COMMIT_ID=$(git rev-parse HEAD) &&
+ test_when_finished "git remote remove parent || true" &&
+ git remote add parent url &&
+ git update-ref refs/remotes/parent/branch $COMMIT_ID &&
+ test_when_finished "git remote remove parent/child" &&
+ git remote rename parent parent/child &&
+ git for-each-ref refs/remotes/ >actual &&
+ printf "$COMMIT_ID commit\trefs/remotes/parent/child/branch\n" >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'rename can nest a remote into itself with a conflicting branch name' '
+ test_commit parent-conflict &&
+ COMMIT_ID=$(git rev-parse HEAD) &&
+ test_when_finished "git remote remove parent || true" &&
+ git remote add parent url &&
+ git update-ref refs/remotes/parent/child $COMMIT_ID &&
+ test_when_finished "git remote remove parent/child" &&
+ test_must_fail git remote rename parent parent/child 2>err &&
+ test_grep "renaming remote references failed" err &&
+ test_grep "The remote you are trying to rename has conflicting references" err &&
+ git for-each-ref refs/remotes/ >actual &&
+ printf "$COMMIT_ID commit\trefs/remotes/parent/child\n" >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'rename can unnest a remote' '
+ test_commit parent-child-commit &&
+ COMMIT_ID=$(git rev-parse HEAD) &&
+ test_when_finished "git remote remove parent/child || true" &&
+ git remote add parent/child url &&
+ git update-ref refs/remotes/parent/child/branch $COMMIT_ID &&
+ git remote rename parent/child parent &&
+ git for-each-ref refs/remotes/ >actual &&
+ printf "$COMMIT_ID commit\trefs/remotes/parent/branch\n" >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'rename moves around the reflog' '
+ test_commit reflog-old &&
+ COMMIT_ID=$(git rev-parse HEAD) &&
+ test_config core.logAllRefUpdates true &&
+ test_when_finished "git remote remove reflog-old || true" &&
+ git remote add reflog-old url &&
+ git update-ref refs/remotes/reflog-old/branch $COMMIT_ID &&
+ test-tool ref-store main for-each-reflog >actual &&
+ test_grep refs/remotes/reflog-old/branch actual &&
+ test-tool ref-store main for-each-reflog-ent refs/remotes/reflog-old/branch >reflog-entries-old &&
+ test_line_count = 1 reflog-entries-old &&
+ git remote rename reflog-old reflog-new &&
+ test-tool ref-store main for-each-reflog >actual &&
+ test_grep ! refs/remotes/reflog-old actual &&
+ test_grep refs/remotes/reflog-new/branch actual &&
+ test-tool ref-store main for-each-reflog-ent refs/remotes/reflog-new/branch >reflog-entries-new &&
+ cat >expect <<-EOF &&
+ $(cat reflog-entries-old)
+ $COMMIT_ID $COMMIT_ID $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1112912173 -0700 remote: renamed refs/remotes/reflog-old/branch to refs/remotes/reflog-new/branch
+ EOF
+ test_cmp expect reflog-entries-new
+'
+
test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index ebc696546b..83d1aadf9f 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -14,8 +14,6 @@ then
test_done
fi
-D=$(pwd)
-
test_expect_success setup '
echo >file original &&
git add file &&
@@ -51,46 +49,50 @@ test_expect_success "clone and setup child repos" '
'
test_expect_success "fetch test" '
- cd "$D" &&
echo >file updated by origin &&
git commit -a -m "updated by origin" &&
- cd two &&
- git fetch &&
- git rev-parse --verify refs/heads/one &&
- mine=$(git rev-parse refs/heads/one) &&
- his=$(cd ../one && git rev-parse refs/heads/main) &&
- test "z$mine" = "z$his"
+ (
+ cd two &&
+ git fetch &&
+ git rev-parse --verify refs/heads/one &&
+ mine=$(git rev-parse refs/heads/one) &&
+ his=$(cd ../one && git rev-parse refs/heads/main) &&
+ test "z$mine" = "z$his"
+ )
'
test_expect_success "fetch test for-merge" '
- cd "$D" &&
- cd three &&
- git fetch &&
- git rev-parse --verify refs/heads/two &&
- git rev-parse --verify refs/heads/one &&
- main_in_two=$(cd ../two && git rev-parse main) &&
- one_in_two=$(cd ../two && git rev-parse one) &&
- {
- echo "$one_in_two " &&
- echo "$main_in_two not-for-merge"
- } >expected &&
- cut -f -2 .git/FETCH_HEAD >actual &&
- test_cmp expected actual'
+ (
+ cd three &&
+ git fetch &&
+ git rev-parse --verify refs/heads/two &&
+ git rev-parse --verify refs/heads/one &&
+ main_in_two=$(cd ../two && git rev-parse main) &&
+ one_in_two=$(cd ../two && git rev-parse one) &&
+ {
+ echo "$one_in_two " &&
+ echo "$main_in_two not-for-merge"
+ } >expected &&
+ cut -f -2 .git/FETCH_HEAD >actual &&
+ test_cmp expected actual
+ )
+'
test_expect_success "fetch test remote HEAD" '
- cd "$D" &&
- cd two &&
- git fetch &&
- git rev-parse --verify refs/remotes/origin/HEAD &&
- git rev-parse --verify refs/remotes/origin/main &&
- head=$(git rev-parse refs/remotes/origin/HEAD) &&
- branch=$(git rev-parse refs/remotes/origin/main) &&
- test "z$head" = "z$branch"'
+ (
+ cd two &&
+ git fetch &&
+ git rev-parse --verify refs/remotes/origin/HEAD &&
+ git rev-parse --verify refs/remotes/origin/main &&
+ head=$(git rev-parse refs/remotes/origin/HEAD) &&
+ branch=$(git rev-parse refs/remotes/origin/main) &&
+ test "z$head" = "z$branch"
+ )
+'
test_expect_success "fetch test remote HEAD in bare repository" '
test_when_finished rm -rf barerepo &&
(
- cd "$D" &&
git init --bare barerepo &&
cd barerepo &&
git remote add upstream ../two &&
@@ -105,262 +107,235 @@ test_expect_success "fetch test remote HEAD in bare repository" '
test_expect_success "fetch test remote HEAD change" '
- cd "$D" &&
- cd two &&
- git switch -c other &&
- git push -u origin other &&
- git rev-parse --verify refs/remotes/origin/HEAD &&
- git rev-parse --verify refs/remotes/origin/main &&
- git rev-parse --verify refs/remotes/origin/other &&
- git remote set-head origin other &&
- git fetch &&
- head=$(git rev-parse refs/remotes/origin/HEAD) &&
- branch=$(git rev-parse refs/remotes/origin/other) &&
- test "z$head" = "z$branch"'
-
-test_expect_success "fetch test followRemoteHEAD never" '
- test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
- (
- cd "$D" &&
- cd two &&
- git update-ref --no-deref -d refs/remotes/origin/HEAD &&
- git config set remote.origin.followRemoteHEAD "never" &&
- GIT_TRACE_PACKET=$PWD/trace.out git fetch &&
- # Confirm that we do not even ask for HEAD when we are
- # not going to act on it.
- test_grep ! "ref-prefix HEAD" trace.out &&
- test_must_fail git rev-parse --verify refs/remotes/origin/HEAD
- )
-'
-
-test_expect_success "fetch test followRemoteHEAD warn no change" '
- test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
(
- cd "$D" &&
cd two &&
- git rev-parse --verify refs/remotes/origin/other &&
- git remote set-head origin other &&
+ git switch -c other &&
+ git push -u origin other &&
git rev-parse --verify refs/remotes/origin/HEAD &&
git rev-parse --verify refs/remotes/origin/main &&
- git config set remote.origin.followRemoteHEAD "warn" &&
- git fetch >output &&
- echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
- "but we have ${SQ}other${SQ} locally." >expect &&
- test_cmp expect output &&
+ git rev-parse --verify refs/remotes/origin/other &&
+ git remote set-head origin other &&
+ git fetch &&
head=$(git rev-parse refs/remotes/origin/HEAD) &&
branch=$(git rev-parse refs/remotes/origin/other) &&
test "z$head" = "z$branch"
)
'
+test_expect_success "fetch test followRemoteHEAD never" '
+ git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
+ test_config -C two remote.origin.followRemoteHEAD "never" &&
+ GIT_TRACE_PACKET=$PWD/trace.out git -C two fetch &&
+ # Confirm that we do not even ask for HEAD when we are
+ # not going to act on it.
+ test_grep ! "ref-prefix HEAD" trace.out &&
+ test_must_fail git -C two rev-parse --verify refs/remotes/origin/HEAD
+'
+
+test_expect_success "fetch test followRemoteHEAD warn no change" '
+ git -C two rev-parse --verify refs/remotes/origin/other &&
+ git -C two remote set-head origin other &&
+ git -C two rev-parse --verify refs/remotes/origin/HEAD &&
+ git -C two rev-parse --verify refs/remotes/origin/main &&
+ test_config -C two remote.origin.followRemoteHEAD "warn" &&
+ git -C two fetch >output &&
+ echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
+ "but we have ${SQ}other${SQ} locally." >expect &&
+ test_cmp expect output &&
+ head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+ branch=$(git -C two rev-parse refs/remotes/origin/other) &&
+ test "z$head" = "z$branch"
+'
+
test_expect_success "fetch test followRemoteHEAD warn create" '
- test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
- (
- cd "$D" &&
- cd two &&
- git update-ref --no-deref -d refs/remotes/origin/HEAD &&
- git config set remote.origin.followRemoteHEAD "warn" &&
- git rev-parse --verify refs/remotes/origin/main &&
- output=$(git fetch) &&
- test "z" = "z$output" &&
- head=$(git rev-parse refs/remotes/origin/HEAD) &&
- branch=$(git rev-parse refs/remotes/origin/main) &&
- test "z$head" = "z$branch"
- )
+ git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
+ test_config -C two remote.origin.followRemoteHEAD "warn" &&
+ git -C two rev-parse --verify refs/remotes/origin/main &&
+ output=$(git -C two fetch) &&
+ test "z" = "z$output" &&
+ head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+ branch=$(git -C two rev-parse refs/remotes/origin/main) &&
+ test "z$head" = "z$branch"
'
test_expect_success "fetch test followRemoteHEAD warn detached" '
- test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
- (
- cd "$D" &&
- cd two &&
- git update-ref --no-deref -d refs/remotes/origin/HEAD &&
- git update-ref refs/remotes/origin/HEAD HEAD &&
- HEAD=$(git log --pretty="%H") &&
- git config set remote.origin.followRemoteHEAD "warn" &&
- git fetch >output &&
- echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
- "but we have a detached HEAD pointing to" \
- "${SQ}${HEAD}${SQ} locally." >expect &&
- test_cmp expect output
- )
+ git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
+ git -C two update-ref refs/remotes/origin/HEAD HEAD &&
+ HEAD=$(git -C two log --pretty="%H") &&
+ test_config -C two remote.origin.followRemoteHEAD "warn" &&
+ git -C two fetch >output &&
+ echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
+ "but we have a detached HEAD pointing to" \
+ "${SQ}${HEAD}${SQ} locally." >expect &&
+ test_cmp expect output
'
test_expect_success "fetch test followRemoteHEAD warn quiet" '
- test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
- (
- cd "$D" &&
- cd two &&
- git rev-parse --verify refs/remotes/origin/other &&
- git remote set-head origin other &&
- git rev-parse --verify refs/remotes/origin/HEAD &&
- git rev-parse --verify refs/remotes/origin/main &&
- git config set remote.origin.followRemoteHEAD "warn" &&
- output=$(git fetch --quiet) &&
- test "z" = "z$output" &&
- head=$(git rev-parse refs/remotes/origin/HEAD) &&
- branch=$(git rev-parse refs/remotes/origin/other) &&
- test "z$head" = "z$branch"
- )
+ git -C two rev-parse --verify refs/remotes/origin/other &&
+ git -C two remote set-head origin other &&
+ git -C two rev-parse --verify refs/remotes/origin/HEAD &&
+ git -C two rev-parse --verify refs/remotes/origin/main &&
+ test_config -C two remote.origin.followRemoteHEAD "warn" &&
+ output=$(git -C two fetch --quiet) &&
+ test "z" = "z$output" &&
+ head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+ branch=$(git -C two rev-parse refs/remotes/origin/other) &&
+ test "z$head" = "z$branch"
'
test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is same" '
- test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
- (
- cd "$D" &&
- cd two &&
- git rev-parse --verify refs/remotes/origin/other &&
- git remote set-head origin other &&
- git rev-parse --verify refs/remotes/origin/HEAD &&
- git rev-parse --verify refs/remotes/origin/main &&
- git config set remote.origin.followRemoteHEAD "warn-if-not-main" &&
- actual=$(git fetch) &&
- test "z" = "z$actual" &&
- head=$(git rev-parse refs/remotes/origin/HEAD) &&
- branch=$(git rev-parse refs/remotes/origin/other) &&
- test "z$head" = "z$branch"
- )
+ git -C two rev-parse --verify refs/remotes/origin/other &&
+ git -C two remote set-head origin other &&
+ git -C two rev-parse --verify refs/remotes/origin/HEAD &&
+ git -C two rev-parse --verify refs/remotes/origin/main &&
+ test_config -C two remote.origin.followRemoteHEAD "warn-if-not-main" &&
+ actual=$(git -C two fetch) &&
+ test "z" = "z$actual" &&
+ head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+ branch=$(git -C two rev-parse refs/remotes/origin/other) &&
+ test "z$head" = "z$branch"
'
test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is different" '
- test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
- (
- cd "$D" &&
- cd two &&
- git rev-parse --verify refs/remotes/origin/other &&
- git remote set-head origin other &&
- git rev-parse --verify refs/remotes/origin/HEAD &&
- git rev-parse --verify refs/remotes/origin/main &&
- git config set remote.origin.followRemoteHEAD "warn-if-not-some/different-branch" &&
- git fetch >actual &&
- echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
- "but we have ${SQ}other${SQ} locally." >expect &&
- test_cmp expect actual &&
- head=$(git rev-parse refs/remotes/origin/HEAD) &&
- branch=$(git rev-parse refs/remotes/origin/other) &&
- test "z$head" = "z$branch"
- )
+ git -C two rev-parse --verify refs/remotes/origin/other &&
+ git -C two remote set-head origin other &&
+ git -C two rev-parse --verify refs/remotes/origin/HEAD &&
+ git -C two rev-parse --verify refs/remotes/origin/main &&
+ test_config -C two remote.origin.followRemoteHEAD "warn-if-not-some/different-branch" &&
+ git -C two fetch >actual &&
+ echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
+ "but we have ${SQ}other${SQ} locally." >expect &&
+ test_cmp expect actual &&
+ head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+ branch=$(git -C two rev-parse refs/remotes/origin/other) &&
+ test "z$head" = "z$branch"
'
test_expect_success "fetch test followRemoteHEAD always" '
- test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
- (
- cd "$D" &&
- cd two &&
- git rev-parse --verify refs/remotes/origin/other &&
- git remote set-head origin other &&
- git rev-parse --verify refs/remotes/origin/HEAD &&
- git rev-parse --verify refs/remotes/origin/main &&
- git config set remote.origin.followRemoteHEAD "always" &&
- git fetch &&
- head=$(git rev-parse refs/remotes/origin/HEAD) &&
- branch=$(git rev-parse refs/remotes/origin/main) &&
- test "z$head" = "z$branch"
- )
+ git -C two rev-parse --verify refs/remotes/origin/other &&
+ git -C two remote set-head origin other &&
+ git -C two rev-parse --verify refs/remotes/origin/HEAD &&
+ git -C two rev-parse --verify refs/remotes/origin/main &&
+ test_config -C two remote.origin.followRemoteHEAD "always" &&
+ git -C two fetch &&
+ head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
+ branch=$(git -C two rev-parse refs/remotes/origin/main) &&
+ test "z$head" = "z$branch"
'
test_expect_success 'followRemoteHEAD does not kick in with refspecs' '
- test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
- (
- cd "$D" &&
- cd two &&
- git remote set-head origin other &&
- git config set remote.origin.followRemoteHEAD always &&
- git fetch origin refs/heads/main:refs/remotes/origin/main &&
- echo refs/remotes/origin/other >expect &&
- git symbolic-ref refs/remotes/origin/HEAD >actual &&
- test_cmp expect actual
- )
+ git -C two remote set-head origin other &&
+ test_config -C two remote.origin.followRemoteHEAD always &&
+ git -C two fetch origin refs/heads/main:refs/remotes/origin/main &&
+ echo refs/remotes/origin/other >expect &&
+ git -C two symbolic-ref refs/remotes/origin/HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'followRemoteHEAD create does not overwrite dangling symref' '
+ git -C two remote add -m does-not-exist custom-head ../one &&
+ test_config -C two remote.custom-head.followRemoteHEAD create &&
+ git -C two fetch custom-head &&
+ echo refs/remotes/custom-head/does-not-exist >expect &&
+ git -C two symbolic-ref refs/remotes/custom-head/HEAD >actual &&
+ test_cmp expect actual
'
test_expect_success 'fetch --prune on its own works as expected' '
- cd "$D" &&
git clone . prune &&
- cd prune &&
- git update-ref refs/remotes/origin/extrabranch main &&
+ (
+ cd prune &&
+ git update-ref refs/remotes/origin/extrabranch main &&
- git fetch --prune origin &&
- test_must_fail git rev-parse origin/extrabranch
+ git fetch --prune origin &&
+ test_must_fail git rev-parse origin/extrabranch
+ )
'
test_expect_success 'fetch --prune with a branch name keeps branches' '
- cd "$D" &&
git clone . prune-branch &&
- cd prune-branch &&
- git update-ref refs/remotes/origin/extrabranch main &&
+ (
+ cd prune-branch &&
+ git update-ref refs/remotes/origin/extrabranch main &&
- git fetch --prune origin main &&
- git rev-parse origin/extrabranch
+ git fetch --prune origin main &&
+ git rev-parse origin/extrabranch
+ )
'
test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
- cd "$D" &&
git clone . prune-namespace &&
- cd prune-namespace &&
+ (
+ cd prune-namespace &&
- git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
- git rev-parse origin/main
+ git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
+ git rev-parse origin/main
+ )
'
test_expect_success 'fetch --prune handles overlapping refspecs' '
- cd "$D" &&
git update-ref refs/pull/42/head main &&
git clone . prune-overlapping &&
- cd prune-overlapping &&
- git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+ (
+ cd prune-overlapping &&
+ git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
- git fetch --prune origin &&
- git rev-parse origin/main &&
- git rev-parse origin/pr/42 &&
+ git fetch --prune origin &&
+ git rev-parse origin/main &&
+ git rev-parse origin/pr/42 &&
- git config --unset-all remote.origin.fetch &&
- git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
- git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
+ git config --unset-all remote.origin.fetch &&
+ git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+ git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
- git fetch --prune origin &&
- git rev-parse origin/main &&
- git rev-parse origin/pr/42
+ git fetch --prune origin &&
+ git rev-parse origin/main &&
+ git rev-parse origin/pr/42
+ )
'
test_expect_success 'fetch --prune --tags prunes branches but not tags' '
- cd "$D" &&
git clone . prune-tags &&
- cd prune-tags &&
- git tag sometag main &&
- # Create what looks like a remote-tracking branch from an earlier
- # fetch that has since been deleted from the remote:
- git update-ref refs/remotes/origin/fake-remote main &&
-
- git fetch --prune --tags origin &&
- git rev-parse origin/main &&
- test_must_fail git rev-parse origin/fake-remote &&
- git rev-parse sometag
+ (
+ cd prune-tags &&
+ git tag sometag main &&
+ # Create what looks like a remote-tracking branch from an earlier
+ # fetch that has since been deleted from the remote:
+ git update-ref refs/remotes/origin/fake-remote main &&
+
+ git fetch --prune --tags origin &&
+ git rev-parse origin/main &&
+ test_must_fail git rev-parse origin/fake-remote &&
+ git rev-parse sometag
+ )
'
test_expect_success 'fetch --prune --tags with branch does not prune other things' '
- cd "$D" &&
git clone . prune-tags-branch &&
- cd prune-tags-branch &&
- git tag sometag main &&
- git update-ref refs/remotes/origin/extrabranch main &&
+ (
+ cd prune-tags-branch &&
+ git tag sometag main &&
+ git update-ref refs/remotes/origin/extrabranch main &&
- git fetch --prune --tags origin main &&
- git rev-parse origin/extrabranch &&
- git rev-parse sometag
+ git fetch --prune --tags origin main &&
+ git rev-parse origin/extrabranch &&
+ git rev-parse sometag
+ )
'
test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' '
- cd "$D" &&
git clone . prune-tags-refspec &&
- cd prune-tags-refspec &&
- git tag sometag main &&
- git update-ref refs/remotes/origin/foo/otherbranch main &&
- git update-ref refs/remotes/origin/extrabranch main &&
-
- git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
- test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
- git rev-parse origin/extrabranch &&
- git rev-parse sometag
+ (
+ cd prune-tags-refspec &&
+ git tag sometag main &&
+ git update-ref refs/remotes/origin/foo/otherbranch main &&
+ git update-ref refs/remotes/origin/extrabranch main &&
+
+ git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
+ test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
+ git rev-parse origin/extrabranch &&
+ git rev-parse sometag
+ )
'
test_expect_success 'fetch --tags gets tags even without a configured remote' '
@@ -381,21 +356,21 @@ test_expect_success 'fetch --tags gets tags even without a configured remote' '
'
test_expect_success REFFILES 'fetch --prune fails to delete branches' '
- cd "$D" &&
git clone . prune-fail &&
- cd prune-fail &&
- git update-ref refs/remotes/origin/extrabranch main &&
- git pack-refs --all &&
- : this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds &&
- >.git/packed-refs.new &&
+ (
+ cd prune-fail &&
+ git update-ref refs/remotes/origin/extrabranch main &&
+ git pack-refs --all &&
+ : this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds &&
+ >.git/packed-refs.new &&
- test_must_fail git fetch --prune origin
+ test_must_fail git fetch --prune origin
+ )
'
test_expect_success 'fetch --atomic works with a single branch' '
- test_when_finished "rm -rf \"$D\"/atomic" &&
+ test_when_finished "rm -rf atomic" &&
- cd "$D" &&
git clone . atomic &&
git branch atomic-branch &&
oid=$(git rev-parse atomic-branch) &&
@@ -408,9 +383,8 @@ test_expect_success 'fetch --atomic works with a single branch' '
'
test_expect_success 'fetch --atomic works with multiple branches' '
- test_when_finished "rm -rf \"$D\"/atomic" &&
+ test_when_finished "rm -rf atomic" &&
- cd "$D" &&
git clone . atomic &&
git branch atomic-branch-1 &&
git branch atomic-branch-2 &&
@@ -423,9 +397,8 @@ test_expect_success 'fetch --atomic works with multiple branches' '
'
test_expect_success 'fetch --atomic works with mixed branches and tags' '
- test_when_finished "rm -rf \"$D\"/atomic" &&
+ test_when_finished "rm -rf atomic" &&
- cd "$D" &&
git clone . atomic &&
git branch atomic-mixed-branch &&
git tag atomic-mixed-tag &&
@@ -437,9 +410,8 @@ test_expect_success 'fetch --atomic works with mixed branches and tags' '
'
test_expect_success 'fetch --atomic prunes references' '
- test_when_finished "rm -rf \"$D\"/atomic" &&
+ test_when_finished "rm -rf atomic" &&
- cd "$D" &&
git branch atomic-prune-delete &&
git clone . atomic &&
git branch --delete atomic-prune-delete &&
@@ -453,9 +425,8 @@ test_expect_success 'fetch --atomic prunes references' '
'
test_expect_success 'fetch --atomic aborts with non-fast-forward update' '
- test_when_finished "rm -rf \"$D\"/atomic" &&
+ test_when_finished "rm -rf atomic" &&
- cd "$D" &&
git branch atomic-non-ff &&
git clone . atomic &&
git rev-parse HEAD >actual &&
@@ -472,9 +443,8 @@ test_expect_success 'fetch --atomic aborts with non-fast-forward update' '
'
test_expect_success 'fetch --atomic executes a single reference transaction only' '
- test_when_finished "rm -rf \"$D\"/atomic" &&
+ test_when_finished "rm -rf atomic" &&
- cd "$D" &&
git clone . atomic &&
git branch atomic-hooks-1 &&
git branch atomic-hooks-2 &&
@@ -499,9 +469,8 @@ test_expect_success 'fetch --atomic executes a single reference transaction only
'
test_expect_success 'fetch --atomic aborts all reference updates if hook aborts' '
- test_when_finished "rm -rf \"$D\"/atomic" &&
+ test_when_finished "rm -rf atomic" &&
- cd "$D" &&
git clone . atomic &&
git branch atomic-hooks-abort-1 &&
git branch atomic-hooks-abort-2 &&
@@ -536,9 +505,8 @@ test_expect_success 'fetch --atomic aborts all reference updates if hook aborts'
'
test_expect_success 'fetch --atomic --append appends to FETCH_HEAD' '
- test_when_finished "rm -rf \"$D\"/atomic" &&
+ test_when_finished "rm -rf atomic" &&
- cd "$D" &&
git clone . atomic &&
oid=$(git rev-parse HEAD) &&
@@ -574,8 +542,7 @@ test_expect_success REFFILES 'fetch --atomic fails transaction if reference lock
'
test_expect_success '--refmap="" ignores configured refspec' '
- cd "$TRASH_DIRECTORY" &&
- git clone "$D" remote-refs &&
+ git clone . remote-refs &&
git -C remote-refs rev-parse remotes/origin/main >old &&
git -C remote-refs update-ref refs/remotes/origin/main main~1 &&
git -C remote-refs rev-parse remotes/origin/main >new &&
@@ -599,34 +566,26 @@ test_expect_success '--refmap="" and --prune' '
test_expect_success 'fetch tags when there is no tags' '
- cd "$D" &&
-
- mkdir notags &&
- cd notags &&
- git init &&
-
- git fetch -t ..
+ git init notags &&
+ git -C notags fetch -t ..
'
test_expect_success 'fetch following tags' '
- cd "$D" &&
git tag -a -m "annotated" anno HEAD &&
git tag light HEAD &&
- mkdir four &&
- cd four &&
- git init &&
-
- git fetch .. :track &&
- git show-ref --verify refs/tags/anno &&
- git show-ref --verify refs/tags/light
-
+ git init four &&
+ (
+ cd four &&
+ git fetch .. :track &&
+ git show-ref --verify refs/tags/anno &&
+ git show-ref --verify refs/tags/light
+ )
'
test_expect_success 'fetch uses remote ref names to describe new refs' '
- cd "$D" &&
git init descriptive &&
(
cd descriptive &&
@@ -654,30 +613,20 @@ test_expect_success 'fetch uses remote ref names to describe new refs' '
test_expect_success 'fetch must not resolve short tag name' '
- cd "$D" &&
-
- mkdir five &&
- cd five &&
- git init &&
-
- test_must_fail git fetch .. anno:five
+ git init five &&
+ test_must_fail git -C five fetch .. anno:five
'
test_expect_success 'fetch can now resolve short remote name' '
- cd "$D" &&
git update-ref refs/remotes/six/HEAD HEAD &&
- mkdir six &&
- cd six &&
- git init &&
-
- git fetch .. six:six
+ git init six &&
+ git -C six fetch .. six:six
'
test_expect_success 'create bundle 1' '
- cd "$D" &&
echo >file updated again by origin &&
git commit -a -m "tip" &&
git bundle create --version=3 bundle1 main^..main
@@ -691,35 +640,36 @@ test_expect_success 'header of bundle looks right' '
OID refs/heads/main
EOF
- sed -e "s/$OID_REGEX/OID/g" -e "5q" "$D"/bundle1 >actual &&
+ sed -e "s/$OID_REGEX/OID/g" -e "5q" bundle1 >actual &&
test_cmp expect actual
'
test_expect_success 'create bundle 2' '
- cd "$D" &&
git bundle create bundle2 main~2..main
'
test_expect_success 'unbundle 1' '
- cd "$D/bundle" &&
- git checkout -b some-branch &&
- test_must_fail git fetch "$D/bundle1" main:main
+ (
+ cd bundle &&
+ git checkout -b some-branch &&
+ test_must_fail git fetch bundle1 main:main
+ )
'
test_expect_success 'bundle 1 has only 3 files ' '
- cd "$D" &&
test_bundle_object_count bundle1 3
'
test_expect_success 'unbundle 2' '
- cd "$D/bundle" &&
- git fetch ../bundle2 main:main &&
- test "tip" = "$(git log -1 --pretty=oneline main | cut -d" " -f2)"
+ (
+ cd bundle &&
+ git fetch ../bundle2 main:main &&
+ test "tip" = "$(git log -1 --pretty=oneline main | cut -d" " -f2)"
+ )
'
test_expect_success 'bundle does not prerequisite objects' '
- cd "$D" &&
touch file2 &&
git add file2 &&
git commit -m add.file2 file2 &&
@@ -729,7 +679,6 @@ test_expect_success 'bundle does not prerequisite objects' '
test_expect_success 'bundle should be able to create a full history' '
- cd "$D" &&
git tag -a -m "1.0" v1.0 main &&
git bundle create bundle4 v1.0
@@ -783,7 +732,6 @@ test_expect_success 'quoting of a strangely named repo' '
test_expect_success 'bundle should record HEAD correctly' '
- cd "$D" &&
git bundle create bundle5 HEAD main &&
git bundle list-heads bundle5 >actual &&
for h in HEAD refs/heads/main
@@ -803,7 +751,6 @@ test_expect_success 'mark initial state of origin/main' '
test_expect_success 'explicit fetch should update tracking' '
- cd "$D" &&
git branch -f side &&
(
cd three &&
@@ -818,7 +765,6 @@ test_expect_success 'explicit fetch should update tracking' '
test_expect_success 'explicit pull should update tracking' '
- cd "$D" &&
git branch -f side &&
(
cd three &&
@@ -832,7 +778,6 @@ test_expect_success 'explicit pull should update tracking' '
'
test_expect_success 'explicit --refmap is allowed only with command-line refspec' '
- cd "$D" &&
(
cd three &&
test_must_fail git fetch --refmap="*:refs/remotes/none/*"
@@ -840,7 +785,6 @@ test_expect_success 'explicit --refmap is allowed only with command-line refspec
'
test_expect_success 'explicit --refmap option overrides remote.*.fetch' '
- cd "$D" &&
git branch -f side &&
(
cd three &&
@@ -855,7 +799,6 @@ test_expect_success 'explicit --refmap option overrides remote.*.fetch' '
'
test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' '
- cd "$D" &&
git branch -f side &&
(
cd three &&
@@ -870,7 +813,6 @@ test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' '
test_expect_success 'configured fetch updates tracking' '
- cd "$D" &&
git branch -f side &&
(
cd three &&
@@ -884,7 +826,6 @@ test_expect_success 'configured fetch updates tracking' '
'
test_expect_success 'non-matching refspecs do not confuse tracking update' '
- cd "$D" &&
git update-ref refs/odd/location HEAD &&
(
cd three &&
@@ -901,14 +842,12 @@ test_expect_success 'non-matching refspecs do not confuse tracking update' '
test_expect_success 'pushing nonexistent branch by mistake should not segv' '
- cd "$D" &&
test_must_fail git push seven no:no
'
test_expect_success 'auto tag following fetches minimum' '
- cd "$D" &&
git clone .git follow &&
git checkout HEAD^0 &&
(
@@ -1307,7 +1246,7 @@ test_expect_success 'fetch --prune prints the remotes url' '
cd only-prunes &&
git fetch --prune origin 2>&1 | head -n1 >../actual
) &&
- echo "From ${D}/." >expect &&
+ echo "From $(pwd)/." >expect &&
test_cmp expect actual
'
@@ -1357,14 +1296,14 @@ test_expect_success 'fetching with auto-gc does not lock up' '
echo "$*" &&
false
EOF
- git clone "file://$D" auto-gc &&
+ git clone "file://$PWD" auto-gc &&
test_commit test2 &&
(
cd auto-gc &&
git config fetch.unpackLimit 1 &&
git config gc.autoPackLimit 1 &&
git config gc.autoDetach false &&
- GIT_ASK_YESNO="$D/askyesno" git fetch --verbose >fetch.out 2>&1 &&
+ GIT_ASK_YESNO="$TRASH_DIRECTORY/askyesno" git fetch --verbose >fetch.out 2>&1 &&
test_grep "Auto packing the repository" fetch.out &&
! grep "Should I try again" fetch.out
)
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index dabcc5f811..46926e7bbd 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -105,7 +105,6 @@ check_push_result () {
}
test_expect_success setup '
-
>path1 &&
git add path1 &&
test_tick &&
@@ -117,7 +116,6 @@ test_expect_success setup '
test_tick &&
git commit -a -m second &&
the_commit=$(git show-ref -s --verify refs/heads/main)
-
'
for cmd in push fetch
@@ -322,104 +320,82 @@ test_expect_success 'push with pushInsteadOf and explicit pushurl (pushInsteadOf
'
test_expect_success 'push with matching heads' '
-
mk_test testrepo heads/main &&
git push testrepo : &&
check_push_result testrepo $the_commit heads/main
-
'
test_expect_success 'push with matching heads on the command line' '
-
mk_test testrepo heads/main &&
git push testrepo : &&
check_push_result testrepo $the_commit heads/main
-
'
test_expect_success 'failed (non-fast-forward) push with matching heads' '
-
mk_test testrepo heads/main &&
git push testrepo : &&
git commit --amend -massaged &&
test_must_fail git push testrepo &&
check_push_result testrepo $the_commit heads/main &&
git reset --hard $the_commit
-
'
test_expect_success 'push --force with matching heads' '
-
mk_test testrepo heads/main &&
git push testrepo : &&
git commit --amend -massaged &&
git push --force testrepo : &&
! check_push_result testrepo $the_commit heads/main &&
git reset --hard $the_commit
-
'
test_expect_success 'push with matching heads and forced update' '
-
mk_test testrepo heads/main &&
git push testrepo : &&
git commit --amend -massaged &&
git push testrepo +: &&
! check_push_result testrepo $the_commit heads/main &&
git reset --hard $the_commit
-
'
test_expect_success 'push with no ambiguity (1)' '
-
mk_test testrepo heads/main &&
git push testrepo main:main &&
check_push_result testrepo $the_commit heads/main
-
'
test_expect_success 'push with no ambiguity (2)' '
-
mk_test testrepo remotes/origin/main &&
git push testrepo main:origin/main &&
check_push_result testrepo $the_commit remotes/origin/main
-
'
test_expect_success 'push with colon-less refspec, no ambiguity' '
-
mk_test testrepo heads/main heads/t/main &&
git branch -f t/main main &&
git push testrepo main &&
check_push_result testrepo $the_commit heads/main &&
check_push_result testrepo $the_first_commit heads/t/main
-
'
test_expect_success 'push with weak ambiguity (1)' '
-
mk_test testrepo heads/main remotes/origin/main &&
git push testrepo main:main &&
check_push_result testrepo $the_commit heads/main &&
check_push_result testrepo $the_first_commit remotes/origin/main
-
'
test_expect_success 'push with weak ambiguity (2)' '
-
mk_test testrepo heads/main remotes/origin/main remotes/another/main &&
git push testrepo main:main &&
check_push_result testrepo $the_commit heads/main &&
check_push_result testrepo $the_first_commit remotes/origin/main remotes/another/main
-
'
test_expect_success 'push with ambiguity' '
-
mk_test testrepo heads/frotz tags/frotz &&
test_must_fail git push testrepo main:frotz &&
check_push_result testrepo $the_first_commit heads/frotz tags/frotz
-
'
test_expect_success 'push with onelevel ref' '
@@ -428,17 +404,14 @@ test_expect_success 'push with onelevel ref' '
'
test_expect_success 'push with colon-less refspec (1)' '
-
mk_test testrepo heads/frotz tags/frotz &&
git branch -f frotz main &&
git push testrepo frotz &&
check_push_result testrepo $the_commit heads/frotz &&
check_push_result testrepo $the_first_commit tags/frotz
-
'
test_expect_success 'push with colon-less refspec (2)' '
-
mk_test testrepo heads/frotz tags/frotz &&
if git show-ref --verify -q refs/heads/frotz
then
@@ -448,7 +421,6 @@ test_expect_success 'push with colon-less refspec (2)' '
git push -f testrepo frotz &&
check_push_result testrepo $the_commit tags/frotz &&
check_push_result testrepo $the_first_commit heads/frotz
-
'
test_expect_success 'push with colon-less refspec (3)' '
@@ -465,7 +437,6 @@ test_expect_success 'push with colon-less refspec (3)' '
'
test_expect_success 'push with colon-less refspec (4)' '
-
mk_test testrepo &&
if git show-ref --verify -q refs/heads/frotz
then
@@ -475,38 +446,34 @@ test_expect_success 'push with colon-less refspec (4)' '
git push testrepo frotz &&
check_push_result testrepo $the_commit tags/frotz &&
test 1 = $( cd testrepo && git show-ref | wc -l )
-
'
test_expect_success 'push head with non-existent, incomplete dest' '
-
mk_test testrepo &&
git push testrepo main:branch &&
check_push_result testrepo $the_commit heads/branch
-
'
test_expect_success 'push tag with non-existent, incomplete dest' '
-
mk_test testrepo &&
git tag -f v1.0 &&
git push testrepo v1.0:tag &&
check_push_result testrepo $the_commit tags/tag
-
'
test_expect_success 'push oid with non-existent, incomplete dest' '
-
mk_test testrepo &&
test_must_fail git push testrepo $(git rev-parse main):foo
-
'
test_expect_success 'push ref expression with non-existent, incomplete dest' '
-
mk_test testrepo &&
test_must_fail git push testrepo main^:branch
+'
+test_expect_success 'push ref expression with non-existent oid src' '
+ mk_test testrepo &&
+ test_must_fail git push testrepo $(test_oid 001):branch
'
for head in HEAD @
@@ -550,7 +517,6 @@ do
git checkout main &&
git push testrepo $head:branch &&
check_push_result testrepo $the_commit heads/branch
-
'
test_expect_success "push with config remote.*.push = $head" '
@@ -596,7 +562,6 @@ test_expect_success 'push with remote.pushdefault' '
'
test_expect_success 'push with config remote.*.pushurl' '
-
mk_test testrepo heads/main &&
git checkout main &&
test_config remote.there.url test2repo &&
@@ -655,7 +620,6 @@ test_expect_success 'push ignores "branch." config without subsection' '
'
test_expect_success 'push with dry-run' '
-
mk_test testrepo heads/main &&
old_commit=$(git -C testrepo show-ref -s --verify refs/heads/main) &&
git push --dry-run testrepo : &&
@@ -663,7 +627,6 @@ test_expect_success 'push with dry-run' '
'
test_expect_success 'push updates local refs' '
-
mk_test testrepo heads/main &&
mk_child testrepo child &&
(
@@ -673,11 +636,9 @@ test_expect_success 'push updates local refs' '
test $(git rev-parse main) = \
$(git rev-parse remotes/origin/main)
)
-
'
test_expect_success 'push updates up-to-date local refs' '
-
mk_test testrepo heads/main &&
mk_child testrepo child1 &&
mk_child testrepo child2 &&
@@ -689,11 +650,9 @@ test_expect_success 'push updates up-to-date local refs' '
test $(git rev-parse main) = \
$(git rev-parse remotes/origin/main)
)
-
'
test_expect_success 'push preserves up-to-date packed refs' '
-
mk_test testrepo heads/main &&
mk_child testrepo child &&
(
@@ -701,11 +660,9 @@ test_expect_success 'push preserves up-to-date packed refs' '
git push &&
! test -f .git/refs/remotes/origin/main
)
-
'
test_expect_success 'push does not update local refs on failure' '
-
mk_test testrepo heads/main &&
mk_child testrepo child &&
echo "#!/no/frobnication/today" >testrepo/.git/hooks/pre-receive &&
@@ -717,16 +674,13 @@ test_expect_success 'push does not update local refs on failure' '
test $(git rev-parse main) != \
$(git rev-parse remotes/origin/main)
)
-
'
test_expect_success 'allow deleting an invalid remote ref' '
-
mk_test testrepo heads/branch &&
rm -f testrepo/.git/objects/??/* &&
git push testrepo :refs/heads/branch &&
(cd testrepo && test_must_fail git rev-parse --verify refs/heads/branch)
-
'
test_expect_success 'pushing valid refs triggers post-receive and post-update hooks' '
@@ -744,8 +698,8 @@ test_expect_success 'pushing valid refs triggers post-receive and post-update ho
EOF
cat >update.expect <<-EOF &&
- refs/heads/main $orgmain $newmain
refs/heads/next $orgnext $newnext
+ refs/heads/main $orgmain $newmain
EOF
cat >post-receive.expect <<-EOF &&
@@ -808,8 +762,8 @@ test_expect_success 'deletion of a non-existent ref is not fed to post-receive a
EOF
cat >update.expect <<-EOF &&
- refs/heads/main $orgmain $newmain
refs/heads/nonexistent $ZERO_OID $ZERO_OID
+ refs/heads/main $orgmain $newmain
EOF
cat >post-receive.expect <<-EOF &&
@@ -868,10 +822,10 @@ test_expect_success 'mixed ref updates, deletes, invalid deletes trigger hooks w
EOF
cat >update.expect <<-EOF &&
- refs/heads/main $orgmain $newmain
refs/heads/next $orgnext $newnext
- refs/heads/seen $orgseen $newseen
refs/heads/nonexistent $ZERO_OID $ZERO_OID
+ refs/heads/main $orgmain $newmain
+ refs/heads/seen $orgseen $newseen
EOF
cat >post-receive.expect <<-EOF &&
@@ -1909,4 +1863,23 @@ test_expect_success 'push with config push.useBitmaps' '
--thin --delta-base-offset -q --no-use-bitmap-index <false
'
+test_expect_success 'push with config pack.usePathWalk=true' '
+ mk_test testrepo heads/main &&
+ git checkout main &&
+ test_config pack.usePathWalk true &&
+ GIT_TRACE2_EVENT="$(pwd)/path-walk.txt" \
+ git push --quiet testrepo main:test &&
+
+ test_region pack-objects path-walk path-walk.txt
+'
+
+test_expect_success 'push with F/D conflict with deletion and creation' '
+ test_when_finished "git branch -D branch" &&
+ git branch branch/conflict &&
+ mk_test testrepo heads/branch/conflict &&
+ git branch -D branch/conflict &&
+ git branch branch &&
+ git push testrepo :refs/heads/branch/conflict refs/heads/branch
+'
+
test_done
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 63c9a8f04b..0e0019347e 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -472,6 +472,66 @@ test_expect_success 'pull --no-autostash & merge.autostash unset' '
test_pull_autostash_fail --no-autostash --no-rebase
'
+test_expect_success 'pull succeeds with dirty working directory and pull.autostash=true' '
+ test_config pull.autostash true &&
+ test_pull_autostash 1 --rebase &&
+ test_pull_autostash 2 --no-rebase &&
+ test_pull_autostash 1 --autostash --rebase &&
+ test_pull_autostash 2 --autostash --no-rebase
+'
+
+test_expect_success 'pull fails with dirty working directory and pull.autostash=false' '
+ test_config pull.autostash false &&
+ test_pull_autostash_fail --rebase &&
+ test_pull_autostash_fail --no-rebase &&
+ test_pull_autostash_fail --no-autostash --rebase &&
+ test_pull_autostash_fail --no-autostash --no-rebase
+'
+
+test_expect_success 'pull --autostash overrides pull.autostash=false' '
+ test_config pull.autostash false &&
+ test_pull_autostash 1 --autostash --rebase &&
+ test_pull_autostash 2 --autostash --no-rebase
+'
+
+test_expect_success 'pull --no-autostash overrides pull.autostash=true' '
+ test_config pull.autostash true &&
+ test_pull_autostash_fail --no-autostash --rebase &&
+ test_pull_autostash_fail --no-autostash --no-rebase
+'
+
+test_expect_success 'pull.autostash=true overrides rebase.autostash' '
+ test_config pull.autostash true &&
+ test_config rebase.autostash true &&
+ test_pull_autostash 1 --rebase &&
+ test_config rebase.autostash false &&
+ test_pull_autostash 1 --rebase
+'
+
+test_expect_success 'pull.autostash=false overrides rebase.autostash' '
+ test_config pull.autostash false &&
+ test_config rebase.autostash true &&
+ test_pull_autostash_fail --rebase &&
+ test_config rebase.autostash false &&
+ test_pull_autostash_fail --rebase
+'
+
+test_expect_success 'pull.autostash=true overrides merge.autostash' '
+ test_config pull.autostash true &&
+ test_config merge.autostash true &&
+ test_pull_autostash 2 --no-rebase &&
+ test_config merge.autostash false &&
+ test_pull_autostash 2 --no-rebase
+'
+
+test_expect_success 'pull.autostash=false overrides merge.autostash' '
+ test_config pull.autostash false &&
+ test_config merge.autostash true &&
+ test_pull_autostash_fail --no-rebase &&
+ test_config merge.autostash false &&
+ test_pull_autostash_fail --no-rebase
+'
+
test_expect_success 'pull.rebase' '
git reset --hard before-rebase &&
test_config pull.rebase true &&
diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh
index 558eedf25a..d40292cfb7 100755
--- a/t/t5530-upload-pack-error.sh
+++ b/t/t5530-upload-pack-error.sh
@@ -4,8 +4,6 @@ test_description='errors in upload-pack'
. ./test-lib.sh
-D=$(pwd)
-
corrupt_repo () {
object_sha1=$(git rev-parse "$1") &&
ob=$(expr "$object_sha1" : "\(..\)") &&
@@ -21,11 +19,7 @@ test_expect_success 'setup and corrupt repository' '
test_tick &&
echo changed >file &&
git commit -a -m changed &&
- corrupt_repo HEAD:file
-
-'
-
-test_expect_success 'fsck fails' '
+ corrupt_repo HEAD:file &&
test_must_fail git fsck
'
@@ -40,17 +34,12 @@ test_expect_success 'upload-pack fails due to error in pack-objects packing' '
'
test_expect_success 'corrupt repo differently' '
-
git hash-object -w file &&
- corrupt_repo HEAD^^{tree}
-
-'
-
-test_expect_success 'fsck fails' '
+ corrupt_repo HEAD^^{tree} &&
test_must_fail git fsck
'
-test_expect_success 'upload-pack fails due to error in rev-list' '
+test_expect_success 'upload-pack fails due to error in rev-list' '
printf "%04xwant %s\n%04xshallow %s00000009done\n0000" \
$(($hexsz + 10)) $(git rev-parse HEAD) \
$(($hexsz + 12)) $(git rev-parse HEAD^) >input &&
@@ -59,7 +48,6 @@ test_expect_success 'upload-pack fails due to error in rev-list' '
'
test_expect_success 'upload-pack fails due to bad want (no object)' '
-
printf "%04xwant %s multi_ack_detailed\n00000009done\n0000" \
$(($hexsz + 29)) $(test_oid deadbeef) >input &&
test_must_fail git upload-pack . <input >output 2>output.err &&
@@ -69,7 +57,6 @@ test_expect_success 'upload-pack fails due to bad want (no object)' '
'
test_expect_success 'upload-pack fails due to bad want (not tip)' '
-
oid=$(echo an object we have | git hash-object -w --stdin) &&
printf "%04xwant %s multi_ack_detailed\n00000009done\n0000" \
$(($hexsz + 29)) "$oid" >input &&
@@ -80,7 +67,6 @@ test_expect_success 'upload-pack fails due to bad want (not tip)' '
'
test_expect_success 'upload-pack fails due to error in pack-objects enumeration' '
-
printf "%04xwant %s\n00000009done\n0000" \
$((hexsz + 10)) $(git rev-parse HEAD) >input &&
test_must_fail git upload-pack . <input >/dev/null 2>output.err &&
@@ -105,18 +91,48 @@ test_expect_success 'upload-pack tolerates EOF just after stateless client wants
test_cmp expect actual
'
-test_expect_success 'create empty repository' '
-
- mkdir foo &&
- cd foo &&
- git init
-
-'
-
test_expect_success 'fetch fails' '
+ git init foo &&
+ test_must_fail git -C foo fetch .. main
+'
- test_must_fail git fetch .. main
+test_expect_success 'upload-pack ACKs repeated non-commit objects repeatedly (protocol v0)' '
+ commit_id=$(git rev-parse HEAD) &&
+ tree_id=$(git rev-parse HEAD^{tree}) &&
+ test-tool pkt-line pack >request <<-EOF &&
+ want $commit_id
+ 0000
+ have $tree_id
+ have $tree_id
+ 0000
+ EOF
+ git upload-pack --stateless-rpc . <request >actual &&
+ depacketize <actual >actual.raw &&
+ grep ^ACK actual.raw >actual.acks &&
+ cat >expect <<-EOF &&
+ ACK $tree_id
+ ACK $tree_id
+ EOF
+ test_cmp expect actual.acks
+'
+test_expect_success 'upload-pack ACKs repeated non-commit objects once only (protocol v2)' '
+ commit_id=$(git rev-parse HEAD) &&
+ tree_id=$(git rev-parse HEAD^{tree}) &&
+ test-tool pkt-line pack >request <<-EOF &&
+ command=fetch
+ object-format=$(test_oid algo)
+ 0001
+ want $commit_id
+ have $tree_id
+ have $tree_id
+ 0000
+ EOF
+ GIT_PROTOCOL=version=2 git upload-pack . <request >actual &&
+ depacketize <actual >actual.raw &&
+ grep ^ACK actual.raw >actual.acks &&
+ echo "ACK $tree_id" >expect &&
+ test_cmp expect actual.acks
'
test_done
diff --git a/t/t5538-push-shallow.sh b/t/t5538-push-shallow.sh
index e91fcc173e..dc0e972943 100755
--- a/t/t5538-push-shallow.sh
+++ b/t/t5538-push-shallow.sh
@@ -123,4 +123,45 @@ EOF
git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null
)
'
+
+test_expect_success 'push new commit from shallow clone has correct object count' '
+ git init origin &&
+ test_commit -C origin a &&
+ test_commit -C origin b &&
+
+ git clone --depth=1 "file://$(pwd)/origin" client &&
+ git -C client checkout -b topic &&
+ git -C client commit --allow-empty -m "empty" &&
+ GIT_PROGRESS_DELAY=0 git -C client push --progress origin topic 2>err &&
+ test_grep "Enumerating objects: 1, done." err
+'
+
+test_expect_success 'push new commit from shallow clone has good deltas' '
+ git init base &&
+ test_seq 1 999 >base/a &&
+ test_commit -C base initial &&
+ git -C base add a &&
+ git -C base commit -m "big a" &&
+
+ git clone --depth=1 "file://$(pwd)/base" deltas &&
+ git -C deltas checkout -b deltas &&
+ test_seq 1 1000 >deltas/a &&
+ git -C deltas commit -a -m "bigger a" &&
+ GIT_PROGRESS_DELAY=0 git -C deltas push --progress origin deltas 2>err &&
+
+ test_grep "Enumerating objects: 5, done" err &&
+
+ # If the delta base is found, then this message uses "bytes".
+ # If the delta base is not found, then this message uses "KiB".
+ test_grep "Writing objects: .* bytes" err &&
+
+ git -C deltas commit --amend -m "changed message" &&
+ GIT_TRACE2_EVENT="$(pwd)/config-push.txt" \
+ GIT_PROGRESS_DELAY=0 git -C deltas -c pack.usePathWalk=true \
+ push --progress -f origin deltas 2>err &&
+
+ test_grep "Enumerating objects: 1, done" err &&
+ test_region pack-objects path-walk config-push.txt
+'
+
test_done
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 256ccaefb7..2c70cc561a 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -409,6 +409,36 @@ test_expect_success 'describe tag object' '
test_grep "fatal: test-blob-1 is neither a commit nor blob" actual
'
+test_expect_success 'describe an unreachable blob' '
+ blob=$(echo not-found-anywhere | git hash-object -w --stdin) &&
+ test_must_fail git describe $blob 2>actual &&
+ test_grep "blob .$blob. not reachable from HEAD" actual
+'
+
+test_expect_success 'describe blob on an unborn branch' '
+ oldbranch=$(git symbolic-ref HEAD) &&
+ test_when_finished "git symbolic-ref HEAD $oldbranch" &&
+ git symbolic-ref HEAD refs/heads/does-not-exist &&
+ test_must_fail git describe test-blob 2>actual &&
+ test_grep "cannot search .* on an unborn branch" actual
+'
+
+# This test creates a repository state that we generally try to disallow: HEAD
+# is pointing to an object that is not a commit. The ref update code forbids
+# non-commit writes directly to HEAD or to any branch in refs/heads/. But we
+# can use the loophole of pointing HEAD to another non-branch ref (something we
+# should forbid, but don't for historical reasons).
+#
+# Do not take this test as an endorsement of the loophole! If we ever tighten
+# it, it is reasonable to just drop this test entirely.
+test_expect_success 'describe blob on a non-commit HEAD' '
+ oldbranch=$(git symbolic-ref HEAD) &&
+ test_when_finished "git symbolic-ref HEAD $oldbranch" &&
+ git symbolic-ref HEAD refs/tags/test-blob &&
+ test_must_fail git describe test-blob 2>actual &&
+ test_grep "blob .* not reachable from HEAD" actual
+'
+
test_expect_success ULIMIT_STACK_SIZE 'name-rev works in a deep repo' '
i=1 &&
while test $i -lt 8000
diff --git a/t/t6137-pathspec-wildcards-literal.sh b/t/t6137-pathspec-wildcards-literal.sh
index 20abad5667..17a03085ef 100755
--- a/t/t6137-pathspec-wildcards-literal.sh
+++ b/t/t6137-pathspec-wildcards-literal.sh
@@ -3,8 +3,8 @@ test_description='test wildcards and literals with git add/commit (subshell styl
. ./test-lib.sh
-test_have_prereq FUNNYNAMES || {
- skip_all='skipping: needs FUNNYNAMES (non-Windows only)'
+test_have_prereq BSLASHPSPEC || {
+ skip_all='skipping: needs BSLASHPSPEC (backslashes in pathspecs)'
test_done
}
@@ -184,7 +184,7 @@ test_expect_success 'add wildcard f?z' '
)
'
-test_expect_success 'add literal \? literal' '
+test_expect_success 'add literal \?' '
git init test-q-lit &&
(
cd test-q-lit &&
@@ -241,7 +241,7 @@ test_expect_success 'add literal hello\?world' '
)
'
-test_expect_success 'add literal [abc]' '
+test_expect_success 'add literal \[abc\]' '
git init test-brackets-lit &&
(
cd test-brackets-lit &&
@@ -280,7 +280,7 @@ test_expect_success 'commit: wildcard *' '
)
'
-test_expect_success 'commit: literal *' '
+test_expect_success 'commit: literal \*' '
git init test-c-asterisk-lit &&
(
cd test-c-asterisk-lit &&
@@ -328,7 +328,7 @@ test_expect_success 'commit: literal f\*' '
)
'
-test_expect_success 'commit: wildcard pathspec limits commit' '
+test_expect_success 'commit: wildcard f**' '
git init test-c-pathlimit &&
(
cd test-c-pathlimit &&
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index ce9af79ab1..1d9809114d 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -6,2150 +6,14 @@
test_description='for-each-ref test'
. ./test-lib.sh
-GNUPGHOME_NOT_USED=$GNUPGHOME
-. "$TEST_DIRECTORY"/lib-gpg.sh
-. "$TEST_DIRECTORY"/lib-terminal.sh
-# Mon Jul 3 23:18:43 2006 +0000
-datestamp=1151968723
-setdate_and_increment () {
- GIT_COMMITTER_DATE="$datestamp +0200"
- datestamp=$(expr "$datestamp" + 1)
- GIT_AUTHOR_DATE="$datestamp +0200"
- datestamp=$(expr "$datestamp" + 1)
- export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
-}
-
-test_object_file_size () {
- oid=$(git rev-parse "$1")
- path=".git/objects/$(test_oid_to_path $oid)"
- test_file_size "$path"
-}
-
-test_expect_success setup '
- # setup .mailmap
- cat >.mailmap <<-EOF &&
- A Thor <athor@example.com> A U Thor <author@example.com>
- C Mitter <cmitter@example.com> C O Mitter <committer@example.com>
- EOF
-
- setdate_and_increment &&
- echo "Using $datestamp" > one &&
- git add one &&
- git commit -m "Initial" &&
- git branch -M main &&
- setdate_and_increment &&
- git tag -a -m "Tagging at $datestamp" testtag &&
- git update-ref refs/remotes/origin/main main &&
- git remote add origin nowhere &&
- git config branch.main.remote origin &&
- git config branch.main.merge refs/heads/main &&
- git remote add myfork elsewhere &&
- git config remote.pushdefault myfork &&
- git config push.default current
-'
-
-test_atom () {
- case "$1" in
- head) ref=refs/heads/main ;;
- tag) ref=refs/tags/testtag ;;
- sym) ref=refs/heads/sym ;;
- *) ref=$1 ;;
- esac
- format=$2
- test_do=test_expect_${4:-success}
-
- printf '%s\n' "$3" >expected
- $test_do $PREREQ "basic atom: $ref $format" '
- git for-each-ref --format="%($format)" "$ref" >actual &&
- sanitize_pgp <actual >actual.clean &&
- test_cmp expected actual.clean
- '
-
- # Automatically test "contents:size" atom after testing "contents"
- if test "$format" = "contents"
- then
- # for commit leg, $3 is changed there
- expect=$(printf '%s' "$3" | wc -c)
- $test_do $PREREQ "basic atom: $ref contents:size" '
- type=$(git cat-file -t "$ref") &&
- case $type in
- tag)
- # We cannot use $3 as it expects sanitize_pgp to run
- git cat-file tag $ref >out &&
- expect=$(tail -n +6 out | wc -c) &&
- rm -f out ;;
- tree | blob)
- expect="" ;;
- commit)
- : "use the calculated expect" ;;
- *)
- BUG "unknown object type" ;;
- esac &&
- # Leave $expect unquoted to lose possible leading whitespaces
- echo $expect >expected &&
- git for-each-ref --format="%(contents:size)" "$ref" >actual &&
- test_cmp expected actual
- '
- fi
-}
-
-hexlen=$(test_oid hexsz)
-
-test_atom head refname refs/heads/main
-test_atom head refname: refs/heads/main
-test_atom head refname:short main
-test_atom head refname:lstrip=1 heads/main
-test_atom head refname:lstrip=2 main
-test_atom head refname:lstrip=-1 main
-test_atom head refname:lstrip=-2 heads/main
-test_atom head refname:rstrip=1 refs/heads
-test_atom head refname:rstrip=2 refs
-test_atom head refname:rstrip=-1 refs
-test_atom head refname:rstrip=-2 refs/heads
-test_atom head refname:strip=1 heads/main
-test_atom head refname:strip=2 main
-test_atom head refname:strip=-1 main
-test_atom head refname:strip=-2 heads/main
-test_atom head upstream refs/remotes/origin/main
-test_atom head upstream:short origin/main
-test_atom head upstream:lstrip=2 origin/main
-test_atom head upstream:lstrip=-2 origin/main
-test_atom head upstream:rstrip=2 refs/remotes
-test_atom head upstream:rstrip=-2 refs/remotes
-test_atom head upstream:strip=2 origin/main
-test_atom head upstream:strip=-2 origin/main
-test_atom head push refs/remotes/myfork/main
-test_atom head push:short myfork/main
-test_atom head push:lstrip=1 remotes/myfork/main
-test_atom head push:lstrip=-1 main
-test_atom head push:rstrip=1 refs/remotes/myfork
-test_atom head push:rstrip=-1 refs
-test_atom head push:strip=1 remotes/myfork/main
-test_atom head push:strip=-1 main
-test_atom head objecttype commit
-test_atom head objectsize $((131 + hexlen))
-test_atom head objectsize:disk $(test_object_file_size refs/heads/main)
-test_atom head deltabase $ZERO_OID
-test_atom head objectname $(git rev-parse refs/heads/main)
-test_atom head objectname:short $(git rev-parse --short refs/heads/main)
-test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/main)
-test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/main)
-test_atom head tree $(git rev-parse refs/heads/main^{tree})
-test_atom head tree:short $(git rev-parse --short refs/heads/main^{tree})
-test_atom head tree:short=1 $(git rev-parse --short=1 refs/heads/main^{tree})
-test_atom head tree:short=10 $(git rev-parse --short=10 refs/heads/main^{tree})
-test_atom head parent ''
-test_atom head parent:short ''
-test_atom head parent:short=1 ''
-test_atom head parent:short=10 ''
-test_atom head numparent 0
-test_atom head object ''
-test_atom head type ''
-test_atom head raw "$(git cat-file commit refs/heads/main)
-"
-test_atom head '*objectname' ''
-test_atom head '*objecttype' ''
-test_atom head author 'A U Thor <author@example.com> 1151968724 +0200'
-test_atom head authorname 'A U Thor'
-test_atom head authorname:mailmap 'A Thor'
-test_atom head authoremail '<author@example.com>'
-test_atom head authoremail:trim 'author@example.com'
-test_atom head authoremail:localpart 'author'
-test_atom head authoremail:trim,localpart 'author'
-test_atom head authoremail:mailmap '<athor@example.com>'
-test_atom head authoremail:mailmap,trim 'athor@example.com'
-test_atom head authoremail:trim,mailmap 'athor@example.com'
-test_atom head authoremail:mailmap,localpart 'athor'
-test_atom head authoremail:localpart,mailmap 'athor'
-test_atom head authoremail:mailmap,trim,localpart,mailmap,trim 'athor'
-test_atom head authordate 'Tue Jul 4 01:18:44 2006 +0200'
-test_atom head committer 'C O Mitter <committer@example.com> 1151968723 +0200'
-test_atom head committername 'C O Mitter'
-test_atom head committername:mailmap 'C Mitter'
-test_atom head committeremail '<committer@example.com>'
-test_atom head committeremail:trim 'committer@example.com'
-test_atom head committeremail:localpart 'committer'
-test_atom head committeremail:localpart,trim 'committer'
-test_atom head committeremail:mailmap '<cmitter@example.com>'
-test_atom head committeremail:mailmap,trim 'cmitter@example.com'
-test_atom head committeremail:trim,mailmap 'cmitter@example.com'
-test_atom head committeremail:mailmap,localpart 'cmitter'
-test_atom head committeremail:localpart,mailmap 'cmitter'
-test_atom head committeremail:trim,mailmap,trim,trim,localpart 'cmitter'
-test_atom head committerdate 'Tue Jul 4 01:18:43 2006 +0200'
-test_atom head tag ''
-test_atom head tagger ''
-test_atom head taggername ''
-test_atom head taggeremail ''
-test_atom head taggeremail:trim ''
-test_atom head taggeremail:localpart ''
-test_atom head taggerdate ''
-test_atom head creator 'C O Mitter <committer@example.com> 1151968723 +0200'
-test_atom head creatordate 'Tue Jul 4 01:18:43 2006 +0200'
-test_atom head subject 'Initial'
-test_atom head subject:sanitize 'Initial'
-test_atom head contents:subject 'Initial'
-test_atom head body ''
-test_atom head contents:body ''
-test_atom head contents:signature ''
-test_atom head contents 'Initial
-'
-test_atom head HEAD '*'
-
-test_atom tag refname refs/tags/testtag
-test_atom tag refname:short testtag
-test_atom tag upstream ''
-test_atom tag push ''
-test_atom tag objecttype tag
-test_atom tag objectsize $((114 + hexlen))
-test_atom tag objectsize:disk $(test_object_file_size refs/tags/testtag)
-test_atom tag '*objectsize:disk' $(test_object_file_size refs/heads/main)
-test_atom tag deltabase $ZERO_OID
-test_atom tag '*deltabase' $ZERO_OID
-test_atom tag objectname $(git rev-parse refs/tags/testtag)
-test_atom tag objectname:short $(git rev-parse --short refs/tags/testtag)
-test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/main)
-test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/main)
-test_atom tag tree ''
-test_atom tag tree:short ''
-test_atom tag tree:short=1 ''
-test_atom tag tree:short=10 ''
-test_atom tag parent ''
-test_atom tag parent:short ''
-test_atom tag parent:short=1 ''
-test_atom tag parent:short=10 ''
-test_atom tag numparent ''
-test_atom tag object $(git rev-parse refs/tags/testtag^0)
-test_atom tag type 'commit'
-test_atom tag '*objectname' $(git rev-parse refs/tags/testtag^{})
-test_atom tag '*objecttype' 'commit'
-test_atom tag author ''
-test_atom tag authorname ''
-test_atom tag authorname:mailmap ''
-test_atom tag authoremail ''
-test_atom tag authoremail:trim ''
-test_atom tag authoremail:localpart ''
-test_atom tag authoremail:trim,localpart ''
-test_atom tag authoremail:mailmap ''
-test_atom tag authoremail:mailmap,trim ''
-test_atom tag authoremail:trim,mailmap ''
-test_atom tag authoremail:mailmap,localpart ''
-test_atom tag authoremail:localpart,mailmap ''
-test_atom tag authoremail:mailmap,trim,localpart,mailmap,trim ''
-test_atom tag authordate ''
-test_atom tag committer ''
-test_atom tag committername ''
-test_atom tag committername:mailmap ''
-test_atom tag committeremail ''
-test_atom tag committeremail:trim ''
-test_atom tag committeremail:localpart ''
-test_atom tag committeremail:localpart,trim ''
-test_atom tag committeremail:mailmap ''
-test_atom tag committeremail:mailmap,trim ''
-test_atom tag committeremail:trim,mailmap ''
-test_atom tag committeremail:mailmap,localpart ''
-test_atom tag committeremail:localpart,mailmap ''
-test_atom tag committeremail:trim,mailmap,trim,trim,localpart ''
-test_atom tag committerdate ''
-test_atom tag tag 'testtag'
-test_atom tag tagger 'C O Mitter <committer@example.com> 1151968725 +0200'
-test_atom tag taggername 'C O Mitter'
-test_atom tag taggername:mailmap 'C Mitter'
-test_atom tag taggeremail '<committer@example.com>'
-test_atom tag taggeremail:trim 'committer@example.com'
-test_atom tag taggeremail:localpart 'committer'
-test_atom tag taggeremail:trim,localpart 'committer'
-test_atom tag taggeremail:mailmap '<cmitter@example.com>'
-test_atom tag taggeremail:mailmap,trim 'cmitter@example.com'
-test_atom tag taggeremail:trim,mailmap 'cmitter@example.com'
-test_atom tag taggeremail:mailmap,localpart 'cmitter'
-test_atom tag taggeremail:localpart,mailmap 'cmitter'
-test_atom tag taggeremail:trim,mailmap,trim,localpart,localpart 'cmitter'
-test_atom tag taggerdate 'Tue Jul 4 01:18:45 2006 +0200'
-test_atom tag creator 'C O Mitter <committer@example.com> 1151968725 +0200'
-test_atom tag creatordate 'Tue Jul 4 01:18:45 2006 +0200'
-test_atom tag subject 'Tagging at 1151968727'
-test_atom tag subject:sanitize 'Tagging-at-1151968727'
-test_atom tag contents:subject 'Tagging at 1151968727'
-test_atom tag body ''
-test_atom tag contents:body ''
-test_atom tag contents:signature ''
-test_atom tag contents 'Tagging at 1151968727
-'
-test_atom tag HEAD ' '
-
-test_expect_success 'basic atom: refs/tags/testtag *raw' '
- git cat-file commit refs/tags/testtag^{} >expected &&
- git for-each-ref --format="%(*raw)" refs/tags/testtag >actual &&
- sanitize_pgp <expected >expected.clean &&
- echo >>expected.clean &&
- sanitize_pgp <actual >actual.clean &&
- test_cmp expected.clean actual.clean
-'
-
-test_expect_success 'Check invalid atoms names are errors' '
- test_must_fail git for-each-ref --format="%(INVALID)" refs/heads
-'
-
-test_expect_success 'for-each-ref does not crash with -h' '
+test_expect_success "for-each-ref does not crash with -h" '
test_expect_code 129 git for-each-ref -h >usage &&
test_grep "[Uu]sage: git for-each-ref " usage &&
test_expect_code 129 nongit git for-each-ref -h >usage &&
test_grep "[Uu]sage: git for-each-ref " usage
'
-test_expect_success 'Check format specifiers are ignored in naming date atoms' '
- git for-each-ref --format="%(authordate)" refs/heads &&
- git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads &&
- git for-each-ref --format="%(authordate) %(authordate:default)" refs/heads &&
- git for-each-ref --format="%(authordate:default) %(authordate:default)" refs/heads
-'
-
-test_expect_success 'Check valid format specifiers for date fields' '
- git for-each-ref --format="%(authordate:default)" refs/heads &&
- git for-each-ref --format="%(authordate:relative)" refs/heads &&
- git for-each-ref --format="%(authordate:short)" refs/heads &&
- git for-each-ref --format="%(authordate:local)" refs/heads &&
- git for-each-ref --format="%(authordate:iso8601)" refs/heads &&
- git for-each-ref --format="%(authordate:rfc2822)" refs/heads
-'
-
-test_expect_success 'Check invalid format specifiers are errors' '
- test_must_fail git for-each-ref --format="%(authordate:INVALID)" refs/heads
-'
-
-test_expect_success 'arguments to %(objectname:short=) must be positive integers' '
- test_must_fail git for-each-ref --format="%(objectname:short=0)" &&
- test_must_fail git for-each-ref --format="%(objectname:short=-1)" &&
- test_must_fail git for-each-ref --format="%(objectname:short=foo)"
-'
-
-test_bad_atom () {
- case "$1" in
- head) ref=refs/heads/main ;;
- tag) ref=refs/tags/testtag ;;
- sym) ref=refs/heads/sym ;;
- *) ref=$1 ;;
- esac
- format=$2
- test_do=test_expect_${4:-success}
-
- printf '%s\n' "$3" >expect
- $test_do $PREREQ "err basic atom: $ref $format" '
- test_must_fail git for-each-ref \
- --format="%($format)" "$ref" 2>error &&
- test_cmp expect error
- '
-}
-
-test_bad_atom head 'authoremail:foo' \
- 'fatal: unrecognized %(authoremail) argument: foo'
-
-test_bad_atom head 'authoremail:mailmap,trim,bar' \
- 'fatal: unrecognized %(authoremail) argument: bar'
-
-test_bad_atom head 'authoremail:trim,' \
- 'fatal: unrecognized %(authoremail) argument: '
-
-test_bad_atom head 'authoremail:mailmaptrim' \
- 'fatal: unrecognized %(authoremail) argument: trim'
-
-test_bad_atom head 'committeremail: ' \
- 'fatal: unrecognized %(committeremail) argument: '
-
-test_bad_atom head 'committeremail: trim,foo' \
- 'fatal: unrecognized %(committeremail) argument: trim,foo'
-
-test_bad_atom head 'committeremail:mailmap,localpart ' \
- 'fatal: unrecognized %(committeremail) argument: '
-
-test_bad_atom head 'committeremail:trim_localpart' \
- 'fatal: unrecognized %(committeremail) argument: _localpart'
-
-test_bad_atom head 'committeremail:localpart,,,trim' \
- 'fatal: unrecognized %(committeremail) argument: ,,trim'
-
-test_bad_atom tag 'taggeremail:mailmap,trim, foo ' \
- 'fatal: unrecognized %(taggeremail) argument: foo '
-
-test_bad_atom tag 'taggeremail:trim,localpart,' \
- 'fatal: unrecognized %(taggeremail) argument: '
-
-test_bad_atom tag 'taggeremail:mailmap;localpart trim' \
- 'fatal: unrecognized %(taggeremail) argument: ;localpart trim'
-
-test_bad_atom tag 'taggeremail:localpart trim' \
- 'fatal: unrecognized %(taggeremail) argument: trim'
-
-test_bad_atom tag 'taggeremail:mailmap,mailmap,trim,qux,localpart,trim' \
- 'fatal: unrecognized %(taggeremail) argument: qux,localpart,trim'
-
-test_date () {
- f=$1 &&
- committer_date=$2 &&
- author_date=$3 &&
- tagger_date=$4 &&
- cat >expected <<-EOF &&
- 'refs/heads/main' '$committer_date' '$author_date'
- 'refs/tags/testtag' '$tagger_date'
- EOF
- (
- git for-each-ref --shell \
- --format="%(refname) %(committerdate${f:+:$f}) %(authordate${f:+:$f})" \
- refs/heads &&
- git for-each-ref --shell \
- --format="%(refname) %(taggerdate${f:+:$f})" \
- refs/tags
- ) >actual &&
- test_cmp expected actual
-}
-
-test_expect_success 'Check unformatted date fields output' '
- test_date "" \
- "Tue Jul 4 01:18:43 2006 +0200" \
- "Tue Jul 4 01:18:44 2006 +0200" \
- "Tue Jul 4 01:18:45 2006 +0200"
-'
-
-test_expect_success 'Check format "default" formatted date fields output' '
- test_date default \
- "Tue Jul 4 01:18:43 2006 +0200" \
- "Tue Jul 4 01:18:44 2006 +0200" \
- "Tue Jul 4 01:18:45 2006 +0200"
-'
-
-test_expect_success 'Check format "default-local" date fields output' '
- test_date default-local "Mon Jul 3 23:18:43 2006" "Mon Jul 3 23:18:44 2006" "Mon Jul 3 23:18:45 2006"
-'
-
-# Don't know how to do relative check because I can't know when this script
-# is going to be run and can't fake the current time to git, and hence can't
-# provide expected output. Instead, I'll just make sure that "relative"
-# doesn't exit in error
-test_expect_success 'Check format "relative" date fields output' '
- f=relative &&
- (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
- git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual
-'
-
-# We just check that this is the same as "relative" for now.
-test_expect_success 'Check format "relative-local" date fields output' '
- test_date relative-local \
- "$(git for-each-ref --format="%(committerdate:relative)" refs/heads)" \
- "$(git for-each-ref --format="%(authordate:relative)" refs/heads)" \
- "$(git for-each-ref --format="%(taggerdate:relative)" refs/tags)"
-'
-
-test_expect_success 'Check format "short" date fields output' '
- test_date short 2006-07-04 2006-07-04 2006-07-04
-'
-
-test_expect_success 'Check format "short-local" date fields output' '
- test_date short-local 2006-07-03 2006-07-03 2006-07-03
-'
-
-test_expect_success 'Check format "local" date fields output' '
- test_date local \
- "Mon Jul 3 23:18:43 2006" \
- "Mon Jul 3 23:18:44 2006" \
- "Mon Jul 3 23:18:45 2006"
-'
-
-test_expect_success 'Check format "iso8601" date fields output' '
- test_date iso8601 \
- "2006-07-04 01:18:43 +0200" \
- "2006-07-04 01:18:44 +0200" \
- "2006-07-04 01:18:45 +0200"
-'
-
-test_expect_success 'Check format "iso8601-local" date fields output' '
- test_date iso8601-local "2006-07-03 23:18:43 +0000" "2006-07-03 23:18:44 +0000" "2006-07-03 23:18:45 +0000"
-'
-
-test_expect_success 'Check format "rfc2822" date fields output' '
- test_date rfc2822 \
- "Tue, 4 Jul 2006 01:18:43 +0200" \
- "Tue, 4 Jul 2006 01:18:44 +0200" \
- "Tue, 4 Jul 2006 01:18:45 +0200"
-'
-
-test_expect_success 'Check format "rfc2822-local" date fields output' '
- test_date rfc2822-local "Mon, 3 Jul 2006 23:18:43 +0000" "Mon, 3 Jul 2006 23:18:44 +0000" "Mon, 3 Jul 2006 23:18:45 +0000"
-'
-
-test_expect_success 'Check format "raw" date fields output' '
- test_date raw "1151968723 +0200" "1151968724 +0200" "1151968725 +0200"
-'
-
-test_expect_success 'Check format "raw-local" date fields output' '
- test_date raw-local "1151968723 +0000" "1151968724 +0000" "1151968725 +0000"
-'
-
-test_expect_success 'Check format of strftime date fields' '
- echo "my date is 2006-07-04" >expected &&
- git for-each-ref \
- --format="%(authordate:format:my date is %Y-%m-%d)" \
- refs/heads >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'Check format of strftime-local date fields' '
- echo "my date is 2006-07-03" >expected &&
- git for-each-ref \
- --format="%(authordate:format-local:my date is %Y-%m-%d)" \
- refs/heads >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'exercise strftime with odd fields' '
- echo >expected &&
- git for-each-ref --format="%(authordate:format:)" refs/heads >actual &&
- test_cmp expected actual &&
- long="long format -- $ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID" &&
- echo $long >expected &&
- git for-each-ref --format="%(authordate:format:$long)" refs/heads >actual &&
- test_cmp expected actual
-'
-
-cat >expected <<\EOF
-refs/heads/main
-refs/remotes/origin/main
-refs/tags/testtag
-EOF
-
-test_expect_success 'Verify ascending sort' '
- git for-each-ref --format="%(refname)" --sort=refname >actual &&
- test_cmp expected actual
-'
-
-
-cat >expected <<\EOF
-refs/tags/testtag
-refs/remotes/origin/main
-refs/heads/main
-EOF
-
-test_expect_success 'Verify descending sort' '
- git for-each-ref --format="%(refname)" --sort=-refname >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'Give help even with invalid sort atoms' '
- test_expect_code 129 git for-each-ref --sort=bogus -h >actual 2>&1 &&
- grep "^usage: git for-each-ref" actual
-'
-
-cat >expected <<\EOF
-refs/tags/testtag
-refs/tags/testtag-2
-EOF
-
-test_expect_success 'exercise patterns with prefixes' '
- git tag testtag-2 &&
- test_when_finished "git tag -d testtag-2" &&
- git for-each-ref --format="%(refname)" \
- refs/tags/testtag refs/tags/testtag-2 >actual &&
- test_cmp expected actual
-'
-
-cat >expected <<\EOF
-refs/tags/testtag
-refs/tags/testtag-2
-EOF
-
-test_expect_success 'exercise glob patterns with prefixes' '
- git tag testtag-2 &&
- test_when_finished "git tag -d testtag-2" &&
- git for-each-ref --format="%(refname)" \
- refs/tags/testtag "refs/tags/testtag-*" >actual &&
- test_cmp expected actual
-'
-
-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'
-EOF
-
-test_expect_success 'Quoting style: shell' '
- git for-each-ref --shell --format="%(refname)" >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'Quoting style: perl' '
- git for-each-ref --perl --format="%(refname)" >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'Quoting style: python' '
- git for-each-ref --python --format="%(refname)" >actual &&
- test_cmp expected actual
-'
-
-cat >expected <<\EOF
-"refs/heads/main"
-"refs/remotes/origin/main"
-"refs/tags/testtag"
-EOF
-
-test_expect_success 'Quoting style: tcl' '
- git for-each-ref --tcl --format="%(refname)" >actual &&
- test_cmp expected actual
-'
-
-for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do
- test_expect_success "more than one quoting style: $i" "
- test_must_fail git for-each-ref $i 2>err &&
- grep '^error: more than one quoting style' err
- "
-done
-
-test_expect_success 'setup for upstream:track[short]' '
- test_commit two
-'
-
-test_atom head upstream:track '[ahead 1]'
-test_atom head upstream:trackshort '>'
-test_atom head upstream:track,nobracket 'ahead 1'
-test_atom head upstream:nobracket,track 'ahead 1'
-
-test_expect_success 'setup for push:track[short]' '
- test_commit third &&
- git update-ref refs/remotes/myfork/main main &&
- git reset main~1
-'
-
-test_atom head push:track '[behind 1]'
-test_atom head push:trackshort '<'
-
-test_expect_success 'Check that :track[short] cannot be used with other atoms' '
- test_must_fail git for-each-ref --format="%(refname:track)" 2>/dev/null &&
- test_must_fail git for-each-ref --format="%(refname:trackshort)" 2>/dev/null
-'
-
-test_expect_success 'Check that :track[short] works when upstream is invalid' '
- cat >expected <<-\EOF &&
- [gone]
-
- EOF
- test_when_finished "git config branch.main.merge refs/heads/main" &&
- git config branch.main.merge refs/heads/does-not-exist &&
- git for-each-ref \
- --format="%(upstream:track)$LF%(upstream:trackshort)" \
- refs/heads >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'Check for invalid refname format' '
- test_must_fail git for-each-ref --format="%(refname:INVALID)"
-'
-
-test_expect_success 'set up color tests' '
- cat >expected.color <<-EOF &&
- $(git rev-parse --short refs/heads/main) <GREEN>main<RESET>
- $(git rev-parse --short refs/remotes/myfork/main) <GREEN>myfork/main<RESET>
- $(git rev-parse --short refs/remotes/origin/main) <GREEN>origin/main<RESET>
- $(git rev-parse --short refs/tags/testtag) <GREEN>testtag<RESET>
- $(git rev-parse --short refs/tags/third) <GREEN>third<RESET>
- $(git rev-parse --short refs/tags/two) <GREEN>two<RESET>
- EOF
- sed "s/<[^>]*>//g" <expected.color >expected.bare &&
- color_format="%(objectname:short) %(color:green)%(refname:short)"
-'
-
-test_expect_success TTY '%(color) shows color with a tty' '
- test_terminal git for-each-ref --format="$color_format" >actual.raw &&
- test_decode_color <actual.raw >actual &&
- test_cmp expected.color actual
-'
-
-test_expect_success '%(color) does not show color without tty' '
- TERM=vt100 git for-each-ref --format="$color_format" >actual &&
- test_cmp expected.bare actual
-'
-
-test_expect_success '--color can override tty check' '
- git for-each-ref --color --format="$color_format" >actual.raw &&
- test_decode_color <actual.raw >actual &&
- test_cmp expected.color actual
-'
-
-test_expect_success 'color.ui=always does not override tty check' '
- git -c color.ui=always for-each-ref --format="$color_format" >actual &&
- 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 at least 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
-EOF
-
-test_expect_success 'Check ambiguous head and tag refs (strict)' '
- git config --bool core.warnambiguousrefs true &&
- git checkout -b newtag &&
- echo "Using $datestamp" > one &&
- git add one &&
- git commit -m "Branch" &&
- setdate_and_increment &&
- git tag -m "Tagging at $datestamp" main &&
- git for-each-ref --format "%(refname:short)" refs/heads/main refs/tags/main >actual &&
- test_cmp expected actual
-'
-
-cat >expected <<\EOF
-heads/main
-main
-EOF
-
-test_expect_success 'Check ambiguous head and tag refs (loose)' '
- git config --bool core.warnambiguousrefs false &&
- git for-each-ref --format "%(refname:short)" refs/heads/main refs/tags/main >actual &&
- test_cmp expected actual
-'
-
-cat >expected <<\EOF
-heads/ambiguous
-ambiguous
-EOF
-
-test_expect_success 'Check ambiguous head and tag refs II (loose)' '
- git checkout main &&
- git tag ambiguous testtag^0 &&
- git branch ambiguous testtag^0 &&
- git for-each-ref --format "%(refname:short)" refs/heads/ambiguous refs/tags/ambiguous >actual &&
- test_cmp expected actual
-'
-
-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 --literally --stdin -w -t tag)
-'
-
-test_atom refs/tags/taggerless type 'commit'
-test_atom refs/tags/taggerless tag 'taggerless'
-test_atom refs/tags/taggerless tagger ''
-test_atom refs/tags/taggerless taggername ''
-test_atom refs/tags/taggerless taggeremail ''
-test_atom refs/tags/taggerless taggeremail:trim ''
-test_atom refs/tags/taggerless taggeremail:localpart ''
-test_atom refs/tags/taggerless taggerdate ''
-test_atom refs/tags/taggerless committer ''
-test_atom refs/tags/taggerless committername ''
-test_atom refs/tags/taggerless committeremail ''
-test_atom refs/tags/taggerless committeremail:trim ''
-test_atom refs/tags/taggerless committeremail:localpart ''
-test_atom refs/tags/taggerless committerdate ''
-test_atom refs/tags/taggerless subject 'Broken tag'
-
-test_expect_success 'an unusual tag with an incomplete line' '
-
- git tag -m "bogo" bogo &&
- bogo=$(git cat-file tag bogo) &&
- bogo=$(printf "%s" "$bogo" | git mktag) &&
- git tag -f bogo "$bogo" &&
- git for-each-ref --format "%(body)" refs/tags/bogo
-
-'
-
-test_expect_success 'create tag with subject and body content' '
- cat >>msg <<-\EOF &&
- the subject line
-
- first body line
- second body line
- EOF
- git tag -F msg subject-body
-'
-test_atom refs/tags/subject-body subject 'the subject line'
-test_atom refs/tags/subject-body subject:sanitize 'the-subject-line'
-test_atom refs/tags/subject-body body 'first body line
-second body line
-'
-test_atom refs/tags/subject-body contents 'the subject line
-
-first body line
-second body line
-'
-
-test_expect_success 'create tag with multiline subject' '
- cat >msg <<-\EOF &&
- first subject line
- second subject line
-
- first body line
- second body line
- EOF
- git tag -F msg multiline
-'
-test_atom refs/tags/multiline subject 'first subject line second subject line'
-test_atom refs/tags/multiline subject:sanitize 'first-subject-line-second-subject-line'
-test_atom refs/tags/multiline contents:subject 'first subject line second subject line'
-test_atom refs/tags/multiline body 'first body line
-second body line
-'
-test_atom refs/tags/multiline contents:body 'first body line
-second body line
-'
-test_atom refs/tags/multiline contents:signature ''
-test_atom refs/tags/multiline contents 'first subject line
-second subject line
-
-first body line
-second body line
-'
-
-test_expect_success GPG 'create signed tags' '
- git tag -s -m "" signed-empty &&
- git tag -s -m "subject line" signed-short &&
- cat >msg <<-\EOF &&
- subject line
-
- body contents
- EOF
- git tag -s -F msg signed-long
-'
-
-sig='-----BEGIN PGP SIGNATURE-----
------END PGP SIGNATURE-----
-'
-
-PREREQ=GPG
-test_atom refs/tags/signed-empty subject ''
-test_atom refs/tags/signed-empty subject:sanitize ''
-test_atom refs/tags/signed-empty contents:subject ''
-test_atom refs/tags/signed-empty body "$sig"
-test_atom refs/tags/signed-empty contents:body ''
-test_atom refs/tags/signed-empty contents:signature "$sig"
-test_atom refs/tags/signed-empty contents "$sig"
-
-test_expect_success GPG 'basic atom: refs/tags/signed-empty raw' '
- git cat-file tag refs/tags/signed-empty >expected &&
- git for-each-ref --format="%(raw)" refs/tags/signed-empty >actual &&
- sanitize_pgp <expected >expected.clean &&
- echo >>expected.clean &&
- sanitize_pgp <actual >actual.clean &&
- test_cmp expected.clean actual.clean
-'
-
-test_atom refs/tags/signed-short subject 'subject line'
-test_atom refs/tags/signed-short subject:sanitize 'subject-line'
-test_atom refs/tags/signed-short contents:subject 'subject line'
-test_atom refs/tags/signed-short body "$sig"
-test_atom refs/tags/signed-short contents:body ''
-test_atom refs/tags/signed-short contents:signature "$sig"
-test_atom refs/tags/signed-short contents "subject line
-$sig"
-
-test_expect_success GPG 'basic atom: refs/tags/signed-short raw' '
- git cat-file tag refs/tags/signed-short >expected &&
- git for-each-ref --format="%(raw)" refs/tags/signed-short >actual &&
- sanitize_pgp <expected >expected.clean &&
- echo >>expected.clean &&
- sanitize_pgp <actual >actual.clean &&
- test_cmp expected.clean actual.clean
-'
-
-test_atom refs/tags/signed-long subject 'subject line'
-test_atom refs/tags/signed-long subject:sanitize 'subject-line'
-test_atom refs/tags/signed-long contents:subject 'subject line'
-test_atom refs/tags/signed-long body "body contents
-$sig"
-test_atom refs/tags/signed-long contents:body 'body contents
-'
-test_atom refs/tags/signed-long contents:signature "$sig"
-test_atom refs/tags/signed-long contents "subject line
-
-body contents
-$sig"
-
-test_expect_success GPG 'basic atom: refs/tags/signed-long raw' '
- git cat-file tag refs/tags/signed-long >expected &&
- git for-each-ref --format="%(raw)" refs/tags/signed-long >actual &&
- sanitize_pgp <expected >expected.clean &&
- echo >>expected.clean &&
- sanitize_pgp <actual >actual.clean &&
- test_cmp expected.clean actual.clean
-'
-
-test_expect_success 'set up refs pointing to tree and blob' '
- git update-ref refs/mytrees/first refs/heads/main^{tree} &&
- git update-ref refs/myblobs/first refs/heads/main:one
-'
-
-test_atom refs/mytrees/first subject ""
-test_atom refs/mytrees/first contents:subject ""
-test_atom refs/mytrees/first body ""
-test_atom refs/mytrees/first contents:body ""
-test_atom refs/mytrees/first contents:signature ""
-test_atom refs/mytrees/first contents ""
-
-test_expect_success 'basic atom: refs/mytrees/first raw' '
- git cat-file tree refs/mytrees/first >expected &&
- echo >>expected &&
- git for-each-ref --format="%(raw)" refs/mytrees/first >actual &&
- test_cmp expected actual &&
- git cat-file -s refs/mytrees/first >expected &&
- git for-each-ref --format="%(raw:size)" refs/mytrees/first >actual &&
- test_cmp expected actual
-'
-
-test_atom refs/myblobs/first subject ""
-test_atom refs/myblobs/first contents:subject ""
-test_atom refs/myblobs/first body ""
-test_atom refs/myblobs/first contents:body ""
-test_atom refs/myblobs/first contents:signature ""
-test_atom refs/myblobs/first contents ""
-
-test_expect_success 'basic atom: refs/myblobs/first raw' '
- git cat-file blob refs/myblobs/first >expected &&
- echo >>expected &&
- git for-each-ref --format="%(raw)" refs/myblobs/first >actual &&
- test_cmp expected actual &&
- git cat-file -s refs/myblobs/first >expected &&
- git for-each-ref --format="%(raw:size)" refs/myblobs/first >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'set up refs pointing to binary blob' '
- printf "a\0b\0c" >blob1 &&
- printf "a\0c\0b" >blob2 &&
- printf "\0a\0b\0c" >blob3 &&
- printf "abc" >blob4 &&
- printf "\0 \0 \0 " >blob5 &&
- printf "\0 \0a\0 " >blob6 &&
- printf " " >blob7 &&
- >blob8 &&
- obj=$(git hash-object -w blob1) &&
- git update-ref refs/myblobs/blob1 "$obj" &&
- obj=$(git hash-object -w blob2) &&
- git update-ref refs/myblobs/blob2 "$obj" &&
- obj=$(git hash-object -w blob3) &&
- git update-ref refs/myblobs/blob3 "$obj" &&
- obj=$(git hash-object -w blob4) &&
- git update-ref refs/myblobs/blob4 "$obj" &&
- obj=$(git hash-object -w blob5) &&
- git update-ref refs/myblobs/blob5 "$obj" &&
- obj=$(git hash-object -w blob6) &&
- git update-ref refs/myblobs/blob6 "$obj" &&
- obj=$(git hash-object -w blob7) &&
- git update-ref refs/myblobs/blob7 "$obj" &&
- obj=$(git hash-object -w blob8) &&
- git update-ref refs/myblobs/blob8 "$obj"
-'
-
-test_expect_success 'Verify sorts with raw' '
- cat >expected <<-EOF &&
- refs/myblobs/blob8
- refs/myblobs/blob5
- refs/myblobs/blob6
- refs/myblobs/blob3
- refs/myblobs/blob7
- refs/mytrees/first
- refs/myblobs/first
- refs/myblobs/blob1
- refs/myblobs/blob2
- refs/myblobs/blob4
- refs/heads/main
- EOF
- git for-each-ref --format="%(refname)" --sort=raw \
- refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'Verify sorts with raw:size' '
- cat >expected <<-EOF &&
- refs/myblobs/blob8
- refs/myblobs/blob7
- 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 &&
- test_cmp expected actual
-'
-
-test_expect_success 'validate raw atom with %(if:equals)' '
- cat >expected <<-EOF &&
- not equals
- not equals
- not equals
- not equals
- not equals
- not equals
- refs/myblobs/blob4
- not equals
- not equals
- not equals
- not equals
- not equals
- EOF
- git for-each-ref --format="%(if:equals=abc)%(raw)%(then)%(refname)%(else)not equals%(end)" \
- refs/myblobs/ refs/heads/ >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'validate raw atom with %(if:notequals)' '
- cat >expected <<-EOF &&
- refs/heads/ambiguous
- refs/heads/main
- refs/heads/newtag
- refs/myblobs/blob1
- refs/myblobs/blob2
- refs/myblobs/blob3
- equals
- refs/myblobs/blob5
- refs/myblobs/blob6
- refs/myblobs/blob7
- refs/myblobs/blob8
- refs/myblobs/first
- EOF
- git for-each-ref --format="%(if:notequals=abc)%(raw)%(then)%(refname)%(else)equals%(end)" \
- refs/myblobs/ refs/heads/ >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'empty raw refs with %(if)' '
- cat >expected <<-EOF &&
- refs/myblobs/blob1 not empty
- refs/myblobs/blob2 not empty
- refs/myblobs/blob3 not empty
- refs/myblobs/blob4 not empty
- refs/myblobs/blob5 not empty
- refs/myblobs/blob6 not empty
- refs/myblobs/blob7 empty
- refs/myblobs/blob8 empty
- refs/myblobs/first not empty
- EOF
- git for-each-ref --format="%(refname) %(if)%(raw)%(then)not empty%(else)empty%(end)" \
- refs/myblobs/ >actual &&
- test_cmp expected actual
-'
-
-test_expect_success '%(raw) with --python must fail' '
- test_must_fail git for-each-ref --format="%(raw)" --python
-'
-
-test_expect_success '%(raw) with --tcl must fail' '
- test_must_fail git for-each-ref --format="%(raw)" --tcl
-'
-
-test_expect_success PERL_TEST_HELPERS '%(raw) with --perl' '
- git for-each-ref --format="\$name= %(raw);
-print \"\$name\"" refs/myblobs/blob1 --perl | perl >actual &&
- cmp blob1 actual &&
- git for-each-ref --format="\$name= %(raw);
-print \"\$name\"" refs/myblobs/blob3 --perl | perl >actual &&
- cmp blob3 actual &&
- git for-each-ref --format="\$name= %(raw);
-print \"\$name\"" refs/myblobs/blob8 --perl | perl >actual &&
- cmp blob8 actual &&
- git for-each-ref --format="\$name= %(raw);
-print \"\$name\"" refs/myblobs/first --perl | perl >actual &&
- cmp one actual &&
- git cat-file tree refs/mytrees/first > expected &&
- git for-each-ref --format="\$name= %(raw);
-print \"\$name\"" refs/mytrees/first --perl | perl >actual &&
- cmp expected actual
-'
-
-test_expect_success '%(raw) with --shell must fail' '
- test_must_fail git for-each-ref --format="%(raw)" --shell
-'
-
-test_expect_success '%(raw) with --shell and --sort=raw must fail' '
- test_must_fail git for-each-ref --format="%(raw)" --sort=raw --shell
-'
-
-test_expect_success '%(raw:size) with --shell' '
- git for-each-ref --format="%(raw:size)" | sed "s/^/$SQ/;s/$/$SQ/" >expect &&
- git for-each-ref --format="%(raw:size)" --shell >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'for-each-ref --format compare with cat-file --batch' '
- git rev-parse refs/mytrees/first | git cat-file --batch >expected &&
- git for-each-ref --format="%(objectname) %(objecttype) %(objectsize)
-%(raw)" refs/mytrees/first >actual &&
- 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
- for email in user1 user2
- do
- for ref in ref1 ref2
- do
- GIT_COMMITTER_DATE="@$when +0000" \
- GIT_COMMITTER_EMAIL="$email@example.com" \
- git tag -m "tag $ref-$when-$email" \
- multi-$ref-$when-$email || return 1
- done
- done
- done
-'
-
-test_expect_success 'Verify sort with multiple keys' '
- cat >expected <<-\EOF &&
- 100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
- 100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
- 100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
- 100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
- 200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
- 200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
- 200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
- 200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
- EOF
- git for-each-ref \
- --format="%(taggerdate:unix) %(taggeremail) %(refname)" \
- --sort=-refname \
- --sort=taggeremail \
- --sort=taggerdate \
- "refs/tags/multi-*" >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'equivalent sorts fall back on refname' '
- cat >expected <<-\EOF &&
- 100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
- 100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
- 100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
- 100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
- 200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
- 200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
- 200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
- 200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
- EOF
- git for-each-ref \
- --format="%(taggerdate:unix) %(taggeremail) %(refname)" \
- --sort=taggerdate \
- "refs/tags/multi-*" >actual &&
- test_cmp expected actual
-'
-
-test_expect_success '--no-sort cancels the previous sort keys' '
- cat >expected <<-\EOF &&
- 100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
- 100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
- 100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
- 100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
- 200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
- 200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
- 200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
- 200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
- EOF
- git for-each-ref \
- --format="%(taggerdate:unix) %(taggeremail) %(refname)" \
- --sort=-refname \
- --sort=taggeremail \
- --no-sort \
- --sort=taggerdate \
- "refs/tags/multi-*" >actual &&
- test_cmp expected actual
-'
-
-test_expect_success '--no-sort without subsequent --sort prints expected refs' '
- cat >expected <<-\EOF &&
- 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
- EOF
-
- # Sort the results with `sort` for a consistent comparison against
- # expected
- git for-each-ref \
- --format="%(refname)" \
- --no-sort \
- "refs/tags/multi-*" | sort >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'set up custom date sorting' '
- # Dates:
- # - Wed Feb 07 2024 21:34:20 +0000
- # - Tue Dec 14 1999 00:05:22 +0000
- # - Fri Jun 04 2021 11:26:51 +0000
- # - Mon Jan 22 2007 16:44:01 GMT+0000
- i=1 &&
- for when in 1707341660 945129922 1622806011 1169484241
- do
- GIT_COMMITTER_DATE="@$when +0000" \
- GIT_COMMITTER_EMAIL="user@example.com" \
- git tag -m "tag $when" custom-dates-$i &&
- i=$(($i+1)) || return 1
- done
-'
-
-test_expect_success 'sort by date defaults to full timestamp' '
- cat >expected <<-\EOF &&
- 945129922 refs/tags/custom-dates-2
- 1169484241 refs/tags/custom-dates-4
- 1622806011 refs/tags/custom-dates-3
- 1707341660 refs/tags/custom-dates-1
- EOF
-
- git for-each-ref \
- --format="%(creatordate:unix) %(refname)" \
- --sort=creatordate \
- "refs/tags/custom-dates-*" >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'sort by custom date format' '
- cat >expected <<-\EOF &&
- 00:05:22 refs/tags/custom-dates-2
- 11:26:51 refs/tags/custom-dates-3
- 16:44:01 refs/tags/custom-dates-4
- 21:34:20 refs/tags/custom-dates-1
- EOF
-
- git for-each-ref \
- --format="%(creatordate:format:%H:%M:%S) %(refname)" \
- --sort="creatordate:format:%H:%M:%S" \
- "refs/tags/custom-dates-*" >actual &&
- test_cmp expected actual
-'
-
-test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' '
- test_when_finished "git checkout main" &&
- git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
- sed -e "s/^\* / /" actual >expect &&
- git checkout --orphan orphaned-branch &&
- git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
- test_cmp expect actual
-'
-
-cat >trailers <<EOF
-Reviewed-by: A U Thor <author@example.com>
-Signed-off-by: A U Thor <author@example.com>
-[ v2 updated patch description ]
-Acked-by: A U Thor
- <author@example.com>
-EOF
-
-unfold () {
- perl -0pe 's/\n\s+/ /g'
-}
-
-test_expect_success 'set up trailers for next test' '
- echo "Some contents" > two &&
- git add two &&
- git commit -F - <<-EOF
- trailers: this commit message has trailers
-
- Some message contents
-
- $(cat trailers)
- EOF
-'
-
-test_trailer_option () {
- if test "$#" -eq 3
- then
- prereq="$1"
- shift
- fi &&
- title=$1 option=$2
- cat >expect
- test_expect_success $prereq "$title" '
- git for-each-ref --format="%($option)" refs/heads/main >actual &&
- test_cmp expect actual &&
- git for-each-ref --format="%(contents:$option)" refs/heads/main >actual &&
- test_cmp expect actual
- '
-}
-
-test_trailer_option PERL_TEST_HELPERS '%(trailers:unfold) unfolds trailers' \
- 'trailers:unfold' <<-EOF
- $(unfold <trailers)
-
- EOF
-
-test_trailer_option '%(trailers:only) shows only "key: value" trailers' \
- 'trailers:only' <<-EOF
- $(grep -v patch.description <trailers)
-
- EOF
-
-test_trailer_option '%(trailers:only=no,only=true) shows only "key: value" trailers' \
- 'trailers:only=no,only=true' <<-EOF
- $(grep -v patch.description <trailers)
-
- EOF
-
-test_trailer_option '%(trailers:only=yes) shows only "key: value" trailers' \
- 'trailers:only=yes' <<-EOF
- $(grep -v patch.description <trailers)
-
- EOF
-
-test_trailer_option '%(trailers:only=no) shows all trailers' \
- 'trailers:only=no' <<-EOF
- $(cat trailers)
-
- EOF
-
-test_trailer_option PERL_TEST_HELPERS '%(trailers:only) and %(trailers:unfold) work together' \
- 'trailers:only,unfold' <<-EOF
- $(grep -v patch.description <trailers | unfold)
-
- EOF
-
-test_trailer_option PERL_TEST_HELPERS '%(trailers:unfold) and %(trailers:only) work together' \
- 'trailers:unfold,only' <<-EOF
- $(grep -v patch.description <trailers | unfold)
-
- EOF
-
-test_trailer_option '%(trailers:key=foo) shows that trailer' \
- 'trailers:key=Signed-off-by' <<-EOF
- Signed-off-by: A U Thor <author@example.com>
-
- EOF
-
-test_trailer_option '%(trailers:key=foo) is case insensitive' \
- 'trailers:key=SiGned-oFf-bY' <<-EOF
- Signed-off-by: A U Thor <author@example.com>
-
- EOF
-
-test_trailer_option '%(trailers:key=foo:) trailing colon also works' \
- 'trailers:key=Signed-off-by:' <<-EOF
- Signed-off-by: A U Thor <author@example.com>
-
- EOF
-
-test_trailer_option '%(trailers:key=foo) multiple keys' \
- 'trailers:key=Reviewed-by:,key=Signed-off-by' <<-EOF
- Reviewed-by: A U Thor <author@example.com>
- Signed-off-by: A U Thor <author@example.com>
-
- EOF
-
-test_trailer_option '%(trailers:key=nonexistent) becomes empty' \
- 'trailers:key=Shined-off-by:' <<-EOF
-
- EOF
-
-test_trailer_option '%(trailers:key=foo) handles multiple lines even if folded' \
- 'trailers:key=Acked-by' <<-EOF
- $(grep -v patch.description <trailers | grep -v Signed-off-by | grep -v Reviewed-by)
-
- EOF
-
-test_trailer_option '%(trailers:key=foo,unfold) properly unfolds' \
- 'trailers:key=Signed-Off-by,unfold' <<-EOF
- $(unfold <trailers | grep Signed-off-by)
-
- EOF
-
-test_trailer_option '%(trailers:key=foo,only=no) also includes nontrailer lines' \
- 'trailers:key=Signed-off-by,only=no' <<-EOF
- Signed-off-by: A U Thor <author@example.com>
- $(grep patch.description <trailers)
-
- EOF
-
-test_trailer_option '%(trailers:key=foo,valueonly) shows only value' \
- 'trailers:key=Signed-off-by,valueonly' <<-EOF
- A U Thor <author@example.com>
-
- EOF
-
-test_trailer_option '%(trailers:separator) changes separator' \
- 'trailers:separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
- Reviewed-by: A U Thor <author@example.com>,Signed-off-by: A U Thor <author@example.com>
- EOF
-
-test_trailer_option '%(trailers:key_value_separator) changes key-value separator' \
- 'trailers:key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
- Reviewed-by,A U Thor <author@example.com>
- Signed-off-by,A U Thor <author@example.com>
-
- EOF
-
-test_trailer_option '%(trailers:separator,key_value_separator) changes both separators' \
- 'trailers:separator=%x2C,key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
- Reviewed-by,A U Thor <author@example.com>,Signed-off-by,A U Thor <author@example.com>
- EOF
-
-test_expect_success 'multiple %(trailers) use their own options' '
- git tag -F - tag-with-trailers <<-\EOF &&
- body
-
- one: foo
- one: bar
- two: baz
- two: qux
- EOF
- t1="%(trailers:key=one,key_value_separator=W,separator=X)" &&
- t2="%(trailers:key=two,key_value_separator=Y,separator=Z)" &&
- git for-each-ref --format="$t1%0a$t2" refs/tags/tag-with-trailers >actual &&
- cat >expect <<-\EOF &&
- oneWfooXoneWbar
- twoYbazZtwoYqux
- EOF
- test_cmp expect actual
-'
-
-test_failing_trailer_option () {
- title=$1 option=$2
- cat >expect
- test_expect_success "$title" '
- # error message cannot be checked under i18n
- test_must_fail git for-each-ref --format="%($option)" refs/heads/main 2>actual &&
- test_cmp expect actual &&
- test_must_fail git for-each-ref --format="%(contents:$option)" refs/heads/main 2>actual &&
- test_cmp expect actual
- '
-}
-
-test_failing_trailer_option '%(trailers) rejects unknown trailers arguments' \
- 'trailers:unsupported' <<-\EOF
- fatal: unknown %(trailers) argument: unsupported
- EOF
-
-test_failing_trailer_option '%(trailers:key) without value is error' \
- 'trailers:key' <<-\EOF
- fatal: expected %(trailers:key=<value>)
- EOF
-
-test_expect_success 'if arguments, %(contents:trailers) shows error if colon is missing' '
- cat >expect <<-EOF &&
- fatal: unrecognized %(contents) argument: trailersonly
- EOF
- test_must_fail git for-each-ref --format="%(contents:trailersonly)" 2>actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'basic atom: head contents:trailers' '
- git for-each-ref --format="%(contents:trailers)" refs/heads/main >actual &&
- sanitize_pgp <actual >actual.clean &&
- # git for-each-ref ends with a blank line
- cat >expect <<-EOF &&
- $(cat trailers)
-
- EOF
- test_cmp expect actual.clean
-'
-
-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
-
- This is the body. The message has a "---" line which would confuse a
- message+patch parser. But here we know we have only a commit message,
- so we get it right.
-
- trailer: wrong
- ---
- This is more body.
-
- trailer: right
- EOF
-
- {
- echo "trailer: right" &&
- echo
- } >expect &&
- git for-each-ref --format="%(trailers)" refs/heads/main >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'Add symbolic ref for the following tests' '
- git symbolic-ref refs/heads/sym refs/heads/main
-'
-
-cat >expected <<EOF
-refs/heads/main
-EOF
-
-test_expect_success 'Verify usage of %(symref) atom' '
- git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
- test_cmp expected actual
-'
-
-cat >expected <<EOF
-heads/main
-EOF
-
-test_expect_success 'Verify usage of %(symref:short) atom' '
- git for-each-ref --format="%(symref:short)" refs/heads/sym >actual &&
- test_cmp expected actual
-'
-
-cat >expected <<EOF
-main
-heads/main
-EOF
-
-test_expect_success 'Verify usage of %(symref:lstrip) atom' '
- git for-each-ref --format="%(symref:lstrip=2)" refs/heads/sym > actual &&
- git for-each-ref --format="%(symref:lstrip=-2)" refs/heads/sym >> actual &&
- test_cmp expected actual &&
-
- git for-each-ref --format="%(symref:strip=2)" refs/heads/sym > actual &&
- git for-each-ref --format="%(symref:strip=-2)" refs/heads/sym >> actual &&
- test_cmp expected actual
-'
-
-cat >expected <<EOF
-refs
-refs/heads
-EOF
-
-test_expect_success 'Verify usage of %(symref:rstrip) atom' '
- git for-each-ref --format="%(symref:rstrip=2)" refs/heads/sym > actual &&
- git for-each-ref --format="%(symref:rstrip=-2)" refs/heads/sym >> actual &&
- test_cmp expected actual
-'
-
-test_expect_success ':remotename and :remoteref' '
- git init remote-tests &&
- (
- cd remote-tests &&
- test_commit initial &&
- git branch -M main &&
- git remote add from fifth.coffee:blub &&
- git config branch.main.remote from &&
- git config branch.main.merge refs/heads/stable &&
- git remote add to southridge.audio:repo &&
- git config remote.to.push "refs/heads/*:refs/heads/pushed/*" &&
- git config branch.main.pushRemote to &&
- for pair in "%(upstream)=refs/remotes/from/stable" \
- "%(upstream:remotename)=from" \
- "%(upstream:remoteref)=refs/heads/stable" \
- "%(push)=refs/remotes/to/pushed/main" \
- "%(push:remotename)=to" \
- "%(push:remoteref)=refs/heads/pushed/main"
- do
- echo "${pair#*=}" >expect &&
- git for-each-ref --format="${pair%=*}" \
- refs/heads/main >actual &&
- test_cmp expect actual || exit 1
- done &&
- git branch push-simple &&
- git config branch.push-simple.pushRemote from &&
- actual="$(git for-each-ref \
- --format="%(push:remotename),%(push:remoteref)" \
- refs/heads/push-simple)" &&
- test from, = "$actual"
- )
-'
-
-test_expect_success 'for-each-ref --ignore-case ignores case' '
- git for-each-ref --format="%(refname)" refs/heads/MAIN >actual &&
- test_must_be_empty actual &&
-
- echo refs/heads/main >expect &&
- git for-each-ref --format="%(refname)" --ignore-case \
- refs/heads/MAIN >actual &&
- 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 &&
- for email in a A b B
- do
- for subject in a A b B
- do
- GIT_COMMITTER_EMAIL="$email@example.com" \
- git tag -m "tag $subject" icase-$(printf %02d $nr) &&
- nr=$((nr+1))||
- return 1
- done
- done &&
- git for-each-ref --ignore-case \
- --format="%(taggeremail) %(subject) %(refname)" \
- --sort=refname \
- --sort=subject \
- --sort=taggeremail \
- refs/tags/icase-* >actual &&
- cat >expect <<-\EOF &&
- <a@example.com> tag a refs/tags/icase-00
- <a@example.com> tag A refs/tags/icase-01
- <A@example.com> tag a refs/tags/icase-04
- <A@example.com> tag A refs/tags/icase-05
- <a@example.com> tag b refs/tags/icase-02
- <a@example.com> tag B refs/tags/icase-03
- <A@example.com> tag b refs/tags/icase-06
- <A@example.com> tag B refs/tags/icase-07
- <b@example.com> tag a refs/tags/icase-08
- <b@example.com> tag A refs/tags/icase-09
- <B@example.com> tag a refs/tags/icase-12
- <B@example.com> tag A refs/tags/icase-13
- <b@example.com> tag b refs/tags/icase-10
- <b@example.com> tag B refs/tags/icase-11
- <B@example.com> tag b refs/tags/icase-14
- <B@example.com> tag B refs/tags/icase-15
- EOF
- test_cmp expect actual
-'
-
-test_expect_success 'for-each-ref reports broken tags' '
- git tag -m "good tag" broken-tag-good HEAD &&
- git cat-file tag broken-tag-good >good &&
- sed s/commit/blob/ <good >bad &&
- bad=$(git hash-object -w -t tag bad) &&
- git update-ref refs/tags/broken-tag-bad $bad &&
- test_must_fail git for-each-ref --format="%(*objectname)" \
- 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 'set up tag with signature and trailers' '
- git tag -F - fake-sig-trailer <<-\EOF
- this is the subject
-
- this is the body
-
- My-Trailer: foo
- -----BEGIN PGP SIGNATURE-----
-
- not a real signature, but we just care about the
- subject/body/trailer parsing.
- -----END PGP SIGNATURE-----
- EOF
-'
-
-# use "separator=" here to suppress the terminating newline
-test_atom refs/tags/fake-sig-trailer trailers:separator= 'My-Trailer: foo'
-
-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
-'
-
-test_expect_success 'git for-each-ref with nested tags' '
- git tag -am "Normal tag" nested/base HEAD &&
- git tag -am "Nested tag" nested/nest1 refs/tags/nested/base &&
- git tag -am "Double nested tag" nested/nest2 refs/tags/nested/nest1 &&
-
- head_oid="$(git rev-parse HEAD)" &&
- base_tag_oid="$(git rev-parse refs/tags/nested/base)" &&
- nest1_tag_oid="$(git rev-parse refs/tags/nested/nest1)" &&
- nest2_tag_oid="$(git rev-parse refs/tags/nested/nest2)" &&
-
- cat >expect <<-EOF &&
- refs/tags/nested/base $base_tag_oid tag $head_oid commit
- refs/tags/nested/nest1 $nest1_tag_oid tag $head_oid commit
- refs/tags/nested/nest2 $nest2_tag_oid tag $head_oid commit
- EOF
-
- git for-each-ref \
- --format="%(refname) %(objectname) %(objecttype) %(*objectname) %(*objecttype)" \
- refs/tags/nested/ >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'is-base atom with non-commits' '
- git for-each-ref --format="%(is-base:HEAD) %(refname)" >out 2>err &&
- grep "(HEAD) refs/heads/main" out &&
-
- test_line_count = 2 err &&
- grep "error: object .* is a commit, not a blob" err &&
- grep "error: bad tag pointer to" err
-'
-
-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_DIRECTORY"/for-each-ref-tests.sh
test_done
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index bb02b86c16..9b80ea1e3b 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -541,4 +541,217 @@ test_expect_success 'validate worktree atom' '
test_cmp expect actual
'
+test_expect_success 'start after with empty value' '
+ cat >expect <<-\EOF &&
+ refs/heads/main
+ refs/heads/main_worktree
+ refs/heads/side
+ refs/odd/spot
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/foo1.10
+ refs/tags/foo1.3
+ refs/tags/foo1.6
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --start-after="" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after a specific reference' '
+ cat >expect <<-\EOF &&
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/foo1.10
+ refs/tags/foo1.3
+ refs/tags/foo1.6
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --start-after=refs/odd/spot >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after a specific reference with partial match' '
+ cat >expect <<-\EOF &&
+ refs/odd/spot
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/foo1.10
+ refs/tags/foo1.3
+ refs/tags/foo1.6
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --start-after=refs/odd/sp >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after, just behind a specific reference' '
+ cat >expect <<-\EOF &&
+ refs/odd/spot
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/foo1.10
+ refs/tags/foo1.3
+ refs/tags/foo1.6
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --start-after=refs/odd/parrot >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after with specific directory match' '
+ cat >expect <<-\EOF &&
+ refs/odd/spot
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/foo1.10
+ refs/tags/foo1.3
+ refs/tags/foo1.6
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --start-after=refs/odd >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after with specific directory and trailing slash' '
+ cat >expect <<-\EOF &&
+ refs/odd/spot
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/foo1.10
+ refs/tags/foo1.3
+ refs/tags/foo1.6
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --start-after=refs/odd/ >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after, just behind a specific directory' '
+ cat >expect <<-\EOF &&
+ refs/odd/spot
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/foo1.10
+ refs/tags/foo1.3
+ refs/tags/foo1.6
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --start-after=refs/lost >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after, overflow specific reference length' '
+ cat >expect <<-\EOF &&
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/foo1.10
+ refs/tags/foo1.3
+ refs/tags/foo1.6
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --start-after=refs/odd/spotnew >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after, overflow specific reference path' '
+ cat >expect <<-\EOF &&
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/foo1.10
+ refs/tags/foo1.3
+ refs/tags/foo1.6
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --start-after=refs/odd/spot/new >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after, with exclude pattern' '
+ cat >expect <<-\EOF &&
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/foo1.10
+ refs/tags/foo1.3
+ refs/tags/foo1.6
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --start-after=refs/odd/spot \
+ --exclude=refs/tags/foo >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after, last reference' '
+ cat >expect <<-\EOF &&
+ EOF
+ git for-each-ref --format="%(refname)" --start-after=refs/tags/two >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after used with a pattern' '
+ cat >expect <<-\EOF &&
+ fatal: cannot use --start-after with patterns
+ EOF
+ test_must_fail git for-each-ref --format="%(refname)" --start-after=refs/odd/spot refs/tags 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'start after used with custom sort order' '
+ cat >expect <<-\EOF &&
+ fatal: cannot use --start-after with custom sort options
+ EOF
+ test_must_fail git for-each-ref --format="%(refname)" --start-after=refs/odd/spot --sort=author 2>actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t6422-merge-rename-corner-cases.sh b/t/t6422-merge-rename-corner-cases.sh
index 9cbe7ca782..f14c0fb30e 100755
--- a/t/t6422-merge-rename-corner-cases.sh
+++ b/t/t6422-merge-rename-corner-cases.sh
@@ -1146,10 +1146,7 @@ test_conflicts_with_adds_and_renames() {
cd simple_${sideL}_${sideR} &&
# Create some related files now
- for i in $(test_seq 1 10)
- do
- echo Random base content line $i
- done >file_v1 &&
+ test_seq -f "Random base content line %d" 1 10 >file_v1 &&
cp file_v1 file_v2 &&
echo modification >>file_v2 &&
@@ -1293,10 +1290,7 @@ test_setup_nested_conflicts_from_rename_rename () {
cd nested_conflicts_from_rename_rename &&
# Create some related files now
- for i in $(test_seq 1 10)
- do
- echo Random base content line $i
- done >file_v1 &&
+ test_seq -f "Random base content line %d" 1 10 >file_v1 &&
cp file_v1 file_v2 &&
cp file_v1 file_v3 &&
diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh
index f48ed6d035..533ac85dc8 100755
--- a/t/t6423-merge-rename-directories.sh
+++ b/t/t6423-merge-rename-directories.sh
@@ -4731,7 +4731,7 @@ test_setup_12i () {
mkdir -p source/subdir &&
echo foo >source/subdir/foo &&
- echo bar >source/bar &&
+ printf "%d\n" 1 2 3 4 5 6 7 >source/bar &&
echo baz >source/baz &&
git add source &&
git commit -m orig &&
@@ -4747,6 +4747,7 @@ test_setup_12i () {
git switch B &&
git mv source/bar source/subdir/bar &&
echo more baz >>source/baz &&
+ git add source/baz &&
git commit -m B
)
}
@@ -4758,6 +4759,88 @@ test_expect_success '12i: Directory rename causes rename-to-self' '
git checkout A^0 &&
+ # NOTE: A potentially better resolution would be for
+ # source/bar -> source/subdir/bar
+ # to use the directory rename to become
+ # source/bar -> source/bar
+ # (a rename to self), and thus we end up with bar with
+ # a path conflict (given merge.directoryRenames=conflict).
+ # However, since the relevant renames optimization
+ # prevents us from noticing
+ # source/bar -> source/subdir/bar
+ # as a rename and looking at it just as
+ # delete source/bar
+ # add source/subdir/bar
+ # the directory rename of source/subdir/bar -> source/bar does
+ # not look like a rename-to-self situation but a
+ # rename-on-top-of-other-file situation. We do not want
+ # stage 1 entries from an unrelated file, so we expect an
+ # error about there being a file in the way.
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+
+ grep "CONFLICT (implicit dir rename).*source/bar in the way" out &&
+ test_path_is_missing source/bar &&
+ test_path_is_file source/subdir/bar &&
+ test_path_is_file source/baz &&
+
+ git ls-files >actual &&
+ uniq <actual >tracked &&
+ test_line_count = 3 tracked &&
+
+ git status --porcelain -uno >actual &&
+ cat >expect <<-\EOF &&
+ M source/baz
+ R source/bar -> source/subdir/bar
+ EOF
+ test_cmp expect actual
+ )
+'
+
+# Testcase 12i2, Identical to 12i except that source/subdir/bar modified on unrenamed side
+# Commit O: source/{subdir/foo, bar, baz_1}
+# Commit A: source/{foo, bar_2, baz_1}
+# Commit B: source/{subdir/{foo, bar}, baz_2}
+# Expected: source/{foo, bar, baz_2}, with conflicts on
+# source/bar vs. source/subdir/bar
+
+test_setup_12i2 () {
+ git init 12i2 &&
+ (
+ cd 12i2 &&
+
+ mkdir -p source/subdir &&
+ echo foo >source/subdir/foo &&
+ printf "%d\n" 1 2 3 4 5 6 7 >source/bar &&
+ echo baz >source/baz &&
+ git add source &&
+ git commit -m orig &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ git mv source/subdir/foo source/foo &&
+ echo 8 >> source/bar &&
+ git add source/bar &&
+ git commit -m A &&
+
+ git switch B &&
+ git mv source/bar source/subdir/bar &&
+ echo more baz >>source/baz &&
+ git add source/baz &&
+ git commit -m B
+ )
+}
+
+test_expect_success '12i2: Directory rename causes rename-to-self' '
+ test_setup_12i2 &&
+ (
+ cd 12i2 &&
+
+ git checkout A^0 &&
+
test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&
test_path_is_missing source/subdir &&
@@ -4771,7 +4854,7 @@ test_expect_success '12i: Directory rename causes rename-to-self' '
git status --porcelain -uno >actual &&
cat >expect <<-\EOF &&
UU source/bar
- M source/baz
+ M source/baz
EOF
test_cmp expect actual
)
@@ -4806,6 +4889,7 @@ test_setup_12j () {
git switch B &&
git mv bar subdir/bar &&
echo more baz >>baz &&
+ git add baz &&
git commit -m B
)
}
@@ -4817,10 +4901,29 @@ test_expect_success '12j: Directory rename to root causes rename-to-self' '
git checkout A^0 &&
- test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&
-
- test_path_is_missing subdir &&
- test_path_is_file bar &&
+ # NOTE: A potentially better resolution would be for
+ # bar -> subdir/bar
+ # to use the directory rename to become
+ # bar -> bar
+ # (a rename to self), and thus we end up with bar with
+ # a path conflict (given merge.directoryRenames=conflict).
+ # However, since the relevant renames optimization
+ # prevents us from noticing
+ # bar -> subdir/bar
+ # as a rename and looking at it just as
+ # delete bar
+ # add subdir/bar
+ # the directory rename of subdir/bar -> bar does not look
+ # like a rename-to-self situation but a
+ # rename-on-top-of-other-file situation. We do not want
+ # stage 1 entries from an unrelated file, so we expect an
+ # error about there being a file in the way.
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+ grep "CONFLICT (implicit dir rename).*bar in the way" out &&
+
+ test_path_is_missing bar &&
+ test_path_is_file subdir/bar &&
test_path_is_file baz &&
git ls-files >actual &&
@@ -4829,8 +4932,8 @@ test_expect_success '12j: Directory rename to root causes rename-to-self' '
git status --porcelain -uno >actual &&
cat >expect <<-\EOF &&
- UU bar
- M baz
+ M baz
+ R bar -> subdir/bar
EOF
test_cmp expect actual
)
@@ -4865,6 +4968,7 @@ test_setup_12k () {
git switch B &&
git mv dirA/bar dirB/bar &&
echo more baz >>dirA/baz &&
+ git add dirA/baz &&
git commit -m B
)
}
@@ -4876,10 +4980,29 @@ test_expect_success '12k: Directory rename with sibling causes rename-to-self' '
git checkout A^0 &&
- test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&
-
- test_path_is_missing dirB &&
- test_path_is_file dirA/bar &&
+ # NOTE: A potentially better resolution would be for
+ # dirA/bar -> dirB/bar
+ # to use the directory rename (dirB/ -> dirA/) to become
+ # dirA/bar -> dirA/bar
+ # (a rename to self), and thus we end up with bar with
+ # a path conflict (given merge.directoryRenames=conflict).
+ # However, since the relevant renames optimization
+ # prevents us from noticing
+ # dirA/bar -> dirB/bar
+ # as a rename and looking at it just as
+ # delete dirA/bar
+ # add dirB/bar
+ # the directory rename of dirA/bar -> dirB/bar does
+ # not look like a rename-to-self situation but a
+ # rename-on-top-of-other-file situation. We do not want
+ # stage 1 entries from an unrelated file, so we expect an
+ # error about there being a file in the way.
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+ grep "CONFLICT (implicit dir rename).*dirA/bar in the way" out &&
+
+ test_path_is_missing dirA/bar &&
+ test_path_is_file dirB/bar &&
test_path_is_file dirA/baz &&
git ls-files >actual &&
@@ -4888,8 +5011,8 @@ test_expect_success '12k: Directory rename with sibling causes rename-to-self' '
git status --porcelain -uno >actual &&
cat >expect <<-\EOF &&
- UU dirA/bar
- M dirA/baz
+ M dirA/baz
+ R dirA/bar -> dirB/bar
EOF
test_cmp expect actual
)
@@ -5056,6 +5179,25 @@ test_expect_success '12m: Change parent of renamed-dir to symlink on other side'
)
'
+# Testcase 12n, Directory rename transitively makes rename back to self
+#
+# (Since this is a cherry-pick instead of merge, the labels are a bit weird.
+# O, the original commit, is A~1 rather than what branch O points to.)
+#
+# Commit O: tools/hello
+# world
+# Commit A: tools/hello
+# tools/world
+# Commit B: hello
+# In words:
+# A: world -> tools/world
+# B: tools/ -> /, i.e. rename all of tools to toplevel directory
+# delete world
+#
+# Expected:
+# CONFLICT (file location): tools/world vs. world
+#
+
test_setup_12n () {
git init 12n &&
(
@@ -5092,10 +5234,357 @@ test_expect_success '12n: Directory rename transitively makes rename back to sel
git checkout -q B^0 &&
test_must_fail git cherry-pick A^0 >out &&
- grep "CONFLICT (file location).*should perhaps be moved" out
+ test_grep "CONFLICT (file location).*should perhaps be moved" out &&
+
+ # Should have 1 entry for hello, and 2 for world
+ test_stdout_line_count = 3 git ls-files -s &&
+ test_stdout_line_count = 1 git ls-files -s hello &&
+ test_stdout_line_count = 2 git ls-files -s world
+ )
+'
+
+# Testcase 12n2, Directory rename transitively makes rename back to self
+#
+# Commit O: tools/hello
+# world
+# Commit A: tools/hello
+# tools/world
+# Commit B: hello
+# In words:
+# A: world -> tools/world
+# B: tools/ -> /, i.e. rename all of tools to toplevel directory
+# delete world
+#
+# Expected:
+# CONFLICT (file location): tools/world vs. world
+#
+
+test_setup_12n2 () {
+ git init 12n2 &&
+ (
+ cd 12n2 &&
+
+ mkdir tools &&
+ echo hello >tools/hello &&
+ git add tools/hello &&
+ echo world >world &&
+ git add world &&
+ git commit -m "O" &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ git mv world tools/world &&
+ git commit -m "Move world into tools/" &&
+
+ git switch B &&
+ git mv tools/hello hello &&
+ git rm world &&
+ git commit -m "Move hello from tools/ to toplevel"
+ )
+}
+
+test_expect_success '12n2: Directory rename transitively makes rename back to self' '
+ test_setup_12n2 &&
+ (
+ cd 12n2 &&
+
+ git checkout -q B^0 &&
+
+ test_might_fail git -c merge.directoryRenames=true merge A^0 >out &&
+
+ # Should have 1 entry for hello, and either 0 or 2 for world
+ #
+ # NOTE: Since merge.directoryRenames=true, there is no path
+ # conflict for world vs. tools/world; it should end up at
+ # world. The fact that world was unmodified on side A, means
+ # there was no content conflict; we should just take the
+ # content from side B -- i.e. delete the file. So merging
+ # could just delete world.
+ #
+ # However, rename-to-self-via-directory-rename is a bit more
+ # challenging. Relax this test to allow world to be treated
+ # as a modify/delete conflict as well, meaning it will have
+ # two higher order stages, that just so happen to match.
+ #
+ test_stdout_line_count = 1 git ls-files -s hello &&
+ test_stdout_line_count = 2 git ls-files -s world &&
+ test_grep "CONFLICT (modify/delete).*world deleted in HEAD" out
)
'
+# Testcase 12o, Directory rename hits other rename source; file still in way on same side
+# Commit O: A/file1_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# C/other
+# Commit A: A/file1_1
+# A/stuff
+# B/stuff
+# C/file1_2
+# C/other
+# Commit B: D/file2_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# A/other
+# In words:
+# A: rename B/file1_2 -> C/file1_2
+# B: rename C/ -> A/
+# rename A/file1_1 -> D/file2_1
+# Rationale:
+# A/stuff is unmodified, it shows up in final output
+# B/stuff is unmodified, it shows up in final output
+# C/other touched on one side (rename to A), so A/other shows up in output
+# A/file1 is renamed to D/file2
+# B/file1 -> C/file1 and even though C/ -> A/, A/file1 is
+# "in the way" so we don't do the directory rename
+# Expected: A/stuff
+# B/stuff
+# A/other
+# D/file2
+# C/file1
+# + CONFLICT (implicit dir rename): A/file1 in way of C/file1
+#
+
+test_setup_12o () {
+ git init 12o &&
+ (
+ cd 12o &&
+
+ mkdir -p A B C &&
+ echo 1 >A/file1 &&
+ echo 2 >B/file1 &&
+ echo other >C/other &&
+ echo Astuff >A/stuff &&
+ echo Bstuff >B/stuff &&
+ git add . &&
+ git commit -m "O" &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ git mv B/file1 C/ &&
+ git add . &&
+ git commit -m "A" &&
+
+ git switch B &&
+ mkdir -p D &&
+ git mv A/file1 D/file2 &&
+ git mv C/other A/other &&
+ git add . &&
+ git commit -m "B"
+ )
+}
+
+test_expect_success '12o: Directory rename hits other rename source; file still in way on same side' '
+ test_setup_12o &&
+ (
+ cd 12o &&
+
+ git checkout -q A^0 &&
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+
+ test_stdout_line_count = 5 git ls-files -s &&
+ test_stdout_line_count = 1 git ls-files -s A/other &&
+ test_stdout_line_count = 1 git ls-files -s A/stuff &&
+ test_stdout_line_count = 1 git ls-files -s B/stuff &&
+ test_stdout_line_count = 1 git ls-files -s D/file2 &&
+
+ grep "CONFLICT (implicit dir rename).*Existing file/dir at A/file1 in the way" out &&
+ test_stdout_line_count = 1 git ls-files -s C/file1
+ )
+'
+
+# Testcase 12p, Directory rename hits other rename source; file still in way on other side
+# Commit O: A/file1_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# C/other
+# Commit A: D/file2_1
+# A/stuff
+# B/stuff
+# C/file1_2
+# C/other
+# Commit B: A/file1_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# A/other
+# Short version:
+# A: rename A/file1_1 -> D/file2_1
+# rename B/file1_2 -> C/file1_2
+# B: Rename C/ -> A/
+# Rationale:
+# A/stuff is unmodified, it shows up in final output
+# B/stuff is unmodified, it shows up in final output
+# C/other touched on one side (rename to A), so A/other shows up in output
+# A/file1 is renamed to D/file2
+# B/file1 -> C/file1 and even though C/ -> A/, A/file1 is
+# "in the way" so we don't do the directory rename
+# Expected: A/stuff
+# B/stuff
+# A/other
+# D/file2
+# C/file1
+# + CONFLICT (implicit dir rename): A/file1 in way of C/file1
+#
+
+test_setup_12p () {
+ git init 12p &&
+ (
+ cd 12p &&
+
+ mkdir -p A B C &&
+ echo 1 >A/file1 &&
+ echo 2 >B/file1 &&
+ echo other >C/other &&
+ echo Astuff >A/stuff &&
+ echo Bstuff >B/stuff &&
+ git add . &&
+ git commit -m "O" &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ mkdir -p D &&
+ git mv A/file1 D/file2 &&
+ git mv B/file1 C/ &&
+ git add . &&
+ git commit -m "A" &&
+
+ git switch B &&
+ git mv C/other A/other &&
+ git add . &&
+ git commit -m "B"
+ )
+}
+
+test_expect_success '12p: Directory rename hits other rename source; file still in way on other side' '
+ test_setup_12p &&
+ (
+ cd 12p &&
+
+ git checkout -q A^0 &&
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+
+ test_stdout_line_count = 5 git ls-files -s &&
+ test_stdout_line_count = 1 git ls-files -s A/other &&
+ test_stdout_line_count = 1 git ls-files -s A/stuff &&
+ test_stdout_line_count = 1 git ls-files -s B/stuff &&
+ test_stdout_line_count = 1 git ls-files -s D/file2 &&
+
+ grep "CONFLICT (implicit dir rename).*Existing file/dir at A/file1 in the way" out &&
+ test_stdout_line_count = 1 git ls-files -s C/file1
+ )
+'
+
+# Testcase 12q, Directory rename hits other rename source; file removed though
+# Commit O: A/file1_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# C/other
+# Commit A: A/stuff
+# B/stuff
+# C/file1_2
+# C/other
+# Commit B: D/file2_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# A/other
+# In words:
+# A: delete A/file1_1, rename B/file1_2 -> C/file1_2
+# B: Rename C/ -> A/, rename A/file1_1 -> D/file2_1
+# Rationale:
+# A/stuff is unmodified, it shows up in final output
+# B/stuff is unmodified, it shows up in final output
+# C/other touched on one side (rename to A), so A/other shows up in output
+# A/file1 is rename/delete to D/file2, so two stages for D/file2
+# B/file1 -> C/file1 and even though C/ -> A/, A/file1 as a source was
+# "in the way" (ish) so we don't do the directory rename
+# Expected: A/stuff
+# B/stuff
+# A/other
+# D/file2 (two stages)
+# C/file1
+# + CONFLICT (implicit dir rename): A/file1 in way of C/file1
+# + CONFLICT (rename/delete): D/file2
+#
+
+test_setup_12q () {
+ git init 12q &&
+ (
+ cd 12q &&
+
+ mkdir -p A B C &&
+ echo 1 >A/file1 &&
+ echo 2 >B/file1 &&
+ echo other >C/other &&
+ echo Astuff >A/stuff &&
+ echo Bstuff >B/stuff &&
+ git add . &&
+ git commit -m "O" &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ git rm A/file1 &&
+ git mv B/file1 C/ &&
+ git add . &&
+ git commit -m "A" &&
+
+ git switch B &&
+ mkdir -p D &&
+ git mv A/file1 D/file2 &&
+ git mv C/other A/other &&
+ git add . &&
+ git commit -m "B"
+ )
+}
+
+test_expect_success '12q: Directory rename hits other rename source; file removed though' '
+ test_setup_12q &&
+ (
+ cd 12q &&
+
+ git checkout -q A^0 &&
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+
+ grep "CONFLICT (rename/delete).*A/file1.*D/file2" out &&
+ grep "CONFLICT (implicit dir rename).*Existing file/dir at A/file1 in the way" out &&
+
+ test_stdout_line_count = 6 git ls-files -s &&
+ test_stdout_line_count = 1 git ls-files -s A/other &&
+ test_stdout_line_count = 1 git ls-files -s A/stuff &&
+ test_stdout_line_count = 1 git ls-files -s B/stuff &&
+ test_stdout_line_count = 2 git ls-files -s D/file2 &&
+
+ # This is a slightly suboptimal resolution; allowing the
+ # rename of C/ -> A/ to affect C/file1 and further rename
+ # it to A/file1 would probably be preferable, but since
+ # A/file1 existed as the source of another rename, allowing
+ # the dir rename of C/file1 -> A/file1 would mean modifying
+ # the code so that renames do not adjust both their source
+ # and target paths in all cases.
+ ! grep "CONFLICT (file location)" out &&
+ test_stdout_line_count = 1 git ls-files -s C/file1
+ )
+'
###########################################################################
# SECTION 13: Checking informational and conflict messages
diff --git a/t/t6601-path-walk.sh b/t/t6601-path-walk.sh
index 8d187f7279..56bd1e3c5b 100755
--- a/t/t6601-path-walk.sh
+++ b/t/t6601-path-walk.sh
@@ -376,6 +376,26 @@ test_expect_success 'topic, not base, boundary with pruning' '
test_cmp_sorted expect out
'
+test_expect_success 'topic, not base, --edge-aggressive with pruning' '
+ test-tool path-walk --prune --edge-aggressive -- topic --not base >out &&
+
+ cat >expect <<-EOF &&
+ 0:commit::$(git rev-parse topic)
+ 1:tree::$(git rev-parse topic^{tree})
+ 1:tree::$(git rev-parse base^{tree}):UNINTERESTING
+ 2:tree:right/:$(git rev-parse topic:right)
+ 2:tree:right/:$(git rev-parse base:right):UNINTERESTING
+ 3:blob:right/c:$(git rev-parse base:right/c):UNINTERESTING
+ 3:blob:right/c:$(git rev-parse topic:right/c)
+ blobs:2
+ commits:1
+ tags:0
+ trees:4
+ EOF
+
+ test_cmp_sorted expect out
+'
+
test_expect_success 'trees are reported exactly once' '
test_when_finished "rm -rf unique-trees" &&
test_create_repo unique-trees &&
diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh
index 5fcf281dfb..c490e5707a 100755
--- a/t/t7005-editor.sh
+++ b/t/t7005-editor.sh
@@ -7,125 +7,96 @@ test_description='GIT_EDITOR, core.editor, and stuff'
unset EDITOR VISUAL GIT_EDITOR
test_expect_success 'determine default editor' '
-
vi=$(TERM=vt100 git var GIT_EDITOR) &&
test -n "$vi"
-
'
-if ! expr "$vi" : '[a-z]*$' >/dev/null
-then
- vi=
-fi
-
-for i in GIT_EDITOR core_editor EDITOR VISUAL $vi
-do
- cat >e-$i.sh <<-EOF
- #!$SHELL_PATH
- echo "Edited by $i" >"\$1"
- EOF
- chmod +x e-$i.sh
-done
+test_expect_success setup '
+ if ! expr "$vi" : "[a-z]*$" >/dev/null
+ then
+ vi=
+ fi &&
-if ! test -z "$vi"
-then
- mv e-$vi.sh $vi
-fi
+ for i in GIT_EDITOR core_editor EDITOR VISUAL $vi
+ do
+ write_script e-$i.sh <<-EOF || return 1
+ echo "Edited by $i" >"\$1"
+ EOF
+ done &&
-test_expect_success setup '
+ if ! test -z "$vi"
+ then
+ mv e-$vi.sh $vi
+ fi &&
msg="Hand-edited" &&
test_commit "$msg" &&
- echo "$msg" >expect &&
- git show -s --format=%s > actual &&
- test_cmp expect actual
-
+ test_commit_message HEAD -m "$msg"
'
-TERM=dumb
-export TERM
test_expect_success 'dumb should error out when falling back on vi' '
-
- if git commit --amend
- then
- echo "Oops?"
- false
- else
- : happy
- fi
+ test_must_fail env TERM=dumb git commit --amend
'
test_expect_success 'dumb should prefer EDITOR to VISUAL' '
-
- EDITOR=./e-EDITOR.sh &&
- VISUAL=./e-VISUAL.sh &&
- export EDITOR VISUAL &&
- git commit --amend &&
- test "$(git show -s --format=%s)" = "Edited by EDITOR"
-
+ TERM=dumb EDITOR=./e-EDITOR.sh VISUAL=./e-VISUAL.sh \
+ git commit --amend &&
+ test_commit_message HEAD -m "Edited by EDITOR"
'
-TERM=vt100
-export TERM
for i in $vi EDITOR VISUAL core_editor GIT_EDITOR
do
- echo "Edited by $i" >expect
- unset EDITOR VISUAL GIT_EDITOR
- git config --unset-all core.editor
- case "$i" in
- core_editor)
- git config core.editor ./e-core_editor.sh
- ;;
- [A-Z]*)
- eval "$i=./e-$i.sh"
- export $i
- ;;
- esac
test_expect_success "Using $i" '
- git --exec-path=. commit --amend &&
- git show -s --pretty=oneline |
- sed -e "s/^[0-9a-f]* //" >actual &&
- test_cmp expect actual
+ if test "$i" = core_editor
+ then
+ test_config core.editor ./e-core_editor.sh
+ fi &&
+ (
+ case "$i" in
+ [A-Z]*)
+ eval "$i=./e-$i.sh" &&
+ export $i
+ ;;
+ esac &&
+ PATH="$PWD:$PATH" TERM=vt100 git commit --amend
+ ) &&
+ test_commit_message HEAD -m "Edited by $i"
'
done
-unset EDITOR VISUAL GIT_EDITOR
-git config --unset-all core.editor
-for i in $vi EDITOR VISUAL core_editor GIT_EDITOR
-do
- echo "Edited by $i" >expect
- case "$i" in
- core_editor)
- git config core.editor ./e-core_editor.sh
- ;;
- [A-Z]*)
- eval "$i=./e-$i.sh"
- export $i
- ;;
- esac
- test_expect_success "Using $i (override)" '
- git --exec-path=. commit --amend &&
- git show -s --pretty=oneline |
- sed -e "s/^[0-9a-f]* //" >actual &&
- test_cmp expect actual
- '
-done
+test_expect_success 'Using editors with overrides' '
+ (
+ TERM=vt100 &&
+ export TERM &&
+ for i in $vi EDITOR VISUAL core_editor GIT_EDITOR
+ do
+ echo "Edited by $i" >expect &&
+ case "$i" in
+ core_editor)
+ git config core.editor ./e-core_editor.sh
+ ;;
+ [A-Z]*)
+ eval "$i=./e-$i.sh" &&
+ export $i
+ ;;
+ esac &&
+ PATH="$PWD:$PATH" git commit --amend &&
+ test_commit_message HEAD expect || exit 1
+ done
+ )
+'
test_expect_success 'editor with a space' '
echo "echo space >\"\$1\"" >"e space.sh" &&
chmod a+x "e space.sh" &&
GIT_EDITOR="./e\ space.sh" git commit --amend &&
- test space = "$(git show -s --pretty=format:%s)"
-
+ test_commit_message HEAD -m space
'
-unset GIT_EDITOR
test_expect_success 'core.editor with a space' '
-
- git config core.editor \"./e\ space.sh\" &&
+ test_config core.editor \"./e\ space.sh\" &&
git commit --amend &&
- test space = "$(git show -s --pretty=format:%s)"
-
+ test_commit_message HEAD -m space
'
test_done
diff --git a/t/t7007-show.sh b/t/t7007-show.sh
index d6cc69e0f2..2d322b53d1 100755
--- a/t/t7007-show.sh
+++ b/t/t7007-show.sh
@@ -167,4 +167,28 @@ test_expect_success 'show --graph is forbidden' '
test_must_fail git show --graph HEAD
'
+test_expect_success 'show unmerged index' '
+ git reset --hard &&
+
+ git switch -C base &&
+ echo "base" >conflicting &&
+ git add conflicting &&
+ git commit -m "base" &&
+
+ git branch hello &&
+ git branch goodbye &&
+
+ git switch hello &&
+ echo "hello" >conflicting &&
+ git commit -am "hello" &&
+
+ git switch goodbye &&
+ echo "goodbye" >conflicting &&
+ git commit -am "goodbye" &&
+
+ git switch hello &&
+ test_must_fail git merge goodbye &&
+ git show --merge HEAD
+'
+
test_done
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index d6a501d453..fd3e7e355e 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -1482,4 +1482,27 @@ test_expect_success '`submodule init` and `init.templateDir`' '
)
'
+test_expect_success 'submodule add fails when name is reused' '
+ git init test-submodule &&
+ (
+ cd test-submodule &&
+ git commit --allow-empty -m init &&
+
+ git init ../child-origin &&
+ git -C ../child-origin commit --allow-empty -m init &&
+
+ git submodule add ../child-origin child &&
+ git commit -m "Add submodule child" &&
+
+ git mv child child_old &&
+ git commit -m "Move child to child_old" &&
+
+ # Now adding a *new* repo at the old name must fail
+ git init ../child2-origin &&
+ git -C ../child2-origin commit --allow-empty -m init &&
+ test_must_fail git submodule add ../child2-origin child 2>err &&
+ test_grep "already used for" err
+ )
+'
+
test_done
diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh
index 9c3cc4cf40..66c3ec2da2 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.sh
@@ -38,10 +38,11 @@ commit_file () {
git commit "$@" -m "Commit $*" >/dev/null
}
-test_create_repo sm1 &&
-add_file . foo >/dev/null
-
-head1=$(add_file sm1 foo1 foo2)
+test_expect_success 'setup submodule' '
+ git init sm1 &&
+ add_file . foo &&
+ head1=$(add_file sm1 foo1 foo2)
+'
test_expect_success 'added submodule' "
git add sm1 &&
@@ -214,9 +215,12 @@ test_expect_success 'typechanged submodule(submodule->blob)' "
test_cmp expected actual
"
-rm -f sm1 &&
-test_create_repo sm1 &&
-head6=$(add_file sm1 foo6 foo7)
+test_expect_success 'setup submodule' '
+ rm -f sm1 &&
+ git init sm1 &&
+ head6=$(add_file sm1 foo6 foo7)
+'
+
test_expect_success 'nonexistent commit' "
git submodule summary >actual &&
cat >expected <<-EOF &&
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index c562bad042..3adab12091 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -1095,12 +1095,15 @@ test_expect_success 'submodule update --quiet passes quietness to fetch with a s
(cd super5 &&
# This test var can mess with the stderr output checked in this test.
GIT_TEST_NAME_HASH_VERSION=1 \
+ GIT_TEST_PACK_PATH_WALK=0 \
git submodule update --quiet --init --depth=1 submodule3 >out 2>err &&
test_must_be_empty out &&
test_must_be_empty err
) &&
git clone super4 super6 &&
(cd super6 &&
+ # This test variable will create a "warning" message to stderr
+ GIT_TEST_PACK_PATH_WALK=0 \
git submodule update --init --depth=1 submodule3 >out 2>err &&
test_file_not_empty out &&
test_file_not_empty err
@@ -1134,6 +1137,67 @@ test_expect_success 'setup clean recursive superproject' '
git clone --recurse-submodules top top-clean
'
+test_expect_success 'submodule update with multiple remotes' '
+ test_when_finished "rm -fr top-cloned" &&
+ cp -r top-clean top-cloned &&
+
+ # Create a commit in each repo, starting with bottom
+ test_commit -C bottom multiple_remote_commit &&
+ # Create middle commit
+ git -C middle/bottom fetch &&
+ git -C middle/bottom checkout -f FETCH_HEAD &&
+ git -C middle add bottom &&
+ git -C middle commit -m "multiple_remote_commit" &&
+ # Create top commit
+ git -C top/middle fetch &&
+ git -C top/middle checkout -f FETCH_HEAD &&
+ git -C top add middle &&
+ git -C top commit -m "multiple_remote_commit" &&
+
+ # rename the submodule remote
+ git -C top-cloned/middle remote rename origin upstream &&
+
+ # Add another remote
+ git -C top-cloned/middle remote add other bogus &&
+
+ # Make the update of "middle" a no-op, otherwise we error out
+ # because of its unmerged state
+ test_config -C top-cloned submodule.middle.update !true &&
+ git -C top-cloned submodule update --recursive 2>actual.err &&
+ cat >expect.err <<-\EOF &&
+ EOF
+ test_cmp expect.err actual.err
+'
+
+test_expect_success 'submodule update with renamed remote' '
+ test_when_finished "rm -fr top-cloned" &&
+ cp -r top-clean top-cloned &&
+
+ # Create a commit in each repo, starting with bottom
+ test_commit -C bottom rename_commit &&
+ # Create middle commit
+ git -C middle/bottom fetch &&
+ git -C middle/bottom checkout -f FETCH_HEAD &&
+ git -C middle add bottom &&
+ git -C middle commit -m "rename_commit" &&
+ # Create top commit
+ git -C top/middle fetch &&
+ git -C top/middle checkout -f FETCH_HEAD &&
+ git -C top add middle &&
+ git -C top commit -m "rename_commit" &&
+
+ # rename the submodule remote
+ git -C top-cloned/middle remote rename origin upstream &&
+
+ # Make the update of "middle" a no-op, otherwise we error out
+ # because of its unmerged state
+ test_config -C top-cloned submodule.middle.update !true &&
+ git -C top-cloned submodule update --recursive 2>actual.err &&
+ cat >expect.err <<-\EOF &&
+ EOF
+ test_cmp expect.err actual.err
+'
+
test_expect_success 'submodule update should skip unmerged submodules' '
test_when_finished "rm -fr top-cloned" &&
cp -r top-clean top-cloned &&
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index 9509dc18fd..6fd3b870de 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -124,4 +124,19 @@ test_expect_success 'is-active, submodule.active and submodule add' '
git -C super2 config --get submodule.mod.active
'
+test_expect_success 'submodule add skips redundant active entry' '
+ git init repo &&
+ (
+ cd repo &&
+ git config submodule.active "lib/*" &&
+ git commit --allow-empty -m init &&
+
+ git init ../lib-origin &&
+ git -C ../lib-origin commit --allow-empty -m init &&
+
+ git submodule add ../lib-origin lib/foo &&
+ test_must_fail git config --get submodule.lib/foo.active
+ )
+'
+
test_done
diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh
index 023a5cbdc4..aea1ddf117 100755
--- a/t/t7422-submodule-output.sh
+++ b/t/t7422-submodule-output.sh
@@ -180,17 +180,14 @@ test_expect_success !MINGW 'git submodule status --recursive propagates SIGPIPE'
COMMIT=$(git rev-parse HEAD) &&
for i in $(test_seq 2000)
do
- printf "[submodule \"sm-$i\"]\npath = recursive-submodule-path-$i\n" "$i" ||
+ echo "[submodule \"sm-$i\"]" &&
+ echo "path = recursive-submodule-path-$i" ||
return 1
done >gitmodules &&
BLOB=$(git hash-object -w --stdin <gitmodules) &&
printf "100644 blob $BLOB\t.gitmodules\n" >tree &&
- for i in $(test_seq 2000)
- do
- printf "160000 commit $COMMIT\trecursive-submodule-path-%d\n" "$i" ||
- return 1
- done >>tree &&
+ test_seq -f "160000 commit $COMMIT\trecursive-submodule-path-%d" 2000 >>tree &&
TREE=$(git mktree <tree) &&
COMMIT=$(git commit-tree "$TREE") &&
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index 14b5743b96..f512eed278 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -401,7 +401,7 @@ test_expect_success SYMLINKS,!WINDOWS,!MINGW 'submodule must not checkout into d
git -C repo commit -m submodule &&
git -c protocol.file.allow=always clone --recurse-submodules repo bad-clone &&
- ! test -f "$PWD/foo" &&
+ ! test -f "$PWD/bad-clone/sub/foo" &&
test -f $(printf "bad-clone/sub\r/post-checkout")
'
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index b37e2018a7..05f6da4ad9 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -956,13 +956,39 @@ test_expect_success 'commit --status with custom comment character' '
test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG
'
-test_expect_success 'switch core.commentchar' '
+test_expect_success !WITH_BREAKING_CHANGES 'switch core.commentchar' '
test_commit "#foo" foo &&
- GIT_EDITOR=.git/FAKE_EDITOR git -c core.commentChar=auto commit --amend &&
+ cat >config-include <<-\EOF &&
+ [core]
+ commentString=:
+ commentString=%
+ commentChar=auto
+ EOF
+ test_when_finished "rm config-include" &&
+ test_config include.path "$(pwd)/config-include" &&
+ test_config core.commentChar ! &&
+ GIT_EDITOR=.git/FAKE_EDITOR git commit --amend 2>err &&
+ sed -n "s/^hint: *\$//p; s/^hint: //p; s/^warning: //p" err >actual &&
+ cat >expect <<-EOF &&
+ Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0
+
+ To use the default comment string (#) please run
+
+ git config unset core.commentChar
+ git config unset --file ~/config-include --all core.commentString
+ git config unset --file ~/config-include core.commentChar
+
+ To set a custom comment string please run
+
+ git config set --file ~/config-include core.commentChar <comment string>
+
+ where ${SQ}<comment string>${SQ} is the string you wish to use.
+ EOF
+ test_cmp expect actual &&
test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG
'
-test_expect_success 'switch core.commentchar but out of options' '
+test_expect_success !WITH_BREAKING_CHANGES 'switch core.commentchar but out of options' '
cat >text <<\EOF &&
# 1
; 2
@@ -982,4 +1008,24 @@ EOF
)
'
+test_expect_success WITH_BREAKING_CHANGES 'core.commentChar=auto is rejected' '
+ test_config core.commentChar auto &&
+ test_must_fail git rev-parse --git-dir 2>err &&
+ sed -n "s/^hint: *\$//p; s/^hint: //p; s/^fatal: //p" err >actual &&
+ cat >expect <<-EOF &&
+ Support for ${SQ}core.commentChar=auto${SQ} has been removed in Git 3.0
+
+ To use the default comment string (#) please run
+
+ git config unset core.commentChar
+
+ To set a custom comment string please run
+
+ git config set core.commentChar <comment string>
+
+ where ${SQ}<comment string>${SQ} is the string you wish to use.
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 39677e859a..1201c85ba6 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -449,7 +449,17 @@ test_expect_success 'custom `gpg.program`' '
test_must_fail env LET_GPG_PROGRAM_FAIL=1 \
git commit -S --allow-empty -m must-fail 2>err &&
- grep zOMG err
+ grep zOMG err &&
+
+ # `gpg.program` starts with `~`, the path should be interpreted to be relative to `$HOME`
+ test_config gpg.program "~/fake-gpg" &&
+ env HOME="$(pwd)" \
+ git commit -S --allow-empty -m signed-commit &&
+
+ # `gpg.program` does not specify an absolute path, it should find a program in `$PATH`
+ test_config gpg.program "fake-gpg" &&
+ env PATH="$PWD:$PATH" \
+ git commit -S --allow-empty -m signed-commit
'
test_done
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
index 065f780636..0f887a3ebe 100755
--- a/t/t7528-signed-commit-ssh.sh
+++ b/t/t7528-signed-commit-ssh.sh
@@ -84,18 +84,26 @@ test_expect_success GPGSSH 'sign commits using literal public keys with ssh-agen
test_config gpg.format ssh &&
eval $(ssh-agent) &&
test_when_finished "kill ${SSH_AGENT_PID}" &&
- ssh-add "${GPGSSH_KEY_PRIMARY}" &&
- echo 1 >file && git add file &&
- git commit -a -m rsa-inline -S"$(cat "${GPGSSH_KEY_PRIMARY}.pub")" &&
- echo 2 >file &&
- test_config user.signingkey "$(cat "${GPGSSH_KEY_PRIMARY}.pub")" &&
- git commit -a -m rsa-config -S &&
- ssh-add "${GPGSSH_KEY_ECDSA}" &&
- echo 3 >file &&
- git commit -a -m ecdsa-inline -S"key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" &&
- echo 4 >file &&
- test_config user.signingkey "key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" &&
- git commit -a -m ecdsa-config -S
+ test_when_finished "test_unconfig user.signingkey" &&
+ mkdir tmpdir &&
+ TMPDIR="$(pwd)/tmpdir" &&
+ (
+ export TMPDIR &&
+ ssh-add "${GPGSSH_KEY_PRIMARY}" &&
+ echo 1 >file && git add file &&
+ git commit -a -m rsa-inline -S"$(cat "${GPGSSH_KEY_PRIMARY}.pub")" &&
+ echo 2 >file &&
+ git config user.signingkey "$(cat "${GPGSSH_KEY_PRIMARY}.pub")" &&
+ git commit -a -m rsa-config -S &&
+ ssh-add "${GPGSSH_KEY_ECDSA}" &&
+ echo 3 >file &&
+ git commit -a -m ecdsa-inline -S"key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" &&
+ echo 4 >file &&
+ git config user.signingkey "key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" &&
+ git commit -a -m ecdsa-config -S
+ ) &&
+ find tmpdir -type f >tmpfiles &&
+ test_must_be_empty tmpfiles
'
test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'create signed commits with keys having defined lifetimes' '
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 2a8df29219..9838094b66 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -185,8 +185,19 @@ test_expect_success 'reject non-strategy with a git-merge-foo name' '
test_expect_success 'merge c0 with c1' '
echo "OBJID HEAD@{0}: merge c1: Fast-forward" >reflog.expected &&
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ create mode 100644 other
+ EOF
+
git reset --hard c0 &&
- git merge c1 &&
+ git merge c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual &&
verify_merge file result.1 &&
verify_head "$c1" &&
@@ -205,6 +216,67 @@ test_expect_success 'merge c0 with c1 with --ff-only' '
verify_head "$c1"
'
+test_expect_success 'the same merge with merge.stat=diffstat' '
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ create mode 100644 other
+ EOF
+
+ git reset --hard c0 &&
+ git -c merge.stat=diffstat merge c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'the same merge with compact summary' '
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other (new) | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ EOF
+
+ git reset --hard c0 &&
+ git merge --compact-summary c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'the same merge with compact summary' '
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other (new) | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ EOF
+
+ git reset --hard c0 &&
+ git merge --compact-summary c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'the same merge with merge.stat=compact' '
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other (new) | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ EOF
+
+ git reset --hard c0 &&
+ git -c merge.stat=compact merge c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual
+'
+
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge from unborn branch' '
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index 611755cc13..73b78bdd88 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -838,4 +838,67 @@ test_expect_success '-n overrides repack.updateServerInfo=true' '
test_server_info_missing
'
+test_expect_success 'pending objects are repacked appropriately' '
+ test_when_finished rm -rf pending &&
+ git init pending &&
+
+ (
+ cd pending &&
+
+ # Commit file, a/b/c and never change them.
+ mkdir -p a/b &&
+ echo singleton >file &&
+ echo stuff >a/b/c &&
+ echo more >a/d &&
+ git add file a &&
+ git commit -m "single blobs" &&
+
+ # Files a/d and a/e will not be singletons.
+ echo d >a/d &&
+ echo e >a/e &&
+ git add a &&
+ git commit -m "more blobs" &&
+
+ # This use of a sparse index helps to force
+ # test that the cache-tree is walked, too.
+ git sparse-checkout set --sparse-index a x &&
+
+ # Create staged changes:
+ # * a/e now has multiple versions.
+ # * a/i now has only one version.
+ echo f >a/d &&
+ echo h >a/e &&
+ echo i >a/i &&
+ git add a &&
+
+ # Stage and unstage a change to make use of
+ # resolve-undo cache and how that impacts fsck.
+ mkdir x &&
+ echo y >x/y &&
+ git add x &&
+ xy=$(git rev-parse :x/y) &&
+ git rm --cached x/y &&
+
+ # The blob for x/y must persist through repacks,
+ # but fsck currently ignores the REUC extension
+ # for finding links to the blob.
+ cat >expect <<-EOF &&
+ dangling blob $xy
+ EOF
+
+ # Bring the loose objects into a packfile to avoid
+ # leftovers in next test. Without this, the loose
+ # objects persist and the test succeeds for other
+ # reasons.
+ git repack -adf &&
+ git fsck >out &&
+ test_cmp expect out &&
+
+ # Test path walk version with pack.useSparse.
+ git -c pack.useSparse=true repack -adf --path-walk &&
+ git fsck >out &&
+ test_cmp expect out
+ )
+'
+
test_done
diff --git a/t/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh
index 8aebfb45f5..aa2e2e6ad8 100755
--- a/t/t7704-repack-cruft.sh
+++ b/t/t7704-repack-cruft.sh
@@ -724,4 +724,149 @@ test_expect_success 'cruft repack respects --quiet' '
)
'
+setup_cruft_exclude_tests() {
+ git init "$1" &&
+ (
+ cd "$1" &&
+
+ git config repack.midxMustContainCruft false &&
+
+ test_commit one &&
+
+ test_commit --no-tag two &&
+ two="$(git rev-parse HEAD)" &&
+ test_commit --no-tag three &&
+ three="$(git rev-parse HEAD)" &&
+ git reset --hard one &&
+ git reflog expire --all --expire=all &&
+
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack --cruft -d &&
+
+ git merge $two &&
+ test_commit four
+ )
+}
+
+test_expect_success 'repack --write-midx excludes cruft where possible' '
+ setup_cruft_exclude_tests exclude-cruft-when-possible &&
+ (
+ cd exclude-cruft-when-possible &&
+
+ GIT_TEST_MULTI_PACK_INDEX=0 \
+ git repack -d --geometric=2 --write-midx --write-bitmap-index &&
+
+ test-tool read-midx --show-objects $objdir >midx &&
+ cruft="$(ls $packdir/*.mtimes)" &&
+ test_grep ! "$(basename "$cruft" .mtimes).idx" midx &&
+
+ git rev-list --all --objects --no-object-names >reachable.raw &&
+ sort reachable.raw >reachable.objects &&
+ awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects &&
+
+ test_cmp reachable.objects midx.objects
+ )
+'
+
+test_expect_success 'repack --write-midx includes cruft when instructed' '
+ setup_cruft_exclude_tests exclude-cruft-when-instructed &&
+ (
+ cd exclude-cruft-when-instructed &&
+
+ GIT_TEST_MULTI_PACK_INDEX=0 \
+ git -c repack.midxMustContainCruft=true repack \
+ -d --geometric=2 --write-midx --write-bitmap-index &&
+
+ test-tool read-midx --show-objects $objdir >midx &&
+ cruft="$(ls $packdir/*.mtimes)" &&
+ test_grep "$(basename "$cruft" .mtimes).idx" midx &&
+
+ git cat-file --batch-check="%(objectname)" --batch-all-objects \
+ >all.objects &&
+ awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects &&
+
+ test_cmp all.objects midx.objects
+ )
+'
+
+test_expect_success 'repack --write-midx includes cruft when necessary' '
+ setup_cruft_exclude_tests exclude-cruft-when-necessary &&
+ (
+ cd exclude-cruft-when-necessary &&
+
+ test_path_is_file $(ls $packdir/pack-*.mtimes) &&
+ ( cd $packdir && ls pack-*.idx ) | sort >packs.all &&
+ git multi-pack-index write --stdin-packs --bitmap <packs.all &&
+
+ test_commit five &&
+ GIT_TEST_MULTI_PACK_INDEX=0 \
+ git repack -d --geometric=2 --write-midx --write-bitmap-index &&
+
+ test-tool read-midx --show-objects $objdir >midx &&
+ awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects &&
+ git cat-file --batch-all-objects --batch-check="%(objectname)" \
+ >expect.objects &&
+ test_cmp expect.objects midx.objects &&
+
+ grep "^pack-" midx >midx.packs &&
+ test_line_count = "$(($(wc -l <packs.all) + 1))" midx.packs
+ )
+'
+
+test_expect_success 'repack --write-midx includes cruft when already geometric' '
+ git init repack--write-midx-geometric-noop &&
+ (
+ cd repack--write-midx-geometric-noop &&
+
+ git branch -M main &&
+ test_commit A &&
+ test_commit B &&
+
+ git checkout -B side &&
+ test_commit --no-tag C &&
+ C="$(git rev-parse HEAD)" &&
+
+ git checkout main &&
+ git branch -D side &&
+ git reflog expire --all --expire=all &&
+
+ # At this point we have two packs: one containing the
+ # objects belonging to commits A and B, and another
+ # (cruft) pack containing the objects belonging to
+ # commit C.
+ git repack --cruft -d &&
+
+ # Create a third pack which contains a merge commit
+ # making commit C reachable again.
+ #
+ # --no-ff is important here, as it ensures that we
+ # actually write a new object and subsequently a new
+ # pack to contain it.
+ git merge --no-ff $C &&
+ git repack -d &&
+
+ ls $packdir/pack-*.idx | sort >packs.all &&
+ cruft="$(ls $packdir/pack-*.mtimes)" &&
+ cruft="${cruft%.mtimes}.idx" &&
+
+ for idx in $(grep -v $cruft <packs.all)
+ do
+ git show-index <$idx >out &&
+ wc -l <out || return 1
+ done >sizes.raw &&
+
+ # Make sure that there are two non-cruft packs, and
+ # that one of them contains at least twice as many
+ # objects as the other, ensuring that they are already
+ # in a geometric progression.
+ sort -n sizes.raw >sizes &&
+ test_line_count = 2 sizes &&
+ s1=$(head -n 1 sizes) &&
+ s2=$(tail -n 1 sizes) &&
+ test "$s2" -gt "$((2 * $s1))" &&
+
+ git -c repack.midxMustContainCruft=false repack --geometric=2 \
+ --write-midx --write-bitmap-index
+ )
+'
+
test_done
diff --git a/t/t7815-grep-binary.sh b/t/t7815-grep-binary.sh
index b7d83f9a5d..55d5e6de17 100755
--- a/t/t7815-grep-binary.sh
+++ b/t/t7815-grep-binary.sh
@@ -63,7 +63,7 @@ test_expect_success 'git grep ile a' '
git grep ile a
'
-test_expect_failure !CYGWIN 'git grep .fi a' '
+test_expect_failure !CYGWIN,!MACOS 'git grep .fi a' '
git grep .fi a
'
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 8cf89e285f..ddd273d8dc 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -49,9 +49,9 @@ test_expect_success 'run [--auto|--quiet]' '
git maintenance run --auto 2>/dev/null &&
GIT_TRACE2_EVENT="$(pwd)/run-no-quiet.txt" \
git maintenance run --no-quiet 2>/dev/null &&
- test_subcommand git gc --quiet --no-detach <run-no-auto.txt &&
- test_subcommand ! git gc --auto --quiet --no-detach <run-auto.txt &&
- test_subcommand git gc --no-quiet --no-detach <run-no-quiet.txt
+ test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-no-auto.txt &&
+ test_subcommand ! git gc --auto --quiet --no-detach --skip-foreground-tasks <run-auto.txt &&
+ test_subcommand git gc --no-quiet --no-detach --skip-foreground-tasks <run-no-quiet.txt
'
test_expect_success 'maintenance.auto config option' '
@@ -154,9 +154,9 @@ test_expect_success 'run --task=<task>' '
git maintenance run --task=commit-graph 2>/dev/null &&
GIT_TRACE2_EVENT="$(pwd)/run-both.txt" \
git maintenance run --task=commit-graph --task=gc 2>/dev/null &&
- test_subcommand ! git gc --quiet --no-detach <run-commit-graph.txt &&
- test_subcommand git gc --quiet --no-detach <run-gc.txt &&
- test_subcommand git gc --quiet --no-detach <run-both.txt &&
+ test_subcommand ! git gc --quiet --no-detach --skip-foreground-tasks <run-commit-graph.txt &&
+ test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-gc.txt &&
+ test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-both.txt &&
test_subcommand git commit-graph write --split --reachable --no-progress <run-commit-graph.txt &&
test_subcommand ! git commit-graph write --split --reachable --no-progress <run-gc.txt &&
test_subcommand git commit-graph write --split --reachable --no-progress <run-both.txt
@@ -610,7 +610,12 @@ test_expect_success 'rerere-gc task with --auto honors maintenance.rerere-gc.aut
test_expect_success '--auto and --schedule incompatible' '
test_must_fail git maintenance run --auto --schedule=daily 2>err &&
- test_grep "at most one" err
+ test_grep "cannot be used together" err
+'
+
+test_expect_success '--task and --schedule incompatible' '
+ test_must_fail git maintenance run --task=pack-refs --schedule=daily 2>err &&
+ test_grep "cannot be used together" err
'
test_expect_success 'invalid --schedule value' '
diff --git a/t/t8020-last-modified.sh b/t/t8020-last-modified.sh
new file mode 100755
index 0000000000..5eb4cef035
--- /dev/null
+++ b/t/t8020-last-modified.sh
@@ -0,0 +1,210 @@
+#!/bin/sh
+
+test_description='last-modified tests'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit 1 file &&
+ mkdir a &&
+ test_commit 2 a/file &&
+ mkdir a/b &&
+ test_commit 3 a/b/file
+'
+
+test_expect_success 'cannot run last-modified on two trees' '
+ test_must_fail git last-modified HEAD HEAD~1
+'
+
+check_last_modified() {
+ local indir= &&
+ while test $# != 0
+ do
+ case "$1" in
+ -C)
+ indir="$2"
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac &&
+ shift
+ done &&
+
+ cat >expect &&
+ test_when_finished "rm -f tmp.*" &&
+ git ${indir:+-C "$indir"} last-modified "$@" >tmp.1 &&
+ git name-rev --annotate-stdin --name-only --tags \
+ <tmp.1 >tmp.2 &&
+ tr '\t' ' ' <tmp.2 >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'last-modified non-recursive' '
+ check_last_modified <<-\EOF
+ 3 a
+ 1 file
+ EOF
+'
+
+test_expect_success 'last-modified recursive' '
+ check_last_modified -r <<-\EOF
+ 3 a/b/file
+ 2 a/file
+ 1 file
+ EOF
+'
+
+test_expect_success 'last-modified recursive with show-trees' '
+ check_last_modified -r -t <<-\EOF
+ 3 a
+ 3 a/b
+ 3 a/b/file
+ 2 a/file
+ 1 file
+ EOF
+'
+
+test_expect_success 'last-modified non-recursive with show-trees' '
+ check_last_modified -t <<-\EOF
+ 3 a
+ 1 file
+ EOF
+'
+
+test_expect_success 'last-modified subdir' '
+ check_last_modified a <<-\EOF
+ 3 a
+ EOF
+'
+
+test_expect_success 'last-modified subdir recursive' '
+ check_last_modified -r a <<-\EOF
+ 3 a/b/file
+ 2 a/file
+ EOF
+'
+
+test_expect_success 'last-modified from non-HEAD commit' '
+ check_last_modified HEAD^ <<-\EOF
+ 2 a
+ 1 file
+ EOF
+'
+
+test_expect_success 'last-modified from subdir defaults to root' '
+ check_last_modified -C a <<-\EOF
+ 3 a
+ 1 file
+ EOF
+'
+
+test_expect_success 'last-modified from subdir uses relative pathspecs' '
+ check_last_modified -C a -r b <<-\EOF
+ 3 a/b/file
+ EOF
+'
+
+test_expect_success 'limit last-modified traversal by count' '
+ check_last_modified -1 <<-\EOF
+ 3 a
+ ^2 file
+ EOF
+'
+
+test_expect_success 'limit last-modified traversal by commit' '
+ check_last_modified HEAD~2..HEAD <<-\EOF
+ 3 a
+ ^1 file
+ EOF
+'
+
+test_expect_success 'only last-modified files in the current tree' '
+ git rm -rf a &&
+ git commit -m "remove a" &&
+ check_last_modified <<-\EOF
+ 1 file
+ EOF
+'
+
+test_expect_success 'cross merge boundaries in blaming' '
+ git checkout HEAD^0 &&
+ git rm -rf . &&
+ test_commit m1 &&
+ git checkout HEAD^ &&
+ git rm -rf . &&
+ test_commit m2 &&
+ git merge m1 &&
+ check_last_modified <<-\EOF
+ m2 m2.t
+ m1 m1.t
+ EOF
+'
+
+test_expect_success 'last-modified merge for resolved conflicts' '
+ git checkout HEAD^0 &&
+ git rm -rf . &&
+ test_commit c1 conflict &&
+ git checkout HEAD^ &&
+ git rm -rf . &&
+ test_commit c2 conflict &&
+ test_must_fail git merge c1 &&
+ test_commit resolved conflict &&
+ check_last_modified conflict <<-\EOF
+ resolved conflict
+ EOF
+'
+
+
+# Consider `file` with this content through history:
+#
+# A---B---B-------B---B
+# \ /
+# C---D
+test_expect_success 'last-modified merge ignores content from branch' '
+ git checkout HEAD^0 &&
+ git rm -rf . &&
+ test_commit a1 file A &&
+ test_commit a2 file B &&
+ test_commit a3 file C &&
+ test_commit a4 file D &&
+ git checkout a2 &&
+ git merge --no-commit --no-ff a4 &&
+ git checkout a2 -- file &&
+ git merge --continue &&
+ check_last_modified <<-\EOF
+ a2 file
+ EOF
+'
+
+# Consider `file` with this content through history:
+#
+# A---B---B---C---D---B---B
+# \ /
+# B-------B
+test_expect_success 'last-modified merge undoes changes' '
+ git checkout HEAD^0 &&
+ git rm -rf . &&
+ test_commit b1 file A &&
+ test_commit b2 file B &&
+ test_commit b3 file C &&
+ test_commit b4 file D &&
+ git checkout b2 &&
+ test_commit b5 file2 2 &&
+ git checkout b4 &&
+ git merge --no-commit --no-ff b5 &&
+ git checkout b2 -- file &&
+ git merge --continue &&
+ check_last_modified <<-\EOF
+ b5 file2
+ b2 file
+ EOF
+'
+
+test_expect_success 'last-modified complains about unknown arguments' '
+ test_must_fail git last-modified --foo 2>err &&
+ grep "unknown last-modified argument: --foo" err
+'
+
+test_done
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 0c1af43f6f..e56e0c8d77 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -201,6 +201,13 @@ test_expect_success $PREREQ 'cc trailer with get_maintainer.pl output' '
test_cmp expected-cc commandline1
'
+test_expect_failure $PREREQ 'invalid smtp server port value' '
+ clean_fake_sendmail &&
+ git send-email -1 --to=recipient@example.com \
+ --smtp-server-port=bogus-symbolic-name \
+ --smtp-server="$(pwd)/fake.sendmail"
+'
+
test_expect_success $PREREQ 'setup expect' "
cat >expected-show-all-headers <<\EOF
0001-Second.patch
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index b258dbf1df..4dc3d645bf 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -120,7 +120,7 @@ test_expect_success 'A: create pack from stdin' '
INPUT_END
git fast-import --export-marks=marks.out <input &&
- git whatchanged main
+ git log --raw main
'
test_expect_success 'A: verify pack' '
@@ -279,7 +279,7 @@ test_expect_success 'A: verify marks import does not crash' '
INPUT_END
git fast-import --import-marks=marks.out <input &&
- git whatchanged verify--import-marks
+ git log --raw verify--import-marks
'
test_expect_success 'A: verify pack' '
@@ -652,7 +652,7 @@ test_expect_success 'C: incremental import create pack from stdin' '
INPUT_END
git fast-import <input &&
- git whatchanged branch
+ git log --raw branch
'
test_expect_success 'C: verify pack' '
@@ -715,7 +715,7 @@ test_expect_success 'D: inline data in commit' '
INPUT_END
git fast-import <input &&
- git whatchanged branch
+ git log --raw branch
'
test_expect_success 'D: verify pack' '
@@ -882,7 +882,7 @@ test_expect_success 'H: deletall, add 1' '
INPUT_END
git fast-import <input &&
- git whatchanged H
+ git log --raw H
'
test_expect_success 'H: verify pack' '
@@ -2066,7 +2066,7 @@ test_expect_success 'Q: commit notes' '
INPUT_END
git fast-import <input &&
- git whatchanged notes-test
+ git log --raw notes-test
'
test_expect_success 'Q: verify pack' '
diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh
index 1ae4d7c0d3..e62173cf1f 100755
--- a/t/t9301-fast-import-notes.sh
+++ b/t/t9301-fast-import-notes.sh
@@ -76,7 +76,7 @@ INPUT_END
test_expect_success 'set up main branch' '
git fast-import <input &&
- git whatchanged main
+ git log --raw main
'
commit4=$(git rev-parse refs/heads/main)
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 76619765fc..8f85c69d62 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -48,12 +48,11 @@ test_expect_success 'fast-export | fast-import' '
mkdir new &&
git --git-dir=new/.git init &&
git fast-export --all >actual &&
- (cd new &&
- git fast-import &&
- test $MAIN = $(git rev-parse --verify refs/heads/main) &&
- test $REIN = $(git rev-parse --verify refs/tags/rein) &&
- test $WER = $(git rev-parse --verify refs/heads/wer) &&
- test $MUSS = $(git rev-parse --verify refs/tags/muss)) <actual
+ git -C new fast-import <actual &&
+ test $MAIN = $(git -C new rev-parse --verify refs/heads/main) &&
+ test $REIN = $(git -C new rev-parse --verify refs/tags/rein) &&
+ test $WER = $(git -C new rev-parse --verify refs/heads/wer) &&
+ test $MUSS = $(git -C new rev-parse --verify refs/tags/muss)
'
@@ -87,13 +86,11 @@ test_expect_success 'fast-export --mark-tags ^muss^{commit} muss' '
test_expect_success 'fast-export main~2..main' '
git fast-export main~2..main >actual &&
- sed "s/main/partial/" actual |
- (cd new &&
- git fast-import &&
- test $MAIN != $(git rev-parse --verify refs/heads/partial) &&
- git diff --exit-code main partial &&
- git diff --exit-code main^ partial^ &&
- test_must_fail git rev-parse partial~2)
+ sed "s/main/partial/" actual | git -C new fast-import &&
+ test $MAIN != $(git -C new rev-parse --verify refs/heads/partial) &&
+ git -C new diff --exit-code main partial &&
+ git -C new diff --exit-code main^ partial^ &&
+ test_must_fail git -C new rev-parse partial~2
'
@@ -102,10 +99,8 @@ test_expect_success 'fast-export --reference-excluded-parents main~2..main' '
git fast-export --reference-excluded-parents main~2..main >actual &&
grep commit.refs/heads/main actual >commit-count &&
test_line_count = 2 commit-count &&
- sed "s/main/rewrite/" actual |
- (cd new &&
- git fast-import &&
- test $MAIN = $(git rev-parse --verify refs/heads/rewrite))
+ sed "s/main/rewrite/" actual | git -C new fast-import &&
+ test $MAIN = $(git -C new rev-parse --verify refs/heads/rewrite)
'
test_expect_success 'fast-export --show-original-ids' '
@@ -133,20 +128,19 @@ test_expect_success ICONV 'reencoding iso-8859-7' '
echo rosten >file &&
git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file &&
git fast-export --reencode=yes wer^..wer >iso-8859-7.fi &&
- sed "s/wer/i18n/" iso-8859-7.fi |
- (cd new &&
- git fast-import &&
- # The commit object, if not re-encoded, would be 200 bytes plus hash.
- # Removing the "encoding iso-8859-7\n" header drops 20 bytes.
- # Re-encoding the Pi character from \xF0 (\360) in iso-8859-7
- # to \xCF\x80 (\317\200) in UTF-8 adds a byte. Check for
- # the expected size.
- test $(($(test_oid hexsz) + 181)) -eq "$(git cat-file -s i18n)" &&
- # ...and for the expected translation of bytes.
- git cat-file commit i18n >actual &&
- grep $(printf "\317\200") actual &&
- # Also make sure the commit does not have the "encoding" header
- ! grep ^encoding actual)
+ sed "s/wer/i18n/" iso-8859-7.fi | git -C new fast-import &&
+
+ # The commit object, if not re-encoded, would be 200 bytes plus hash.
+ # Removing the "encoding iso-8859-7\n" header drops 20 bytes.
+ # Re-encoding the Pi character from \xF0 (\360) in iso-8859-7
+ # to \xCF\x80 (\317\200) in UTF-8 adds a byte. Check for
+ # the expected size.
+ test $(($(test_oid hexsz) + 181)) -eq "$(git -C new cat-file -s i18n)" &&
+ # ...and for the expected translation of bytes.
+ git -C new cat-file commit i18n >actual &&
+ grep $(printf "\317\200") actual &&
+ # Also make sure the commit does not have the "encoding" header
+ ! grep ^encoding actual
'
test_expect_success 'aborting on iso-8859-7' '
@@ -165,20 +159,19 @@ test_expect_success 'preserving iso-8859-7' '
echo rosten >file &&
git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file &&
git fast-export --reencode=no wer^..wer >iso-8859-7.fi &&
- sed "s/wer/i18n-no-recoding/" iso-8859-7.fi |
- (cd new &&
- git fast-import &&
- # The commit object, if not re-encoded, is 200 bytes plus hash.
- # Removing the "encoding iso-8859-7\n" header would drops 20
- # bytes. Re-encoding the Pi character from \xF0 (\360) in
- # iso-8859-7 to \xCF\x80 (\317\200) in UTF-8 adds a byte.
- # Check for the expected size...
- test $(($(test_oid hexsz) + 200)) -eq "$(git cat-file -s i18n-no-recoding)" &&
- # ...as well as the expected byte.
- git cat-file commit i18n-no-recoding >actual &&
- grep $(printf "\360") actual &&
- # Also make sure the commit has the "encoding" header
- grep ^encoding actual)
+ sed "s/wer/i18n-no-recoding/" iso-8859-7.fi | git -C new fast-import &&
+
+ # The commit object, if not re-encoded, is 200 bytes plus hash.
+ # Removing the "encoding iso-8859-7\n" header would drops 20
+ # bytes. Re-encoding the Pi character from \xF0 (\360) in
+ # iso-8859-7 to \xCF\x80 (\317\200) in UTF-8 adds a byte.
+ # Check for the expected size...
+ test $(($(test_oid hexsz) + 200)) -eq "$(git -C new cat-file -s i18n-no-recoding)" &&
+ # ...as well as the expected byte.
+ git -C new cat-file commit i18n-no-recoding >actual &&
+ grep $(printf "\360") actual &&
+ # Also make sure the commit has the "encoding" header
+ grep ^encoding actual
'
test_expect_success 'encoding preserved if reencoding fails' '
@@ -188,18 +181,17 @@ test_expect_success 'encoding preserved if reencoding fails' '
echo rosten >file &&
git commit -s -F "$TEST_DIRECTORY/t9350/broken-iso-8859-7-commit-message.txt" file &&
git fast-export --reencode=yes wer^..wer >iso-8859-7.fi &&
- sed "s/wer/i18n-invalid/" iso-8859-7.fi |
- (cd new &&
- git fast-import &&
- git cat-file commit i18n-invalid >actual &&
- # Make sure the commit still has the encoding header
- grep ^encoding actual &&
- # Verify that the commit has the expected size; i.e.
- # that no bytes were re-encoded to a different encoding.
- test $(($(test_oid hexsz) + 212)) -eq "$(git cat-file -s i18n-invalid)" &&
- # ...and check for the original special bytes
- grep $(printf "\360") actual &&
- grep $(printf "\377") actual)
+ sed "s/wer/i18n-invalid/" iso-8859-7.fi | git -C new fast-import &&
+ git -C new cat-file commit i18n-invalid >actual &&
+
+ # Make sure the commit still has the encoding header
+ grep ^encoding actual &&
+ # Verify that the commit has the expected size; i.e.
+ # that no bytes were re-encoded to a different encoding.
+ test $(($(test_oid hexsz) + 212)) -eq "$(git -C new cat-file -s i18n-invalid)" &&
+ # ...and check for the original special bytes
+ grep $(printf "\360") actual &&
+ grep $(printf "\377") actual
'
test_expect_success 'import/export-marks' '
@@ -314,29 +306,23 @@ test_expect_success GPG 'signed-commits=abort' '
test_expect_success GPG 'signed-commits=verbatim' '
git fast-export --signed-commits=verbatim --reencode=no commit-signing >output &&
- grep "^gpgsig sha" output &&
+ test_grep -E "^gpgsig $GIT_DEFAULT_HASH openpgp" output &&
grep "encoding ISO-8859-1" output &&
- (
- cd new &&
- git fast-import &&
- STRIPPED=$(git rev-parse --verify refs/heads/commit-signing) &&
- test $COMMIT_SIGNING = $STRIPPED
- ) <output
+ git -C new fast-import <output &&
+ STRIPPED=$(git -C new rev-parse --verify refs/heads/commit-signing) &&
+ test $COMMIT_SIGNING = $STRIPPED
'
test_expect_success GPG 'signed-commits=warn-verbatim' '
git fast-export --signed-commits=warn-verbatim --reencode=no commit-signing >output 2>err &&
- grep "^gpgsig sha" output &&
+ test_grep -E "^gpgsig $GIT_DEFAULT_HASH openpgp" output &&
grep "encoding ISO-8859-1" output &&
test -s err &&
- (
- cd new &&
- git fast-import &&
- STRIPPED=$(git rev-parse --verify refs/heads/commit-signing) &&
- test $COMMIT_SIGNING = $STRIPPED
- ) <output
+ git -C new fast-import <output &&
+ STRIPPED=$(git -C new rev-parse --verify refs/heads/commit-signing) &&
+ test $COMMIT_SIGNING = $STRIPPED
'
@@ -345,12 +331,9 @@ test_expect_success GPG 'signed-commits=strip' '
git fast-export --signed-commits=strip --reencode=no commit-signing >output &&
! grep ^gpgsig output &&
grep "^encoding ISO-8859-1" output &&
- sed "s/commit-signing/commit-strip-signing/" output | (
- cd new &&
- git fast-import &&
- STRIPPED=$(git rev-parse --verify refs/heads/commit-strip-signing) &&
- test $COMMIT_SIGNING != $STRIPPED
- )
+ sed "s/commit-signing/commit-strip-signing/" output | git -C new fast-import &&
+ STRIPPED=$(git -C new rev-parse --verify refs/heads/commit-strip-signing) &&
+ test $COMMIT_SIGNING != $STRIPPED
'
@@ -360,12 +343,59 @@ test_expect_success GPG 'signed-commits=warn-strip' '
! grep ^gpgsig output &&
grep "^encoding ISO-8859-1" output &&
test -s err &&
- sed "s/commit-signing/commit-strip-signing/" output | (
- cd new &&
- git fast-import &&
- STRIPPED=$(git rev-parse --verify refs/heads/commit-strip-signing) &&
- test $COMMIT_SIGNING != $STRIPPED
- )
+ sed "s/commit-signing/commit-strip-signing/" output | git -C new fast-import &&
+ STRIPPED=$(git -C new rev-parse --verify refs/heads/commit-strip-signing) &&
+ test $COMMIT_SIGNING != $STRIPPED
+
+'
+
+test_expect_success GPGSM 'setup X.509 signed commit' '
+
+ git checkout -b x509-signing main &&
+ test_config gpg.format x509 &&
+ test_config user.signingkey $GIT_COMMITTER_EMAIL &&
+ echo "X.509 content" >file &&
+ git add file &&
+ git commit -S -m "X.509 signed commit" &&
+ X509_COMMIT=$(git rev-parse HEAD) &&
+ git checkout main
+
+'
+
+test_expect_success GPGSM 'round-trip X.509 signed commit' '
+
+ git fast-export --signed-commits=verbatim x509-signing >output &&
+ test_grep -E "^gpgsig $GIT_DEFAULT_HASH x509" output &&
+ git -C new fast-import <output &&
+ git -C new cat-file commit refs/heads/x509-signing >actual &&
+ grep "^gpgsig" actual &&
+ IMPORTED=$(git -C new rev-parse refs/heads/x509-signing) &&
+ test $X509_COMMIT = $IMPORTED
+
+'
+
+test_expect_success GPGSSH 'setup SSH signed commit' '
+
+ git checkout -b ssh-signing main &&
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+ echo "SSH content" >file &&
+ git add file &&
+ git commit -S -m "SSH signed commit" &&
+ SSH_COMMIT=$(git rev-parse HEAD) &&
+ git checkout main
+
+'
+
+test_expect_success GPGSSH 'round-trip SSH signed commit' '
+
+ git fast-export --signed-commits=verbatim ssh-signing >output &&
+ test_grep -E "^gpgsig $GIT_DEFAULT_HASH ssh" output &&
+ git -C new fast-import <output &&
+ git -C new cat-file commit refs/heads/ssh-signing >actual &&
+ grep "^gpgsig" actual &&
+ IMPORTED=$(git -C new rev-parse refs/heads/ssh-signing) &&
+ test $SSH_COMMIT = $IMPORTED
'
@@ -405,14 +435,13 @@ test_expect_success 'submodule fast-export | fast-import' '
mkdir new &&
git --git-dir=new/.git init &&
git fast-export --signed-tags=strip --all >actual &&
- (cd new &&
- git fast-import &&
- test "$SUBENT1" = "$(git ls-tree refs/heads/main^ sub)" &&
- test "$SUBENT2" = "$(git ls-tree refs/heads/main sub)" &&
- git checkout main &&
- git submodule init &&
- git submodule update &&
- cmp sub/file ../sub/file) <actual
+ git -C new fast-import <actual &&
+ test "$SUBENT1" = "$(git -C new ls-tree refs/heads/main^ sub)" &&
+ test "$SUBENT2" = "$(git -C new ls-tree refs/heads/main sub)" &&
+ git -C new checkout main &&
+ git -C new submodule init &&
+ git -C new submodule update &&
+ cmp new/sub/file sub/file
'
@@ -454,10 +483,8 @@ test_expect_success 'fast-export -C -C | fast-import' '
git --git-dir=new/.git init &&
git fast-export -C -C --signed-tags=strip --all > output &&
grep "^C file2 file4\$" output &&
- cat output |
- (cd new &&
- git fast-import &&
- test $ENTRY = $(git rev-parse --verify refs/heads/copy))
+ git -C new fast-import <output &&
+ test $ENTRY = $(git -C new rev-parse --verify refs/heads/copy)
'
@@ -905,4 +932,42 @@ test_expect_success 'fast-export handles --end-of-options' '
test_cmp expect actual
'
+test_expect_success GPG 'setup a commit with dual signatures on its SHA-1 and SHA-256 formats' '
+ # Create a signed SHA-256 commit
+ git init --object-format=sha256 explicit-sha256 &&
+ git -C explicit-sha256 config extensions.compatObjectFormat sha1 &&
+ git -C explicit-sha256 checkout -b dual-signed &&
+ test_commit -C explicit-sha256 A &&
+ echo B >explicit-sha256/B &&
+ git -C explicit-sha256 add B &&
+ test_tick &&
+ git -C explicit-sha256 commit -S -m "signed" B &&
+ SHA256_B=$(git -C explicit-sha256 rev-parse dual-signed) &&
+
+ # Create the corresponding SHA-1 commit
+ SHA1_B=$(git -C explicit-sha256 rev-parse --output-object-format=sha1 dual-signed) &&
+
+ # Check that the resulting SHA-1 commit has both signatures
+ echo $SHA1_B | git -C explicit-sha256 cat-file --batch >out &&
+ test_grep -E "^gpgsig " out &&
+ test_grep -E "^gpgsig-sha256 " out
+'
+
+test_expect_success GPG 'export and import of doubly signed commit' '
+ git -C explicit-sha256 fast-export --signed-commits=verbatim dual-signed >output &&
+ test_grep -E "^gpgsig sha1 openpgp" output &&
+ test_grep -E "^gpgsig sha256 openpgp" output &&
+ git -C new fast-import <output &&
+ git -C new cat-file commit refs/heads/dual-signed >actual &&
+ test_grep -E "^gpgsig " actual &&
+ test_grep -E "^gpgsig-sha256 " actual &&
+ IMPORTED=$(git -C new rev-parse refs/heads/dual-signed) &&
+ if test "$GIT_DEFAULT_HASH" = "sha1"
+ then
+ test $SHA1_B = $IMPORTED
+ else
+ test $SHA256_B = $IMPORTED
+ fi
+'
+
test_done
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 7679780fb8..578d6c8b32 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -700,19 +700,17 @@ test_expect_success \
# ----------------------------------------------------------------------
# syntax highlighting
+test_lazy_prereq HIGHLIGHT '
+ highlight_version=$(highlight --version </dev/null 2>/dev/null) &&
+ test -n "$highlight_version"
+'
-highlight_version=$(highlight --version </dev/null 2>/dev/null)
-if [ $? -eq 127 ]; then
- say "Skipping syntax highlighting tests: 'highlight' not found"
-elif test -z "$highlight_version"; then
- say "Skipping syntax highlighting tests: incorrect 'highlight' found"
-else
- test_set_prereq HIGHLIGHT
+test_expect_success HIGHLIGHT '
cat >>gitweb_config.perl <<-\EOF
our $highlight_bin = "highlight";
- $feature{'highlight'}{'override'} = 1;
+ $feature{"highlight"}{"override"} = 1;
EOF
-fi
+'
test_expect_success HIGHLIGHT \
'syntax highlighting (no highlight, unknown syntax)' \
diff --git a/t/t9822-git-p4-path-encoding.sh b/t/t9822-git-p4-path-encoding.sh
index 572d395498..e6e07facd4 100755
--- a/t/t9822-git-p4-path-encoding.sh
+++ b/t/t9822-git-p4-path-encoding.sh
@@ -7,12 +7,17 @@ test_description='Clone repositories with non ASCII paths'
UTF8_ESCAPED="a-\303\244_o-\303\266_u-\303\274.txt"
ISO8859_ESCAPED="a-\344_o-\366_u-\374.txt"
-ISO8859="$(printf "$ISO8859_ESCAPED")" &&
-echo content123 >"$ISO8859" &&
-rm "$ISO8859" || {
+test_lazy_prereq FS_ACCEPTS_ISO_8859_1 '
+ ISO8859="$(printf "$ISO8859_ESCAPED")" &&
+ echo content123 >"$ISO8859" &&
+ rm "$ISO8859"
+'
+
+if ! test_have_prereq FS_ACCEPTS_ISO_8859_1
+then
skip_all="fs does not accept ISO-8859-1 filenames"
test_done
-}
+fi
test_expect_success 'start p4d' '
start_p4d
diff --git a/t/t9835-git-p4-metadata-encoding-python2.sh b/t/t9835-git-p4-metadata-encoding-python2.sh
index 6116f806f6..b969c7e0d5 100755
--- a/t/t9835-git-p4-metadata-encoding-python2.sh
+++ b/t/t9835-git-p4-metadata-encoding-python2.sh
@@ -12,23 +12,25 @@ failing, and produces maximally sane output in git.'
## SECTION REPEATED IN t9836 ##
###############################
+EXTRA_PATH="$(pwd)/temp_python"
+mkdir "$EXTRA_PATH"
+PATH="$EXTRA_PATH:$PATH"
+export PATH
+
# These tests are specific to Python 2. Write a custom script that executes
# git-p4 directly with the Python 2 interpreter to ensure that we use that
# version even if Git was compiled with Python 3.
-python_target_binary=$(which python2)
-if test -n "$python_target_binary"
-then
- mkdir temp_python
- PATH="$(pwd)/temp_python:$PATH"
- export PATH
-
- write_script temp_python/git-p4-python2 <<-EOF
+test_lazy_prereq P4_PYTHON2 '
+ python_target_binary=$(which python2) &&
+ test -n "$python_target_binary" &&
+ write_script "$EXTRA_PATH"/git-p4-python2 <<-EOF &&
exec "$python_target_binary" "$(git --exec-path)/git-p4" "\$@"
EOF
-fi
+ ( git p4-python2 || true ) >err &&
+ test_grep "valid commands" err
+'
-git p4-python2 >err
-if ! grep 'valid commands' err
+if ! test_have_prereq P4_PYTHON2
then
skip_all="skipping python2 git p4 tests; python2 not available"
test_done
diff --git a/t/t9836-git-p4-metadata-encoding-python3.sh b/t/t9836-git-p4-metadata-encoding-python3.sh
index 5e5217a66b..da6669bf71 100755
--- a/t/t9836-git-p4-metadata-encoding-python3.sh
+++ b/t/t9836-git-p4-metadata-encoding-python3.sh
@@ -12,23 +12,25 @@ failing, and produces maximally sane output in git.'
## SECTION REPEATED IN t9835 ##
###############################
+EXTRA_PATH="$(pwd)/temp_python"
+mkdir "$EXTRA_PATH"
+PATH="$EXTRA_PATH:$PATH"
+export PATH
+
# These tests are specific to Python 3. Write a custom script that executes
# git-p4 directly with the Python 3 interpreter to ensure that we use that
# version even if Git was compiled with Python 2.
-python_target_binary=$(which python3)
-if test -n "$python_target_binary"
-then
- mkdir temp_python
- PATH="$(pwd)/temp_python:$PATH"
- export PATH
-
- write_script temp_python/git-p4-python3 <<-EOF
+test_lazy_prereq P4_PYTHON3 '
+ python_target_binary=$(which python3) &&
+ test -n "$python_target_binary" &&
+ write_script "$EXTRA_PATH"/git-p4-python3 <<-EOF &&
exec "$python_target_binary" "$(git --exec-path)/git-p4" "\$@"
EOF
-fi
+ ( git p4-python3 || true ) >err &&
+ test_grep "valid commands" err
+'
-git p4-python3 >err
-if ! grep 'valid commands' err
+if ! test_have_prereq P4_PYTHON3
then
skip_all="skipping python3 git p4 tests; python3 not available"
test_done
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 343b8cd191..6650d33fba 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2596,6 +2596,8 @@ test_expect_success 'double dash "git checkout"' '
--merge Z
--conflict=Z
--patch Z
+ --unified=Z
+ --inter-hunk-context=Z
--ignore-skip-worktree-bits Z
--ignore-other-worktrees Z
--recurse-submodules Z
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index d667dda654..637a6f13a6 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -66,10 +66,6 @@ test_expect_success 'prompt - unborn branch' '
test_cmp expected "$actual"
'
-if test_have_prereq !FUNNYNAMES; then
- say 'Your filesystem does not allow newlines in filenames.'
-fi
-
test_expect_success FUNNYNAMES 'prompt - with newline in path' '
repo_with_newline="repo
with
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index bee4a2ca34..a28de7b19b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1451,9 +1451,21 @@ test_cmp_fspath () {
# test_seq 1 5 -- outputs 1 2 3 4 5 one line at a time
#
# or with one argument (end), in which case it starts counting
-# from 1.
+# from 1. In addition to the start/end arguments, you can pass an optional
+# printf format. For example:
+#
+# test_seq -f "line %d" 1 5
+#
+# would print 5 lines, "line 1" through "line 5".
test_seq () {
+ local fmt="%d"
+ case "$1" in
+ -f)
+ fmt="$2"
+ shift 2
+ ;;
+ esac
case $# in
1) set 1 "$@" ;;
2) ;;
@@ -1462,7 +1474,7 @@ test_seq () {
test_seq_counter__=$1
while test "$test_seq_counter__" -le "$2"
do
- echo "$test_seq_counter__"
+ printf "$fmt\n" "$test_seq_counter__"
test_seq_counter__=$(( $test_seq_counter__ + 1 ))
done
}
@@ -1695,7 +1707,7 @@ test_set_hash () {
# Detect the hash algorithm in use.
test_detect_hash () {
- case "$GIT_TEST_DEFAULT_HASH" in
+ case "${GIT_TEST_DEFAULT_HASH:-$GIT_TEST_BUILTIN_HASH}" in
"sha256")
test_hash_algo=sha256
test_compat_hash_algo=sha1
@@ -1767,6 +1779,9 @@ test_oid () {
--hash=compat)
algo="$test_compat_hash_algo" &&
shift;;
+ --hash=builtin)
+ algo="$GIT_TEST_BUILTIN_HASH" &&
+ shift;;
--hash=*)
algo="${1#--hash=}" &&
shift;;
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 92d0db13d7..621cd31ae1 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -134,7 +134,8 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
################################################################
# It appears that people try to run tests without building...
-"${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X" >/dev/null
+GIT_BINARY="${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X"
+"$GIT_BINARY" >/dev/null
if test $? != 1
then
if test -n "$GIT_TEST_INSTALLED"
@@ -470,7 +471,7 @@ then
then
: Executed by a Bash version supporting BASH_XTRACEFD. Good.
else
- echo >&2 "warning: ignoring -x; '$0' is untraceable without BASH_XTRACEFD"
+ echo >&2 "# warning: ignoring -x; '$0' is untraceable without BASH_XTRACEFD"
trace=
fi
fi
@@ -536,7 +537,8 @@ export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
export EDITOR
-GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-sha1}"
+GIT_TEST_BUILTIN_HASH=$("$GIT_BINARY" version --build-options | sed -ne 's/^default-hash: //p')
+GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-$GIT_TEST_BUILTIN_HASH}"
export GIT_DEFAULT_HASH
GIT_DEFAULT_REF_FORMAT="${GIT_TEST_DEFAULT_REF_FORMAT:-files}"
export GIT_DEFAULT_REF_FORMAT
@@ -707,7 +709,7 @@ then
exec 3>>"$GIT_TEST_TEE_OUTPUT_FILE" 4>&3
elif test "$verbose" = "t"
then
- exec 4>&2 3>&1
+ exec 4>&2 3>&2
else
exec 4>/dev/null 3>/dev/null
fi
@@ -949,7 +951,7 @@ maybe_setup_verbose () {
test -z "$verbose_only" && return
if match_pattern_list $test_count "$verbose_only"
then
- exec 4>&2 3>&1
+ exec 4>&2 3>&2
# Emit a delimiting blank line when going from
# non-verbose to verbose. Within verbose mode the
# delimiter is printed by test_expect_*. The choice
@@ -1272,7 +1274,14 @@ test_done () {
check_test_results_san_file_ "$test_failure"
- if test -z "$skip_all" && test -n "$invert_exit_code"
+ if test "$test_fixed" != 0
+ then
+ if test -z "$invert_exit_code"
+ then
+ GIT_EXIT_OK=t
+ exit 1
+ fi
+ elif test -z "$skip_all" && test -n "$invert_exit_code"
then
say_color warn "# faking up non-zero exit with --invert-exit-code"
GIT_EXIT_OK=t
@@ -1638,6 +1647,12 @@ fi
# Fix some commands on Windows, and other OS-specific things
uname_s=$(uname -s)
case $uname_s in
+Darwin)
+ test_set_prereq MACOS
+ test_set_prereq POSIXPERM
+ test_set_prereq BSLASHPSPEC
+ test_set_prereq EXECKEEPSPID
+ ;;
*MINGW*)
# Windows has its own (incompatible) sort and find
sort () {
@@ -1895,6 +1910,10 @@ test_lazy_prereq SHA1 '
esac
'
+test_lazy_prereq DEFAULT_HASH_ALGORITHM '
+ test "$GIT_TEST_BUILTIN_HASH" = "$GIT_DEFAULT_HASH"
+'
+
test_lazy_prereq DEFAULT_REPO_FORMAT '
test_have_prereq SHA1,REFFILES
'
diff --git a/t/unit-tests/clar/clar.c b/t/unit-tests/clar/clar.c
index d54e455367..03a3aa8e87 100644
--- a/t/unit-tests/clar/clar.c
+++ b/t/unit-tests/clar/clar.c
@@ -350,7 +350,7 @@ static void
clar_run_suite(const struct clar_suite *suite, const char *filter)
{
const struct clar_func *test = suite->tests;
- size_t i, matchlen;
+ size_t i, matchlen = 0;
struct clar_report *report;
int exact = 0;
diff --git a/t/unit-tests/lib-reftable.c b/t/unit-tests/lib-reftable.c
index 8a69612266..fdb5b11a20 100644
--- a/t/unit-tests/lib-reftable.c
+++ b/t/unit-tests/lib-reftable.c
@@ -1,12 +1,14 @@
-#define DISABLE_SIGN_COMPARE_WARNINGS
-
+#include "unit-test.h"
#include "lib-reftable.h"
-#include "test-lib.h"
+#include "hex.h"
+#include "parse-options.h"
#include "reftable/constants.h"
#include "reftable/writer.h"
#include "strbuf.h"
+#include "string-list.h"
+#include "strvec.h"
-void t_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id)
+void cl_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id)
{
memset(p, (uint8_t)i, hash_size(id));
}
@@ -22,17 +24,17 @@ static int strbuf_writer_flush(void *arg UNUSED)
return 0;
}
-struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf,
+struct reftable_writer *cl_reftable_strbuf_writer(struct reftable_buf *buf,
struct reftable_write_options *opts)
{
struct reftable_writer *writer;
int ret = reftable_writer_new(&writer, &strbuf_writer_write, &strbuf_writer_flush,
buf, opts);
- check(!ret);
+ cl_assert(!ret);
return writer;
}
-void t_reftable_write_to_buf(struct reftable_buf *buf,
+void cl_reftable_write_to_buf(struct reftable_buf *buf,
struct reftable_ref_record *refs,
size_t nrefs,
struct reftable_log_record *logs,
@@ -64,35 +66,36 @@ void t_reftable_write_to_buf(struct reftable_buf *buf,
min = ui;
}
- writer = t_reftable_strbuf_writer(buf, &opts);
- reftable_writer_set_limits(writer, min, max);
+ writer = cl_reftable_strbuf_writer(buf, &opts);
+ ret = reftable_writer_set_limits(writer, min, max);
+ cl_assert(!ret);
if (nrefs) {
ret = reftable_writer_add_refs(writer, refs, nrefs);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
}
if (nlogs) {
ret = reftable_writer_add_logs(writer, logs, nlogs);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
}
ret = reftable_writer_close(writer);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
stats = reftable_writer_stats(writer);
- for (size_t i = 0; i < stats->ref_stats.blocks; i++) {
+ for (size_t i = 0; i < (size_t)stats->ref_stats.blocks; i++) {
size_t off = i * (opts.block_size ? opts.block_size
: DEFAULT_BLOCK_SIZE);
if (!off)
off = header_size(opts.hash_id == REFTABLE_HASH_SHA256 ? 2 : 1);
- check_char(buf->buf[off], ==, 'r');
+ cl_assert(buf->buf[off] == 'r');
}
if (nrefs)
- check_int(stats->ref_stats.blocks, >, 0);
+ cl_assert(stats->ref_stats.blocks > 0);
if (nlogs)
- check_int(stats->log_stats.blocks, >, 0);
+ cl_assert(stats->log_stats.blocks > 0);
reftable_writer_free(writer);
}
diff --git a/t/unit-tests/lib-reftable.h b/t/unit-tests/lib-reftable.h
index e4c360fa7e..d7e6d3136f 100644
--- a/t/unit-tests/lib-reftable.h
+++ b/t/unit-tests/lib-reftable.h
@@ -1,21 +1,20 @@
-#ifndef LIB_REFTABLE_H
-#define LIB_REFTABLE_H
-
+#include "git-compat-util.h"
+#include "clar/clar.h"
+#include "clar-decls.h"
#include "git-compat-util.h"
#include "reftable/reftable-writer.h"
+#include "strbuf.h"
struct reftable_buf;
-void t_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id);
+void cl_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id);
-struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf,
+struct reftable_writer *cl_reftable_strbuf_writer(struct reftable_buf *buf,
struct reftable_write_options *opts);
-void t_reftable_write_to_buf(struct reftable_buf *buf,
+void cl_reftable_write_to_buf(struct reftable_buf *buf,
struct reftable_ref_record *refs,
size_t nrecords,
struct reftable_log_record *logs,
size_t nlogs,
struct reftable_write_options *opts);
-
-#endif
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c
deleted file mode 100644
index c9e751e49e..0000000000
--- a/t/unit-tests/t-reftable-basics.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
-Copyright 2020 Google LLC
-
-Use of this source code is governed by a BSD-style
-license that can be found in the LICENSE file or at
-https://developers.google.com/open-source/licenses/bsd
-*/
-
-#include "test-lib.h"
-#include "reftable/basics.h"
-
-struct integer_needle_lesseq_args {
- int needle;
- int *haystack;
-};
-
-static int integer_needle_lesseq(size_t i, void *_args)
-{
- struct integer_needle_lesseq_args *args = _args;
- return args->needle <= args->haystack[i];
-}
-
-static void *realloc_stub(void *p UNUSED, size_t size UNUSED)
-{
- return NULL;
-}
-
-int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
-{
- if_test ("binary search with binsearch works") {
- int haystack[] = { 2, 4, 6, 8, 10 };
- struct {
- int needle;
- size_t expected_idx;
- } testcases[] = {
- {-9000, 0},
- {-1, 0},
- {0, 0},
- {2, 0},
- {3, 1},
- {4, 1},
- {7, 3},
- {9, 4},
- {10, 4},
- {11, 5},
- {9000, 5},
- };
-
- for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) {
- struct integer_needle_lesseq_args args = {
- .haystack = haystack,
- .needle = testcases[i].needle,
- };
- size_t idx;
-
- idx = binsearch(ARRAY_SIZE(haystack),
- &integer_needle_lesseq, &args);
- check_int(idx, ==, testcases[i].expected_idx);
- }
- }
-
- if_test ("names_length returns size of a NULL-terminated string array") {
- const char *a[] = { "a", "b", NULL };
- check_int(names_length(a), ==, 2);
- }
-
- if_test ("names_equal compares NULL-terminated string arrays") {
- const char *a[] = { "a", "b", "c", NULL };
- const char *b[] = { "a", "b", "d", NULL };
- const char *c[] = { "a", "b", NULL };
-
- check(names_equal(a, a));
- check(!names_equal(a, b));
- check(!names_equal(a, c));
- }
-
- if_test ("parse_names works for basic input") {
- char in1[] = "line\n";
- char in2[] = "a\nb\nc";
- char **out = parse_names(in1, strlen(in1));
- check(out != NULL);
- check_str(out[0], "line");
- check(!out[1]);
- free_names(out);
-
- out = parse_names(in2, strlen(in2));
- check(out != NULL);
- check_str(out[0], "a");
- check_str(out[1], "b");
- check_str(out[2], "c");
- check(!out[3]);
- free_names(out);
- }
-
- if_test ("parse_names drops empty string") {
- char in[] = "a\n\nb\n";
- char **out = parse_names(in, strlen(in));
- check(out != NULL);
- check_str(out[0], "a");
- /* simply '\n' should be dropped as empty string */
- check_str(out[1], "b");
- check(!out[2]);
- free_names(out);
- }
-
- if_test ("common_prefix_size works") {
- struct reftable_buf a = REFTABLE_BUF_INIT;
- struct reftable_buf b = REFTABLE_BUF_INIT;
- struct {
- const char *a, *b;
- int want;
- } cases[] = {
- {"abcdef", "abc", 3},
- { "abc", "ab", 2 },
- { "", "abc", 0 },
- { "abc", "abd", 2 },
- { "abc", "pqr", 0 },
- };
-
- for (size_t i = 0; i < ARRAY_SIZE(cases); i++) {
- check(!reftable_buf_addstr(&a, cases[i].a));
- check(!reftable_buf_addstr(&b, cases[i].b));
- check_uint(common_prefix_size(&a, &b), ==, cases[i].want);
- reftable_buf_reset(&a);
- reftable_buf_reset(&b);
- }
- reftable_buf_release(&a);
- reftable_buf_release(&b);
- }
-
- if_test ("reftable_put_be64 and reftable_get_be64 work") {
- uint64_t in = 0x1122334455667788;
- uint8_t dest[8];
- uint64_t out;
- reftable_put_be64(dest, in);
- out = reftable_get_be64(dest);
- check_int(in, ==, out);
- }
-
- if_test ("reftable_put_be32 and reftable_get_be32 work") {
- uint32_t in = 0x11223344;
- uint8_t dest[4];
- uint32_t out;
- reftable_put_be32(dest, in);
- out = reftable_get_be32(dest);
- check_int(in, ==, out);
- }
-
- if_test ("reftable_put_be24 and reftable_get_be24 work") {
- uint32_t in = 0x112233;
- uint8_t dest[3];
- uint32_t out;
- reftable_put_be24(dest, in);
- out = reftable_get_be24(dest);
- check_int(in, ==, out);
- }
-
- if_test ("put_be16 and get_be16 work") {
- uint32_t in = 0xfef1;
- uint8_t dest[3];
- uint32_t out;
- reftable_put_be16(dest, in);
- out = reftable_get_be16(dest);
- check_int(in, ==, out);
- }
-
- if_test ("REFTABLE_ALLOC_GROW works") {
- int *arr = NULL, *old_arr;
- size_t alloc = 0, old_alloc;
-
- check(!REFTABLE_ALLOC_GROW(arr, 1, alloc));
- check(arr != NULL);
- check_uint(alloc, >=, 1);
- arr[0] = 42;
-
- old_alloc = alloc;
- old_arr = arr;
- reftable_set_alloc(NULL, realloc_stub, NULL);
- check(REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc));
- check(arr == old_arr);
- check_uint(alloc, ==, old_alloc);
-
- old_alloc = alloc;
- reftable_set_alloc(NULL, NULL, NULL);
- check(!REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc));
- check(arr != NULL);
- check_uint(alloc, >, old_alloc);
- arr[alloc - 1] = 42;
-
- reftable_free(arr);
- }
-
- if_test ("REFTABLE_ALLOC_GROW_OR_NULL works") {
- int *arr = NULL;
- size_t alloc = 0, old_alloc;
-
- REFTABLE_ALLOC_GROW_OR_NULL(arr, 1, alloc);
- check(arr != NULL);
- check_uint(alloc, >=, 1);
- arr[0] = 42;
-
- old_alloc = alloc;
- REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc);
- check(arr != NULL);
- check_uint(alloc, >, old_alloc);
- arr[alloc - 1] = 42;
-
- old_alloc = alloc;
- reftable_set_alloc(NULL, realloc_stub, NULL);
- REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc);
- check(arr == NULL);
- check_uint(alloc, ==, 0);
- reftable_set_alloc(NULL, NULL, NULL);
-
- reftable_free(arr);
- }
-
- return test_done();
-}
diff --git a/t/unit-tests/u-dir.c b/t/unit-tests/u-dir.c
new file mode 100644
index 0000000000..2d0adaa39e
--- /dev/null
+++ b/t/unit-tests/u-dir.c
@@ -0,0 +1,47 @@
+#include "unit-test.h"
+#include "dir.h"
+
+#define TEST_WITHIN_DEPTH(path, depth, max_depth, expect) do { \
+ int actual = within_depth(path, strlen(path), \
+ depth, max_depth); \
+ if (actual != expect) \
+ cl_failf("path '%s' with depth '%d' and max-depth '%d': expected %d, got %d", \
+ path, depth, max_depth, expect, actual); \
+ } while (0)
+
+void test_dir__within_depth(void)
+{
+ /* depth = 0; max_depth = 0 */
+ TEST_WITHIN_DEPTH("", 0, 0, 1);
+ TEST_WITHIN_DEPTH("file", 0, 0, 1);
+ TEST_WITHIN_DEPTH("a", 0, 0, 1);
+ TEST_WITHIN_DEPTH("a/file", 0, 0, 0);
+ TEST_WITHIN_DEPTH("a/b", 0, 0, 0);
+ TEST_WITHIN_DEPTH("a/b/file", 0, 0, 0);
+
+ /* depth = 0; max_depth = 1 */
+ TEST_WITHIN_DEPTH("", 0, 1, 1);
+ TEST_WITHIN_DEPTH("file", 0, 1, 1);
+ TEST_WITHIN_DEPTH("a", 0, 1, 1);
+ TEST_WITHIN_DEPTH("a/file", 0, 1, 1);
+ TEST_WITHIN_DEPTH("a/b", 0, 1, 1);
+ TEST_WITHIN_DEPTH("a/b/file", 0, 1, 0);
+
+ /* depth = 1; max_depth = 1 */
+ TEST_WITHIN_DEPTH("", 1, 1, 1);
+ TEST_WITHIN_DEPTH("file", 1, 1, 1);
+ TEST_WITHIN_DEPTH("a", 1, 1, 1);
+ TEST_WITHIN_DEPTH("a/file", 1, 1, 0);
+ TEST_WITHIN_DEPTH("a/b", 1, 1, 0);
+ TEST_WITHIN_DEPTH("a/b/file", 1, 1, 0);
+
+ /* depth = 1; max_depth = 0 */
+ TEST_WITHIN_DEPTH("", 1, 0, 0);
+ TEST_WITHIN_DEPTH("file", 1, 0, 0);
+ TEST_WITHIN_DEPTH("a", 1, 0, 0);
+ TEST_WITHIN_DEPTH("a/file", 1, 0, 0);
+ TEST_WITHIN_DEPTH("a/b", 1, 0, 0);
+ TEST_WITHIN_DEPTH("a/b/file", 1, 0, 0);
+
+
+}
diff --git a/t/unit-tests/u-prio-queue.c b/t/unit-tests/u-prio-queue.c
index 145e689c9c..63e58114ae 100644
--- a/t/unit-tests/u-prio-queue.c
+++ b/t/unit-tests/u-prio-queue.c
@@ -13,6 +13,7 @@ static int intcmp(const void *va, const void *vb, void *data UNUSED)
#define STACK -3
#define GET -4
#define REVERSE -5
+#define REPLACE -6
static int show(int *v)
{
@@ -51,6 +52,15 @@ static void test_prio_queue(int *input, size_t input_size,
case REVERSE:
prio_queue_reverse(&pq);
break;
+ case REPLACE:
+ peek = prio_queue_peek(&pq);
+ cl_assert(i + 1 < input_size);
+ cl_assert(input[i + 1] >= 0);
+ cl_assert(j < result_size);
+ cl_assert_equal_i(result[j], show(peek));
+ j++;
+ prio_queue_replace(&pq, &input[++i]);
+ break;
default:
prio_queue_put(&pq, &input[i]);
break;
@@ -81,6 +91,13 @@ void test_prio_queue__empty(void)
((int []){ 1, 2, MISSING, 1, 2, MISSING }));
}
+void test_prio_queue__replace(void)
+{
+ TEST_INPUT(((int []){ REPLACE, 6, 2, 4, REPLACE, 5, 7, GET,
+ REPLACE, 1, DUMP }),
+ ((int []){ MISSING, 2, 4, 5, 1, 6, 7 }));
+}
+
void test_prio_queue__stack(void)
{
TEST_INPUT(((int []){ STACK, 8, 1, 5, 4, 6, 2, 3, DUMP }),
@@ -92,3 +109,9 @@ void test_prio_queue__reverse_stack(void)
TEST_INPUT(((int []){ STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP }),
((int []){ 1, 2, 3, 4, 5, 6 }));
}
+
+void test_prio_queue__replace_stack(void)
+{
+ TEST_INPUT(((int []){ STACK, 8, 1, 5, REPLACE, 4, 6, 2, 3, DUMP }),
+ ((int []){ 5, 3, 2, 6, 4, 1, 8 }));
+}
diff --git a/t/unit-tests/u-reftable-basics.c b/t/unit-tests/u-reftable-basics.c
new file mode 100644
index 0000000000..a0471083e7
--- /dev/null
+++ b/t/unit-tests/u-reftable-basics.c
@@ -0,0 +1,227 @@
+/*
+Copyright 2020 Google LLC
+
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file or at
+https://developers.google.com/open-source/licenses/bsd
+*/
+
+#include "unit-test.h"
+#include "lib-reftable.h"
+#include "reftable/basics.h"
+
+struct integer_needle_lesseq_args {
+ int needle;
+ int *haystack;
+};
+
+static int integer_needle_lesseq(size_t i, void *_args)
+{
+ struct integer_needle_lesseq_args *args = _args;
+ return args->needle <= args->haystack[i];
+}
+
+static void *realloc_stub(void *p UNUSED, size_t size UNUSED)
+{
+ return NULL;
+}
+
+void test_reftable_basics__binsearch(void)
+{
+ int haystack[] = { 2, 4, 6, 8, 10 };
+ struct {
+ int needle;
+ size_t expected_idx;
+ } testcases[] = {
+ {-9000, 0},
+ {-1, 0},
+ {0, 0},
+ {2, 0},
+ {3, 1},
+ {4, 1},
+ {7, 3},
+ {9, 4},
+ {10, 4},
+ {11, 5},
+ {9000, 5},
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) {
+ struct integer_needle_lesseq_args args = {
+ .haystack = haystack,
+ .needle = testcases[i].needle,
+ };
+ size_t idx;
+
+ idx = binsearch(ARRAY_SIZE(haystack),
+ &integer_needle_lesseq, &args);
+ cl_assert_equal_i(idx, testcases[i].expected_idx);
+ }
+}
+
+void test_reftable_basics__names_length(void)
+{
+ const char *a[] = { "a", "b", NULL };
+ cl_assert_equal_i(names_length(a), 2);
+}
+
+void test_reftable_basics__names_equal(void)
+{
+ const char *a[] = { "a", "b", "c", NULL };
+ const char *b[] = { "a", "b", "d", NULL };
+ const char *c[] = { "a", "b", NULL };
+
+ cl_assert(names_equal(a, a));
+ cl_assert(!names_equal(a, b));
+ cl_assert(!names_equal(a, c));
+}
+
+void test_reftable_basics__parse_names(void)
+{
+ char in1[] = "line\n";
+ char in2[] = "a\nb\nc";
+ char **out = parse_names(in1, strlen(in1));
+ cl_assert(out != NULL);
+ cl_assert_equal_s(out[0], "line");
+ cl_assert(!out[1]);
+ free_names(out);
+
+ out = parse_names(in2, strlen(in2));
+ cl_assert(out != NULL);
+ cl_assert_equal_s(out[0], "a");
+ cl_assert_equal_s(out[1], "b");
+ cl_assert_equal_s(out[2], "c");
+ cl_assert(!out[3]);
+ free_names(out);
+}
+
+void test_reftable_basics__parse_names_drop_empty_string(void)
+{
+ char in[] = "a\n\nb\n";
+ char **out = parse_names(in, strlen(in));
+ cl_assert(out != NULL);
+ cl_assert_equal_s(out[0], "a");
+ /* simply '\n' should be dropped as empty string */
+ cl_assert_equal_s(out[1], "b");
+ cl_assert(out[2] == NULL);
+ free_names(out);
+}
+
+void test_reftable_basics__common_prefix_size(void)
+{
+ struct reftable_buf a = REFTABLE_BUF_INIT;
+ struct reftable_buf b = REFTABLE_BUF_INIT;
+ struct {
+ const char *a, *b;
+ int want;
+ } cases[] = {
+ {"abcdef", "abc", 3},
+ { "abc", "ab", 2 },
+ { "", "abc", 0 },
+ { "abc", "abd", 2 },
+ { "abc", "pqr", 0 },
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(cases); i++) {
+ cl_assert_equal_i(reftable_buf_addstr(&a, cases[i].a), 0);
+ cl_assert_equal_i(reftable_buf_addstr(&b, cases[i].b), 0);
+ cl_assert_equal_i(common_prefix_size(&a, &b), cases[i].want);
+ reftable_buf_reset(&a);
+ reftable_buf_reset(&b);
+ }
+ reftable_buf_release(&a);
+ reftable_buf_release(&b);
+}
+
+void test_reftable_basics__put_get_be64(void)
+{
+ uint64_t in = 0x1122334455667788;
+ uint8_t dest[8];
+ uint64_t out;
+ reftable_put_be64(dest, in);
+ out = reftable_get_be64(dest);
+ cl_assert(in == out);
+}
+
+void test_reftable_basics__put_get_be32(void)
+{
+ uint32_t in = 0x11223344;
+ uint8_t dest[4];
+ uint32_t out;
+ reftable_put_be32(dest, in);
+ out = reftable_get_be32(dest);
+ cl_assert_equal_i(in, out);
+}
+
+void test_reftable_basics__put_get_be24(void)
+{
+ uint32_t in = 0x112233;
+ uint8_t dest[3];
+ uint32_t out;
+ reftable_put_be24(dest, in);
+ out = reftable_get_be24(dest);
+ cl_assert_equal_i(in, out);
+}
+
+void test_reftable_basics__put_get_be16(void)
+{
+ uint32_t in = 0xfef1;
+ uint8_t dest[3];
+ uint32_t out;
+ reftable_put_be16(dest, in);
+ out = reftable_get_be16(dest);
+ cl_assert_equal_i(in, out);
+}
+
+void test_reftable_basics__alloc_grow(void)
+{
+ int *arr = NULL, *old_arr;
+ size_t alloc = 0, old_alloc;
+
+ cl_assert_equal_i(REFTABLE_ALLOC_GROW(arr, 1, alloc), 0);
+ cl_assert(arr != NULL);
+ cl_assert(alloc >= 1);
+ arr[0] = 42;
+
+ old_alloc = alloc;
+ old_arr = arr;
+ reftable_set_alloc(NULL, realloc_stub, NULL);
+ cl_assert(REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc));
+ cl_assert(arr == old_arr);
+ cl_assert_equal_i(alloc, old_alloc);
+
+ old_alloc = alloc;
+ reftable_set_alloc(NULL, NULL, NULL);
+ cl_assert_equal_i(REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc), 0);
+ cl_assert(arr != NULL);
+ cl_assert(alloc > old_alloc);
+ arr[alloc - 1] = 42;
+
+ reftable_free(arr);
+}
+
+void test_reftable_basics__alloc_grow_or_null(void)
+{
+ int *arr = NULL;
+ size_t alloc = 0, old_alloc;
+
+ REFTABLE_ALLOC_GROW_OR_NULL(arr, 1, alloc);
+ cl_assert(arr != NULL);
+ cl_assert(alloc >= 1);
+ arr[0] = 42;
+
+ old_alloc = alloc;
+ REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc);
+ cl_assert(arr != NULL);
+ cl_assert(alloc > old_alloc);
+ arr[alloc - 1] = 42;
+
+ old_alloc = alloc;
+ reftable_set_alloc(NULL, realloc_stub, NULL);
+ REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc);
+ cl_assert(arr == NULL);
+ cl_assert_equal_i(alloc, 0);
+ reftable_set_alloc(NULL, NULL, NULL);
+
+ reftable_free(arr);
+}
diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/u-reftable-block.c
index 52f1dae1c9..f4bded7d26 100644
--- a/t/unit-tests/t-reftable-block.c
+++ b/t/unit-tests/u-reftable-block.c
@@ -6,14 +6,15 @@ license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/
-#include "test-lib.h"
+#include "unit-test.h"
+#include "lib-reftable.h"
#include "reftable/block.h"
#include "reftable/blocksource.h"
#include "reftable/constants.h"
#include "reftable/reftable-error.h"
#include "strbuf.h"
-static void t_ref_block_read_write(void)
+void test_reftable_block__read_write(void)
{
const int header_off = 21; /* random */
struct reftable_record recs[30];
@@ -34,17 +35,18 @@ static void t_ref_block_read_write(void)
struct reftable_buf block_data = REFTABLE_BUF_INIT;
REFTABLE_CALLOC_ARRAY(block_data.buf, block_size);
- check(block_data.buf != NULL);
+ cl_assert(block_data.buf != NULL);
block_data.len = block_size;
- ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_REF, (uint8_t *) block_data.buf, block_size,
+ ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_REF,
+ (uint8_t *) block_data.buf, block_size,
header_off, hash_size(REFTABLE_HASH_SHA1));
- check(!ret);
+ cl_assert(!ret);
rec.u.ref.refname = (char *) "";
rec.u.ref.value_type = REFTABLE_REF_DELETION;
ret = block_writer_add(&bw, &rec);
- check_int(ret, ==, REFTABLE_API_ERROR);
+ cl_assert_equal_i(ret, REFTABLE_API_ERROR);
for (i = 0; i < N; i++) {
rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i);
@@ -55,11 +57,11 @@ static void t_ref_block_read_write(void)
ret = block_writer_add(&bw, &rec);
rec.u.ref.refname = NULL;
rec.u.ref.value_type = REFTABLE_REF_DELETION;
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
}
ret = block_writer_finish(&bw);
- check_int(ret, >, 0);
+ cl_assert(ret > 0);
block_writer_release(&bw);
@@ -71,32 +73,32 @@ static void t_ref_block_read_write(void)
for (i = 0; ; i++) {
ret = block_iter_next(&it, &rec);
- check_int(ret, >=, 0);
+ cl_assert(ret >= 0);
if (ret > 0) {
- check_int(i, ==, N);
+ cl_assert_equal_i(i, N);
break;
}
- check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
}
for (i = 0; i < N; i++) {
reftable_record_key(&recs[i], &want);
ret = block_iter_seek_key(&it, &want);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
ret = block_iter_next(&it, &rec);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
- check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
want.len--;
ret = block_iter_seek_key(&it, &want);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
ret = block_iter_next(&it, &rec);
- check_int(ret, ==, 0);
- check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(ret, 0);
+ cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
}
reftable_block_release(&block);
@@ -108,7 +110,7 @@ static void t_ref_block_read_write(void)
reftable_record_release(&recs[i]);
}
-static void t_log_block_read_write(void)
+void test_reftable_block__log_read_write(void)
{
const int header_off = 21;
struct reftable_record recs[30];
@@ -129,12 +131,12 @@ static void t_log_block_read_write(void)
struct reftable_buf block_data = REFTABLE_BUF_INIT;
REFTABLE_CALLOC_ARRAY(block_data.buf, block_size);
- check(block_data.buf != NULL);
+ cl_assert(block_data.buf != NULL);
block_data.len = block_size;
ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_LOG, (uint8_t *) block_data.buf, block_size,
header_off, hash_size(REFTABLE_HASH_SHA1));
- check(!ret);
+ cl_assert(!ret);
for (i = 0; i < N; i++) {
rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i);
@@ -145,11 +147,11 @@ static void t_log_block_read_write(void)
ret = block_writer_add(&bw, &rec);
rec.u.log.refname = NULL;
rec.u.log.value_type = REFTABLE_LOG_DELETION;
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
}
ret = block_writer_finish(&bw);
- check_int(ret, >, 0);
+ cl_assert(ret > 0);
block_writer_release(&bw);
@@ -161,33 +163,33 @@ static void t_log_block_read_write(void)
for (i = 0; ; i++) {
ret = block_iter_next(&it, &rec);
- check_int(ret, >=, 0);
+ cl_assert(ret >= 0);
if (ret > 0) {
- check_int(i, ==, N);
+ cl_assert_equal_i(i, N);
break;
}
- check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
}
for (i = 0; i < N; i++) {
reftable_buf_reset(&want);
- check(!reftable_buf_addstr(&want, recs[i].u.log.refname));
+ cl_assert(reftable_buf_addstr(&want, recs[i].u.log.refname) == 0);
ret = block_iter_seek_key(&it, &want);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
ret = block_iter_next(&it, &rec);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
- check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
want.len--;
ret = block_iter_seek_key(&it, &want);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
ret = block_iter_next(&it, &rec);
- check_int(ret, ==, 0);
- check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(ret, 0);
+ cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
}
reftable_block_release(&block);
@@ -199,7 +201,7 @@ static void t_log_block_read_write(void)
reftable_record_release(&recs[i]);
}
-static void t_obj_block_read_write(void)
+void test_reftable_block__obj_read_write(void)
{
const int header_off = 21;
struct reftable_record recs[30];
@@ -220,12 +222,12 @@ static void t_obj_block_read_write(void)
struct reftable_buf block_data = REFTABLE_BUF_INIT;
REFTABLE_CALLOC_ARRAY(block_data.buf, block_size);
- check(block_data.buf != NULL);
+ cl_assert(block_data.buf != NULL);
block_data.len = block_size;
ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_OBJ, (uint8_t *) block_data.buf, block_size,
header_off, hash_size(REFTABLE_HASH_SHA1));
- check(!ret);
+ cl_assert(!ret);
for (i = 0; i < N; i++) {
uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated;
@@ -238,11 +240,11 @@ static void t_obj_block_read_write(void)
ret = block_writer_add(&bw, &rec);
rec.u.obj.hash_prefix = NULL;
rec.u.obj.hash_prefix_len = 0;
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
}
ret = block_writer_finish(&bw);
- check_int(ret, >, 0);
+ cl_assert(ret > 0);
block_writer_release(&bw);
@@ -254,24 +256,24 @@ static void t_obj_block_read_write(void)
for (i = 0; ; i++) {
ret = block_iter_next(&it, &rec);
- check_int(ret, >=, 0);
+ cl_assert(ret >= 0);
if (ret > 0) {
- check_int(i, ==, N);
+ cl_assert_equal_i(i, N);
break;
}
- check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
}
for (i = 0; i < N; i++) {
reftable_record_key(&recs[i], &want);
ret = block_iter_seek_key(&it, &want);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
ret = block_iter_next(&it, &rec);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
- check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
}
reftable_block_release(&block);
@@ -283,7 +285,7 @@ static void t_obj_block_read_write(void)
reftable_record_release(&recs[i]);
}
-static void t_index_block_read_write(void)
+void test_reftable_block__ref_read_write(void)
{
const int header_off = 21;
struct reftable_record recs[30];
@@ -305,12 +307,12 @@ static void t_index_block_read_write(void)
struct reftable_buf block_data = REFTABLE_BUF_INIT;
REFTABLE_CALLOC_ARRAY(block_data.buf, block_size);
- check(block_data.buf != NULL);
+ cl_assert(block_data.buf != NULL);
block_data.len = block_size;
ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_INDEX, (uint8_t *) block_data.buf, block_size,
header_off, hash_size(REFTABLE_HASH_SHA1));
- check(!ret);
+ cl_assert(!ret);
for (i = 0; i < N; i++) {
char buf[128];
@@ -319,15 +321,15 @@ static void t_index_block_read_write(void)
reftable_buf_init(&recs[i].u.idx.last_key);
recs[i].type = REFTABLE_BLOCK_TYPE_INDEX;
- check(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf));
+ cl_assert(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf));
recs[i].u.idx.offset = i;
ret = block_writer_add(&bw, &recs[i]);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
}
ret = block_writer_finish(&bw);
- check_int(ret, >, 0);
+ cl_assert(ret > 0);
block_writer_release(&bw);
@@ -339,32 +341,32 @@ static void t_index_block_read_write(void)
for (i = 0; ; i++) {
ret = block_iter_next(&it, &rec);
- check_int(ret, >=, 0);
+ cl_assert(ret >= 0);
if (ret > 0) {
- check_int(i, ==, N);
+ cl_assert_equal_i(i, N);
break;
}
- check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
}
for (i = 0; i < N; i++) {
reftable_record_key(&recs[i], &want);
ret = block_iter_seek_key(&it, &want);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
ret = block_iter_next(&it, &rec);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
- check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
want.len--;
ret = block_iter_seek_key(&it, &want);
- check_int(ret, ==, 0);
+ cl_assert_equal_i(ret, 0);
ret = block_iter_next(&it, &rec);
- check_int(ret, ==, 0);
- check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(ret, 0);
+ cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1);
}
reftable_block_release(&block);
@@ -376,7 +378,7 @@ static void t_index_block_read_write(void)
reftable_record_release(&recs[i]);
}
-static void t_block_iterator(void)
+void test_reftable_block__iterator(void)
{
struct reftable_block_source source = { 0 };
struct block_writer writer = {
@@ -391,11 +393,12 @@ static void t_block_iterator(void)
data.len = 1024;
REFTABLE_CALLOC_ARRAY(data.buf, data.len);
- check(data.buf != NULL);
+ cl_assert(data.buf != NULL);
- err = block_writer_init(&writer, REFTABLE_BLOCK_TYPE_REF, (uint8_t *) data.buf, data.len,
+ err = block_writer_init(&writer, REFTABLE_BLOCK_TYPE_REF,
+ (uint8_t *) data.buf, data.len,
0, hash_size(REFTABLE_HASH_SHA1));
- check(!err);
+ cl_assert(!err);
for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) {
expected_refs[i] = (struct reftable_record) {
@@ -408,42 +411,42 @@ static void t_block_iterator(void)
memset(expected_refs[i].u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1);
err = block_writer_add(&writer, &expected_refs[i]);
- check_int(err, ==, 0);
+ cl_assert_equal_i(err, 0);
}
err = block_writer_finish(&writer);
- check_int(err, >, 0);
+ cl_assert(err > 0);
block_source_from_buf(&source, &data);
reftable_block_init(&block, &source, 0, 0, data.len,
REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF);
err = reftable_block_init_iterator(&block, &it);
- check_int(err, ==, 0);
+ cl_assert_equal_i(err, 0);
for (size_t i = 0; ; i++) {
err = reftable_iterator_next_ref(&it, &ref);
if (err > 0) {
- check_int(i, ==, ARRAY_SIZE(expected_refs));
+ cl_assert_equal_i(i, ARRAY_SIZE(expected_refs));
break;
}
- check_int(err, ==, 0);
+ cl_assert_equal_i(err, 0);
- check(reftable_ref_record_equal(&ref, &expected_refs[i].u.ref,
- REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(reftable_ref_record_equal(&ref,
+ &expected_refs[i].u.ref, REFTABLE_HASH_SIZE_SHA1));
}
err = reftable_iterator_seek_ref(&it, "refs/heads/does-not-exist");
- check_int(err, ==, 0);
+ cl_assert_equal_i(err, 0);
err = reftable_iterator_next_ref(&it, &ref);
- check_int(err, ==, 1);
+ cl_assert_equal_i(err, 1);
err = reftable_iterator_seek_ref(&it, "refs/heads/branch-13");
- check_int(err, ==, 0);
+ cl_assert_equal_i(err, 0);
err = reftable_iterator_next_ref(&it, &ref);
- check_int(err, ==, 0);
- check(reftable_ref_record_equal(&ref, &expected_refs[13].u.ref,
- REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(err, 0);
+ cl_assert(reftable_ref_record_equal(&ref,
+ &expected_refs[13].u.ref,REFTABLE_HASH_SIZE_SHA1));
for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++)
reftable_free(expected_refs[i].u.ref.refname);
@@ -453,14 +456,3 @@ static void t_block_iterator(void)
block_writer_release(&writer);
reftable_buf_release(&data);
}
-
-int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
-{
- TEST(t_index_block_read_write(), "read-write operations on index blocks work");
- TEST(t_log_block_read_write(), "read-write operations on log blocks work");
- TEST(t_obj_block_read_write(), "read-write operations on obj blocks work");
- TEST(t_ref_block_read_write(), "read-write operations on ref blocks work");
- TEST(t_block_iterator(), "block iterator works");
-
- return test_done();
-}
diff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/u-reftable-merged.c
index 18c3251a56..54cb7fc2a7 100644
--- a/t/unit-tests/t-reftable-merged.c
+++ b/t/unit-tests/u-reftable-merged.c
@@ -6,7 +6,7 @@ license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/
-#include "test-lib.h"
+#include "unit-test.h"
#include "lib-reftable.h"
#include "reftable/blocksource.h"
#include "reftable/constants.h"
@@ -29,21 +29,21 @@ merged_table_from_records(struct reftable_ref_record **refs,
int err;
REFTABLE_CALLOC_ARRAY(*tables, n);
- check(*tables != NULL);
+ cl_assert(*tables != NULL);
REFTABLE_CALLOC_ARRAY(*source, n);
- check(*source != NULL);
+ cl_assert(*source != NULL);
for (size_t i = 0; i < n; i++) {
- t_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts);
+ cl_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts);
block_source_from_buf(&(*source)[i], &buf[i]);
err = reftable_table_new(&(*tables)[i], &(*source)[i],
"name");
- check(!err);
+ cl_assert(!err);
}
err = reftable_merged_table_new(&mt, *tables, n, REFTABLE_HASH_SHA1);
- check(!err);
+ cl_assert(!err);
return mt;
}
@@ -54,7 +54,7 @@ static void tables_destroy(struct reftable_table **tables, const size_t n)
reftable_free(tables);
}
-static void t_merged_single_record(void)
+void test_reftable_merged__single_record(void)
{
struct reftable_ref_record r1[] = { {
.refname = (char *) "b",
@@ -85,13 +85,14 @@ static void t_merged_single_record(void)
int err;
err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_ref(&it, "a");
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_next_ref(&it, &ref);
- check(!err);
- check(reftable_ref_record_equal(&r2[0], &ref, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(!err);
+ cl_assert(reftable_ref_record_equal(&r2[0], &ref,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_ref_record_release(&ref);
reftable_iterator_destroy(&it);
tables_destroy(tables, 3);
@@ -101,7 +102,7 @@ static void t_merged_single_record(void)
reftable_free(bs);
}
-static void t_merged_refs(void)
+void test_reftable_merged__refs(void)
{
struct reftable_ref_record r1[] = {
{
@@ -165,12 +166,12 @@ static void t_merged_refs(void)
size_t i;
err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_ref(&it, "a");
- check(!err);
- check_int(reftable_merged_table_hash_id(mt), ==, REFTABLE_HASH_SHA1);
- check_int(reftable_merged_table_min_update_index(mt), ==, 1);
- check_int(reftable_merged_table_max_update_index(mt), ==, 3);
+ cl_assert(err == 0);
+ cl_assert_equal_i(reftable_merged_table_hash_id(mt), REFTABLE_HASH_SHA1);
+ cl_assert_equal_i(reftable_merged_table_min_update_index(mt), 1);
+ cl_assert_equal_i(reftable_merged_table_max_update_index(mt), 3);
while (len < 100) { /* cap loops/recursion. */
struct reftable_ref_record ref = { 0 };
@@ -178,15 +179,15 @@ static void t_merged_refs(void)
if (err > 0)
break;
- check(!REFTABLE_ALLOC_GROW(out, len + 1, cap));
+ cl_assert(REFTABLE_ALLOC_GROW(out, len + 1, cap) == 0);
out[len++] = ref;
}
reftable_iterator_destroy(&it);
- check_int(ARRAY_SIZE(want), ==, len);
+ cl_assert_equal_i(ARRAY_SIZE(want), len);
for (i = 0; i < len; i++)
- check(reftable_ref_record_equal(want[i], &out[i],
- REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(reftable_ref_record_equal(want[i], &out[i],
+ REFTABLE_HASH_SIZE_SHA1) != 0);
for (i = 0; i < len; i++)
reftable_ref_record_release(&out[i]);
reftable_free(out);
@@ -198,7 +199,7 @@ static void t_merged_refs(void)
reftable_free(bs);
}
-static void t_merged_seek_multiple_times(void)
+void test_reftable_merged__seek_multiple_times(void)
{
struct reftable_ref_record r1[] = {
{
@@ -248,20 +249,17 @@ static void t_merged_seek_multiple_times(void)
for (size_t i = 0; i < 5; i++) {
int err = reftable_iterator_seek_ref(&it, "c");
- check(!err);
+ cl_assert(!err);
- err = reftable_iterator_next_ref(&it, &rec);
- check(!err);
- err = reftable_ref_record_equal(&rec, &r1[1], REFTABLE_HASH_SIZE_SHA1);
- check(err == 1);
+ cl_assert(reftable_iterator_next_ref(&it, &rec) == 0);
+ cl_assert_equal_i(reftable_ref_record_equal(&rec, &r1[1],
+ REFTABLE_HASH_SIZE_SHA1), 1);
- err = reftable_iterator_next_ref(&it, &rec);
- check(!err);
- err = reftable_ref_record_equal(&rec, &r2[1], REFTABLE_HASH_SIZE_SHA1);
- check(err == 1);
+ cl_assert(reftable_iterator_next_ref(&it, &rec) == 0);
+ cl_assert_equal_i(reftable_ref_record_equal(&rec, &r2[1],
+ REFTABLE_HASH_SIZE_SHA1), 1);
- err = reftable_iterator_next_ref(&it, &rec);
- check(err > 0);
+ cl_assert(reftable_iterator_next_ref(&it, &rec) > 0);
}
for (size_t i = 0; i < ARRAY_SIZE(bufs); i++)
@@ -273,7 +271,7 @@ static void t_merged_seek_multiple_times(void)
reftable_free(sources);
}
-static void t_merged_seek_multiple_times_without_draining(void)
+void test_reftable_merged__seek_multiple_times_no_drain(void)
{
struct reftable_ref_record r1[] = {
{
@@ -317,24 +315,19 @@ static void t_merged_seek_multiple_times_without_draining(void)
struct reftable_ref_record rec = { 0 };
struct reftable_iterator it = { 0 };
struct reftable_merged_table *mt;
- int err;
mt = merged_table_from_records(refs, &sources, &tables, sizes, bufs, 2);
merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF);
- err = reftable_iterator_seek_ref(&it, "b");
- check(!err);
- err = reftable_iterator_next_ref(&it, &rec);
- check(!err);
- err = reftable_ref_record_equal(&rec, &r2[0], REFTABLE_HASH_SIZE_SHA1);
- check(err == 1);
+ cl_assert(reftable_iterator_seek_ref(&it, "b") == 0);
+ cl_assert(reftable_iterator_next_ref(&it, &rec) == 0);
+ cl_assert_equal_i(reftable_ref_record_equal(&rec, &r2[0],
+ REFTABLE_HASH_SIZE_SHA1), 1);
- err = reftable_iterator_seek_ref(&it, "a");
- check(!err);
- err = reftable_iterator_next_ref(&it, &rec);
- check(!err);
- err = reftable_ref_record_equal(&rec, &r1[0], REFTABLE_HASH_SIZE_SHA1);
- check(err == 1);
+ cl_assert(reftable_iterator_seek_ref(&it, "a") == 0);
+ cl_assert(reftable_iterator_next_ref(&it, &rec) == 0);
+ cl_assert_equal_i(reftable_ref_record_equal(&rec, &r1[0],
+ REFTABLE_HASH_SIZE_SHA1), 1);
for (size_t i = 0; i < ARRAY_SIZE(bufs); i++)
reftable_buf_release(&bufs[i]);
@@ -359,25 +352,25 @@ merged_table_from_log_records(struct reftable_log_record **logs,
int err;
REFTABLE_CALLOC_ARRAY(*tables, n);
- check(*tables != NULL);
+ cl_assert(*tables != NULL);
REFTABLE_CALLOC_ARRAY(*source, n);
- check(*source != NULL);
+ cl_assert(*source != NULL);
for (size_t i = 0; i < n; i++) {
- t_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts);
+ cl_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts);
block_source_from_buf(&(*source)[i], &buf[i]);
err = reftable_table_new(&(*tables)[i], &(*source)[i],
"name");
- check(!err);
+ cl_assert(!err);
}
err = reftable_merged_table_new(&mt, *tables, n, REFTABLE_HASH_SHA1);
- check(!err);
+ cl_assert(!err);
return mt;
}
-static void t_merged_logs(void)
+void test_reftable_merged__logs(void)
{
struct reftable_log_record r1[] = {
{
@@ -439,19 +432,19 @@ static void t_merged_logs(void)
struct reftable_merged_table *mt = merged_table_from_log_records(
logs, &bs, &tables, sizes, bufs, 3);
struct reftable_iterator it = { 0 };
- int err;
struct reftable_log_record *out = NULL;
size_t len = 0;
size_t cap = 0;
size_t i;
+ int err;
err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_log(&it, "a");
- check(!err);
- check_int(reftable_merged_table_hash_id(mt), ==, REFTABLE_HASH_SHA1);
- check_int(reftable_merged_table_min_update_index(mt), ==, 1);
- check_int(reftable_merged_table_max_update_index(mt), ==, 3);
+ cl_assert(!err);
+ cl_assert_equal_i(reftable_merged_table_hash_id(mt), REFTABLE_HASH_SHA1);
+ cl_assert_equal_i(reftable_merged_table_min_update_index(mt), 1);
+ cl_assert_equal_i(reftable_merged_table_max_update_index(mt), 3);
while (len < 100) { /* cap loops/recursion. */
struct reftable_log_record log = { 0 };
@@ -459,24 +452,24 @@ static void t_merged_logs(void)
if (err > 0)
break;
- check(!REFTABLE_ALLOC_GROW(out, len + 1, cap));
+ cl_assert(REFTABLE_ALLOC_GROW(out, len + 1, cap) == 0);
out[len++] = log;
}
reftable_iterator_destroy(&it);
- check_int(ARRAY_SIZE(want), ==, len);
+ cl_assert_equal_i(ARRAY_SIZE(want), len);
for (i = 0; i < len; i++)
- check(reftable_log_record_equal(want[i], &out[i],
- REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(reftable_log_record_equal(want[i], &out[i],
+ REFTABLE_HASH_SIZE_SHA1) != 0);
err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_log_at(&it, "a", 2);
- check(!err);
+ cl_assert(!err);
reftable_log_record_release(&out[0]);
- err = reftable_iterator_next_log(&it, &out[0]);
- check(!err);
- check(reftable_log_record_equal(&out[0], &r3[0], REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(reftable_iterator_next_log(&it, &out[0]) == 0);
+ cl_assert(reftable_log_record_equal(&out[0], &r3[0],
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_iterator_destroy(&it);
for (i = 0; i < len; i++)
@@ -490,11 +483,11 @@ static void t_merged_logs(void)
reftable_free(bs);
}
-static void t_default_write_opts(void)
+void test_reftable_merged__default_write_opts(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_buf buf = REFTABLE_BUF_INIT;
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record rec = {
.refname = (char *) "master",
.update_index = 1,
@@ -507,40 +500,25 @@ static void t_default_write_opts(void)
reftable_writer_set_limits(w, 1, 1);
- err = reftable_writer_add_ref(w, &rec);
- check(!err);
+ cl_assert_equal_i(reftable_writer_add_ref(w, &rec), 0);
- err = reftable_writer_close(w);
- check(!err);
+ cl_assert_equal_i(reftable_writer_close(w), 0);
reftable_writer_free(w);
block_source_from_buf(&source, &buf);
err = reftable_table_new(&table, &source, "filename");
- check(!err);
+ cl_assert(!err);
hash_id = reftable_table_hash_id(table);
- check_int(hash_id, ==, REFTABLE_HASH_SHA1);
+ cl_assert_equal_i(hash_id, REFTABLE_HASH_SHA1);
err = reftable_merged_table_new(&merged, &table, 1, REFTABLE_HASH_SHA256);
- check_int(err, ==, REFTABLE_FORMAT_ERROR);
+ cl_assert_equal_i(err, REFTABLE_FORMAT_ERROR);
err = reftable_merged_table_new(&merged, &table, 1, REFTABLE_HASH_SHA1);
- check(!err);
+ cl_assert(!err);
reftable_table_decref(table);
reftable_merged_table_free(merged);
reftable_buf_release(&buf);
}
-
-
-int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
-{
- TEST(t_default_write_opts(), "merged table with default write opts");
- TEST(t_merged_logs(), "merged table with multiple log updates for same ref");
- TEST(t_merged_refs(), "merged table with multiple updates to same ref");
- TEST(t_merged_seek_multiple_times(), "merged table can seek multiple times");
- TEST(t_merged_seek_multiple_times_without_draining(), "merged table can seek multiple times without draining");
- TEST(t_merged_single_record(), "ref occurring in only one record can be fetched");
-
- return test_done();
-}
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/u-reftable-pq.c
index fb5a4eb187..f8a28f6e07 100644
--- a/t/unit-tests/t-reftable-pq.c
+++ b/t/unit-tests/u-reftable-pq.c
@@ -6,7 +6,8 @@ license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/
-#include "test-lib.h"
+#include "unit-test.h"
+#include "lib-reftable.h"
#include "reftable/constants.h"
#include "reftable/pq.h"
#include "strbuf.h"
@@ -15,18 +16,18 @@ static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq)
{
for (size_t i = 1; i < pq->len; i++) {
size_t parent = (i - 1) / 2;
- check(pq_less(&pq->heap[parent], &pq->heap[i]));
+ cl_assert(pq_less(&pq->heap[parent], &pq->heap[i]) != 0);
}
}
static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b)
{
int cmp;
- check(!reftable_record_cmp(a->rec, b->rec, &cmp));
+ cl_assert_equal_i(reftable_record_cmp(a->rec, b->rec, &cmp), 0);
return !cmp && (a->index == b->index);
}
-static void t_pq_record(void)
+void test_reftable_pq__record(void)
{
struct merged_iter_pqueue pq = { 0 };
struct reftable_record recs[54];
@@ -34,7 +35,8 @@ static void t_pq_record(void)
char *last = NULL;
for (i = 0; i < N; i++) {
- check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF));
+ cl_assert(!reftable_record_init(&recs[i],
+ REFTABLE_BLOCK_TYPE_REF));
recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i);
}
@@ -53,13 +55,13 @@ static void t_pq_record(void)
struct pq_entry top = merged_iter_pqueue_top(pq);
struct pq_entry e;
- check(!merged_iter_pqueue_remove(&pq, &e));
+ cl_assert_equal_i(merged_iter_pqueue_remove(&pq, &e), 0);
merged_iter_pqueue_check(&pq);
- check(pq_entry_equal(&top, &e));
- check(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF);
+ cl_assert(pq_entry_equal(&top, &e));
+ cl_assert(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF);
if (last)
- check_int(strcmp(last, e.rec->u.ref.refname), <, 0);
+ cl_assert(strcmp(last, e.rec->u.ref.refname) < 0);
last = e.rec->u.ref.refname;
}
@@ -68,7 +70,7 @@ static void t_pq_record(void)
merged_iter_pqueue_release(&pq);
}
-static void t_pq_index(void)
+void test_reftable_pq__index(void)
{
struct merged_iter_pqueue pq = { 0 };
struct reftable_record recs[13];
@@ -76,7 +78,8 @@ static void t_pq_index(void)
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF));
+ cl_assert(!reftable_record_init(&recs[i],
+ REFTABLE_BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
@@ -96,28 +99,29 @@ static void t_pq_index(void)
struct pq_entry top = merged_iter_pqueue_top(pq);
struct pq_entry e;
- check(!merged_iter_pqueue_remove(&pq, &e));
+ cl_assert_equal_i(merged_iter_pqueue_remove(&pq, &e), 0);
merged_iter_pqueue_check(&pq);
- check(pq_entry_equal(&top, &e));
- check(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF);
- check_int(e.index, ==, i);
+ cl_assert(pq_entry_equal(&top, &e));
+ cl_assert(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF);
+ cl_assert_equal_i(e.index, i);
if (last)
- check_str(last, e.rec->u.ref.refname);
+ cl_assert_equal_s(last, e.rec->u.ref.refname);
last = e.rec->u.ref.refname;
}
merged_iter_pqueue_release(&pq);
}
-static void t_merged_iter_pqueue_top(void)
+void test_reftable_pq__merged_iter_pqueue_top(void)
{
struct merged_iter_pqueue pq = { 0 };
struct reftable_record recs[13];
size_t N = ARRAY_SIZE(recs), i;
for (i = 0; i < N; i++) {
- check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF));
+ cl_assert(!reftable_record_init(&recs[i],
+ REFTABLE_BLOCK_TYPE_REF));
recs[i].u.ref.refname = (char *) "refs/heads/master";
}
@@ -137,25 +141,16 @@ static void t_merged_iter_pqueue_top(void)
struct pq_entry top = merged_iter_pqueue_top(pq);
struct pq_entry e;
- check(!merged_iter_pqueue_remove(&pq, &e));
+ cl_assert_equal_i(merged_iter_pqueue_remove(&pq, &e), 0);
merged_iter_pqueue_check(&pq);
- check(pq_entry_equal(&top, &e));
- check(reftable_record_equal(top.rec, &recs[i], REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(pq_entry_equal(&top, &e) != 0);
+ cl_assert(reftable_record_equal(top.rec, &recs[i], REFTABLE_HASH_SIZE_SHA1) != 0);
for (size_t j = 0; i < pq.len; j++) {
- check(pq_less(&top, &pq.heap[j]));
- check_int(top.index, >, j);
+ cl_assert(pq_less(&top, &pq.heap[j]) != 0);
+ cl_assert(top.index > j);
}
}
merged_iter_pqueue_release(&pq);
}
-
-int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
-{
- TEST(t_pq_record(), "pq works with record-based comparison");
- TEST(t_pq_index(), "pq works with index-based comparison");
- TEST(t_merged_iter_pqueue_top(), "merged_iter_pqueue_top works");
-
- return test_done();
-}
diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/u-reftable-readwrite.c
index 4c49129439..4d8c4be5f1 100644
--- a/t/unit-tests/t-reftable-readwrite.c
+++ b/t/unit-tests/u-reftable-readwrite.c
@@ -8,7 +8,7 @@ https://developers.google.com/open-source/licenses/bsd
#define DISABLE_SIGN_COMPARE_WARNINGS
-#include "test-lib.h"
+#include "unit-test.h"
#include "lib-reftable.h"
#include "reftable/basics.h"
#include "reftable/blocksource.h"
@@ -19,24 +19,24 @@ https://developers.google.com/open-source/licenses/bsd
static const int update_index = 5;
-static void t_buffer(void)
+void test_reftable_readwrite__buffer(void)
{
struct reftable_buf buf = REFTABLE_BUF_INIT;
struct reftable_block_source source = { 0 };
struct reftable_block_data out = { 0 };
int n;
uint8_t in[] = "hello";
- check(!reftable_buf_add(&buf, in, sizeof(in)));
+ cl_assert_equal_i(reftable_buf_add(&buf, in, sizeof(in)), 0);
block_source_from_buf(&source, &buf);
- check_int(block_source_size(&source), ==, 6);
+ cl_assert_equal_i(block_source_size(&source), 6);
n = block_source_read_data(&source, &out, 0, sizeof(in));
- check_int(n, ==, sizeof(in));
- check(!memcmp(in, out.data, n));
+ cl_assert_equal_i(n, sizeof(in));
+ cl_assert(!memcmp(in, out.data, n));
block_source_release_data(&out);
n = block_source_read_data(&source, &out, 1, 2);
- check_int(n, ==, 2);
- check(!memcmp(out.data, "el", 2));
+ cl_assert_equal_i(n, 2);
+ cl_assert(!memcmp(out.data, "el", 2));
block_source_release_data(&out);
block_source_close(&source);
@@ -55,41 +55,41 @@ static void write_table(char ***names, struct reftable_buf *buf, int N,
int i;
REFTABLE_CALLOC_ARRAY(*names, N + 1);
- check(*names != NULL);
+ cl_assert(*names != NULL);
REFTABLE_CALLOC_ARRAY(refs, N);
- check(refs != NULL);
+ cl_assert(refs != NULL);
REFTABLE_CALLOC_ARRAY(logs, N);
- check(logs != NULL);
+ cl_assert(logs != NULL);
for (i = 0; i < N; i++) {
refs[i].refname = (*names)[i] = xstrfmt("refs/heads/branch%02d", i);
refs[i].update_index = update_index;
refs[i].value_type = REFTABLE_REF_VAL1;
- t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(refs[i].value.val1, i,
+ REFTABLE_HASH_SHA1);
}
for (i = 0; i < N; i++) {
logs[i].refname = (*names)[i];
logs[i].update_index = update_index;
logs[i].value_type = REFTABLE_LOG_UPDATE;
- t_reftable_set_hash(logs[i].value.update.new_hash, i,
- REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(logs[i].value.update.new_hash, i,
+ REFTABLE_HASH_SHA1);
logs[i].value.update.message = (char *) "message";
}
- t_reftable_write_to_buf(buf, refs, N, logs, N, &opts);
+ cl_reftable_write_to_buf(buf, refs, N, logs, N, &opts);
reftable_free(refs);
reftable_free(logs);
}
-static void t_log_buffer_size(void)
+void test_reftable_readwrite__log_buffer_size(void)
{
struct reftable_buf buf = REFTABLE_BUF_INIT;
struct reftable_write_options opts = {
.block_size = 4096,
};
- int err;
int i;
struct reftable_log_record
log = { .refname = (char *) "refs/heads/master",
@@ -102,7 +102,8 @@ static void t_log_buffer_size(void)
.time = 0x5e430672,
.message = (char *) "commit: 9\n",
} } };
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf,
+ &opts);
/* This tests buffer extension for log compression. Must use a random
hash, to ensure that the compressed part is larger than the original.
@@ -112,22 +113,19 @@ static void t_log_buffer_size(void)
log.value.update.new_hash[i] = (uint8_t)(git_rand(0) % 256);
}
reftable_writer_set_limits(w, update_index, update_index);
- err = reftable_writer_add_log(w, &log);
- check(!err);
- err = reftable_writer_close(w);
- check(!err);
+ cl_assert_equal_i(reftable_writer_add_log(w, &log), 0);
+ cl_assert_equal_i(reftable_writer_close(w), 0);
reftable_writer_free(w);
reftable_buf_release(&buf);
}
-static void t_log_overflow(void)
+void test_reftable_readwrite__log_overflow(void)
{
struct reftable_buf buf = REFTABLE_BUF_INIT;
char msg[256] = { 0 };
struct reftable_write_options opts = {
.block_size = ARRAY_SIZE(msg),
};
- int err;
struct reftable_log_record log = {
.refname = (char *) "refs/heads/master",
.update_index = update_index,
@@ -144,21 +142,22 @@ static void t_log_overflow(void)
},
},
};
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf,
+ &opts);
memset(msg, 'x', sizeof(msg) - 1);
reftable_writer_set_limits(w, update_index, update_index);
- err = reftable_writer_add_log(w, &log);
- check_int(err, ==, REFTABLE_ENTRY_TOO_BIG_ERROR);
+ cl_assert_equal_i(reftable_writer_add_log(w, &log), REFTABLE_ENTRY_TOO_BIG_ERROR);
reftable_writer_free(w);
reftable_buf_release(&buf);
}
-static void t_log_write_limits(void)
+void test_reftable_readwrite__log_write_limits(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_buf buf = REFTABLE_BUF_INIT;
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf,
+ &opts);
struct reftable_log_record log = {
.refname = (char *)"refs/head/master",
.update_index = 0,
@@ -174,29 +173,25 @@ static void t_log_write_limits(void)
},
},
};
- int err;
reftable_writer_set_limits(w, 1, 1);
/* write with update_index (0) below set limits (1, 1) */
- err = reftable_writer_add_log(w, &log);
- check_int(err, ==, 0);
+ cl_assert_equal_i(reftable_writer_add_log(w, &log), 0);
/* write with update_index (1) in the set limits (1, 1) */
log.update_index = 1;
- err = reftable_writer_add_log(w, &log);
- check_int(err, ==, 0);
+ cl_assert_equal_i(reftable_writer_add_log(w, &log), 0);
/* write with update_index (3) above set limits (1, 1) */
log.update_index = 3;
- err = reftable_writer_add_log(w, &log);
- check_int(err, ==, REFTABLE_API_ERROR);
+ cl_assert_equal_i(reftable_writer_add_log(w, &log), REFTABLE_API_ERROR);
reftable_writer_free(w);
reftable_buf_release(&buf);
}
-static void t_log_write_read(void)
+void test_reftable_readwrite__log_write_read(void)
{
struct reftable_write_options opts = {
.block_size = 256,
@@ -207,13 +202,14 @@ static void t_log_write_read(void)
struct reftable_table *table;
struct reftable_block_source source = { 0 };
struct reftable_buf buf = REFTABLE_BUF_INIT;
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts);
const struct reftable_stats *stats = NULL;
- int N = 2, err, i, n;
+ int N = 2, i;
char **names;
+ int err;
names = reftable_calloc(N + 1, sizeof(*names));
- check(names != NULL);
+ cl_assert(names != NULL);
reftable_writer_set_limits(w, 0, N);
@@ -225,8 +221,7 @@ static void t_log_write_read(void)
ref.refname = name;
ref.update_index = i;
- err = reftable_writer_add_ref(w, &ref);
- check(!err);
+ cl_assert_equal_i(reftable_writer_add_ref(w, &ref), 0);
}
for (i = 0; i < N; i++) {
@@ -235,60 +230,57 @@ static void t_log_write_read(void)
log.refname = names[i];
log.update_index = i;
log.value_type = REFTABLE_LOG_UPDATE;
- t_reftable_set_hash(log.value.update.old_hash, i,
- REFTABLE_HASH_SHA1);
- t_reftable_set_hash(log.value.update.new_hash, i + 1,
- REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(log.value.update.old_hash, i,
+ REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(log.value.update.new_hash, i + 1,
+ REFTABLE_HASH_SHA1);
- err = reftable_writer_add_log(w, &log);
- check(!err);
+ cl_assert_equal_i(reftable_writer_add_log(w, &log), 0);
}
- n = reftable_writer_close(w);
- check_int(n, ==, 0);
+ cl_assert_equal_i(reftable_writer_close(w), 0);
stats = reftable_writer_stats(w);
- check_int(stats->log_stats.blocks, >, 0);
+ cl_assert(stats->log_stats.blocks > 0);
reftable_writer_free(w);
w = NULL;
block_source_from_buf(&source, &buf);
err = reftable_table_new(&table, &source, "file.log");
- check(!err);
+ cl_assert(!err);
err = reftable_table_init_ref_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_ref(&it, names[N - 1]);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_next_ref(&it, &ref);
- check(!err);
+ cl_assert(!err);
/* end of iteration. */
- err = reftable_iterator_next_ref(&it, &ref);
- check_int(err, >, 0);
+ cl_assert(reftable_iterator_next_ref(&it, &ref) > 0);
reftable_iterator_destroy(&it);
reftable_ref_record_release(&ref);
err = reftable_table_init_log_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_log(&it, "");
- check(!err);
+ cl_assert(!err);
for (i = 0; ; i++) {
int err = reftable_iterator_next_log(&it, &log);
if (err > 0)
break;
- check(!err);
- check_str(names[i], log.refname);
- check_int(i, ==, log.update_index);
+ cl_assert(!err);
+ cl_assert_equal_s(names[i], log.refname);
+ cl_assert_equal_i(i, log.update_index);
reftable_log_record_release(&log);
}
- check_int(i, ==, N);
+ cl_assert_equal_i(i, N);
reftable_iterator_destroy(&it);
/* cleanup. */
@@ -297,7 +289,7 @@ static void t_log_write_read(void)
reftable_table_decref(table);
}
-static void t_log_zlib_corruption(void)
+void test_reftable_readwrite__log_zlib_corruption(void)
{
struct reftable_write_options opts = {
.block_size = 256,
@@ -306,10 +298,12 @@ static void t_log_zlib_corruption(void)
struct reftable_table *table;
struct reftable_block_source source = { 0 };
struct reftable_buf buf = REFTABLE_BUF_INIT;
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf,
+ &opts);
const struct reftable_stats *stats = NULL;
char message[100] = { 0 };
- int err, i, n;
+ int i;
+ int err;
struct reftable_log_record log = {
.refname = (char *) "refname",
.value_type = REFTABLE_LOG_UPDATE,
@@ -329,14 +323,11 @@ static void t_log_zlib_corruption(void)
reftable_writer_set_limits(w, 1, 1);
- err = reftable_writer_add_log(w, &log);
- check(!err);
-
- n = reftable_writer_close(w);
- check_int(n, ==, 0);
+ cl_assert_equal_i(reftable_writer_add_log(w, &log), 0);
+ cl_assert_equal_i(reftable_writer_close(w), 0);
stats = reftable_writer_stats(w);
- check_int(stats->log_stats.blocks, >, 0);
+ cl_assert(stats->log_stats.blocks > 0);
reftable_writer_free(w);
w = NULL;
@@ -346,12 +337,12 @@ static void t_log_zlib_corruption(void)
block_source_from_buf(&source, &buf);
err = reftable_table_new(&table, &source, "file.log");
- check(!err);
+ cl_assert(!err);
err = reftable_table_init_log_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_log(&it, "refname");
- check_int(err, ==, REFTABLE_ZLIB_ERROR);
+ cl_assert_equal_i(err, REFTABLE_ZLIB_ERROR);
reftable_iterator_destroy(&it);
@@ -360,7 +351,7 @@ static void t_log_zlib_corruption(void)
reftable_buf_release(&buf);
}
-static void t_table_read_write_sequential(void)
+void test_reftable_readwrite__table_read_write_sequential(void)
{
char **names;
struct reftable_buf buf = REFTABLE_BUF_INIT;
@@ -376,24 +367,24 @@ static void t_table_read_write_sequential(void)
block_source_from_buf(&source, &buf);
err = reftable_table_new(&table, &source, "file.ref");
- check(!err);
+ cl_assert(!err);
err = reftable_table_init_ref_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_ref(&it, "");
- check(!err);
+ cl_assert(!err);
for (j = 0; ; j++) {
struct reftable_ref_record ref = { 0 };
int r = reftable_iterator_next_ref(&it, &ref);
- check_int(r, >=, 0);
+ cl_assert(r >= 0);
if (r > 0)
break;
- check_str(names[j], ref.refname);
- check_int(update_index, ==, ref.update_index);
+ cl_assert_equal_s(names[j], ref.refname);
+ cl_assert_equal_i(update_index, ref.update_index);
reftable_ref_record_release(&ref);
}
- check_int(j, ==, N);
+ cl_assert_equal_i(j, N);
reftable_iterator_destroy(&it);
reftable_table_decref(table);
@@ -401,42 +392,42 @@ static void t_table_read_write_sequential(void)
free_names(names);
}
-static void t_table_write_small_table(void)
+void test_reftable_readwrite__table_write_small_table(void)
{
char **names;
struct reftable_buf buf = REFTABLE_BUF_INIT;
int N = 1;
write_table(&names, &buf, N, 4096, REFTABLE_HASH_SHA1);
- check_int(buf.len, <, 200);
+ cl_assert(buf.len < 200);
reftable_buf_release(&buf);
free_names(names);
}
-static void t_table_read_api(void)
+void test_reftable_readwrite__table_read_api(void)
{
char **names;
struct reftable_buf buf = REFTABLE_BUF_INIT;
int N = 50;
struct reftable_table *table;
struct reftable_block_source source = { 0 };
- int err;
struct reftable_log_record log = { 0 };
struct reftable_iterator it = { 0 };
+ int err;
write_table(&names, &buf, N, 256, REFTABLE_HASH_SHA1);
block_source_from_buf(&source, &buf);
err = reftable_table_new(&table, &source, "file.ref");
- check(!err);
+ cl_assert(!err);
err = reftable_table_init_ref_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_ref(&it, names[0]);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_next_log(&it, &log);
- check_int(err, ==, REFTABLE_API_ERROR);
+ cl_assert_equal_i(err, REFTABLE_API_ERROR);
reftable_buf_release(&buf);
free_names(names);
@@ -464,42 +455,43 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id)
block_source_from_buf(&source, &buf);
err = reftable_table_new(&table, &source, "file.ref");
- check(!err);
- check_int(hash_id, ==, reftable_table_hash_id(table));
+ cl_assert(!err);
+ cl_assert_equal_i(hash_id, reftable_table_hash_id(table));
if (!index) {
table->ref_offsets.index_offset = 0;
} else {
- check_int(table->ref_offsets.index_offset, >, 0);
+ cl_assert(table->ref_offsets.index_offset > 0);
}
for (i = 1; i < N; i++) {
err = reftable_table_init_ref_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_ref(&it, names[i]);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_next_ref(&it, &ref);
- check(!err);
- check_str(names[i], ref.refname);
- check_int(REFTABLE_REF_VAL1, ==, ref.value_type);
- check_int(i, ==, ref.value.val1[0]);
+ cl_assert(!err);
+ cl_assert_equal_s(names[i], ref.refname);
+ cl_assert_equal_i(REFTABLE_REF_VAL1, ref.value_type);
+ cl_assert_equal_i(i, ref.value.val1[0]);
reftable_ref_record_release(&ref);
reftable_iterator_destroy(&it);
}
- check(!reftable_buf_addstr(&pastLast, names[N - 1]));
- check(!reftable_buf_addstr(&pastLast, "/"));
+ cl_assert_equal_i(reftable_buf_addstr(&pastLast, names[N - 1]),
+ 0);
+ cl_assert_equal_i(reftable_buf_addstr(&pastLast, "/"), 0);
err = reftable_table_init_ref_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_ref(&it, pastLast.buf);
if (err == 0) {
struct reftable_ref_record ref = { 0 };
int err = reftable_iterator_next_ref(&it, &ref);
- check_int(err, >, 0);
+ cl_assert(err > 0);
} else {
- check_int(err, >, 0);
+ cl_assert(err > 0);
}
reftable_buf_release(&pastLast);
@@ -510,17 +502,17 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id)
reftable_table_decref(table);
}
-static void t_table_read_write_seek_linear(void)
+void test_reftable_readwrite__table_read_write_seek_linear(void)
{
t_table_read_write_seek(0, REFTABLE_HASH_SHA1);
}
-static void t_table_read_write_seek_linear_sha256(void)
+void test_reftable_readwrite__table_read_write_seek_linear_sha256(void)
{
t_table_read_write_seek(0, REFTABLE_HASH_SHA256);
}
-static void t_table_read_write_seek_index(void)
+void test_reftable_readwrite__table_read_write_seek_index(void)
{
t_table_read_write_seek(1, REFTABLE_HASH_SHA1);
}
@@ -538,14 +530,16 @@ static void t_table_refs_for(int indexed)
struct reftable_table *table;
struct reftable_block_source source = { 0 };
struct reftable_buf buf = REFTABLE_BUF_INIT;
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf,
+ &opts);
struct reftable_iterator it = { 0 };
- int N = 50, n, j, err, i;
+ int N = 50, j, i;
+ int err;
want_names = reftable_calloc(N + 1, sizeof(*want_names));
- check(want_names != NULL);
+ cl_assert(want_names != NULL);
- t_reftable_set_hash(want_hash, 4, REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(want_hash, 4, REFTABLE_HASH_SHA1);
for (i = 0; i < N; i++) {
uint8_t hash[REFTABLE_HASH_SIZE_SHA1];
@@ -561,24 +555,22 @@ static void t_table_refs_for(int indexed)
ref.refname = name;
ref.value_type = REFTABLE_REF_VAL2;
- t_reftable_set_hash(ref.value.val2.value, i / 4,
- REFTABLE_HASH_SHA1);
- t_reftable_set_hash(ref.value.val2.target_value, 3 + i / 4,
- REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(ref.value.val2.value, i / 4,
+ REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(ref.value.val2.target_value,
+ 3 + i / 4, REFTABLE_HASH_SHA1);
/* 80 bytes / entry, so 3 entries per block. Yields 17
*/
/* blocks. */
- n = reftable_writer_add_ref(w, &ref);
- check_int(n, ==, 0);
+ cl_assert_equal_i(reftable_writer_add_ref(w, &ref), 0);
if (!memcmp(ref.value.val2.value, want_hash, REFTABLE_HASH_SIZE_SHA1) ||
!memcmp(ref.value.val2.target_value, want_hash, REFTABLE_HASH_SIZE_SHA1))
want_names[want_names_len++] = xstrdup(name);
}
- n = reftable_writer_close(w);
- check_int(n, ==, 0);
+ cl_assert_equal_i(reftable_writer_close(w), 0);
reftable_writer_free(w);
w = NULL;
@@ -586,29 +578,29 @@ static void t_table_refs_for(int indexed)
block_source_from_buf(&source, &buf);
err = reftable_table_new(&table, &source, "file.ref");
- check(!err);
+ cl_assert(!err);
if (!indexed)
table->obj_offsets.is_present = 0;
err = reftable_table_init_ref_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_ref(&it, "");
- check(!err);
+ cl_assert(!err);
reftable_iterator_destroy(&it);
err = reftable_table_refs_for(table, &it, want_hash);
- check(!err);
+ cl_assert(!err);
for (j = 0; ; j++) {
int err = reftable_iterator_next_ref(&it, &ref);
- check_int(err, >=, 0);
+ cl_assert(err >= 0);
if (err > 0)
break;
- check_int(j, <, want_names_len);
- check_str(ref.refname, want_names[j]);
+ cl_assert(j < want_names_len);
+ cl_assert_equal_s(ref.refname, want_names[j]);
reftable_ref_record_release(&ref);
}
- check_int(j, ==, want_names_len);
+ cl_assert_equal_i(j, want_names_len);
reftable_buf_release(&buf);
free_names(want_names);
@@ -616,21 +608,21 @@ static void t_table_refs_for(int indexed)
reftable_table_decref(table);
}
-static void t_table_refs_for_no_index(void)
+void test_reftable_readwrite__table_refs_for_no_index(void)
{
t_table_refs_for(0);
}
-static void t_table_refs_for_obj_index(void)
+void test_reftable_readwrite__table_refs_for_obj_index(void)
{
t_table_refs_for(1);
}
-static void t_write_empty_table(void)
+void test_reftable_readwrite__write_empty_table(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_buf buf = REFTABLE_BUF_INIT;
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts);
struct reftable_block_source source = { 0 };
struct reftable_table *table = NULL;
struct reftable_ref_record rec = { 0 };
@@ -639,43 +631,41 @@ static void t_write_empty_table(void)
reftable_writer_set_limits(w, 1, 1);
- err = reftable_writer_close(w);
- check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR);
+ cl_assert_equal_i(reftable_writer_close(w), REFTABLE_EMPTY_TABLE_ERROR);
reftable_writer_free(w);
- check_uint(buf.len, ==, header_size(1) + footer_size(1));
+ cl_assert_equal_i(buf.len, header_size(1) + footer_size(1));
block_source_from_buf(&source, &buf);
err = reftable_table_new(&table, &source, "filename");
- check(!err);
+ cl_assert(!err);
err = reftable_table_init_ref_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_ref(&it, "");
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_next_ref(&it, &rec);
- check_int(err, >, 0);
+ cl_assert(err > 0);
reftable_iterator_destroy(&it);
reftable_table_decref(table);
reftable_buf_release(&buf);
}
-static void t_write_object_id_min_length(void)
+void test_reftable_readwrite__write_object_id_min_length(void)
{
struct reftable_write_options opts = {
.block_size = 75,
};
struct reftable_buf buf = REFTABLE_BUF_INIT;
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record ref = {
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
.value.val1 = {42},
};
- int err;
int i;
reftable_writer_set_limits(w, 1, 1);
@@ -686,30 +676,27 @@ static void t_write_object_id_min_length(void)
char name[256];
snprintf(name, sizeof(name), "ref%05d", i);
ref.refname = name;
- err = reftable_writer_add_ref(w, &ref);
- check(!err);
+ cl_assert_equal_i(reftable_writer_add_ref(w, &ref), 0);
}
- err = reftable_writer_close(w);
- check(!err);
- check_int(reftable_writer_stats(w)->object_id_len, ==, 2);
+ cl_assert_equal_i(reftable_writer_close(w), 0);
+ cl_assert_equal_i(reftable_writer_stats(w)->object_id_len, 2);
reftable_writer_free(w);
reftable_buf_release(&buf);
}
-static void t_write_object_id_length(void)
+void test_reftable_readwrite__write_object_id_length(void)
{
struct reftable_write_options opts = {
.block_size = 75,
};
struct reftable_buf buf = REFTABLE_BUF_INIT;
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record ref = {
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
.value.val1 = {42},
};
- int err;
int i;
reftable_writer_set_limits(w, 1, 1);
@@ -721,44 +708,39 @@ static void t_write_object_id_length(void)
snprintf(name, sizeof(name), "ref%05d", i);
ref.refname = name;
ref.value.val1[15] = i;
- err = reftable_writer_add_ref(w, &ref);
- check(!err);
+ cl_assert(reftable_writer_add_ref(w, &ref) == 0);
}
- err = reftable_writer_close(w);
- check(!err);
- check_int(reftable_writer_stats(w)->object_id_len, ==, 16);
+ cl_assert_equal_i(reftable_writer_close(w), 0);
+ cl_assert_equal_i(reftable_writer_stats(w)->object_id_len, 16);
reftable_writer_free(w);
reftable_buf_release(&buf);
}
-static void t_write_empty_key(void)
+void test_reftable_readwrite__write_empty_key(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_buf buf = REFTABLE_BUF_INIT;
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record ref = {
.refname = (char *) "",
.update_index = 1,
.value_type = REFTABLE_REF_DELETION,
};
- int err;
reftable_writer_set_limits(w, 1, 1);
- err = reftable_writer_add_ref(w, &ref);
- check_int(err, ==, REFTABLE_API_ERROR);
-
- err = reftable_writer_close(w);
- check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR);
+ cl_assert_equal_i(reftable_writer_add_ref(w, &ref), REFTABLE_API_ERROR);
+ cl_assert_equal_i(reftable_writer_close(w),
+ REFTABLE_EMPTY_TABLE_ERROR);
reftable_writer_free(w);
reftable_buf_release(&buf);
}
-static void t_write_key_order(void)
+void test_reftable_readwrite__write_key_order(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_buf buf = REFTABLE_BUF_INIT;
- struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
+ struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record refs[2] = {
{
.refname = (char *) "b",
@@ -776,24 +758,21 @@ static void t_write_key_order(void)
},
}
};
- int err;
reftable_writer_set_limits(w, 1, 1);
- err = reftable_writer_add_ref(w, &refs[0]);
- check(!err);
- err = reftable_writer_add_ref(w, &refs[1]);
- check_int(err, ==, REFTABLE_API_ERROR);
+ cl_assert_equal_i(reftable_writer_add_ref(w, &refs[0]), 0);
+ cl_assert_equal_i(reftable_writer_add_ref(w, &refs[1]),
+ REFTABLE_API_ERROR);
refs[0].update_index = 2;
- err = reftable_writer_add_ref(w, &refs[0]);
- check_int(err, ==, REFTABLE_API_ERROR);
+ cl_assert_equal_i(reftable_writer_add_ref(w, &refs[0]), REFTABLE_API_ERROR);
reftable_writer_close(w);
reftable_writer_free(w);
reftable_buf_release(&buf);
}
-static void t_write_multiple_indices(void)
+void test_reftable_readwrite__write_multiple_indices(void)
{
struct reftable_write_options opts = {
.block_size = 100,
@@ -805,9 +784,10 @@ static void t_write_multiple_indices(void)
struct reftable_writer *writer;
struct reftable_table *table;
char buf[128];
- int err, i;
+ int i;
+ int err;
- writer = t_reftable_strbuf_writer(&writer_buf, &opts);
+ writer = cl_reftable_strbuf_writer(&writer_buf, &opts);
reftable_writer_set_limits(writer, 1, 1);
for (i = 0; i < 100; i++) {
struct reftable_ref_record ref = {
@@ -819,8 +799,7 @@ static void t_write_multiple_indices(void)
snprintf(buf, sizeof(buf), "refs/heads/%04d", i);
ref.refname = buf;
- err = reftable_writer_add_ref(writer, &ref);
- check(!err);
+ cl_assert_equal_i(reftable_writer_add_ref(writer, &ref), 0);
}
for (i = 0; i < 100; i++) {
@@ -836,8 +815,7 @@ static void t_write_multiple_indices(void)
snprintf(buf, sizeof(buf), "refs/heads/%04d", i);
log.refname = buf;
- err = reftable_writer_add_log(writer, &log);
- check(!err);
+ cl_assert_equal_i(reftable_writer_add_log(writer, &log), 0);
}
reftable_writer_close(writer);
@@ -847,22 +825,22 @@ static void t_write_multiple_indices(void)
* for each of the block types.
*/
stats = reftable_writer_stats(writer);
- check_int(stats->ref_stats.index_offset, >, 0);
- check_int(stats->obj_stats.index_offset, >, 0);
- check_int(stats->log_stats.index_offset, >, 0);
+ cl_assert(stats->ref_stats.index_offset > 0);
+ cl_assert(stats->obj_stats.index_offset > 0);
+ cl_assert(stats->log_stats.index_offset > 0);
block_source_from_buf(&source, &writer_buf);
err = reftable_table_new(&table, &source, "filename");
- check(!err);
+ cl_assert(!err);
/*
* Seeking the log uses the log index now. In case there is any
* confusion regarding indices we would notice here.
*/
err = reftable_table_init_log_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_log(&it, "");
- check(!err);
+ cl_assert(!err);
reftable_iterator_destroy(&it);
reftable_writer_free(writer);
@@ -870,7 +848,7 @@ static void t_write_multiple_indices(void)
reftable_buf_release(&writer_buf);
}
-static void t_write_multi_level_index(void)
+void test_reftable_readwrite__write_multi_level_index(void)
{
struct reftable_write_options opts = {
.block_size = 100,
@@ -883,7 +861,7 @@ static void t_write_multi_level_index(void)
struct reftable_table *table;
int err;
- writer = t_reftable_strbuf_writer(&writer_buf, &opts);
+ writer = cl_reftable_strbuf_writer(&writer_buf, &opts);
reftable_writer_set_limits(writer, 1, 1);
for (size_t i = 0; i < 200; i++) {
struct reftable_ref_record ref = {
@@ -896,8 +874,7 @@ static void t_write_multi_level_index(void)
snprintf(buf, sizeof(buf), "refs/heads/%03" PRIuMAX, (uintmax_t)i);
ref.refname = buf;
- err = reftable_writer_add_ref(writer, &ref);
- check(!err);
+ cl_assert_equal_i(reftable_writer_add_ref(writer, &ref), 0);
}
reftable_writer_close(writer);
@@ -906,19 +883,19 @@ static void t_write_multi_level_index(void)
* multi-level index.
*/
stats = reftable_writer_stats(writer);
- check_int(stats->ref_stats.max_index_level, ==, 2);
+ cl_assert_equal_i(stats->ref_stats.max_index_level, 2);
block_source_from_buf(&source, &writer_buf);
err = reftable_table_new(&table, &source, "filename");
- check(!err);
+ cl_assert(!err);
/*
* Seeking the last ref should work as expected.
*/
err = reftable_table_init_ref_iterator(table, &it);
- check(!err);
+ cl_assert(!err);
err = reftable_iterator_seek_ref(&it, "refs/heads/199");
- check(!err);
+ cl_assert(!err);
reftable_iterator_destroy(&it);
reftable_writer_free(writer);
@@ -927,7 +904,7 @@ static void t_write_multi_level_index(void)
reftable_buf_release(&buf);
}
-static void t_corrupt_table_empty(void)
+void test_reftable_readwrite__corrupt_table_empty(void)
{
struct reftable_buf buf = REFTABLE_BUF_INIT;
struct reftable_block_source source = { 0 };
@@ -936,50 +913,22 @@ static void t_corrupt_table_empty(void)
block_source_from_buf(&source, &buf);
err = reftable_table_new(&table, &source, "file.log");
- check_int(err, ==, REFTABLE_FORMAT_ERROR);
+ cl_assert_equal_i(err, REFTABLE_FORMAT_ERROR);
}
-static void t_corrupt_table(void)
+void test_reftable_readwrite__corrupt_table(void)
{
uint8_t zeros[1024] = { 0 };
struct reftable_buf buf = REFTABLE_BUF_INIT;
struct reftable_block_source source = { 0 };
struct reftable_table *table;
int err;
- check(!reftable_buf_add(&buf, zeros, sizeof(zeros)));
+
+ cl_assert(!reftable_buf_add(&buf, zeros, sizeof(zeros)));
block_source_from_buf(&source, &buf);
err = reftable_table_new(&table, &source, "file.log");
- check_int(err, ==, REFTABLE_FORMAT_ERROR);
+ cl_assert_equal_i(err, REFTABLE_FORMAT_ERROR);
reftable_buf_release(&buf);
}
-
-int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
-{
- TEST(t_buffer(), "strbuf works as blocksource");
- TEST(t_corrupt_table(), "read-write on corrupted table");
- TEST(t_corrupt_table_empty(), "read-write on an empty table");
- TEST(t_log_buffer_size(), "buffer extension for log compression");
- TEST(t_log_overflow(), "log overflow returns expected error");
- TEST(t_log_write_limits(), "writer limits for writing log records");
- TEST(t_log_write_read(), "read-write on log records");
- TEST(t_log_zlib_corruption(), "reading corrupted log record returns expected error");
- TEST(t_table_read_api(), "read on a table");
- TEST(t_table_read_write_seek_index(), "read-write on a table with index");
- TEST(t_table_read_write_seek_linear(), "read-write on a table without index (SHA1)");
- TEST(t_table_read_write_seek_linear_sha256(), "read-write on a table without index (SHA256)");
- TEST(t_table_read_write_sequential(), "sequential read-write on a table");
- TEST(t_table_refs_for_no_index(), "refs-only table with no index");
- TEST(t_table_refs_for_obj_index(), "refs-only table with index");
- TEST(t_table_write_small_table(), "write_table works");
- TEST(t_write_empty_key(), "write on refs with empty keys");
- TEST(t_write_empty_table(), "read-write on empty tables");
- TEST(t_write_key_order(), "refs must be written in increasing order");
- TEST(t_write_multi_level_index(), "table with multi-level index");
- TEST(t_write_multiple_indices(), "table with indices for multiple block types");
- TEST(t_write_object_id_length(), "prefix compression on writing refs");
- TEST(t_write_object_id_min_length(), "prefix compression on writing refs");
-
- return test_done();
-}
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/u-reftable-record.c
index 553a007664..6c8c0d5374 100644
--- a/t/unit-tests/t-reftable-record.c
+++ b/t/unit-tests/u-reftable-record.c
@@ -6,7 +6,8 @@
https://developers.google.com/open-source/licenses/bsd
*/
-#include "test-lib.h"
+#include "unit-test.h"
+#include "lib-reftable.h"
#include "reftable/basics.h"
#include "reftable/constants.h"
#include "reftable/record.h"
@@ -17,16 +18,17 @@ static void t_copy(struct reftable_record *rec)
uint8_t typ;
typ = reftable_record_type(rec);
- check(!reftable_record_init(&copy, typ));
+ cl_assert_equal_i(reftable_record_init(&copy, typ), 0);
reftable_record_copy_from(&copy, rec, REFTABLE_HASH_SIZE_SHA1);
/* do it twice to catch memory leaks */
reftable_record_copy_from(&copy, rec, REFTABLE_HASH_SIZE_SHA1);
- check(reftable_record_equal(rec, &copy, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(reftable_record_equal(rec, &copy,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_record_release(&copy);
}
-static void t_varint_roundtrip(void)
+void test_reftable_record__varint_roundtrip(void)
{
uint64_t inputs[] = { 0,
1,
@@ -49,16 +51,16 @@ static void t_varint_roundtrip(void)
int n = put_var_int(&out, in);
uint64_t got = 0;
- check_int(n, >, 0);
+ cl_assert(n > 0);
out.len = n;
n = get_var_int(&got, &out);
- check_int(n, >, 0);
+ cl_assert(n > 0);
- check_int(got, ==, in);
+ cl_assert_equal_i(got, in);
}
}
-static void t_varint_overflow(void)
+void test_reftable_record__varint_overflow(void)
{
unsigned char buf[] = {
0xFF, 0xFF, 0xFF, 0xFF,
@@ -70,8 +72,7 @@ static void t_varint_overflow(void)
.len = sizeof(buf),
};
uint64_t value;
- int err = get_var_int(&value, &view);
- check_int(err, ==, -1);
+ cl_assert_equal_i(get_var_int(&value, &view), -1);
}
static void set_hash(uint8_t *h, int j)
@@ -80,7 +81,7 @@ static void set_hash(uint8_t *h, int j)
h[i] = (j >> i) & 0xff;
}
-static void t_reftable_ref_record_comparison(void)
+void test_reftable_record__ref_record_comparison(void)
{
struct reftable_record in[3] = {
{
@@ -102,21 +103,23 @@ static void t_reftable_ref_record_comparison(void)
};
int cmp;
- check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1], &cmp));
- check(!cmp);
+ cl_assert(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1) == 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0);
+ cl_assert(!cmp);
- check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[1], &in[2], &cmp));
- check_int(cmp, >, 0);
+ cl_assert(reftable_record_equal(&in[1], &in[2],
+ REFTABLE_HASH_SIZE_SHA1) == 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0);
+ cl_assert(cmp > 0);
in[1].u.ref.value_type = in[0].u.ref.value_type;
- check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1], &cmp));
- check(!cmp);
+ cl_assert(reftable_record_equal(&in[0], &in[1],
+ REFTABLE_HASH_SIZE_SHA1) != 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0);
+ cl_assert(!cmp);
}
-static void t_reftable_ref_record_compare_name(void)
+void test_reftable_record__ref_record_compare_name(void)
{
struct reftable_ref_record recs[3] = {
{
@@ -130,12 +133,15 @@ static void t_reftable_ref_record_compare_name(void)
},
};
- check_int(reftable_ref_record_compare_name(&recs[0], &recs[1]), <, 0);
- check_int(reftable_ref_record_compare_name(&recs[1], &recs[0]), >, 0);
- check_int(reftable_ref_record_compare_name(&recs[0], &recs[2]), ==, 0);
+ cl_assert(reftable_ref_record_compare_name(&recs[0],
+ &recs[1]) < 0);
+ cl_assert(reftable_ref_record_compare_name(&recs[1],
+ &recs[0]) > 0);
+ cl_assert_equal_i(reftable_ref_record_compare_name(&recs[0],
+ &recs[2]), 0);
}
-static void t_reftable_ref_record_roundtrip(void)
+void test_reftable_record__ref_record_roundtrip(void)
{
struct reftable_buf scratch = REFTABLE_BUF_INIT;
@@ -172,19 +178,21 @@ static void t_reftable_ref_record_roundtrip(void)
t_copy(&in);
- check_int(reftable_record_val_type(&in), ==, i);
- check_int(reftable_record_is_deletion(&in), ==, i == REFTABLE_REF_DELETION);
+ cl_assert_equal_i(reftable_record_val_type(&in), i);
+ cl_assert_equal_i(reftable_record_is_deletion(&in),
+ i == REFTABLE_REF_DELETION);
reftable_record_key(&in, &key);
n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1);
- check_int(n, >, 0);
+ cl_assert(n > 0);
/* decode into a non-zero reftable_record to test for leaks. */
m = reftable_record_decode(&out, key, i, dest, REFTABLE_HASH_SIZE_SHA1, &scratch);
- check_int(n, ==, m);
+ cl_assert_equal_i(n, m);
- check(reftable_ref_record_equal(&in.u.ref, &out.u.ref,
- REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(reftable_ref_record_equal(&in.u.ref,
+ &out.u.ref,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_record_release(&in);
reftable_buf_release(&key);
@@ -194,7 +202,7 @@ static void t_reftable_ref_record_roundtrip(void)
reftable_buf_release(&scratch);
}
-static void t_reftable_log_record_comparison(void)
+void test_reftable_record__log_record_comparison(void)
{
struct reftable_record in[3] = {
{
@@ -215,21 +223,24 @@ static void t_reftable_log_record_comparison(void)
};
int cmp;
- check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[1], &in[2], &cmp));
- check_int(cmp, >, 0);
+ cl_assert_equal_i(reftable_record_equal(&in[0], &in[1],
+ REFTABLE_HASH_SIZE_SHA1), 0);
+ cl_assert_equal_i(reftable_record_equal(&in[1], &in[2],
+ REFTABLE_HASH_SIZE_SHA1), 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0);
+ cl_assert(cmp > 0);
/* comparison should be reversed for equal keys, because
* comparison is now performed on the basis of update indices */
- check(!reftable_record_cmp(&in[0], &in[1], &cmp));
- check_int(cmp, <, 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0);
+ cl_assert(cmp < 0);
in[1].u.log.update_index = in[0].u.log.update_index;
- check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1], &cmp));
+ cl_assert(reftable_record_equal(&in[0], &in[1],
+ REFTABLE_HASH_SIZE_SHA1) != 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0);
}
-static void t_reftable_log_record_compare_key(void)
+void test_reftable_record__log_record_compare_key(void)
{
struct reftable_log_record logs[3] = {
{
@@ -246,19 +257,24 @@ static void t_reftable_log_record_compare_key(void)
},
};
- check_int(reftable_log_record_compare_key(&logs[0], &logs[1]), <, 0);
- check_int(reftable_log_record_compare_key(&logs[1], &logs[0]), >, 0);
+ cl_assert(reftable_log_record_compare_key(&logs[0],
+ &logs[1]) < 0);
+ cl_assert(reftable_log_record_compare_key(&logs[1],
+ &logs[0]) > 0);
logs[1].update_index = logs[0].update_index;
- check_int(reftable_log_record_compare_key(&logs[0], &logs[1]), <, 0);
+ cl_assert(reftable_log_record_compare_key(&logs[0],
+ &logs[1]) < 0);
- check_int(reftable_log_record_compare_key(&logs[0], &logs[2]), >, 0);
- check_int(reftable_log_record_compare_key(&logs[2], &logs[0]), <, 0);
+ cl_assert(reftable_log_record_compare_key(&logs[0],
+ &logs[2]) > 0);
+ cl_assert(reftable_log_record_compare_key(&logs[2],
+ &logs[0]) < 0);
logs[2].update_index = logs[0].update_index;
- check_int(reftable_log_record_compare_key(&logs[0], &logs[2]), ==, 0);
+ cl_assert_equal_i(reftable_log_record_compare_key(&logs[0], &logs[2]), 0);
}
-static void t_reftable_log_record_roundtrip(void)
+void test_reftable_record__log_record_roundtrip(void)
{
struct reftable_log_record in[] = {
{
@@ -292,9 +308,9 @@ static void t_reftable_log_record_roundtrip(void)
set_hash(in[2].value.update.new_hash, 3);
set_hash(in[2].value.update.old_hash, 4);
- check(!reftable_log_record_is_deletion(&in[0]));
- check(reftable_log_record_is_deletion(&in[1]));
- check(!reftable_log_record_is_deletion(&in[2]));
+ cl_assert_equal_i(reftable_log_record_is_deletion(&in[0]), 0);
+ cl_assert(reftable_log_record_is_deletion(&in[1]) != 0);
+ cl_assert_equal_i(reftable_log_record_is_deletion(&in[2]), 0);
for (size_t i = 0; i < ARRAY_SIZE(in); i++) {
struct reftable_record rec = { .type = REFTABLE_BLOCK_TYPE_LOG };
@@ -328,14 +344,14 @@ static void t_reftable_log_record_roundtrip(void)
reftable_record_key(&rec, &key);
n = reftable_record_encode(&rec, dest, REFTABLE_HASH_SIZE_SHA1);
- check_int(n, >=, 0);
+ cl_assert(n >= 0);
valtype = reftable_record_val_type(&rec);
m = reftable_record_decode(&out, key, valtype, dest,
REFTABLE_HASH_SIZE_SHA1, &scratch);
- check_int(n, ==, m);
+ cl_assert_equal_i(n, m);
- check(reftable_log_record_equal(&in[i], &out.u.log,
- REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(reftable_log_record_equal(&in[i], &out.u.log,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_log_record_release(&in[i]);
reftable_buf_release(&key);
reftable_record_release(&out);
@@ -344,7 +360,7 @@ static void t_reftable_log_record_roundtrip(void)
reftable_buf_release(&scratch);
}
-static void t_key_roundtrip(void)
+void test_reftable_record__key_roundtrip(void)
{
uint8_t buffer[1024] = { 0 };
struct string_view dest = {
@@ -359,25 +375,28 @@ static void t_key_roundtrip(void)
int n, m;
uint8_t rt_extra;
- check(!reftable_buf_addstr(&last_key, "refs/heads/master"));
- check(!reftable_buf_addstr(&key, "refs/tags/bla"));
+ cl_assert_equal_i(reftable_buf_addstr(&last_key,
+ "refs/heads/master"), 0);
+ cl_assert_equal_i(reftable_buf_addstr(&key,
+ "refs/tags/bla"), 0);
extra = 6;
n = reftable_encode_key(&restart, dest, last_key, key, extra);
- check(!restart);
- check_int(n, >, 0);
+ cl_assert(!restart);
+ cl_assert(n > 0);
- check(!reftable_buf_addstr(&roundtrip, "refs/heads/master"));
+ cl_assert_equal_i(reftable_buf_addstr(&roundtrip,
+ "refs/heads/master"), 0);
m = reftable_decode_key(&roundtrip, &rt_extra, dest);
- check_int(n, ==, m);
- check(!reftable_buf_cmp(&key, &roundtrip));
- check_int(rt_extra, ==, extra);
+ cl_assert_equal_i(n, m);
+ cl_assert_equal_i(reftable_buf_cmp(&key, &roundtrip), 0);
+ cl_assert_equal_i(rt_extra, extra);
reftable_buf_release(&last_key);
reftable_buf_release(&key);
reftable_buf_release(&roundtrip);
}
-static void t_reftable_obj_record_comparison(void)
+void test_reftable_record__obj_record_comparison(void)
{
uint8_t id_bytes[] = { 0, 1, 2, 3, 4, 5, 6 };
@@ -405,21 +424,23 @@ static void t_reftable_obj_record_comparison(void)
};
int cmp;
- check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1], &cmp));
- check(!cmp);
+ cl_assert_equal_i(reftable_record_equal(&in[0], &in[1],
+ REFTABLE_HASH_SIZE_SHA1), 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0);
+ cl_assert(!cmp);
- check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[1], &in[2], &cmp));
- check_int(cmp, >, 0);
+ cl_assert_equal_i(reftable_record_equal(&in[1], &in[2],
+ REFTABLE_HASH_SIZE_SHA1), 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0);
+ cl_assert(cmp > 0);
in[1].u.obj.offset_len = in[0].u.obj.offset_len;
- check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1], &cmp));
- check(!cmp);
+ cl_assert(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1) != 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0);
+ cl_assert(!cmp);
}
-static void t_reftable_obj_record_roundtrip(void)
+void test_reftable_record__obj_record_roundtrip(void)
{
uint8_t testHash1[REFTABLE_HASH_SIZE_SHA1] = { 1, 2, 3, 4, 0 };
uint64_t till9[] = { 1, 2, 3, 4, 500, 600, 700, 800, 9000 };
@@ -460,17 +481,18 @@ static void t_reftable_obj_record_roundtrip(void)
int n, m;
uint8_t extra;
- check(!reftable_record_is_deletion(&in));
+ cl_assert_equal_i(reftable_record_is_deletion(&in), 0);
t_copy(&in);
reftable_record_key(&in, &key);
n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1);
- check_int(n, >, 0);
+ cl_assert(n > 0);
extra = reftable_record_val_type(&in);
m = reftable_record_decode(&out, key, extra, dest,
REFTABLE_HASH_SIZE_SHA1, &scratch);
- check_int(n, ==, m);
+ cl_assert_equal_i(n, m);
- check(reftable_record_equal(&in, &out, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(reftable_record_equal(&in, &out,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_buf_release(&key);
reftable_record_release(&out);
}
@@ -478,7 +500,7 @@ static void t_reftable_obj_record_roundtrip(void)
reftable_buf_release(&scratch);
}
-static void t_reftable_index_record_comparison(void)
+void test_reftable_record__index_record_comparison(void)
{
struct reftable_record in[3] = {
{
@@ -499,28 +521,33 @@ static void t_reftable_index_record_comparison(void)
};
int cmp;
- check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master"));
- check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master"));
- check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch"));
+ cl_assert_equal_i(reftable_buf_addstr(&in[0].u.idx.last_key,
+ "refs/heads/master"), 0);
+ cl_assert_equal_i(reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master"), 0);
+ cl_assert(reftable_buf_addstr(&in[2].u.idx.last_key,
+ "refs/heads/branch") == 0);
- check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1], &cmp));
- check(!cmp);
+ cl_assert_equal_i(reftable_record_equal(&in[0], &in[1],
+ REFTABLE_HASH_SIZE_SHA1), 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0);
+ cl_assert(!cmp);
- check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[1], &in[2], &cmp));
- check_int(cmp, >, 0);
+ cl_assert_equal_i(reftable_record_equal(&in[1], &in[2],
+ REFTABLE_HASH_SIZE_SHA1), 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0);
+ cl_assert(cmp > 0);
in[1].u.idx.offset = in[0].u.idx.offset;
- check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1));
- check(!reftable_record_cmp(&in[0], &in[1], &cmp));
- check(!cmp);
+ cl_assert(reftable_record_equal(&in[0], &in[1],
+ REFTABLE_HASH_SIZE_SHA1) != 0);
+ cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0);
+ cl_assert(!cmp);
for (size_t i = 0; i < ARRAY_SIZE(in); i++)
reftable_record_release(&in[i]);
}
-static void t_reftable_index_record_roundtrip(void)
+void test_reftable_record__index_record_roundtrip(void)
{
struct reftable_record in = {
.type = REFTABLE_BLOCK_TYPE_INDEX,
@@ -543,43 +570,26 @@ static void t_reftable_index_record_roundtrip(void)
int n, m;
uint8_t extra;
- check(!reftable_buf_addstr(&in.u.idx.last_key, "refs/heads/master"));
+ cl_assert_equal_i(reftable_buf_addstr(&in.u.idx.last_key,
+ "refs/heads/master"), 0);
reftable_record_key(&in, &key);
t_copy(&in);
- check(!reftable_record_is_deletion(&in));
- check(!reftable_buf_cmp(&key, &in.u.idx.last_key));
+ cl_assert_equal_i(reftable_record_is_deletion(&in), 0);
+ cl_assert_equal_i(reftable_buf_cmp(&key, &in.u.idx.last_key), 0);
n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1);
- check_int(n, >, 0);
+ cl_assert(n > 0);
extra = reftable_record_val_type(&in);
- m = reftable_record_decode(&out, key, extra, dest, REFTABLE_HASH_SIZE_SHA1,
- &scratch);
- check_int(m, ==, n);
+ m = reftable_record_decode(&out, key, extra, dest,
+ REFTABLE_HASH_SIZE_SHA1, &scratch);
+ cl_assert_equal_i(m, n);
- check(reftable_record_equal(&in, &out, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(reftable_record_equal(&in, &out,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_record_release(&out);
reftable_buf_release(&key);
reftable_buf_release(&scratch);
reftable_buf_release(&in.u.idx.last_key);
}
-
-int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
-{
- TEST(t_reftable_ref_record_comparison(), "comparison operations work on ref record");
- TEST(t_reftable_log_record_comparison(), "comparison operations work on log record");
- TEST(t_reftable_index_record_comparison(), "comparison operations work on index record");
- TEST(t_reftable_obj_record_comparison(), "comparison operations work on obj record");
- TEST(t_reftable_ref_record_compare_name(), "reftable_ref_record_compare_name works");
- TEST(t_reftable_log_record_compare_key(), "reftable_log_record_compare_key works");
- TEST(t_reftable_log_record_roundtrip(), "record operations work on log record");
- TEST(t_reftable_ref_record_roundtrip(), "record operations work on ref record");
- TEST(t_varint_roundtrip(), "put_var_int and get_var_int work");
- TEST(t_varint_overflow(), "get_var_int notices an integer overflow");
- TEST(t_key_roundtrip(), "reftable_encode_key and reftable_decode_key work");
- TEST(t_reftable_obj_record_roundtrip(), "record operations work on obj record");
- TEST(t_reftable_index_record_roundtrip(), "record operations work on index record");
-
- return test_done();
-}
diff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/u-reftable-stack.c
index 2f49c97519..a8b91812e8 100644
--- a/t/unit-tests/t-reftable-stack.c
+++ b/t/unit-tests/u-reftable-stack.c
@@ -8,9 +8,9 @@ https://developers.google.com/open-source/licenses/bsd
#define DISABLE_SIGN_COMPARE_WARNINGS
-#include "test-lib.h"
-#include "lib-reftable.h"
+#include "unit-test.h"
#include "dir.h"
+#include "lib-reftable.h"
#include "reftable/merged.h"
#include "reftable/reftable-error.h"
#include "reftable/stack.h"
@@ -70,11 +70,11 @@ static char *get_tmp_template(int linenumber)
static char *get_tmp_dir(int linenumber)
{
char *dir = get_tmp_template(linenumber);
- check(mkdtemp(dir) != NULL);
+ cl_assert(mkdtemp(dir) != NULL);
return dir;
}
-static void t_read_file(void)
+void test_reftable_stack__read_file(void)
{
char *fn = get_tmp_template(__LINE__);
struct tempfile *tmp = mks_tempfile(fn);
@@ -84,17 +84,17 @@ static void t_read_file(void)
char **names = NULL;
const char *want[] = { "line1", "line2", "line3" };
- check_int(fd, >, 0);
+ cl_assert(fd > 0);
n = write_in_full(fd, out, strlen(out));
- check_int(n, ==, strlen(out));
+ cl_assert_equal_i(n, strlen(out));
err = close(fd);
- check_int(err, >=, 0);
+ cl_assert(err >= 0);
err = read_lines(fn, &names);
- check(!err);
+ cl_assert(!err);
for (size_t i = 0; names[i]; i++)
- check_str(want[i], names[i]);
+ cl_assert_equal_s(want[i], names[i]);
free_names(names);
(void) remove(fn);
delete_tempfile(&tmp);
@@ -103,8 +103,8 @@ static void t_read_file(void)
static int write_test_ref(struct reftable_writer *wr, void *arg)
{
struct reftable_ref_record *ref = arg;
- check(!reftable_writer_set_limits(wr, ref->update_index,
- ref->update_index));
+ cl_assert_equal_i(reftable_writer_set_limits(wr,
+ ref->update_index, ref->update_index), 0);
return reftable_writer_add_ref(wr, ref);
}
@@ -112,7 +112,6 @@ static void write_n_ref_tables(struct reftable_stack *st,
size_t n)
{
int disable_auto_compact;
- int err;
disable_auto_compact = st->opts.disable_auto_compact;
st->opts.disable_auto_compact = 1;
@@ -126,10 +125,10 @@ static void write_n_ref_tables(struct reftable_stack *st,
snprintf(buf, sizeof(buf), "refs/heads/branch-%04"PRIuMAX, (uintmax_t)i);
ref.refname = buf;
- t_reftable_set_hash(ref.value.val1, i, REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(ref.value.val1, i, REFTABLE_HASH_SHA1);
- err = reftable_stack_add(st, &write_test_ref, &ref);
- check(!err);
+ cl_assert_equal_i(reftable_stack_add(st,
+ &write_test_ref, &ref, 0), 0);
}
st->opts.disable_auto_compact = disable_auto_compact;
@@ -144,12 +143,13 @@ static int write_test_log(struct reftable_writer *wr, void *arg)
{
struct write_log_arg *wla = arg;
- check(!reftable_writer_set_limits(wr, wla->update_index,
- wla->update_index));
+ cl_assert_equal_i(reftable_writer_set_limits(wr,
+ wla->update_index,
+ wla->update_index), 0);
return reftable_writer_add_log(wr, wla->log);
}
-static void t_reftable_stack_add_one(void)
+void test_reftable_stack__add_one(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_buf scratch = REFTABLE_BUF_INIT;
@@ -158,7 +158,6 @@ static void t_reftable_stack_add_one(void)
.default_permissions = 0660,
};
struct reftable_stack *st = NULL;
- int err;
struct reftable_ref_record ref = {
.refname = (char *) "HEAD",
.update_index = 1,
@@ -167,32 +166,37 @@ static void t_reftable_stack_add_one(void)
};
struct reftable_ref_record dest = { 0 };
struct stat stat_result = { 0 };
+ int err;
+
err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert(!err);
- err = reftable_stack_add(st, write_test_ref, &ref);
- check(!err);
+ err = reftable_stack_add(st, write_test_ref, &ref, 0);
+ cl_assert(!err);
err = reftable_stack_read_ref(st, ref.refname, &dest);
- check(!err);
- check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1));
- check_int(st->tables_len, >, 0);
+ cl_assert(!err);
+ cl_assert(reftable_ref_record_equal(&ref, &dest,
+ REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(st->tables_len > 0);
#ifndef GIT_WINDOWS_NATIVE
- check(!reftable_buf_addstr(&scratch, dir));
- check(!reftable_buf_addstr(&scratch, "/tables.list"));
- err = stat(scratch.buf, &stat_result);
- check(!err);
- check_int((stat_result.st_mode & 0777), ==, opts.default_permissions);
+ cl_assert_equal_i(reftable_buf_addstr(&scratch, dir), 0);
+ cl_assert_equal_i(reftable_buf_addstr(&scratch,
+ "/tables.list"), 0);
+ cl_assert_equal_i(stat(scratch.buf, &stat_result), 0);
+ cl_assert_equal_i((stat_result.st_mode & 0777),
+ opts.default_permissions);
reftable_buf_reset(&scratch);
- check(!reftable_buf_addstr(&scratch, dir));
- check(!reftable_buf_addstr(&scratch, "/"));
+ cl_assert_equal_i(reftable_buf_addstr(&scratch, dir), 0);
+ cl_assert_equal_i(reftable_buf_addstr(&scratch, "/"), 0);
/* do not try at home; not an external API for reftable. */
- check(!reftable_buf_addstr(&scratch, st->tables[0]->name));
+ cl_assert(!reftable_buf_addstr(&scratch, st->tables[0]->name));
err = stat(scratch.buf, &stat_result);
- check(!err);
- check_int((stat_result.st_mode & 0777), ==, opts.default_permissions);
+ cl_assert(!err);
+ cl_assert_equal_i((stat_result.st_mode & 0777),
+ opts.default_permissions);
#else
(void) stat_result;
#endif
@@ -204,14 +208,13 @@ static void t_reftable_stack_add_one(void)
umask(mask);
}
-static void t_reftable_stack_uptodate(void)
+void test_reftable_stack__uptodate(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL;
struct reftable_stack *st2 = NULL;
char *dir = get_tmp_dir(__LINE__);
- int err;
struct reftable_ref_record ref1 = {
.refname = (char *) "HEAD",
.update_index = 1,
@@ -229,34 +232,25 @@ static void t_reftable_stack_uptodate(void)
/* simulate multi-process access to the same stack
by creating two stacks for the same directory.
*/
- err = reftable_new_stack(&st1, dir, &opts);
- check(!err);
-
- err = reftable_new_stack(&st2, dir, &opts);
- check(!err);
-
- err = reftable_stack_add(st1, write_test_ref, &ref1);
- check(!err);
-
- err = reftable_stack_add(st2, write_test_ref, &ref2);
- check_int(err, ==, REFTABLE_OUTDATED_ERROR);
-
- err = reftable_stack_reload(st2);
- check(!err);
-
- err = reftable_stack_add(st2, write_test_ref, &ref2);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0);
+ cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0);
+ cl_assert_equal_i(reftable_stack_add(st1, write_test_ref,
+ &ref1, 0), 0);
+ cl_assert_equal_i(reftable_stack_add(st2, write_test_ref,
+ &ref2, 0), REFTABLE_OUTDATED_ERROR);
+ cl_assert_equal_i(reftable_stack_reload(st2), 0);
+ cl_assert_equal_i(reftable_stack_add(st2, write_test_ref,
+ &ref2, 0), 0);
reftable_stack_destroy(st1);
reftable_stack_destroy(st2);
clear_dir(dir);
}
-static void t_reftable_stack_transaction_api(void)
+void test_reftable_stack__transaction_api(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
- int err;
struct reftable_addition *add = NULL;
struct reftable_ref_record ref = {
@@ -267,37 +261,32 @@ static void t_reftable_stack_transaction_api(void)
};
struct reftable_ref_record dest = { 0 };
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
reftable_addition_destroy(add);
- err = reftable_stack_new_addition(&add, st, 0);
- check(!err);
-
- err = reftable_addition_add(add, write_test_ref, &ref);
- check(!err);
-
- err = reftable_addition_commit(add);
- check(!err);
+ cl_assert_equal_i(reftable_stack_new_addition(&add, st, 0), 0);
+ cl_assert_equal_i(reftable_addition_add(add, write_test_ref,
+ &ref), 0);
+ cl_assert_equal_i(reftable_addition_commit(add), 0);
reftable_addition_destroy(add);
- err = reftable_stack_read_ref(st, ref.refname, &dest);
- check(!err);
- check_int(REFTABLE_REF_SYMREF, ==, dest.value_type);
- check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_stack_read_ref(st, ref.refname,
+ &dest), 0);
+ cl_assert_equal_i(REFTABLE_REF_SYMREF, dest.value_type);
+ cl_assert(reftable_ref_record_equal(&ref, &dest,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_ref_record_release(&dest);
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void t_reftable_stack_transaction_with_reload(void)
+void test_reftable_stack__transaction_with_reload(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_stack *st1 = NULL, *st2 = NULL;
- int err;
struct reftable_addition *add = NULL;
struct reftable_ref_record refs[2] = {
{
@@ -315,17 +304,12 @@ static void t_reftable_stack_transaction_with_reload(void)
};
struct reftable_ref_record ref = { 0 };
- err = reftable_new_stack(&st1, dir, NULL);
- check(!err);
- err = reftable_new_stack(&st2, dir, NULL);
- check(!err);
-
- err = reftable_stack_new_addition(&add, st1, 0);
- check(!err);
- err = reftable_addition_add(add, write_test_ref, &refs[0]);
- check(!err);
- err = reftable_addition_commit(add);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st1, dir, NULL), 0);
+ cl_assert_equal_i(reftable_new_stack(&st2, dir, NULL), 0);
+ cl_assert_equal_i(reftable_stack_new_addition(&add, st1, 0), 0);
+ cl_assert_equal_i(reftable_addition_add(add, write_test_ref,
+ &refs[0]), 0);
+ cl_assert_equal_i(reftable_addition_commit(add), 0);
reftable_addition_destroy(add);
/*
@@ -333,20 +317,20 @@ static void t_reftable_stack_transaction_with_reload(void)
* create the addition and lock the stack by default, but allow the
* reload to happen when REFTABLE_STACK_NEW_ADDITION_RELOAD is set.
*/
- err = reftable_stack_new_addition(&add, st2, 0);
- check_int(err, ==, REFTABLE_OUTDATED_ERROR);
- err = reftable_stack_new_addition(&add, st2, REFTABLE_STACK_NEW_ADDITION_RELOAD);
- check(!err);
- err = reftable_addition_add(add, write_test_ref, &refs[1]);
- check(!err);
- err = reftable_addition_commit(add);
- check(!err);
+ cl_assert_equal_i(reftable_stack_new_addition(&add, st2, 0),
+ REFTABLE_OUTDATED_ERROR);
+ cl_assert_equal_i(reftable_stack_new_addition(&add, st2,
+ REFTABLE_STACK_NEW_ADDITION_RELOAD), 0);
+ cl_assert_equal_i(reftable_addition_add(add, write_test_ref,
+ &refs[1]), 0);
+ cl_assert_equal_i(reftable_addition_commit(add), 0);
reftable_addition_destroy(add);
for (size_t i = 0; i < ARRAY_SIZE(refs); i++) {
- err = reftable_stack_read_ref(st2, refs[i].refname, &ref);
- check(!err);
- check(reftable_ref_record_equal(&refs[i], &ref, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_stack_read_ref(st2,
+ refs[i].refname, &ref) , 0);
+ cl_assert(reftable_ref_record_equal(&refs[i], &ref,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
}
reftable_ref_record_release(&ref);
@@ -355,17 +339,15 @@ static void t_reftable_stack_transaction_with_reload(void)
clear_dir(dir);
}
-static void t_reftable_stack_transaction_api_performs_auto_compaction(void)
+void test_reftable_stack__transaction_api_performs_auto_compaction(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = {0};
struct reftable_addition *add = NULL;
struct reftable_stack *st = NULL;
size_t n = 20;
- int err;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
for (size_t i = 0; i <= n; i++) {
struct reftable_ref_record ref = {
@@ -385,14 +367,11 @@ static void t_reftable_stack_transaction_api_performs_auto_compaction(void)
*/
st->opts.disable_auto_compact = i != n;
- err = reftable_stack_new_addition(&add, st, 0);
- check(!err);
-
- err = reftable_addition_add(add, write_test_ref, &ref);
- check(!err);
-
- err = reftable_addition_commit(add);
- check(!err);
+ cl_assert_equal_i(reftable_stack_new_addition(&add,
+ st, 0), 0);
+ cl_assert_equal_i(reftable_addition_add(add,
+ write_test_ref, &ref), 0);
+ cl_assert_equal_i(reftable_addition_commit(add), 0);
reftable_addition_destroy(add);
@@ -402,16 +381,16 @@ static void t_reftable_stack_transaction_api_performs_auto_compaction(void)
* all tables in the stack.
*/
if (i != n)
- check_int(st->merged->tables_len, ==, i + 1);
+ cl_assert_equal_i(st->merged->tables_len, i + 1);
else
- check_int(st->merged->tables_len, ==, 1);
+ cl_assert_equal_i(st->merged->tables_len, 1);
}
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void t_reftable_stack_auto_compaction_fails_gracefully(void)
+void test_reftable_stack__auto_compaction_fails_gracefully(void)
{
struct reftable_ref_record ref = {
.refname = (char *) "refs/heads/master",
@@ -425,32 +404,31 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)
char *dir = get_tmp_dir(__LINE__);
int err;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
-
- err = reftable_stack_add(st, write_test_ref, &ref);
- check(!err);
- check_int(st->merged->tables_len, ==, 1);
- check_int(st->stats.attempts, ==, 0);
- check_int(st->stats.failures, ==, 0);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
+ cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+ &ref, 0), 0);
+ cl_assert_equal_i(st->merged->tables_len, 1);
+ cl_assert_equal_i(st->stats.attempts, 0);
+ cl_assert_equal_i(st->stats.failures, 0);
/*
* Lock the newly written table such that it cannot be compacted.
* Adding a new table to the stack should not be impacted by this, even
* though auto-compaction will now fail.
*/
- check(!reftable_buf_addstr(&table_path, dir));
- check(!reftable_buf_addstr(&table_path, "/"));
- check(!reftable_buf_addstr(&table_path, st->tables[0]->name));
- check(!reftable_buf_addstr(&table_path, ".lock"));
+ cl_assert(!reftable_buf_addstr(&table_path, dir));
+ cl_assert(!reftable_buf_addstr(&table_path, "/"));
+ cl_assert(!reftable_buf_addstr(&table_path,
+ st->tables[0]->name));
+ cl_assert(!reftable_buf_addstr(&table_path, ".lock"));
write_file_buf(table_path.buf, "", 0);
ref.update_index = 2;
- err = reftable_stack_add(st, write_test_ref, &ref);
- check(!err);
- check_int(st->merged->tables_len, ==, 2);
- check_int(st->stats.attempts, ==, 1);
- check_int(st->stats.failures, ==, 1);
+ err = reftable_stack_add(st, write_test_ref, &ref, 0);
+ cl_assert(!err);
+ cl_assert_equal_i(st->merged->tables_len, 2);
+ cl_assert_equal_i(st->stats.attempts, 1);
+ cl_assert_equal_i(st->stats.failures, 1);
reftable_stack_destroy(st);
reftable_buf_release(&table_path);
@@ -462,12 +440,11 @@ static int write_error(struct reftable_writer *wr UNUSED, void *arg)
return *((int *)arg);
}
-static void t_reftable_stack_update_index_check(void)
+void test_reftable_stack__update_index_check(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
- int err;
struct reftable_ref_record ref1 = {
.refname = (char *) "name1",
.update_index = 1,
@@ -481,39 +458,33 @@ static void t_reftable_stack_update_index_check(void)
.value.symref = (char *) "master",
};
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
-
- err = reftable_stack_add(st, write_test_ref, &ref1);
- check(!err);
-
- err = reftable_stack_add(st, write_test_ref, &ref2);
- check_int(err, ==, REFTABLE_API_ERROR);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
+ cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+ &ref1, 0), 0);
+ cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+ &ref2, 0), REFTABLE_API_ERROR);
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void t_reftable_stack_lock_failure(void)
+void test_reftable_stack__lock_failure(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
- int err, i;
+ int i;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
- for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--) {
- err = reftable_stack_add(st, write_error, &i);
- check_int(err, ==, i);
- }
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
+ for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--)
+ cl_assert_equal_i(reftable_stack_add(st, write_error,
+ &i, 0), i);
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void t_reftable_stack_add(void)
+void test_reftable_stack__add(void)
{
- int err = 0;
struct reftable_write_options opts = {
.exact_log_message = 1,
.default_permissions = 0660,
@@ -526,9 +497,10 @@ static void t_reftable_stack_add(void)
struct reftable_buf path = REFTABLE_BUF_INIT;
struct stat stat_result;
size_t i, N = ARRAY_SIZE(refs);
+ int err = 0;
err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert(!err);
for (i = 0; i < N; i++) {
char buf[256];
@@ -536,66 +508,66 @@ static void t_reftable_stack_add(void)
refs[i].refname = xstrdup(buf);
refs[i].update_index = i + 1;
refs[i].value_type = REFTABLE_REF_VAL1;
- t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(refs[i].value.val1, i,
+ REFTABLE_HASH_SHA1);
logs[i].refname = xstrdup(buf);
logs[i].update_index = N + i + 1;
logs[i].value_type = REFTABLE_LOG_UPDATE;
logs[i].value.update.email = xstrdup("identity@invalid");
- t_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(logs[i].value.update.new_hash, i,
+ REFTABLE_HASH_SHA1);
}
- for (i = 0; i < N; i++) {
- int err = reftable_stack_add(st, write_test_ref, &refs[i]);
- check(!err);
- }
+ for (i = 0; i < N; i++)
+ cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+ &refs[i], 0), 0);
for (i = 0; i < N; i++) {
struct write_log_arg arg = {
.log = &logs[i],
.update_index = reftable_stack_next_update_index(st),
};
- int err = reftable_stack_add(st, write_test_log, &arg);
- check(!err);
+ cl_assert_equal_i(reftable_stack_add(st, write_test_log,
+ &arg, 0), 0);
}
- err = reftable_stack_compact_all(st, NULL);
- check(!err);
+ cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0);
for (i = 0; i < N; i++) {
struct reftable_ref_record dest = { 0 };
- int err = reftable_stack_read_ref(st, refs[i].refname, &dest);
- check(!err);
- check(reftable_ref_record_equal(&dest, refs + i,
- REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_stack_read_ref(st,
+ refs[i].refname, &dest), 0);
+ cl_assert(reftable_ref_record_equal(&dest, refs + i,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_ref_record_release(&dest);
}
for (i = 0; i < N; i++) {
struct reftable_log_record dest = { 0 };
- int err = reftable_stack_read_log(st, refs[i].refname, &dest);
- check(!err);
- check(reftable_log_record_equal(&dest, logs + i,
- REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_stack_read_log(st,
+ refs[i].refname, &dest), 0);
+ cl_assert(reftable_log_record_equal(&dest, logs + i,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_log_record_release(&dest);
}
#ifndef GIT_WINDOWS_NATIVE
- check(!reftable_buf_addstr(&path, dir));
- check(!reftable_buf_addstr(&path, "/tables.list"));
- err = stat(path.buf, &stat_result);
- check(!err);
- check_int((stat_result.st_mode & 0777), ==, opts.default_permissions);
+ cl_assert_equal_i(reftable_buf_addstr(&path, dir), 0);
+ cl_assert_equal_i(reftable_buf_addstr(&path, "/tables.list"), 0);
+ cl_assert_equal_i(stat(path.buf, &stat_result), 0);
+ cl_assert_equal_i((stat_result.st_mode & 0777), opts.default_permissions);
reftable_buf_reset(&path);
- check(!reftable_buf_addstr(&path, dir));
- check(!reftable_buf_addstr(&path, "/"));
+ cl_assert_equal_i(reftable_buf_addstr(&path, dir), 0);
+ cl_assert_equal_i(reftable_buf_addstr(&path, "/"), 0);
/* do not try at home; not an external API for reftable. */
- check(!reftable_buf_addstr(&path, st->tables[0]->name));
+ cl_assert(!reftable_buf_addstr(&path, st->tables[0]->name));
err = stat(path.buf, &stat_result);
- check(!err);
- check_int((stat_result.st_mode & 0777), ==, opts.default_permissions);
+ cl_assert(!err);
+ cl_assert_equal_i((stat_result.st_mode & 0777),
+ opts.default_permissions);
#else
(void) stat_result;
#endif
@@ -610,7 +582,7 @@ static void t_reftable_stack_add(void)
clear_dir(dir);
}
-static void t_reftable_stack_iterator(void)
+void test_reftable_stack__iterator(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
@@ -621,27 +593,27 @@ static void t_reftable_stack_iterator(void)
size_t N = ARRAY_SIZE(refs), i;
int err;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
for (i = 0; i < N; i++) {
refs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i);
refs[i].update_index = i + 1;
refs[i].value_type = REFTABLE_REF_VAL1;
- t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(refs[i].value.val1, i,
+ REFTABLE_HASH_SHA1);
logs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i);
logs[i].update_index = i + 1;
logs[i].value_type = REFTABLE_LOG_UPDATE;
logs[i].value.update.email = xstrdup("johndoe@invalid");
logs[i].value.update.message = xstrdup("commit\n");
- t_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(logs[i].value.update.new_hash, i,
+ REFTABLE_HASH_SHA1);
}
- for (i = 0; i < N; i++) {
- err = reftable_stack_add(st, write_test_ref, &refs[i]);
- check(!err);
- }
+ for (i = 0; i < N; i++)
+ cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+ &refs[i], 0), 0);
for (i = 0; i < N; i++) {
struct write_log_arg arg = {
@@ -649,8 +621,8 @@ static void t_reftable_stack_iterator(void)
.update_index = reftable_stack_next_update_index(st),
};
- err = reftable_stack_add(st, write_test_log, &arg);
- check(!err);
+ cl_assert_equal_i(reftable_stack_add(st, write_test_log,
+ &arg, 0), 0);
}
reftable_stack_init_ref_iterator(st, &it);
@@ -661,16 +633,16 @@ static void t_reftable_stack_iterator(void)
err = reftable_iterator_next_ref(&it, &ref);
if (err > 0)
break;
- check(!err);
- check(reftable_ref_record_equal(&ref, &refs[i], REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(!err);
+ cl_assert(reftable_ref_record_equal(&ref, &refs[i],
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_ref_record_release(&ref);
}
- check_int(i, ==, N);
+ cl_assert_equal_i(i, N);
reftable_iterator_destroy(&it);
- err = reftable_stack_init_log_iterator(st, &it);
- check(!err);
+ cl_assert_equal_i(reftable_stack_init_log_iterator(st, &it), 0);
reftable_iterator_seek_log(&it, logs[0].refname);
for (i = 0; ; i++) {
@@ -679,11 +651,12 @@ static void t_reftable_stack_iterator(void)
err = reftable_iterator_next_log(&it, &log);
if (err > 0)
break;
- check(!err);
- check(reftable_log_record_equal(&log, &logs[i], REFTABLE_HASH_SIZE_SHA1));
+ cl_assert(!err);
+ cl_assert(reftable_log_record_equal(&log, &logs[i],
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_log_record_release(&log);
}
- check_int(i, ==, N);
+ cl_assert_equal_i(i, N);
reftable_stack_destroy(st);
reftable_iterator_destroy(&it);
@@ -694,9 +667,8 @@ static void t_reftable_stack_iterator(void)
clear_dir(dir);
}
-static void t_reftable_stack_log_normalize(void)
+void test_reftable_stack__log_normalize(void)
{
- int err = 0;
struct reftable_write_options opts = {
0,
};
@@ -721,28 +693,26 @@ static void t_reftable_stack_log_normalize(void)
.update_index = 1,
};
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
input.value.update.message = (char *) "one\ntwo";
- err = reftable_stack_add(st, write_test_log, &arg);
- check_int(err, ==, REFTABLE_API_ERROR);
+ cl_assert_equal_i(reftable_stack_add(st, write_test_log,
+ &arg, 0), REFTABLE_API_ERROR);
input.value.update.message = (char *) "one";
- err = reftable_stack_add(st, write_test_log, &arg);
- check(!err);
-
- err = reftable_stack_read_log(st, input.refname, &dest);
- check(!err);
- check_str(dest.value.update.message, "one\n");
+ cl_assert_equal_i(reftable_stack_add(st, write_test_log,
+ &arg, 0), 0);
+ cl_assert_equal_i(reftable_stack_read_log(st, input.refname,
+ &dest), 0);
+ cl_assert_equal_s(dest.value.update.message, "one\n");
input.value.update.message = (char *) "two\n";
arg.update_index = 2;
- err = reftable_stack_add(st, write_test_log, &arg);
- check(!err);
- err = reftable_stack_read_log(st, input.refname, &dest);
- check(!err);
- check_str(dest.value.update.message, "two\n");
+ cl_assert_equal_i(reftable_stack_add(st, write_test_log,
+ &arg, 0), 0);
+ cl_assert_equal_i(reftable_stack_read_log(st, input.refname,
+ &dest), 0);
+ cl_assert_equal_s(dest.value.update.message, "two\n");
/* cleanup */
reftable_stack_destroy(st);
@@ -750,20 +720,18 @@ static void t_reftable_stack_log_normalize(void)
clear_dir(dir);
}
-static void t_reftable_stack_tombstone(void)
+void test_reftable_stack__tombstone(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
- int err;
struct reftable_ref_record refs[2] = { 0 };
struct reftable_log_record logs[2] = { 0 };
size_t i, N = ARRAY_SIZE(refs);
struct reftable_ref_record dest = { 0 };
struct reftable_log_record log_dest = { 0 };
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
/* even entries add the refs, odd entries delete them. */
for (i = 0; i < N; i++) {
@@ -772,8 +740,8 @@ static void t_reftable_stack_tombstone(void)
refs[i].update_index = i + 1;
if (i % 2 == 0) {
refs[i].value_type = REFTABLE_REF_VAL1;
- t_reftable_set_hash(refs[i].value.val1, i,
- REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(refs[i].value.val1, i,
+ REFTABLE_HASH_SHA1);
}
logs[i].refname = xstrdup(buf);
@@ -785,42 +753,37 @@ static void t_reftable_stack_tombstone(void)
logs[i].update_index = 1;
if (i % 2 == 0) {
logs[i].value_type = REFTABLE_LOG_UPDATE;
- t_reftable_set_hash(logs[i].value.update.new_hash, i,
- REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1);
logs[i].value.update.email =
xstrdup("identity@invalid");
}
}
- for (i = 0; i < N; i++) {
- int err = reftable_stack_add(st, write_test_ref, &refs[i]);
- check(!err);
- }
+ for (i = 0; i < N; i++)
+ cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+ &refs[i], 0), 0);
for (i = 0; i < N; i++) {
struct write_log_arg arg = {
.log = &logs[i],
.update_index = reftable_stack_next_update_index(st),
};
- int err = reftable_stack_add(st, write_test_log, &arg);
- check(!err);
+ cl_assert_equal_i(reftable_stack_add(st, write_test_log,
+ &arg, 0), 0);
}
- err = reftable_stack_read_ref(st, "branch", &dest);
- check_int(err, ==, 1);
+ cl_assert_equal_i(reftable_stack_read_ref(st, "branch",
+ &dest), 1);
reftable_ref_record_release(&dest);
- err = reftable_stack_read_log(st, "branch", &log_dest);
- check_int(err, ==, 1);
+ cl_assert_equal_i(reftable_stack_read_log(st, "branch",
+ &log_dest), 1);
reftable_log_record_release(&log_dest);
- err = reftable_stack_compact_all(st, NULL);
- check(!err);
-
- err = reftable_stack_read_ref(st, "branch", &dest);
- check_int(err, ==, 1);
-
- err = reftable_stack_read_log(st, "branch", &log_dest);
- check_int(err, ==, 1);
+ cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0);
+ cl_assert_equal_i(reftable_stack_read_ref(st, "branch",
+ &dest), 1);
+ cl_assert_equal_i(reftable_stack_read_log(st, "branch",
+ &log_dest), 1);
reftable_ref_record_release(&dest);
reftable_log_record_release(&log_dest);
@@ -833,12 +796,11 @@ static void t_reftable_stack_tombstone(void)
clear_dir(dir);
}
-static void t_reftable_stack_hash_id(void)
+void test_reftable_stack__hash_id(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
- int err;
struct reftable_ref_record ref = {
.refname = (char *) "master",
@@ -852,62 +814,57 @@ static void t_reftable_stack_hash_id(void)
struct reftable_stack *st_default = NULL;
struct reftable_ref_record dest = { 0 };
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
-
- err = reftable_stack_add(st, write_test_ref, &ref);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
+ cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+ &ref, 0), 0);
/* can't read it with the wrong hash ID. */
- err = reftable_new_stack(&st32, dir, &opts32);
- check_int(err, ==, REFTABLE_FORMAT_ERROR);
+ cl_assert_equal_i(reftable_new_stack(&st32, dir,
+ &opts32), REFTABLE_FORMAT_ERROR);
/* check that we can read it back with default opts too. */
- err = reftable_new_stack(&st_default, dir, &opts_default);
- check(!err);
-
- err = reftable_stack_read_ref(st_default, "master", &dest);
- check(!err);
-
- check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1));
+ cl_assert_equal_i(reftable_new_stack(&st_default, dir,
+ &opts_default), 0);
+ cl_assert_equal_i(reftable_stack_read_ref(st_default, "master",
+ &dest), 0);
+ cl_assert(reftable_ref_record_equal(&ref, &dest,
+ REFTABLE_HASH_SIZE_SHA1) != 0);
reftable_ref_record_release(&dest);
reftable_stack_destroy(st);
reftable_stack_destroy(st_default);
clear_dir(dir);
}
-static void t_suggest_compaction_segment(void)
+void test_reftable_stack__suggest_compaction_segment(void)
{
uint64_t sizes[] = { 512, 64, 17, 16, 9, 9, 9, 16, 2, 16 };
struct segment min =
suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2);
- check_int(min.start, ==, 1);
- check_int(min.end, ==, 10);
+ cl_assert_equal_i(min.start, 1);
+ cl_assert_equal_i(min.end, 10);
}
-static void t_suggest_compaction_segment_nothing(void)
+void test_reftable_stack__suggest_compaction_segment_nothing(void)
{
uint64_t sizes[] = { 64, 32, 16, 8, 4, 2 };
struct segment result =
suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2);
- check_int(result.start, ==, result.end);
+ cl_assert_equal_i(result.start, result.end);
}
-static void t_reflog_expire(void)
+void test_reftable_stack__reflog_expire(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
struct reftable_log_record logs[20] = { 0 };
size_t i, N = ARRAY_SIZE(logs) - 1;
- int err;
struct reftable_log_expiry_config expiry = {
.time = 10,
};
struct reftable_log_record log = { 0 };
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
for (i = 1; i <= N; i++) {
char buf[256];
@@ -918,8 +875,8 @@ static void t_reflog_expire(void)
logs[i].value_type = REFTABLE_LOG_UPDATE;
logs[i].value.update.time = i;
logs[i].value.update.email = xstrdup("identity@invalid");
- t_reftable_set_hash(logs[i].value.update.new_hash, i,
- REFTABLE_HASH_SHA1);
+ cl_reftable_set_hash(logs[i].value.update.new_hash, i,
+ REFTABLE_HASH_SHA1);
}
for (i = 1; i <= N; i++) {
@@ -927,31 +884,23 @@ static void t_reflog_expire(void)
.log = &logs[i],
.update_index = reftable_stack_next_update_index(st),
};
- int err = reftable_stack_add(st, write_test_log, &arg);
- check(!err);
+ cl_assert_equal_i(reftable_stack_add(st, write_test_log,
+ &arg, 0), 0);
}
- err = reftable_stack_compact_all(st, NULL);
- check(!err);
-
- err = reftable_stack_compact_all(st, &expiry);
- check(!err);
-
- err = reftable_stack_read_log(st, logs[9].refname, &log);
- check_int(err, ==, 1);
-
- err = reftable_stack_read_log(st, logs[11].refname, &log);
- check(!err);
+ cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0);
+ cl_assert_equal_i(reftable_stack_compact_all(st, &expiry), 0);
+ cl_assert_equal_i(reftable_stack_read_log(st, logs[9].refname,
+ &log), 1);
+ cl_assert_equal_i(reftable_stack_read_log(st, logs[11].refname,
+ &log), 0);
expiry.min_update_index = 15;
- err = reftable_stack_compact_all(st, &expiry);
- check(!err);
-
- err = reftable_stack_read_log(st, logs[14].refname, &log);
- check_int(err, ==, 1);
-
- err = reftable_stack_read_log(st, logs[16].refname, &log);
- check(!err);
+ cl_assert_equal_i(reftable_stack_compact_all(st, &expiry), 0);
+ cl_assert_equal_i(reftable_stack_read_log(st, logs[14].refname,
+ &log), 1);
+ cl_assert_equal_i(reftable_stack_read_log(st, logs[16].refname,
+ &log), 0);
/* cleanup */
reftable_stack_destroy(st);
@@ -963,26 +912,21 @@ static void t_reflog_expire(void)
static int write_nothing(struct reftable_writer *wr, void *arg UNUSED)
{
- check(!reftable_writer_set_limits(wr, 1, 1));
+ cl_assert_equal_i(reftable_writer_set_limits(wr, 1, 1), 0);
return 0;
}
-static void t_empty_add(void)
+void test_reftable_stack__empty_add(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
- int err;
char *dir = get_tmp_dir(__LINE__);
struct reftable_stack *st2 = NULL;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
-
- err = reftable_stack_add(st, write_nothing, NULL);
- check(!err);
-
- err = reftable_new_stack(&st2, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
+ cl_assert_equal_i(reftable_stack_add(st, write_nothing,
+ NULL, 0), 0);
+ cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0);
clear_dir(dir);
reftable_stack_destroy(st);
reftable_stack_destroy(st2);
@@ -998,18 +942,17 @@ static int fastlogN(uint64_t sz, uint64_t N)
return l - 1;
}
-static void t_reftable_stack_auto_compaction(void)
+void test_reftable_stack__auto_compaction(void)
{
struct reftable_write_options opts = {
.disable_auto_compact = 1,
};
struct reftable_stack *st = NULL;
char *dir = get_tmp_dir(__LINE__);
- int err;
size_t i, N = 100;
+ int err;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
for (i = 0; i < N; i++) {
char name[100];
@@ -1021,33 +964,32 @@ static void t_reftable_stack_auto_compaction(void)
};
snprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i);
- err = reftable_stack_add(st, write_test_ref, &ref);
- check(!err);
+ err = reftable_stack_add(st, write_test_ref, &ref, 0);
+ cl_assert(!err);
err = reftable_stack_auto_compact(st);
- check(!err);
- check(i < 2 || st->merged->tables_len < 2 * fastlogN(i, 2));
+ cl_assert(!err);
+ cl_assert(i < 2 || st->merged->tables_len < 2 * fastlogN(i, 2));
}
- check_int(reftable_stack_compaction_stats(st)->entries_written, <,
- (uint64_t)(N * fastlogN(N, 2)));
+ cl_assert(reftable_stack_compaction_stats(st)->entries_written <
+ (uint64_t)(N * fastlogN(N, 2)));
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void t_reftable_stack_auto_compaction_factor(void)
+void test_reftable_stack__auto_compaction_factor(void)
{
struct reftable_write_options opts = {
.auto_compaction_factor = 5,
};
struct reftable_stack *st = NULL;
char *dir = get_tmp_dir(__LINE__);
- int err;
size_t N = 100;
+ int err;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
for (size_t i = 0; i < N; i++) {
char name[20];
@@ -1058,17 +1000,17 @@ static void t_reftable_stack_auto_compaction_factor(void)
};
xsnprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i);
- err = reftable_stack_add(st, &write_test_ref, &ref);
- check(!err);
+ err = reftable_stack_add(st, &write_test_ref, &ref, 0);
+ cl_assert(!err);
- check(i < 5 || st->merged->tables_len < 5 * fastlogN(i, 5));
+ cl_assert(i < 5 || st->merged->tables_len < 5 * fastlogN(i, 5));
}
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void t_reftable_stack_auto_compaction_with_locked_tables(void)
+void test_reftable_stack__auto_compaction_with_locked_tables(void)
{
struct reftable_write_options opts = {
.disable_auto_compact = 1,
@@ -1078,21 +1020,20 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)
char *dir = get_tmp_dir(__LINE__);
int err;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
write_n_ref_tables(st, 5);
- check_int(st->merged->tables_len, ==, 5);
+ cl_assert_equal_i(st->merged->tables_len, 5);
/*
* Given that all tables we have written should be roughly the same
* size, we expect that auto-compaction will want to compact all of the
* tables. Locking any of the tables will keep it from doing so.
*/
- check(!reftable_buf_addstr(&buf, dir));
- check(!reftable_buf_addstr(&buf, "/"));
- check(!reftable_buf_addstr(&buf, st->tables[2]->name));
- check(!reftable_buf_addstr(&buf, ".lock"));
+ cl_assert(!reftable_buf_addstr(&buf, dir));
+ cl_assert(!reftable_buf_addstr(&buf, "/"));
+ cl_assert(!reftable_buf_addstr(&buf, st->tables[2]->name));
+ cl_assert(!reftable_buf_addstr(&buf, ".lock"));
write_file_buf(buf.buf, "", 0);
/*
@@ -1102,25 +1043,23 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void)
* only compact the newest two tables.
*/
err = reftable_stack_auto_compact(st);
- check(!err);
- check_int(st->stats.failures, ==, 0);
- check_int(st->merged->tables_len, ==, 4);
+ cl_assert(!err);
+ cl_assert_equal_i(st->stats.failures, 0);
+ cl_assert_equal_i(st->merged->tables_len, 4);
reftable_stack_destroy(st);
reftable_buf_release(&buf);
clear_dir(dir);
}
-static void t_reftable_stack_add_performs_auto_compaction(void)
+void test_reftable_stack__add_performs_auto_compaction(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
char *dir = get_tmp_dir(__LINE__);
- int err;
size_t i, n = 20;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
for (i = 0; i <= n; i++) {
struct reftable_ref_record ref = {
@@ -1140,8 +1079,8 @@ static void t_reftable_stack_add_performs_auto_compaction(void)
snprintf(buf, sizeof(buf), "branch-%04"PRIuMAX, (uintmax_t)i);
ref.refname = buf;
- err = reftable_stack_add(st, write_test_ref, &ref);
- check(!err);
+ cl_assert_equal_i(reftable_stack_add(st, write_test_ref,
+ &ref, 0), 0);
/*
* The stack length should grow continuously for all runs where
@@ -1149,16 +1088,16 @@ static void t_reftable_stack_add_performs_auto_compaction(void)
* all tables in the stack.
*/
if (i != n)
- check_int(st->merged->tables_len, ==, i + 1);
+ cl_assert_equal_i(st->merged->tables_len, i + 1);
else
- check_int(st->merged->tables_len, ==, 1);
+ cl_assert_equal_i(st->merged->tables_len, 1);
}
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void t_reftable_stack_compaction_with_locked_tables(void)
+void test_reftable_stack__compaction_with_locked_tables(void)
{
struct reftable_write_options opts = {
.disable_auto_compact = 1,
@@ -1168,17 +1107,16 @@ static void t_reftable_stack_compaction_with_locked_tables(void)
char *dir = get_tmp_dir(__LINE__);
int err;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
write_n_ref_tables(st, 3);
- check_int(st->merged->tables_len, ==, 3);
+ cl_assert_equal_i(st->merged->tables_len, 3);
/* Lock one of the tables that we're about to compact. */
- check(!reftable_buf_addstr(&buf, dir));
- check(!reftable_buf_addstr(&buf, "/"));
- check(!reftable_buf_addstr(&buf, st->tables[1]->name));
- check(!reftable_buf_addstr(&buf, ".lock"));
+ cl_assert(!reftable_buf_addstr(&buf, dir));
+ cl_assert(!reftable_buf_addstr(&buf, "/"));
+ cl_assert(!reftable_buf_addstr(&buf, st->tables[1]->name));
+ cl_assert(!reftable_buf_addstr(&buf, ".lock"));
write_file_buf(buf.buf, "", 0);
/*
@@ -1186,36 +1124,31 @@ static void t_reftable_stack_compaction_with_locked_tables(void)
* compact all tables.
*/
err = reftable_stack_compact_all(st, NULL);
- check_int(err, ==, REFTABLE_LOCK_ERROR);
- check_int(st->stats.failures, ==, 1);
- check_int(st->merged->tables_len, ==, 3);
+ cl_assert_equal_i(err, REFTABLE_LOCK_ERROR);
+ cl_assert_equal_i(st->stats.failures, 1);
+ cl_assert_equal_i(st->merged->tables_len, 3);
reftable_stack_destroy(st);
reftable_buf_release(&buf);
clear_dir(dir);
}
-static void t_reftable_stack_compaction_concurrent(void)
+void test_reftable_stack__compaction_concurrent(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL, *st2 = NULL;
char *dir = get_tmp_dir(__LINE__);
- int err;
- err = reftable_new_stack(&st1, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0);
write_n_ref_tables(st1, 3);
- err = reftable_new_stack(&st2, dir, &opts);
- check(!err);
-
- err = reftable_stack_compact_all(st1, NULL);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0);
+ cl_assert_equal_i(reftable_stack_compact_all(st1, NULL), 0);
reftable_stack_destroy(st1);
reftable_stack_destroy(st2);
- check_int(count_dir_entries(dir), ==, 2);
+ cl_assert_equal_i(count_dir_entries(dir), 2);
clear_dir(dir);
}
@@ -1228,32 +1161,24 @@ static void unclean_stack_close(struct reftable_stack *st)
REFTABLE_FREE_AND_NULL(st->tables);
}
-static void t_reftable_stack_compaction_concurrent_clean(void)
+void test_reftable_stack__compaction_concurrent_clean(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL, *st2 = NULL, *st3 = NULL;
char *dir = get_tmp_dir(__LINE__);
- int err;
- err = reftable_new_stack(&st1, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0);
write_n_ref_tables(st1, 3);
- err = reftable_new_stack(&st2, dir, &opts);
- check(!err);
-
- err = reftable_stack_compact_all(st1, NULL);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0);
+ cl_assert_equal_i(reftable_stack_compact_all(st1, NULL), 0);
unclean_stack_close(st1);
unclean_stack_close(st2);
- err = reftable_new_stack(&st3, dir, &opts);
- check(!err);
-
- err = reftable_stack_clean(st3);
- check(!err);
- check_int(count_dir_entries(dir), ==, 2);
+ cl_assert_equal_i(reftable_new_stack(&st3, dir, &opts), 0);
+ cl_assert_equal_i(reftable_stack_clean(st3), 0);
+ cl_assert_equal_i(count_dir_entries(dir), 2);
reftable_stack_destroy(st1);
reftable_stack_destroy(st2);
@@ -1262,7 +1187,7 @@ static void t_reftable_stack_compaction_concurrent_clean(void)
clear_dir(dir);
}
-static void t_reftable_stack_read_across_reload(void)
+void test_reftable_stack__read_across_reload(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL, *st2 = NULL;
@@ -1272,37 +1197,35 @@ static void t_reftable_stack_read_across_reload(void)
int err;
/* Create a first stack and set up an iterator for it. */
- err = reftable_new_stack(&st1, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0);
write_n_ref_tables(st1, 2);
- check_int(st1->merged->tables_len, ==, 2);
+ cl_assert_equal_i(st1->merged->tables_len, 2);
reftable_stack_init_ref_iterator(st1, &it);
- err = reftable_iterator_seek_ref(&it, "");
- check(!err);
+ cl_assert_equal_i(reftable_iterator_seek_ref(&it, ""), 0);
/* Set up a second stack for the same directory and compact it. */
err = reftable_new_stack(&st2, dir, &opts);
- check(!err);
- check_int(st2->merged->tables_len, ==, 2);
+ cl_assert(!err);
+ cl_assert_equal_i(st2->merged->tables_len, 2);
err = reftable_stack_compact_all(st2, NULL);
- check(!err);
- check_int(st2->merged->tables_len, ==, 1);
+ cl_assert(!err);
+ cl_assert_equal_i(st2->merged->tables_len, 1);
/*
* Verify that we can continue to use the old iterator even after we
* have reloaded its stack.
*/
err = reftable_stack_reload(st1);
- check(!err);
- check_int(st1->merged->tables_len, ==, 1);
+ cl_assert(!err);
+ cl_assert_equal_i(st1->merged->tables_len, 1);
err = reftable_iterator_next_ref(&it, &rec);
- check(!err);
- check_str(rec.refname, "refs/heads/branch-0000");
+ cl_assert(!err);
+ cl_assert_equal_s(rec.refname, "refs/heads/branch-0000");
err = reftable_iterator_next_ref(&it, &rec);
- check(!err);
- check_str(rec.refname, "refs/heads/branch-0001");
+ cl_assert(!err);
+ cl_assert_equal_s(rec.refname, "refs/heads/branch-0001");
err = reftable_iterator_next_ref(&it, &rec);
- check_int(err, >, 0);
+ cl_assert(err > 0);
reftable_ref_record_release(&rec);
reftable_iterator_destroy(&it);
@@ -1311,7 +1234,7 @@ static void t_reftable_stack_read_across_reload(void)
clear_dir(dir);
}
-static void t_reftable_stack_reload_with_missing_table(void)
+void test_reftable_stack__reload_with_missing_table(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
@@ -1322,46 +1245,40 @@ static void t_reftable_stack_reload_with_missing_table(void)
int err;
/* Create a first stack and set up an iterator for it. */
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
write_n_ref_tables(st, 2);
- check_int(st->merged->tables_len, ==, 2);
+ cl_assert_equal_i(st->merged->tables_len, 2);
reftable_stack_init_ref_iterator(st, &it);
- err = reftable_iterator_seek_ref(&it, "");
- check(!err);
+ cl_assert_equal_i(reftable_iterator_seek_ref(&it, ""), 0);
/*
* Update the tables.list file with some garbage data, while reusing
* our old tables. This should trigger a partial reload of the stack,
* where we try to reuse our old tables.
*/
- check(!reftable_buf_addstr(&content, st->tables[0]->name));
- check(!reftable_buf_addstr(&content, "\n"));
- check(!reftable_buf_addstr(&content, st->tables[1]->name));
- check(!reftable_buf_addstr(&content, "\n"));
- check(!reftable_buf_addstr(&content, "garbage\n"));
- check(!reftable_buf_addstr(&table_path, st->list_file));
- check(!reftable_buf_addstr(&table_path, ".lock"));
+ cl_assert(!reftable_buf_addstr(&content, st->tables[0]->name));
+ cl_assert(!reftable_buf_addstr(&content, "\n"));
+ cl_assert(!reftable_buf_addstr(&content, st->tables[1]->name));
+ cl_assert(!reftable_buf_addstr(&content, "\n"));
+ cl_assert(!reftable_buf_addstr(&content, "garbage\n"));
+ cl_assert(!reftable_buf_addstr(&table_path, st->list_file));
+ cl_assert(!reftable_buf_addstr(&table_path, ".lock"));
write_file_buf(table_path.buf, content.buf, content.len);
- err = rename(table_path.buf, st->list_file);
- check(!err);
+ cl_assert_equal_i(rename(table_path.buf, st->list_file), 0);
err = reftable_stack_reload(st);
- check_int(err, ==, -4);
- check_int(st->merged->tables_len, ==, 2);
+ cl_assert_equal_i(err, -4);
+ cl_assert_equal_i(st->merged->tables_len, 2);
/*
* Even though the reload has failed, we should be able to continue
* using the iterator.
*/
- err = reftable_iterator_next_ref(&it, &rec);
- check(!err);
- check_str(rec.refname, "refs/heads/branch-0000");
- err = reftable_iterator_next_ref(&it, &rec);
- check(!err);
- check_str(rec.refname, "refs/heads/branch-0001");
- err = reftable_iterator_next_ref(&it, &rec);
- check_int(err, >, 0);
+ cl_assert_equal_i(reftable_iterator_next_ref(&it, &rec), 0);
+ cl_assert_equal_s(rec.refname, "refs/heads/branch-0000");
+ cl_assert_equal_i(reftable_iterator_next_ref(&it, &rec), 0);
+ cl_assert_equal_s(rec.refname, "refs/heads/branch-0001");
+ cl_assert(reftable_iterator_next_ref(&it, &rec) > 0);
reftable_ref_record_release(&rec);
reftable_iterator_destroy(&it);
@@ -1374,12 +1291,13 @@ static void t_reftable_stack_reload_with_missing_table(void)
static int write_limits_after_ref(struct reftable_writer *wr, void *arg)
{
struct reftable_ref_record *ref = arg;
- check(!reftable_writer_set_limits(wr, ref->update_index, ref->update_index));
- check(!reftable_writer_add_ref(wr, ref));
+ cl_assert_equal_i(reftable_writer_set_limits(wr,
+ ref->update_index, ref->update_index), 0);
+ cl_assert_equal_i(reftable_writer_add_ref(wr, ref), 0);
return reftable_writer_set_limits(wr, ref->update_index, ref->update_index);
}
-static void t_reftable_invalid_limit_updates(void)
+void test_reftable_stack__invalid_limit_updates(void)
{
struct reftable_ref_record ref = {
.refname = (char *) "HEAD",
@@ -1393,59 +1311,22 @@ static void t_reftable_invalid_limit_updates(void)
struct reftable_addition *add = NULL;
char *dir = get_tmp_dir(__LINE__);
struct reftable_stack *st = NULL;
- int err;
- err = reftable_new_stack(&st, dir, &opts);
- check(!err);
+ cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0);
reftable_addition_destroy(add);
- err = reftable_stack_new_addition(&add, st, 0);
- check(!err);
+ cl_assert_equal_i(reftable_stack_new_addition(&add, st, 0), 0);
/*
* write_limits_after_ref also updates the update indexes after adding
* the record. This should cause an err to be returned, since the limits
* must be set at the start.
*/
- err = reftable_addition_add(add, write_limits_after_ref, &ref);
- check_int(err, ==, REFTABLE_API_ERROR);
+ cl_assert_equal_i(reftable_addition_add(add,
+ write_limits_after_ref, &ref), REFTABLE_API_ERROR);
reftable_addition_destroy(add);
reftable_stack_destroy(st);
clear_dir(dir);
}
-
-int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
-{
- TEST(t_empty_add(), "empty addition to stack");
- TEST(t_read_file(), "read_lines works");
- TEST(t_reflog_expire(), "expire reflog entries");
- TEST(t_reftable_invalid_limit_updates(), "prevent limit updates after adding records");
- TEST(t_reftable_stack_add(), "add multiple refs and logs to stack");
- TEST(t_reftable_stack_add_one(), "add a single ref record to stack");
- TEST(t_reftable_stack_add_performs_auto_compaction(), "addition to stack triggers auto-compaction");
- TEST(t_reftable_stack_auto_compaction(), "stack must form geometric sequence after compaction");
- TEST(t_reftable_stack_auto_compaction_factor(), "auto-compaction with non-default geometric factor");
- TEST(t_reftable_stack_auto_compaction_fails_gracefully(), "failure on auto-compaction");
- TEST(t_reftable_stack_auto_compaction_with_locked_tables(), "auto compaction with locked tables");
- TEST(t_reftable_stack_compaction_concurrent(), "compaction with concurrent stack");
- TEST(t_reftable_stack_compaction_concurrent_clean(), "compaction with unclean stack shutdown");
- TEST(t_reftable_stack_compaction_with_locked_tables(), "compaction with locked tables");
- TEST(t_reftable_stack_hash_id(), "read stack with wrong hash ID");
- TEST(t_reftable_stack_iterator(), "log and ref iterator for reftable stack");
- TEST(t_reftable_stack_lock_failure(), "stack addition with lockfile failure");
- TEST(t_reftable_stack_log_normalize(), "log messages should be normalized");
- TEST(t_reftable_stack_read_across_reload(), "stack iterators work across reloads");
- TEST(t_reftable_stack_reload_with_missing_table(), "stack iteration with garbage tables");
- TEST(t_reftable_stack_tombstone(), "'tombstone' refs in stack");
- TEST(t_reftable_stack_transaction_api(), "update transaction to stack");
- TEST(t_reftable_stack_transaction_with_reload(), "transaction with reload");
- TEST(t_reftable_stack_transaction_api_performs_auto_compaction(), "update transaction triggers auto-compaction");
- TEST(t_reftable_stack_update_index_check(), "update transactions with equal update indices");
- TEST(t_reftable_stack_uptodate(), "stack must be reloaded before ref update");
- TEST(t_suggest_compaction_segment(), "suggest_compaction_segment with basic input");
- TEST(t_suggest_compaction_segment_nothing(), "suggest_compaction_segment with pre-compacted input");
-
- return test_done();
-}
diff --git a/t/unit-tests/t-reftable-table.c b/t/unit-tests/u-reftable-table.c
index 7e1eb533d0..14fae8b199 100644
--- a/t/unit-tests/t-reftable-table.c
+++ b/t/unit-tests/u-reftable-table.c
@@ -1,4 +1,4 @@
-#include "test-lib.h"
+#include "unit-test.h"
#include "lib-reftable.h"
#include "reftable/blocksource.h"
#include "reftable/constants.h"
@@ -6,7 +6,7 @@
#include "reftable/table.h"
#include "strbuf.h"
-static int t_table_seek_once(void)
+void test_reftable_table__seek_once(void)
{
struct reftable_ref_record records[] = {
{
@@ -22,32 +22,32 @@ static int t_table_seek_once(void)
struct reftable_buf buf = REFTABLE_BUF_INIT;
int ret;
- t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);
+ cl_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);
block_source_from_buf(&source, &buf);
ret = reftable_table_new(&table, &source, "name");
- check(!ret);
+ cl_assert(!ret);
reftable_table_init_ref_iterator(table, &it);
ret = reftable_iterator_seek_ref(&it, "");
- check(!ret);
+ cl_assert(!ret);
ret = reftable_iterator_next_ref(&it, &ref);
- check(!ret);
+ cl_assert(!ret);
- ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1);
- check_int(ret, ==, 1);
+ ret = reftable_ref_record_equal(&ref, &records[0],
+ REFTABLE_HASH_SIZE_SHA1);
+ cl_assert_equal_i(ret, 1);
ret = reftable_iterator_next_ref(&it, &ref);
- check_int(ret, ==, 1);
+ cl_assert_equal_i(ret, 1);
reftable_ref_record_release(&ref);
reftable_iterator_destroy(&it);
reftable_table_decref(table);
reftable_buf_release(&buf);
- return 0;
}
-static int t_table_reseek(void)
+void test_reftable_table__reseek(void)
{
struct reftable_ref_record records[] = {
{
@@ -63,35 +63,35 @@ static int t_table_reseek(void)
struct reftable_buf buf = REFTABLE_BUF_INIT;
int ret;
- t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);
+ cl_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records),
+ NULL, 0, NULL);
block_source_from_buf(&source, &buf);
ret = reftable_table_new(&table, &source, "name");
- check(!ret);
+ cl_assert(!ret);
reftable_table_init_ref_iterator(table, &it);
for (size_t i = 0; i < 5; i++) {
ret = reftable_iterator_seek_ref(&it, "");
- check(!ret);
+ cl_assert(!ret);
ret = reftable_iterator_next_ref(&it, &ref);
- check(!ret);
+ cl_assert(!ret);
ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1);
- check_int(ret, ==, 1);
+ cl_assert_equal_i(ret, 1);
ret = reftable_iterator_next_ref(&it, &ref);
- check_int(ret, ==, 1);
+ cl_assert_equal_i(ret, 1);
}
reftable_ref_record_release(&ref);
reftable_iterator_destroy(&it);
reftable_table_decref(table);
reftable_buf_release(&buf);
- return 0;
}
-static int t_table_block_iterator(void)
+void test_reftable_table__block_iterator(void)
{
struct reftable_block_source source = { 0 };
struct reftable_table_iterator it = { 0 };
@@ -147,14 +147,14 @@ static int t_table_block_iterator(void)
(uintmax_t) i);
}
- t_reftable_write_to_buf(&buf, records, nrecords, NULL, 0, NULL);
+ cl_reftable_write_to_buf(&buf, records, nrecords, NULL, 0, NULL);
block_source_from_buf(&source, &buf);
ret = reftable_table_new(&table, &source, "name");
- check(!ret);
+ cl_assert(!ret);
ret = reftable_table_iterator_init(&it, table);
- check(!ret);
+ cl_assert(!ret);
for (size_t i = 0; i < ARRAY_SIZE(expected_blocks); i++) {
struct reftable_iterator record_it = { 0 };
@@ -163,22 +163,26 @@ static int t_table_block_iterator(void)
};
ret = reftable_table_iterator_next(&it, &block);
- check(!ret);
+ cl_assert(!ret);
- check_int(block->block_type, ==, expected_blocks[i].block_type);
- check_int(block->header_off, ==, expected_blocks[i].header_off);
- check_int(block->restart_count, ==, expected_blocks[i].restart_count);
+ cl_assert_equal_i(block->block_type,
+ expected_blocks[i].block_type);
+ cl_assert_equal_i(block->header_off,
+ expected_blocks[i].header_off);
+ cl_assert_equal_i(block->restart_count,
+ expected_blocks[i].restart_count);
ret = reftable_block_init_iterator(block, &record_it);
- check(!ret);
+ cl_assert(!ret);
for (size_t j = 0; ; j++) {
ret = iterator_next(&record_it, &record);
if (ret > 0) {
- check_int(j, ==, expected_blocks[i].record_count);
+ cl_assert_equal_i(j,
+ expected_blocks[i].record_count);
break;
}
- check(!ret);
+ cl_assert(!ret);
}
reftable_iterator_destroy(&record_it);
@@ -186,7 +190,7 @@ static int t_table_block_iterator(void)
}
ret = reftable_table_iterator_next(&it, &block);
- check_int(ret, ==, 1);
+ cl_assert_equal_i(ret, 1);
for (size_t i = 0; i < nrecords; i++)
reftable_free(records[i].refname);
@@ -194,13 +198,4 @@ static int t_table_block_iterator(void)
reftable_table_decref(table);
reftable_buf_release(&buf);
reftable_free(records);
- return 0;
-}
-
-int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
-{
- TEST(t_table_seek_once(), "table can seek once");
- TEST(t_table_reseek(), "table can reseek multiple times");
- TEST(t_table_block_iterator(), "table can iterate through blocks");
- return test_done();
}
diff --git a/t/unit-tests/u-string-list.c b/t/unit-tests/u-string-list.c
new file mode 100644
index 0000000000..a2457d7b1e
--- /dev/null
+++ b/t/unit-tests/u-string-list.c
@@ -0,0 +1,306 @@
+#include "unit-test.h"
+#include "string-list.h"
+
+static void t_vcreate_string_list_dup(struct string_list *list,
+ int free_util, va_list ap)
+{
+ const char *arg;
+
+ cl_assert(list->strdup_strings);
+
+ string_list_clear(list, free_util);
+ while ((arg = va_arg(ap, const char *)))
+ string_list_append(list, arg);
+}
+
+static void t_create_string_list_dup(struct string_list *list, int free_util, ...)
+{
+ va_list ap;
+
+ cl_assert(list->strdup_strings);
+
+ string_list_clear(list, free_util);
+ va_start(ap, free_util);
+ t_vcreate_string_list_dup(list, free_util, ap);
+ va_end(ap);
+}
+
+static void t_string_list_clear(struct string_list *list, int free_util)
+{
+ string_list_clear(list, free_util);
+ cl_assert_equal_p(list->items, NULL);
+ cl_assert_equal_i(list->nr, 0);
+ cl_assert_equal_i(list->alloc, 0);
+}
+
+static void t_string_list_equal(struct string_list *list,
+ struct string_list *expected_strings)
+{
+ cl_assert_equal_i(list->nr, expected_strings->nr);
+ cl_assert(list->nr <= list->alloc);
+ for (size_t i = 0; i < expected_strings->nr; i++)
+ cl_assert_equal_s(list->items[i].string,
+ expected_strings->items[i].string);
+}
+
+static void t_string_list_split(const char *data, const char *delim, int maxsplit, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
+ struct string_list list = STRING_LIST_INIT_DUP;
+ va_list ap;
+ int len;
+
+ va_start(ap, maxsplit);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
+ string_list_clear(&list, 0);
+ len = string_list_split(&list, data, delim, maxsplit);
+ cl_assert_equal_i(len, expected_strings.nr);
+ t_string_list_equal(&list, &expected_strings);
+
+ string_list_clear(&expected_strings, 0);
+ string_list_clear(&list, 0);
+}
+
+static void t_string_list_split_f(const char *data, const char *delim,
+ int maxsplit, unsigned flags, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
+ struct string_list list = STRING_LIST_INIT_DUP;
+ va_list ap;
+ int len;
+
+ va_start(ap, flags);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
+ string_list_clear(&list, 0);
+ len = string_list_split_f(&list, data, delim, maxsplit, flags);
+ cl_assert_equal_i(len, expected_strings.nr);
+ t_string_list_equal(&list, &expected_strings);
+
+ string_list_clear(&expected_strings, 0);
+ string_list_clear(&list, 0);
+}
+
+void test_string_list__split_f(void)
+{
+ t_string_list_split_f("::foo:bar:baz:", ":", -1, 0,
+ "", "", "foo", "bar", "baz", "", NULL);
+ t_string_list_split_f(" foo:bar : baz", ":", -1, STRING_LIST_SPLIT_TRIM,
+ "foo", "bar", "baz", NULL);
+ t_string_list_split_f(" a b c ", " ", 1, STRING_LIST_SPLIT_TRIM,
+ "a", "b c", NULL);
+ t_string_list_split_f("::foo::bar:baz:", ":", -1, STRING_LIST_SPLIT_NONEMPTY,
+ "foo", "bar", "baz", NULL);
+ t_string_list_split_f("foo:baz", ":", -1, STRING_LIST_SPLIT_NONEMPTY,
+ "foo", "baz", NULL);
+ t_string_list_split_f("foo :: : baz", ":", -1,
+ STRING_LIST_SPLIT_NONEMPTY | STRING_LIST_SPLIT_TRIM,
+ "foo", "baz", NULL);
+}
+
+static void t_string_list_split_in_place_f(const char *data_, const char *delim,
+ int maxsplit, unsigned flags, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
+ struct string_list list = STRING_LIST_INIT_NODUP;
+ char *data = xstrdup(data_);
+ va_list ap;
+ int len;
+
+ va_start(ap, flags);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
+ string_list_clear(&list, 0);
+ len = string_list_split_in_place_f(&list, data, delim, maxsplit, flags);
+ cl_assert_equal_i(len, expected_strings.nr);
+ t_string_list_equal(&list, &expected_strings);
+
+ free(data);
+ string_list_clear(&expected_strings, 0);
+ string_list_clear(&list, 0);
+}
+
+void test_string_list__split_in_place_f(void)
+{
+ t_string_list_split_in_place_f("::foo:bar:baz:", ":", -1, 0,
+ "", "", "foo", "bar", "baz", "", NULL);
+ t_string_list_split_in_place_f(" foo:bar : baz", ":", -1, STRING_LIST_SPLIT_TRIM,
+ "foo", "bar", "baz", NULL);
+ t_string_list_split_in_place_f(" a b c ", " ", 1, STRING_LIST_SPLIT_TRIM,
+ "a", "b c", NULL);
+ t_string_list_split_in_place_f("::foo::bar:baz:", ":", -1,
+ STRING_LIST_SPLIT_NONEMPTY,
+ "foo", "bar", "baz", NULL);
+ t_string_list_split_in_place_f("foo:baz", ":", -1, STRING_LIST_SPLIT_NONEMPTY,
+ "foo", "baz", NULL);
+ t_string_list_split_in_place_f("foo :: : baz", ":", -1,
+ STRING_LIST_SPLIT_NONEMPTY | STRING_LIST_SPLIT_TRIM,
+ "foo", "baz", NULL);
+}
+
+void test_string_list__split(void)
+{
+ t_string_list_split("foo:bar:baz", ":", -1, "foo", "bar", "baz", NULL);
+ t_string_list_split("foo:bar:baz", ":", 0, "foo:bar:baz", NULL);
+ t_string_list_split("foo:bar:baz", ":", 1, "foo", "bar:baz", NULL);
+ t_string_list_split("foo:bar:baz", ":", 2, "foo", "bar", "baz", NULL);
+ t_string_list_split("foo:bar:", ":", -1, "foo", "bar", "", NULL);
+ t_string_list_split("", ":", -1, "", NULL);
+ t_string_list_split(":", ":", -1, "", "", NULL);
+}
+
+static void t_string_list_split_in_place(const char *data, const char *delim,
+ int maxsplit, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
+ struct string_list list = STRING_LIST_INIT_NODUP;
+ char *string = xstrdup(data);
+ va_list ap;
+ int len;
+
+ va_start(ap, maxsplit);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
+ string_list_clear(&list, 0);
+ len = string_list_split_in_place(&list, string, delim, maxsplit);
+ cl_assert_equal_i(len, expected_strings.nr);
+ t_string_list_equal(&list, &expected_strings);
+
+ free(string);
+ string_list_clear(&expected_strings, 0);
+ string_list_clear(&list, 0);
+}
+
+void test_string_list__split_in_place(void)
+{
+ t_string_list_split_in_place("foo:;:bar:;:baz:;:", ":;", -1,
+ "foo", "", "", "bar", "", "", "baz", "", "", "", NULL);
+ t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 0,
+ "foo:;:bar:;:baz", NULL);
+ t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 1,
+ "foo", ";:bar:;:baz", NULL);
+ t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 2,
+ "foo", "", ":bar:;:baz", NULL);
+ t_string_list_split_in_place("foo:;:bar:;:", ":;", -1,
+ "foo", "", "", "bar", "", "", "", NULL);
+}
+
+static int prefix_cb(struct string_list_item *item, void *cb_data)
+{
+ const char *prefix = (const char *)cb_data;
+ return starts_with(item->string, prefix);
+}
+
+static void t_string_list_filter(struct string_list *list, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
+ const char *prefix = "y";
+ va_list ap;
+
+ va_start(ap, list);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
+ filter_string_list(list, 0, prefix_cb, (void *)prefix);
+ t_string_list_equal(list, &expected_strings);
+
+ string_list_clear(&expected_strings, 0);
+}
+
+void test_string_list__filter(void)
+{
+ struct string_list list = STRING_LIST_INIT_DUP;
+
+ t_create_string_list_dup(&list, 0, NULL);
+ t_string_list_filter(&list, NULL);
+
+ t_create_string_list_dup(&list, 0, "no", NULL);
+ t_string_list_filter(&list, NULL);
+
+ t_create_string_list_dup(&list, 0, "yes", NULL);
+ t_string_list_filter(&list, "yes", NULL);
+
+ t_create_string_list_dup(&list, 0, "no", "yes", NULL);
+ t_string_list_filter(&list, "yes", NULL);
+
+ t_create_string_list_dup(&list, 0, "yes", "no", NULL);
+ t_string_list_filter(&list, "yes", NULL);
+
+ t_create_string_list_dup(&list, 0, "y1", "y2", NULL);
+ t_string_list_filter(&list, "y1", "y2", NULL);
+
+ t_create_string_list_dup(&list, 0, "y2", "y1", NULL);
+ t_string_list_filter(&list, "y2", "y1", NULL);
+
+ t_create_string_list_dup(&list, 0, "x1", "x2", NULL);
+ t_string_list_filter(&list, NULL);
+
+ t_string_list_clear(&list, 0);
+}
+
+static void t_string_list_remove_duplicates(struct string_list *list, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
+ va_list ap;
+
+ va_start(ap, list);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
+ string_list_remove_duplicates(list, 0);
+ t_string_list_equal(list, &expected_strings);
+
+ string_list_clear(&expected_strings, 0);
+}
+
+void test_string_list__remove_duplicates(void)
+{
+ struct string_list list = STRING_LIST_INIT_DUP;
+
+ t_create_string_list_dup(&list, 0, NULL);
+ t_string_list_remove_duplicates(&list, NULL);
+
+ t_create_string_list_dup(&list, 0, "", NULL);
+ t_string_list_remove_duplicates(&list, "", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", NULL);
+ t_string_list_remove_duplicates(&list, "a", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", NULL);
+ t_string_list_remove_duplicates(&list, "a", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", "a", NULL);
+ t_string_list_remove_duplicates(&list, "a", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", "b", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "b", "b", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "b", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", "b", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "b", "b", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "b", "c", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", "b", "b", "c", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_create_string_list_dup(&list, 0, "a", "a", "a", "b", "b", "b",
+ "c", "c", "c", NULL);
+ t_string_list_remove_duplicates(&list, "a", "b", "c", NULL);
+
+ t_string_list_clear(&list, 0);
+}
diff --git a/t/unit-tests/unit-test.h b/t/unit-tests/unit-test.h
index 85e5d6a948..39a0b72a05 100644
--- a/t/unit-tests/unit-test.h
+++ b/t/unit-tests/unit-test.h
@@ -1,8 +1,13 @@
#include "git-compat-util.h"
#include "clar/clar.h"
-#include "clar-decls.h"
#include "strbuf.h"
+#ifndef GIT_CLAR_DECLS_H
+# include "clar-decls.h"
+#else
+# include GIT_CLAR_DECLS_H
+#endif
+
#define cl_failf(fmt, ...) do { \
char desc[4096]; \
snprintf(desc, sizeof(desc), fmt, __VA_ARGS__); \