summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/.gitattributes1
-rw-r--r--t/README14
-rw-r--r--t/helper/test-bitmap.c10
-rw-r--r--t/helper/test-genzeros.c21
-rw-r--r--t/helper/test-mergesort.c368
-rw-r--r--t/helper/test-oid-array.c4
-rw-r--r--t/helper/test-oidtree.c3
-rw-r--r--t/helper/test-parse-options.c7
-rw-r--r--t/helper/test-prio-queue.c2
-rw-r--r--t/helper/test-read-cache.c5
-rw-r--r--t/helper/test-read-midx.c32
-rw-r--r--t/helper/test-ref-store.c6
-rw-r--r--t/helper/test-run-command.c6
-rw-r--r--t/helper/test-simple-ipc.c233
-rw-r--r--t/lib-diff-data.sh22
-rw-r--r--t/lib-diff.sh2
-rw-r--r--t/lib-diff/COPYING361
-rw-r--r--t/lib-diff/README46
-rw-r--r--t/lib-gpg.sh35
-rw-r--r--t/lib-httpd.sh1
-rw-r--r--t/lib-httpd/apache.conf4
-rw-r--r--t/lib-httpd/error-no-report.sh6
-rw-r--r--t/lib-midx.sh8
-rw-r--r--t/lib-subtest.sh95
-rw-r--r--t/oid-info/oid2
-rwxr-xr-xt/perf/aggregate.perl4
-rw-r--r--t/perf/config2
-rwxr-xr-xt/perf/p0071-sort.sh40
-rwxr-xr-xt/perf/p2000-sparse-operations.sh3
-rwxr-xr-xt/perf/p3400-rebase.sh2
-rwxr-xr-xt/perf/p5326-multi-pack-bitmaps.sh15
-rw-r--r--t/perf/perf-lib.sh5
-rwxr-xr-xt/t0000-basic.sh448
-rwxr-xr-xt/t0001-init.sh1
-rwxr-xr-xt/t0002-gitfile.sh1
-rwxr-xr-xt/t0003-attributes.sh1
-rwxr-xr-xt/t0004-unwritable.sh50
-rwxr-xr-xt/t0005-signals.sh2
-rwxr-xr-xt/t0006-date.sh4
-rwxr-xr-xt/t0007-git-var.sh22
-rwxr-xr-xt/t0008-ignores.sh44
-rwxr-xr-xt/t0009-prio-queue.sh2
-rwxr-xr-xt/t0010-racy-git.sh1
-rwxr-xr-xt/t0011-hashmap.sh2
-rwxr-xr-xt/t0012-help.sh49
-rwxr-xr-xt/t0013-sha1dc.sh2
-rwxr-xr-xt/t0016-oidmap.sh2
-rwxr-xr-xt/t0017-env-helper.sh1
-rwxr-xr-xt/t0018-advice.sh1
-rwxr-xr-xt/t0020-crlf.sh1
-rwxr-xr-xt/t0022-crlf-rename.sh1
-rwxr-xr-xt/t0024-crlf-archive.sh1
-rwxr-xr-xt/t0025-crlf-renormalize.sh1
-rwxr-xr-xt/t0026-eol-config.sh1
-rwxr-xr-xt/t0029-core-unsetenvvars.sh1
-rwxr-xr-xt/t0030-stripspace.sh1
-rwxr-xr-xt/t0040-parse-options.sh43
-rwxr-xr-xt/t0052-simple-ipc.sh1
-rwxr-xr-xt/t0055-beyond-symlinks.sh1
-rwxr-xr-xt/t0061-run-command.sh1
-rwxr-xr-xt/t0063-string-list.sh1
-rwxr-xr-xt/t0064-oid-array.sh2
-rwxr-xr-xt/t0065-strcmp-offset.sh1
-rwxr-xr-xt/t0066-dir-iterator.sh1
-rwxr-xr-xt/t0067-parse_pathspec_file.sh1
-rwxr-xr-xt/t0069-oidtree.sh1
-rwxr-xr-xt/t0071-sort.sh11
-rwxr-xr-xt/t0091-bugreport.sh1
-rwxr-xr-xt/t0110-urlmatch-normalization.sh2
-rwxr-xr-xt/t0210-trace2-normal.sh2
-rwxr-xr-xt/t0211-trace2-perf.sh2
-rwxr-xr-xt/t0212-trace2-event.sh2
-rwxr-xr-xt/t0410-partial-clone.sh6
-rwxr-xr-xt/t1000-read-tree-m-3way.sh2
-rwxr-xr-xt/t1001-read-tree-m-2way.sh2
-rwxr-xr-xt/t1003-read-tree-prefix.sh1
-rwxr-xr-xt/t1005-read-tree-reset.sh1
-rwxr-xr-xt/t1006-cat-file.sh297
-rwxr-xr-xt/t1008-read-tree-overlay.sh1
-rwxr-xr-xt/t1009-read-tree-new-index.sh1
-rwxr-xr-xt/t1010-mktree.sh1
-rwxr-xr-xt/t1012-read-tree-df.sh1
-rwxr-xr-xt/t1013-read-tree-submodule.sh1
-rwxr-xr-xt/t1014-read-tree-confusing.sh2
-rwxr-xr-xt/t1050-large.sh8
-rwxr-xr-xt/t1051-large-conversion.sh26
-rwxr-xr-xt/t1091-sparse-checkout-builtin.sh29
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh262
-rwxr-xr-xt/t1100-commit-tree-options.sh1
-rwxr-xr-xt/t1305-config-include.sh1
-rwxr-xr-xt/t1403-show-ref.sh1
-rwxr-xr-xt/t1405-main-ref-store.sh2
-rwxr-xr-xt/t1406-submodule-ref-store.sh3
-rwxr-xr-xt/t1417-reflog-updateref.sh65
-rwxr-xr-xt/t1430-bad-ref-name.sh3
-rwxr-xr-xt/t1450-fsck.sh97
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh54
-rwxr-xr-xt/t1504-ceiling-dirs.sh2
-rwxr-xr-xt/t1505-rev-parse-last.sh1
-rwxr-xr-xt/t1510-repo-setup.sh1
-rwxr-xr-xt/t1600-index.sh13
-rwxr-xr-xt/t1700-split-index.sh34
-rwxr-xr-xt/t2002-checkout-cache-u.sh1
-rwxr-xr-xt/t2003-checkout-cache-mkdir.sh1
-rwxr-xr-xt/t2004-checkout-cache-temp.sh1
-rwxr-xr-xt/t2005-checkout-index-symlinks.sh1
-rwxr-xr-xt/t2007-checkout-symlink.sh1
-rwxr-xr-xt/t2008-checkout-subdir.sh1
-rwxr-xr-xt/t2009-checkout-statinfo.sh1
-rwxr-xr-xt/t2010-checkout-ambiguous.sh1
-rwxr-xr-xt/t2011-checkout-invalid-head.sh1
-rwxr-xr-xt/t2014-checkout-switch.sh2
-rwxr-xr-xt/t2017-checkout-orphan.sh1
-rwxr-xr-xt/t2019-checkout-ambiguous-ref.sh2
-rwxr-xr-xt/t2021-checkout-overwrite.sh2
-rwxr-xr-xt/t2022-checkout-paths.sh1
-rwxr-xr-xt/t2026-checkout-pathspec-file.sh1
-rwxr-xr-xt/t2050-git-dir-relative.sh1
-rwxr-xr-xt/t2081-parallel-checkout-collisions.sh1
-rwxr-xr-xt/t2106-update-index-assume-unchanged.sh1
-rwxr-xr-xt/t2200-add-update.sh3
-rwxr-xr-xt/t2300-cd-to-toplevel.sh1
-rwxr-xr-xt/t2500-untracked-overwriting.sh244
-rwxr-xr-xt/t3000-ls-files-others.sh2
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh5
-rwxr-xr-xt/t3002-ls-files-dashpath.sh2
-rwxr-xr-xt/t3003-ls-files-exclude.sh2
-rwxr-xr-xt/t3004-ls-files-basic.sh1
-rwxr-xr-xt/t3005-ls-files-relative.sh1
-rwxr-xr-xt/t3006-ls-files-long.sh2
-rwxr-xr-xt/t3008-ls-files-lazy-init-name-hash.sh1
-rwxr-xr-xt/t3020-ls-files-error-unmatch.sh2
-rwxr-xr-xt/t3040-subprojects-basic.sh2
-rwxr-xr-xt/t3070-wildmatch.sh1
-rwxr-xr-xt/t3100-ls-tree-restrict.sh2
-rwxr-xr-xt/t3101-ls-tree-dirname.sh2
-rwxr-xr-xt/t3102-ls-tree-wildcards.sh1
-rwxr-xr-xt/t3103-ls-tree-misc.sh1
-rwxr-xr-xt/t3200-branch.sh34
-rwxr-xr-xt/t3205-branch-color.sh1
-rwxr-xr-xt/t3211-peel-ref.sh1
-rwxr-xr-xt/t3300-funny-names.sh1
-rwxr-xr-xt/t3305-notes-fanout.sh1
-rwxr-xr-xt/t3404-rebase-interactive.sh76
-rwxr-xr-xt/t3408-rebase-multi-line.sh10
-rwxr-xr-xt/t3409-rebase-preserve-merges.sh130
-rwxr-xr-xt/t3410-rebase-preserve-dropped-merges.sh90
-rwxr-xr-xt/t3411-rebase-preserve-around-merges.sh80
-rwxr-xr-xt/t3412-rebase-root.sh37
-rwxr-xr-xt/t3414-rebase-preserve-onto.sh85
-rwxr-xr-xt/t3418-rebase-continue.sh15
-rwxr-xr-xt/t3421-rebase-topology-linear.sh19
-rwxr-xr-xt/t3422-rebase-incompatible-options.sh13
-rwxr-xr-xt/t3425-rebase-topology-merges.sh151
-rwxr-xr-xt/t3427-rebase-subtree.sh26
-rwxr-xr-xt/t3436-rebase-more-options.sh29
-rwxr-xr-xt/t3601-rm-pathspec-file.sh1
-rwxr-xr-xt/t3602-rm-sparse-checkout.sh69
-rwxr-xr-xt/t3700-add.sh1
-rwxr-xr-xt/t3705-add-sparse-checkout.sh85
-rwxr-xr-xt/t3902-quoted.sh1
-rwxr-xr-xt/t3903-stash.sh11
-rwxr-xr-xt/t3905-stash-include-untracked.sh6
-rwxr-xr-xt/t4002-diff-basic.sh2
-rwxr-xr-xt/t4003-diff-rename-1.sh4
-rwxr-xr-xt/t4005-diff-rename-2.sh4
-rwxr-xr-xt/t4007-rename-3.sh5
-rwxr-xr-xt/t4008-diff-break-rewrite.sh4
-rwxr-xr-xt/t4009-diff-rename-4.sh4
-rwxr-xr-xt/t4016-diff-quote.sh1
-rwxr-xr-xt/t4019-diff-wserror.sh1
-rwxr-xr-xt/t4022-diff-rewrite.sh6
-rwxr-xr-xt/t4023-diff-rename-typechange.sh11
-rwxr-xr-xt/t4025-hunk-header.sh1
-rwxr-xr-xt/t4026-color.sh2
-rw-r--r--t/t4034/cpp/expect63
-rw-r--r--t/t4034/cpp/post47
-rw-r--r--t/t4034/cpp/pre41
-rwxr-xr-xt/t4115-apply-symlink.sh1
-rwxr-xr-xt/t4121-apply-diffs.sh1
-rwxr-xr-xt/t4202-log.sh74
-rwxr-xr-xt/t4204-patch-id.sh1
-rwxr-xr-xt/t4210-log-i18n.sh7
-rwxr-xr-xt/t4300-merge-tree.sh2
-rwxr-xr-xt/t5310-pack-bitmaps.sh1
-rwxr-xr-xt/t5312-prune-corruption.sh48
-rwxr-xr-xt/t5318-commit-graph.sh28
-rwxr-xr-xt/t5319-multi-pack-index.sh26
-rwxr-xr-xt/t5324-split-commit-graph.sh20
-rwxr-xr-xt/t5326-multi-pack-bitmaps.sh112
-rwxr-xr-xt/t5410-receive-pack-alternates.sh1
-rwxr-xr-xt/t5516-fetch-push.sh28
-rwxr-xr-xt/t5520-pull.sh24
-rwxr-xr-xt/t5521-pull-options.sh24
-rwxr-xr-xt/t5526-fetch-submodules.sh3
-rwxr-xr-xt/t5531-deep-submodule-push.sh3
-rwxr-xr-xt/t5534-push-signed.sh101
-rwxr-xr-xt/t5541-http-push-smart.sh16
-rwxr-xr-xt/t5545-push-options.sh3
-rwxr-xr-xt/t5572-pull-submodule.sh3
-rwxr-xr-xt/t5580-unc-paths.sh1
-rwxr-xr-xt/t5600-clone-fail-cleanup.sh4
-rwxr-xr-xt/t5609-clone-branch.sh1
-rwxr-xr-xt/t5615-alternate-env.sh2
-rwxr-xr-xt/t5702-protocol-v2.sh51
-rwxr-xr-xt/t6000-rev-list-misc.sh31
-rwxr-xr-xt/t6200-fmt-merge-msg.sh28
-rwxr-xr-xt/t6300-for-each-ref.sh26
-rwxr-xr-xt/t6407-merge-binary.sh1
-rwxr-xr-xt/t6414-merge-rename-nocruft.sh1
-rwxr-xr-xt/t6437-submodule-merge.sh3
-rwxr-xr-xt/t7001-mv.sh5
-rwxr-xr-xt/t7002-mv-sparse-checkout.sh209
-rwxr-xr-xt/t7006-pager.sh54
-rwxr-xr-xt/t7031-verify-tag-signed-ssh.sh161
-rwxr-xr-xt/t7064-wtstatus-pv2.sh15
-rwxr-xr-xt/t7101-reset-empty-subdirs.sh11
-rwxr-xr-xt/t7102-reset.sh17
-rwxr-xr-xt/t7104-reset-hard.sh1
-rwxr-xr-xt/t7112-reset-submodule.sh1
-rwxr-xr-xt/t7113-post-index-change-hook.sh1
-rwxr-xr-xt/t7418-submodule-sparse-gitmodules.sh3
-rwxr-xr-xt/t7504-commit-msg-hook.sh8
-rwxr-xr-xt/t7505-prepare-commit-msg-hook.sh1
-rwxr-xr-xt/t7509-commit-authorship.sh1
-rwxr-xr-xt/t7510-signed-commit.sh29
-rwxr-xr-xt/t7517-per-repo-email.sh13
-rwxr-xr-xt/t7518-ident-corner-cases.sh2
-rwxr-xr-xt/t7519-status-fsmonitor.sh68
-rwxr-xr-xt/t7528-signed-commit-ssh.sh398
-rwxr-xr-xt/t7601-merge-pull-config.sh22
-rwxr-xr-xt/t7604-merge-custom-message.sh1
-rwxr-xr-xt/t7700-repack.sh138
-rwxr-xr-xt/t7703-repack-geometric.sh24
-rwxr-xr-xt/t7800-difftool.sh7
-rwxr-xr-xt/t7811-grep-open.sh3
-rwxr-xr-xt/t7813-grep-icase-iso.sh1
-rwxr-xr-xt/t7814-grep-recurse-submodules.sh103
-rwxr-xr-xt/t7815-grep-binary.sh1
-rwxr-xr-xt/t7816-grep-binary-pattern.sh1
-rwxr-xr-xt/t7900-maintenance.sh34
-rwxr-xr-xt/t9102-git-svn-deep-rmdir.sh2
-rwxr-xr-xt/t9123-git-svn-rebuild-with-rewriteroot.sh1
-rwxr-xr-xt/t9128-git-svn-cmd-branch.sh2
-rwxr-xr-xt/t9167-git-svn-cmd-branch-subproject.sh2
-rwxr-xr-xt/t9902-completion.sh3
-rw-r--r--t/test-lib.sh69
247 files changed, 4483 insertions, 2067 deletions
diff --git a/t/.gitattributes b/t/.gitattributes
index dafa17c3e6..9930e28351 100644
--- a/t/.gitattributes
+++ b/t/.gitattributes
@@ -1,6 +1,5 @@
t[0-9][0-9][0-9][0-9]/* -whitespace
/chainlint/*.expect eol=lf
-/lib-diff/* eol=lf
/t0110/url-* binary
/t3206/* eol=lf
/t3900/*.txt eol=lf
diff --git a/t/README b/t/README
index 51065d0800..29f72354bf 100644
--- a/t/README
+++ b/t/README
@@ -366,6 +366,13 @@ excluded as so much relies on it, but this might change in the future.
GIT_TEST_SPLIT_INDEX=<boolean> forces split-index mode on the whole
test suite. Accept any boolean values that are accepted by git-config.
+GIT_TEST_PASSING_SANITIZE_LEAK=<boolean> when compiled with
+SANITIZE=leak will run only those tests that have whitelisted
+themselves as passing with no memory leaks. Tests can be whitelisted
+by setting "TEST_PASSES_SANITIZE_LEAK=true" before sourcing
+"test-lib.sh" itself at the top of the test script. This test mode is
+used by the "linux-leaks" CI target.
+
GIT_TEST_PROTOCOL_VERSION=<n>, when set, makes 'protocol.version'
default to n.
@@ -456,11 +463,8 @@ GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=<boolean>, when true, makes
registering submodule ODBs as alternates a fatal action. Support for
this environment variable can be removed once the migration to
explicitly providing repositories when accessing submodule objects is
-complete (in which case we might want to replace this with a trace2
-call so that users can make it visible if accessing submodule objects
-without an explicit repository still happens) or needs to be abandoned
-for whatever reason (in which case the migrated codepaths still retain
-their performance benefits).
+complete or needs to be abandoned for whatever reason (in which case the
+migrated codepaths still retain their performance benefits).
Naming Tests
------------
diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c
index 134a1e9d76..ff35f5999b 100644
--- a/t/helper/test-bitmap.c
+++ b/t/helper/test-bitmap.c
@@ -7,6 +7,11 @@ static int bitmap_list_commits(void)
return test_bitmap_commits(the_repository);
}
+static int bitmap_dump_hashes(void)
+{
+ return test_bitmap_hashes(the_repository);
+}
+
int cmd__bitmap(int argc, const char **argv)
{
setup_git_directory();
@@ -16,9 +21,12 @@ int cmd__bitmap(int argc, const char **argv)
if (!strcmp(argv[1], "list-commits"))
return bitmap_list_commits();
+ if (!strcmp(argv[1], "dump-hashes"))
+ return bitmap_dump_hashes();
usage:
- usage("\ttest-tool bitmap list-commits");
+ usage("\ttest-tool bitmap list-commits\n"
+ "\ttest-tool bitmap dump-hashes");
return -1;
}
diff --git a/t/helper/test-genzeros.c b/t/helper/test-genzeros.c
index 9532f5bac9..8ca988d621 100644
--- a/t/helper/test-genzeros.c
+++ b/t/helper/test-genzeros.c
@@ -3,18 +3,31 @@
int cmd__genzeros(int argc, const char **argv)
{
- long count;
+ /* static, so that it is NUL-initialized */
+ static const char zeros[256 * 1024];
+ intmax_t count;
+ ssize_t n;
if (argc > 2) {
fprintf(stderr, "usage: %s [<count>]\n", argv[0]);
return 1;
}
- count = argc > 1 ? strtol(argv[1], NULL, 0) : -1L;
+ count = argc > 1 ? strtoimax(argv[1], NULL, 0) : -1;
- while (count < 0 || count--) {
- if (putchar(0) == EOF)
+ /* Writing out individual NUL bytes is slow... */
+ while (count < 0)
+ if (write(1, zeros, ARRAY_SIZE(zeros)) < 0)
return -1;
+
+ while (count > 0) {
+ n = write(1, zeros, count < ARRAY_SIZE(zeros) ?
+ count : ARRAY_SIZE(zeros));
+
+ if (n < 0)
+ return -1;
+
+ count -= n;
}
return 0;
diff --git a/t/helper/test-mergesort.c b/t/helper/test-mergesort.c
index c5cffaa4b7..ebf68f7de8 100644
--- a/t/helper/test-mergesort.c
+++ b/t/helper/test-mergesort.c
@@ -2,6 +2,12 @@
#include "cache.h"
#include "mergesort.h"
+static uint32_t minstd_rand(uint32_t *state)
+{
+ *state = (uint64_t)*state * 48271 % 2147483647;
+ return *state;
+}
+
struct line {
char *text;
struct line *next;
@@ -23,14 +29,12 @@ static int compare_strings(const void *a, const void *b)
return strcmp(x->text, y->text);
}
-int cmd__mergesort(int argc, const char **argv)
+static int sort_stdin(void)
{
struct line *line, *p = NULL, *lines = NULL;
struct strbuf sb = STRBUF_INIT;
- for (;;) {
- if (strbuf_getwholeline(&sb, stdin, '\n'))
- break;
+ while (!strbuf_getline(&sb, stdin)) {
line = xmalloc(sizeof(struct line));
line->text = strbuf_detach(&sb, NULL);
if (p) {
@@ -46,8 +50,362 @@ int cmd__mergesort(int argc, const char **argv)
lines = llist_mergesort(lines, get_next, set_next, compare_strings);
while (lines) {
- printf("%s", lines->text);
+ puts(lines->text);
lines = lines->next;
}
return 0;
}
+
+static void dist_sawtooth(int *arr, int n, int m)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ arr[i] = i % m;
+}
+
+static void dist_rand(int *arr, int n, int m)
+{
+ int i;
+ uint32_t seed = 1;
+ for (i = 0; i < n; i++)
+ arr[i] = minstd_rand(&seed) % m;
+}
+
+static void dist_stagger(int *arr, int n, int m)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ arr[i] = (i * m + i) % n;
+}
+
+static void dist_plateau(int *arr, int n, int m)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ arr[i] = (i < m) ? i : m;
+}
+
+static void dist_shuffle(int *arr, int n, int m)
+{
+ int i, j, k;
+ uint32_t seed = 1;
+ for (i = j = 0, k = 1; i < n; i++)
+ arr[i] = minstd_rand(&seed) % m ? (j += 2) : (k += 2);
+}
+
+#define DIST(name) { #name, dist_##name }
+
+static struct dist {
+ const char *name;
+ void (*fn)(int *arr, int n, int m);
+} dist[] = {
+ DIST(sawtooth),
+ DIST(rand),
+ DIST(stagger),
+ DIST(plateau),
+ DIST(shuffle),
+};
+
+static const struct dist *get_dist_by_name(const char *name)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(dist); i++) {
+ if (!strcmp(dist[i].name, name))
+ return &dist[i];
+ }
+ return NULL;
+}
+
+static void mode_copy(int *arr, int n)
+{
+ /* nothing */
+}
+
+static void mode_reverse(int *arr, int n)
+{
+ int i, j;
+ for (i = 0, j = n - 1; i < j; i++, j--)
+ SWAP(arr[i], arr[j]);
+}
+
+static void mode_reverse_1st_half(int *arr, int n)
+{
+ mode_reverse(arr, n / 2);
+}
+
+static void mode_reverse_2nd_half(int *arr, int n)
+{
+ int half = n / 2;
+ mode_reverse(arr + half, n - half);
+}
+
+static int compare_ints(const void *av, const void *bv)
+{
+ const int *ap = av, *bp = bv;
+ int a = *ap, b = *bp;
+ return (a > b) - (a < b);
+}
+
+static void mode_sort(int *arr, int n)
+{
+ QSORT(arr, n, compare_ints);
+}
+
+static void mode_dither(int *arr, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ arr[i] += i % 5;
+}
+
+static void unriffle(int *arr, int n, int *tmp)
+{
+ int i, j;
+ COPY_ARRAY(tmp, arr, n);
+ for (i = j = 0; i < n; i += 2)
+ arr[j++] = tmp[i];
+ for (i = 1; i < n; i += 2)
+ arr[j++] = tmp[i];
+}
+
+static void unriffle_recursively(int *arr, int n, int *tmp)
+{
+ if (n > 1) {
+ int half = n / 2;
+ unriffle(arr, n, tmp);
+ unriffle_recursively(arr, half, tmp);
+ unriffle_recursively(arr + half, n - half, tmp);
+ }
+}
+
+static void mode_unriffle(int *arr, int n)
+{
+ int *tmp;
+ ALLOC_ARRAY(tmp, n);
+ unriffle_recursively(arr, n, tmp);
+ free(tmp);
+}
+
+static unsigned int prev_pow2(unsigned int n)
+{
+ unsigned int pow2 = 1;
+ while (pow2 * 2 < n)
+ pow2 *= 2;
+ return pow2;
+}
+
+static void unriffle_recursively_skewed(int *arr, int n, int *tmp)
+{
+ if (n > 1) {
+ int pow2 = prev_pow2(n);
+ int rest = n - pow2;
+ unriffle(arr + pow2 - rest, rest * 2, tmp);
+ unriffle_recursively_skewed(arr, pow2, tmp);
+ unriffle_recursively_skewed(arr + pow2, rest, tmp);
+ }
+}
+
+static void mode_unriffle_skewed(int *arr, int n)
+{
+ int *tmp;
+ ALLOC_ARRAY(tmp, n);
+ unriffle_recursively_skewed(arr, n, tmp);
+ free(tmp);
+}
+
+#define MODE(name) { #name, mode_##name }
+
+static struct mode {
+ const char *name;
+ void (*fn)(int *arr, int n);
+} mode[] = {
+ MODE(copy),
+ MODE(reverse),
+ MODE(reverse_1st_half),
+ MODE(reverse_2nd_half),
+ MODE(sort),
+ MODE(dither),
+ MODE(unriffle),
+ MODE(unriffle_skewed),
+};
+
+static const struct mode *get_mode_by_name(const char *name)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(mode); i++) {
+ if (!strcmp(mode[i].name, name))
+ return &mode[i];
+ }
+ return NULL;
+}
+
+static int generate(int argc, const char **argv)
+{
+ const struct dist *dist = NULL;
+ const struct mode *mode = NULL;
+ int i, n, m, *arr;
+
+ if (argc != 4)
+ return 1;
+
+ dist = get_dist_by_name(argv[0]);
+ mode = get_mode_by_name(argv[1]);
+ n = strtol(argv[2], NULL, 10);
+ m = strtol(argv[3], NULL, 10);
+ if (!dist || !mode)
+ return 1;
+
+ ALLOC_ARRAY(arr, n);
+ dist->fn(arr, n, m);
+ mode->fn(arr, n);
+ for (i = 0; i < n; i++)
+ printf("%08x\n", arr[i]);
+ free(arr);
+ return 0;
+}
+
+static struct stats {
+ int get_next, set_next, compare;
+} stats;
+
+struct number {
+ int value, rank;
+ struct number *next;
+};
+
+static void *get_next_number(const void *a)
+{
+ stats.get_next++;
+ return ((const struct number *)a)->next;
+}
+
+static void set_next_number(void *a, void *b)
+{
+ stats.set_next++;
+ ((struct number *)a)->next = b;
+}
+
+static int compare_numbers(const void *av, const void *bv)
+{
+ const struct number *an = av, *bn = bv;
+ int a = an->value, b = bn->value;
+ stats.compare++;
+ return (a > b) - (a < b);
+}
+
+static void clear_numbers(struct number *list)
+{
+ while (list) {
+ struct number *next = list->next;
+ free(list);
+ list = next;
+ }
+}
+
+static int test(const struct dist *dist, const struct mode *mode, int n, int m)
+{
+ int *arr;
+ size_t i;
+ struct number *curr, *list, **tail;
+ int is_sorted = 1;
+ int is_stable = 1;
+ const char *verdict;
+ int result = -1;
+
+ ALLOC_ARRAY(arr, n);
+ dist->fn(arr, n, m);
+ mode->fn(arr, n);
+ for (i = 0, tail = &list; i < n; i++) {
+ curr = xmalloc(sizeof(*curr));
+ curr->value = arr[i];
+ curr->rank = i;
+ *tail = curr;
+ tail = &curr->next;
+ }
+ *tail = NULL;
+
+ stats.get_next = stats.set_next = stats.compare = 0;
+ list = llist_mergesort(list, get_next_number, set_next_number,
+ compare_numbers);
+
+ QSORT(arr, n, compare_ints);
+ for (i = 0, curr = list; i < n && curr; i++, curr = curr->next) {
+ if (arr[i] != curr->value)
+ is_sorted = 0;
+ if (curr->next && curr->value == curr->next->value &&
+ curr->rank >= curr->next->rank)
+ is_stable = 0;
+ }
+ if (i < n) {
+ verdict = "too short";
+ } else if (curr) {
+ verdict = "too long";
+ } else if (!is_sorted) {
+ verdict = "not sorted";
+ } else if (!is_stable) {
+ verdict = "unstable";
+ } else {
+ verdict = "OK";
+ result = 0;
+ }
+
+ printf("%-9s %-16s %8d %8d %8d %8d %8d %s\n",
+ dist->name, mode->name, n, m, stats.get_next, stats.set_next,
+ stats.compare, verdict);
+
+ clear_numbers(list);
+ free(arr);
+
+ return result;
+}
+
+/*
+ * A version of the qsort certification program from "Engineering a Sort
+ * Function" by Bentley and McIlroy, Software—Practice and Experience,
+ * Volume 23, Issue 11, 1249–1265 (November 1993).
+ */
+static int run_tests(int argc, const char **argv)
+{
+ const char *argv_default[] = { "100", "1023", "1024", "1025" };
+ if (!argc)
+ return run_tests(ARRAY_SIZE(argv_default), argv_default);
+ printf("%-9s %-16s %8s %8s %8s %8s %8s %s\n",
+ "distribut", "mode", "n", "m", "get_next", "set_next",
+ "compare", "verdict");
+ while (argc--) {
+ int i, j, m, n = strtol(*argv++, NULL, 10);
+ for (i = 0; i < ARRAY_SIZE(dist); i++) {
+ for (j = 0; j < ARRAY_SIZE(mode); j++) {
+ for (m = 1; m < 2 * n; m *= 2) {
+ if (test(&dist[i], &mode[j], n, m))
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int cmd__mergesort(int argc, const char **argv)
+{
+ int i;
+ const char *sep;
+
+ if (argc == 6 && !strcmp(argv[1], "generate"))
+ return generate(argc - 2, argv + 2);
+ if (argc == 2 && !strcmp(argv[1], "sort"))
+ return sort_stdin();
+ if (argc > 1 && !strcmp(argv[1], "test"))
+ return run_tests(argc - 2, argv + 2);
+ fprintf(stderr, "usage: test-tool mergesort generate <distribution> <mode> <n> <m>\n");
+ fprintf(stderr, " or: test-tool mergesort sort\n");
+ fprintf(stderr, " or: test-tool mergesort test [<n>...]\n");
+ fprintf(stderr, "\n");
+ for (i = 0, sep = "distributions: "; i < ARRAY_SIZE(dist); i++, sep = ", ")
+ fprintf(stderr, "%s%s", sep, dist[i].name);
+ fprintf(stderr, "\n");
+ for (i = 0, sep = "modes: "; i < ARRAY_SIZE(mode); i++, sep = ", ")
+ fprintf(stderr, "%s%s", sep, mode[i].name);
+ fprintf(stderr, "\n");
+ return 129;
+}
diff --git a/t/helper/test-oid-array.c b/t/helper/test-oid-array.c
index b16cd0b11b..d1324d086a 100644
--- a/t/helper/test-oid-array.c
+++ b/t/helper/test-oid-array.c
@@ -35,5 +35,9 @@ int cmd__oid_array(int argc, const char **argv)
else
die("unknown command: %s", line.buf);
}
+
+ strbuf_release(&line);
+ oid_array_clear(&array);
+
return 0;
}
diff --git a/t/helper/test-oidtree.c b/t/helper/test-oidtree.c
index 180ee28dd9..d48a409f4e 100644
--- a/t/helper/test-oidtree.c
+++ b/t/helper/test-oidtree.c
@@ -45,5 +45,8 @@ int cmd__oidtree(int argc, const char **argv)
die("unknown command: %s", line.buf);
}
}
+
+ strbuf_release(&line);
+
return 0;
}
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index a282b6ff13..48d3cf6692 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -14,7 +14,6 @@ static int dry_run = 0, quiet = 0;
static char *string = NULL;
static char *file = NULL;
static int ambiguous;
-static struct string_list list = STRING_LIST_INIT_NODUP;
static struct {
int called;
@@ -107,6 +106,8 @@ int cmd__parse_options(int argc, const char **argv)
NULL
};
struct string_list expect = STRING_LIST_INIT_NODUP;
+ struct string_list list = STRING_LIST_INIT_NODUP;
+
struct option options[] = {
OPT_BOOL(0, "yes", &boolean, "get a boolean"),
OPT_BOOL('D', "no-doubt", &boolean, "begins with 'no-'"),
@@ -185,5 +186,9 @@ int cmd__parse_options(int argc, const char **argv)
for (i = 0; i < argc; i++)
show(&expect, &ret, "arg %02d: %s", i, argv[i]);
+ expect.strdup_strings = 1;
+ string_list_clear(&expect, 0);
+ string_list_clear(&list, 0);
+
return ret;
}
diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c
index f4028442e3..133b5e6f4a 100644
--- a/t/helper/test-prio-queue.c
+++ b/t/helper/test-prio-queue.c
@@ -46,5 +46,7 @@ int cmd__prio_queue(int argc, const char **argv)
}
}
+ clear_prio_queue(&pq);
+
return 0;
}
diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index b52c174acc..0d9f08931a 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -39,8 +39,6 @@ int cmd__read_cache(int argc, const char **argv)
int table = 0, expand = 0;
initialize_the_repository();
- prepare_repo_settings(r);
- r->settings.command_requires_full_index = 0;
for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) {
if (skip_prefix(*argv, "--print-and-refresh=", &name))
@@ -56,6 +54,9 @@ int cmd__read_cache(int argc, const char **argv)
setup_git_directory();
git_config(git_default_config, NULL);
+ prepare_repo_settings(r);
+ r->settings.command_requires_full_index = 0;
+
for (i = 0; i < cnt; i++) {
repo_read_index(r);
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
index cb0d27049a..27072ba94d 100644
--- a/t/helper/test-read-midx.c
+++ b/t/helper/test-read-midx.c
@@ -3,6 +3,7 @@
#include "midx.h"
#include "repository.h"
#include "object-store.h"
+#include "pack-bitmap.h"
static int read_midx_file(const char *object_dir, int show_objects)
{
@@ -54,9 +55,10 @@ static int read_midx_file(const char *object_dir, int show_objects)
printf("%s %"PRIu64"\t%s\n",
oid_to_hex(&oid), e.offset, e.p->pack_name);
}
- return 0;
}
+ close_midx(m);
+
return 0;
}
@@ -72,14 +74,40 @@ static int read_midx_checksum(const char *object_dir)
return 0;
}
+static int read_midx_preferred_pack(const char *object_dir)
+{
+ struct multi_pack_index *midx = NULL;
+ struct bitmap_index *bitmap = NULL;
+
+ setup_git_directory();
+
+ midx = load_multi_pack_index(object_dir, 1);
+ if (!midx)
+ return 1;
+
+ bitmap = prepare_bitmap_git(the_repository);
+ if (!bitmap)
+ return 1;
+ if (!bitmap_is_midx(bitmap)) {
+ free_bitmap_index(bitmap);
+ return 1;
+ }
+
+ printf("%s\n", midx->pack_names[midx_preferred_pack(bitmap)]);
+ free_bitmap_index(bitmap);
+ return 0;
+}
+
int cmd__read_midx(int argc, const char **argv)
{
if (!(argc == 2 || argc == 3))
- usage("read-midx [--show-objects|--checksum] <object-dir>");
+ usage("read-midx [--show-objects|--checksum|--preferred-pack] <object-dir>");
if (!strcmp(argv[1], "--show-objects"))
return read_midx_file(argv[2], 1);
else if (!strcmp(argv[1], "--checksum"))
return read_midx_checksum(argv[2]);
+ else if (!strcmp(argv[1], "--preferred-pack"))
+ return read_midx_preferred_pack(argv[2]);
return read_midx_file(argv[1], 0);
}
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index b314b81a45..73461c29d3 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -123,9 +123,10 @@ static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
int resolve_flags = arg_flags(*argv++, "resolve-flags");
int flags;
const char *ref;
+ int ignore_errno;
ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
- &oid, &flags);
+ &oid, &flags, &ignore_errno);
printf("%s %s 0x%x\n", oid_to_hex(&oid), ref ? ref : "(null)", flags);
return ref ? 0 : 1;
}
@@ -181,11 +182,10 @@ static int cmd_reflog_exists(struct ref_store *refs, const char **argv)
static int cmd_create_reflog(struct ref_store *refs, const char **argv)
{
const char *refname = notnull(*argv++, "refname");
- int force_create = arg_flags(*argv++, "force-create");
struct strbuf err = STRBUF_INIT;
int ret;
- ret = refs_create_reflog(refs, refname, force_create, &err);
+ ret = refs_create_reflog(refs, refname, &err);
if (err.len)
puts(err.buf);
return ret;
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index 14c57365e7..3c4fb86223 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -60,8 +60,10 @@ struct testsuite {
int next;
int quiet, immediate, verbose, verbose_log, trace, write_junit_xml;
};
-#define TESTSUITE_INIT \
- { STRING_LIST_INIT_DUP, STRING_LIST_INIT_DUP, 0, 0, 0, 0, 0, 0, 0 }
+#define TESTSUITE_INIT { \
+ .tests = STRING_LIST_INIT_DUP, \
+ .failed = STRING_LIST_INIT_DUP, \
+}
static int next_test(struct child_process *cp, struct strbuf *err, void *cb,
void **task_cb)
diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
index 42040ef81b..28365ff85b 100644
--- a/t/helper/test-simple-ipc.c
+++ b/t/helper/test-simple-ipc.c
@@ -9,6 +9,7 @@
#include "parse-options.h"
#include "thread-utils.h"
#include "strvec.h"
+#include "run-command.h"
#ifndef SUPPORTS_SIMPLE_IPC
int cmd__simple_ipc(int argc, const char **argv)
@@ -112,7 +113,7 @@ static int app__slow_command(ipc_server_reply_cb *reply_cb,
/*
* The client sent a command followed by a (possibly very) large buffer.
*/
-static int app__sendbytes_command(const char *received,
+static int app__sendbytes_command(const char *received, size_t received_len,
ipc_server_reply_cb *reply_cb,
struct ipc_server_reply_data *reply_data)
{
@@ -123,6 +124,13 @@ static int app__sendbytes_command(const char *received,
int errs = 0;
int ret;
+ /*
+ * The test is setup to send:
+ * "sendbytes" SP <n * char>
+ */
+ if (received_len < strlen("sendbytes "))
+ BUG("received_len is short in app__sendbytes_command");
+
if (skip_prefix(received, "sendbytes ", &p))
len_ballast = strlen(p);
@@ -160,7 +168,7 @@ static ipc_server_application_cb test_app_cb;
* by this application.
*/
static int test_app_cb(void *application_data,
- const char *command,
+ const char *command, size_t command_len,
ipc_server_reply_cb *reply_cb,
struct ipc_server_reply_data *reply_data)
{
@@ -173,7 +181,7 @@ static int test_app_cb(void *application_data,
if (application_data != (void*)&my_app_data)
BUG("application_cb: application_data pointer wrong");
- if (!strcmp(command, "quit")) {
+ if (command_len == 4 && !strncmp(command, "quit", 4)) {
/*
* The client sent a "quit" command. This is an async
* request for the server to shutdown.
@@ -193,22 +201,23 @@ static int test_app_cb(void *application_data,
return SIMPLE_IPC_QUIT;
}
- if (!strcmp(command, "ping")) {
+ if (command_len == 4 && !strncmp(command, "ping", 4)) {
const char *answer = "pong";
return reply_cb(reply_data, answer, strlen(answer));
}
- if (!strcmp(command, "big"))
+ if (command_len == 3 && !strncmp(command, "big", 3))
return app__big_command(reply_cb, reply_data);
- if (!strcmp(command, "chunk"))
+ if (command_len == 5 && !strncmp(command, "chunk", 5))
return app__chunk_command(reply_cb, reply_data);
- if (!strcmp(command, "slow"))
+ if (command_len == 4 && !strncmp(command, "slow", 4))
return app__slow_command(reply_cb, reply_data);
- if (starts_with(command, "sendbytes "))
- return app__sendbytes_command(command, reply_cb, reply_data);
+ if (command_len >= 10 && starts_with(command, "sendbytes "))
+ return app__sendbytes_command(command, command_len,
+ reply_cb, reply_data);
return app__unhandled_command(command, reply_cb, reply_data);
}
@@ -259,186 +268,72 @@ static int daemon__run_server(void)
*/
ret = ipc_server_run(cl_args.path, &opts, test_app_cb, (void*)&my_app_data);
if (ret == -2)
- error(_("socket/pipe already in use: '%s'"), cl_args.path);
+ error("socket/pipe already in use: '%s'", cl_args.path);
else if (ret == -1)
- error_errno(_("could not start server on: '%s'"), cl_args.path);
+ error_errno("could not start server on: '%s'", cl_args.path);
return ret;
}
-#ifndef GIT_WINDOWS_NATIVE
-/*
- * This is adapted from `daemonize()`. Use `fork()` to directly create and
- * run the daemon in a child process.
- */
-static int spawn_server(pid_t *pid)
-{
- struct ipc_server_opts opts = {
- .nr_threads = cl_args.nr_threads,
- };
-
- *pid = fork();
+static start_bg_wait_cb bg_wait_cb;
- switch (*pid) {
- case 0:
- if (setsid() == -1)
- error_errno(_("setsid failed"));
- close(0);
- close(1);
- close(2);
- sanitize_stdfds();
+static int bg_wait_cb(const struct child_process *cp, void *cb_data)
+{
+ int s = ipc_get_active_state(cl_args.path);
- return ipc_server_run(cl_args.path, &opts, test_app_cb,
- (void*)&my_app_data);
+ switch (s) {
+ case IPC_STATE__LISTENING:
+ /* child is "ready" */
+ return 0;
- case -1:
- return error_errno(_("could not spawn daemon in the background"));
+ case IPC_STATE__NOT_LISTENING:
+ case IPC_STATE__PATH_NOT_FOUND:
+ /* give child more time */
+ return 1;
default:
- return 0;
+ case IPC_STATE__INVALID_PATH:
+ case IPC_STATE__OTHER_ERROR:
+ /* all the time in world won't help */
+ return -1;
}
}
-#else
-/*
- * Conceptually like `daemonize()` but different because Windows does not
- * have `fork(2)`. Spawn a normal Windows child process but without the
- * limitations of `start_command()` and `finish_command()`.
- */
-static int spawn_server(pid_t *pid)
-{
- char test_tool_exe[MAX_PATH];
- struct strvec args = STRVEC_INIT;
- int in, out;
-
- GetModuleFileNameA(NULL, test_tool_exe, MAX_PATH);
-
- in = open("/dev/null", O_RDONLY);
- out = open("/dev/null", O_WRONLY);
-
- strvec_push(&args, test_tool_exe);
- strvec_push(&args, "simple-ipc");
- strvec_push(&args, "run-daemon");
- strvec_pushf(&args, "--name=%s", cl_args.path);
- strvec_pushf(&args, "--threads=%d", cl_args.nr_threads);
- *pid = mingw_spawnvpe(args.v[0], args.v, NULL, NULL, in, out, out);
- close(in);
- close(out);
-
- strvec_clear(&args);
-
- if (*pid < 0)
- return error(_("could not spawn daemon in the background"));
-
- return 0;
-}
-#endif
-
-/*
- * This is adapted from `wait_or_whine()`. Watch the child process and
- * let it get started and begin listening for requests on the socket
- * before reporting our success.
- */
-static int wait_for_server_startup(pid_t pid_child)
+static int daemon__start_server(void)
{
- int status;
- pid_t pid_seen;
- enum ipc_active_state s;
- time_t time_limit, now;
+ struct child_process cp = CHILD_PROCESS_INIT;
+ enum start_bg_result sbgr;
- time(&time_limit);
- time_limit += cl_args.max_wait_sec;
+ strvec_push(&cp.args, "test-tool");
+ strvec_push(&cp.args, "simple-ipc");
+ strvec_push(&cp.args, "run-daemon");
+ strvec_pushf(&cp.args, "--name=%s", cl_args.path);
+ strvec_pushf(&cp.args, "--threads=%d", cl_args.nr_threads);
- for (;;) {
- pid_seen = waitpid(pid_child, &status, WNOHANG);
-
- if (pid_seen == -1)
- return error_errno(_("waitpid failed"));
-
- else if (pid_seen == 0) {
- /*
- * The child is still running (this should be
- * the normal case). Try to connect to it on
- * the socket and see if it is ready for
- * business.
- *
- * If there is another daemon already running,
- * our child will fail to start (possibly
- * after a timeout on the lock), but we don't
- * care (who responds) if the socket is live.
- */
- s = ipc_get_active_state(cl_args.path);
- if (s == IPC_STATE__LISTENING)
- return 0;
+ cp.no_stdin = 1;
+ cp.no_stdout = 1;
+ cp.no_stderr = 1;
- time(&now);
- if (now > time_limit)
- return error(_("daemon not online yet"));
+ sbgr = start_bg_command(&cp, bg_wait_cb, NULL, cl_args.max_wait_sec);
- continue;
- }
+ switch (sbgr) {
+ case SBGR_READY:
+ return 0;
- else if (pid_seen == pid_child) {
- /*
- * The new child daemon process shutdown while
- * it was starting up, so it is not listening
- * on the socket.
- *
- * Try to ping the socket in the odd chance
- * that another daemon started (or was already
- * running) while our child was starting.
- *
- * Again, we don't care who services the socket.
- */
- s = ipc_get_active_state(cl_args.path);
- if (s == IPC_STATE__LISTENING)
- return 0;
+ default:
+ case SBGR_ERROR:
+ case SBGR_CB_ERROR:
+ return error("daemon failed to start");
- /*
- * We don't care about the WEXITSTATUS() nor
- * any of the WIF*(status) values because
- * `cmd__simple_ipc()` does the `!!result`
- * trick on all function return values.
- *
- * So it is sufficient to just report the
- * early shutdown as an error.
- */
- return error(_("daemon failed to start"));
- }
+ case SBGR_TIMEOUT:
+ return error("daemon not online yet");
- else
- return error(_("waitpid is confused"));
+ case SBGR_DIED:
+ return error("daemon terminated");
}
}
/*
- * This process will start a simple-ipc server in a background process and
- * wait for it to become ready. This is like `daemonize()` but gives us
- * more control and better error reporting (and makes it easier to write
- * unit tests).
- */
-static int daemon__start_server(void)
-{
- pid_t pid_child;
- int ret;
-
- /*
- * Run the actual daemon in a background process.
- */
- ret = spawn_server(&pid_child);
- if (pid_child <= 0)
- return ret;
-
- /*
- * Let the parent wait for the child process to get started
- * and begin listening for requests on the socket.
- */
- ret = wait_for_server_startup(pid_child);
-
- return ret;
-}
-
-/*
* This process will run a quick probe to see if a simple-ipc server
* is active on this path.
*
@@ -488,7 +383,9 @@ static int client__send_ipc(void)
options.wait_if_busy = 1;
options.wait_if_not_found = 0;
- if (!ipc_client_send_command(cl_args.path, &options, command, &buf)) {
+ if (!ipc_client_send_command(cl_args.path, &options,
+ command, strlen(command),
+ &buf)) {
if (buf.len) {
printf("%s\n", buf.buf);
fflush(stdout);
@@ -538,7 +435,7 @@ static int client__stop_server(void)
time(&now);
if (now > time_limit)
- return error(_("daemon has not shutdown yet"));
+ return error("daemon has not shutdown yet");
}
}
@@ -556,7 +453,9 @@ static int do_sendbytes(int bytecount, char byte, const char *path,
strbuf_addstr(&buf_send, "sendbytes ");
strbuf_addchars(&buf_send, byte, bytecount);
- if (!ipc_client_send_command(path, options, buf_send.buf, &buf_resp)) {
+ if (!ipc_client_send_command(path, options,
+ buf_send.buf, buf_send.len,
+ &buf_resp)) {
strbuf_rtrim(&buf_resp);
printf("sent:%c%08d %s\n", byte, bytecount, buf_resp.buf);
fflush(stdout);
diff --git a/t/lib-diff-data.sh b/t/lib-diff-data.sh
new file mode 100644
index 0000000000..c64ec18324
--- /dev/null
+++ b/t/lib-diff-data.sh
@@ -0,0 +1,22 @@
+COPYING_test_data () {
+ cat <<\EOF
+
+ Note that the only valid version of the GPL as far as this project
+ is concerned is _this_ particular version of the license (ie v2, not
+ v2.2 or v3.x or whatever), unless explicitly otherwise stated.
+
+ HOWEVER, in order to allow a migration to GPLv3 if that seems like
+ a good idea, I also ask that people involved with the project make
+ their preferences known. In particular, if you trust me to make that
+ decision, you might note so in your copyright message, ie something
+ like
+
+ This file is licensed under the GPL v2, or a later version
+ at the discretion of Linus.
+
+ might avoid issues. But we can also just decide to synchronize and
+ contact all copyright holders on record if/when the occasion arises.
+
+ Linus Torvalds
+EOF
+}
diff --git a/t/lib-diff.sh b/t/lib-diff.sh
index 2de880f7a5..c4606bd4b7 100644
--- a/t/lib-diff.sh
+++ b/t/lib-diff.sh
@@ -1,3 +1,5 @@
+. "$TEST_DIRECTORY"/lib-diff-data.sh
+
:
sanitize_diff_raw='/^:/s/ '"\($OID_REGEX\)"' '"\($OID_REGEX\)"' \([A-Z]\)[0-9]* / \1 \2 \3# /'
diff --git a/t/lib-diff/COPYING b/t/lib-diff/COPYING
deleted file mode 100644
index 6ff87c4664..0000000000
--- a/t/lib-diff/COPYING
+++ /dev/null
@@ -1,361 +0,0 @@
-
- Note that the only valid version of the GPL as far as this project
- is concerned is _this_ particular version of the license (ie v2, not
- v2.2 or v3.x or whatever), unless explicitly otherwise stated.
-
- HOWEVER, in order to allow a migration to GPLv3 if that seems like
- a good idea, I also ask that people involved with the project make
- their preferences known. In particular, if you trust me to make that
- decision, you might note so in your copyright message, ie something
- like
-
- This file is licensed under the GPL v2, or a later version
- at the discretion of Linus.
-
- might avoid issues. But we can also just decide to synchronize and
- contact all copyright holders on record if/when the occasion arises.
-
- Linus Torvalds
-
-----------------------------------------
-
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/t/lib-diff/README b/t/lib-diff/README
deleted file mode 100644
index 548142c327..0000000000
--- a/t/lib-diff/README
+++ /dev/null
@@ -1,46 +0,0 @@
-////////////////////////////////////////////////////////////////
-
- GIT - the stupid content tracker
-
-////////////////////////////////////////////////////////////////
-
-"git" can mean anything, depending on your mood.
-
- - random three-letter combination that is pronounceable, and not
- actually used by any common UNIX command. The fact that it is a
- mispronunciation of "get" may or may not be relevant.
- - stupid. contemptible and despicable. simple. Take your pick from the
- dictionary of slang.
- - "global information tracker": you're in a good mood, and it actually
- works for you. Angels sing, and a light suddenly fills the room.
- - "goddamn idiotic truckload of sh*t": when it breaks
-
-Git is a fast, scalable, distributed revision control system with an
-unusually rich command set that provides both high-level operations
-and full access to internals.
-
-Git is an Open Source project covered by the GNU General Public License.
-It was originally written by Linus Torvalds with help of a group of
-hackers around the net. It is currently maintained by Junio C Hamano.
-
-Please read the file INSTALL for installation instructions.
-See Documentation/tutorial.txt to get started, then see
-Documentation/everyday.txt for a useful minimum set of commands,
-and "man git-commandname" for documentation of each command.
-CVS users may also want to read Documentation/cvs-migration.txt.
-
-Many Git online resources are accessible from http://git.or.cz/
-including full documentation and Git related tools.
-
-The user discussion and development of Git take place on the Git
-mailing list -- everyone is welcome to post bug reports, feature
-requests, comments and patches to git@vger.kernel.org. To subscribe
-to the list, send an email with just "subscribe git" in the body to
-majordomo@vger.kernel.org. The mailing list archives are available at
-http://marc.theaimsgroup.com/?l=git and other archival sites.
-
-The messages titled "A note from the maintainer", "What's in
-git.git (stable)" and "What's cooking in git.git (topics)" and
-the discussion following them on the mailing list give a good
-reference for project status, development direction and
-remaining tasks.
diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh
index 9fc5241228..a3f285f515 100644
--- a/t/lib-gpg.sh
+++ b/t/lib-gpg.sh
@@ -87,6 +87,41 @@ test_lazy_prereq RFC1991 '
echo | gpg --homedir "${GNUPGHOME}" -b --rfc1991 >/dev/null
'
+GPGSSH_KEY_PRIMARY="${GNUPGHOME}/ed25519_ssh_signing_key"
+GPGSSH_KEY_SECONDARY="${GNUPGHOME}/rsa_2048_ssh_signing_key"
+GPGSSH_KEY_UNTRUSTED="${GNUPGHOME}/untrusted_ssh_signing_key"
+GPGSSH_KEY_WITH_PASSPHRASE="${GNUPGHOME}/protected_ssh_signing_key"
+GPGSSH_KEY_PASSPHRASE="super_secret"
+GPGSSH_ALLOWED_SIGNERS="${GNUPGHOME}/ssh.all_valid.allowedSignersFile"
+
+GPGSSH_GOOD_SIGNATURE_TRUSTED='Good "git" signature for'
+GPGSSH_GOOD_SIGNATURE_UNTRUSTED='Good "git" signature with'
+GPGSSH_KEY_NOT_TRUSTED="No principal matched"
+GPGSSH_BAD_SIGNATURE="Signature verification failed"
+
+test_lazy_prereq GPGSSH '
+ ssh_version=$(ssh-keygen -Y find-principals -n "git" 2>&1)
+ test $? != 127 || exit 1
+ echo $ssh_version | grep -q "find-principals:missing signature file"
+ test $? = 0 || exit 1;
+
+ # some broken versions of ssh-keygen segfault on find-principals;
+ # avoid testing with them.
+ ssh-keygen -Y find-principals -f /dev/null -s /dev/null
+ test $? = 139 && exit 1
+
+ mkdir -p "${GNUPGHOME}" &&
+ chmod 0700 "${GNUPGHOME}" &&
+ (setfacl -k "${GNUPGHOME}" 2>/dev/null || true) &&
+ ssh-keygen -t ed25519 -N "" -C "git ed25519 key" -f "${GPGSSH_KEY_PRIMARY}" >/dev/null &&
+ echo "\"principal with number 1\" $(cat "${GPGSSH_KEY_PRIMARY}.pub")" >> "${GPGSSH_ALLOWED_SIGNERS}" &&
+ ssh-keygen -t rsa -b 2048 -N "" -C "git rsa2048 key" -f "${GPGSSH_KEY_SECONDARY}" >/dev/null &&
+ echo "\"principal with number 2\" $(cat "${GPGSSH_KEY_SECONDARY}.pub")" >> "${GPGSSH_ALLOWED_SIGNERS}" &&
+ ssh-keygen -t ed25519 -N "${GPGSSH_KEY_PASSPHRASE}" -C "git ed25519 encrypted key" -f "${GPGSSH_KEY_WITH_PASSPHRASE}" >/dev/null &&
+ echo "\"principal with number 3\" $(cat "${GPGSSH_KEY_WITH_PASSPHRASE}.pub")" >> "${GPGSSH_ALLOWED_SIGNERS}" &&
+ ssh-keygen -t ed25519 -N "" -f "${GPGSSH_KEY_UNTRUSTED}" >/dev/null
+'
+
sanitize_pgp() {
perl -ne '
/^-----END PGP/ and $in_pgp = 0;
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index d2edfa4c50..782891908d 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -131,6 +131,7 @@ prepare_httpd() {
cp "$TEST_PATH"/passwd "$HTTPD_ROOT_PATH"
install_script incomplete-length-upload-pack-v2-http.sh
install_script incomplete-body-upload-pack-v2-http.sh
+ install_script error-no-report.sh
install_script broken-smart-http.sh
install_script error-smart-http.sh
install_script error.sh
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 180a41fe96..497b9b9d92 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -122,6 +122,7 @@ Alias /auth/dumb/ www/auth/dumb/
</LocationMatch>
ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/
ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/
+ScriptAlias /smart/no_report/git-receive-pack error-no-report.sh/
ScriptAliasMatch /error_git_upload_pack/(.*)/git-upload-pack error.sh/
ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1
ScriptAlias /broken_smart/ broken-smart-http.sh/
@@ -137,6 +138,9 @@ ScriptAliasMatch /one_time_perl/(.*) apply-one-time-perl.sh/$1
<Files incomplete-body-upload-pack-v2-http.sh>
Options ExecCGI
</Files>
+<Files error-no-report.sh>
+ Options ExecCGI
+</Files>
<Files broken-smart-http.sh>
Options ExecCGI
</Files>
diff --git a/t/lib-httpd/error-no-report.sh b/t/lib-httpd/error-no-report.sh
new file mode 100644
index 0000000000..39ff75bbc4
--- /dev/null
+++ b/t/lib-httpd/error-no-report.sh
@@ -0,0 +1,6 @@
+echo "Content-Type: application/x-git-receive-pack-result"
+echo
+printf '0013\001000eunpack ok\n'
+printf '0015\002skipping report\n'
+printf '0009\0010000'
+printf '0000'
diff --git a/t/lib-midx.sh b/t/lib-midx.sh
new file mode 100644
index 0000000000..1261994744
--- /dev/null
+++ b/t/lib-midx.sh
@@ -0,0 +1,8 @@
+# test_midx_consistent <objdir>
+test_midx_consistent () {
+ ls $1/pack/pack-*.idx | xargs -n 1 basename | sort >expect &&
+ test-tool read-midx $1 | grep ^pack-.*\.idx$ | sort >actual &&
+
+ test_cmp expect actual &&
+ git multi-pack-index --object-dir=$1 verify
+}
diff --git a/t/lib-subtest.sh b/t/lib-subtest.sh
new file mode 100644
index 0000000000..56ee927f0c
--- /dev/null
+++ b/t/lib-subtest.sh
@@ -0,0 +1,95 @@
+write_sub_test_lib_test () {
+ name="$1" # stdin is the body of the test code
+ mkdir "$name" &&
+ write_script "$name/$name.sh" "$TEST_SHELL_PATH" <<-EOF &&
+ test_description='A test of test-lib.sh itself'
+
+ # Point to the t/test-lib.sh, which isn't in ../ as usual
+ . "\$TEST_DIRECTORY"/test-lib.sh
+ EOF
+ cat >>"$name/$name.sh"
+}
+
+_run_sub_test_lib_test_common () {
+ cmp_op="$1" want_code="$2" name="$3" # stdin is the body of the test code
+ shift 3
+
+ # intercept pseudo-options at the front of the argument list that we
+ # will not pass to child script
+ skip=
+ while test $# -gt 0
+ do
+ case "$1" in
+ --skip=*)
+ skip=${1#--*=}
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+
+ (
+ cd "$name" &&
+
+ # Pretend we're not running under a test harness, whether we
+ # are or not. The test-lib output depends on the setting of
+ # this variable, so we need a stable setting under which to run
+ # the sub-test.
+ sane_unset HARNESS_ACTIVE &&
+
+ export TEST_DIRECTORY &&
+ # The child test re-sources GIT-BUILD-OPTIONS and may thus
+ # override the test output directory. We thus pass it as an
+ # explicit override to the child.
+ TEST_OUTPUT_DIRECTORY_OVERRIDE=$(pwd) &&
+ export TEST_OUTPUT_DIRECTORY_OVERRIDE &&
+ GIT_SKIP_TESTS=$skip &&
+ export GIT_SKIP_TESTS &&
+ sane_unset GIT_TEST_FAIL_PREREQS &&
+ ./"$name.sh" "$@" >out 2>err;
+ ret=$? &&
+ test "$ret" "$cmp_op" "$want_code"
+ )
+}
+
+write_and_run_sub_test_lib_test () {
+ name="$1" descr="$2" # stdin is the body of the test code
+ write_sub_test_lib_test "$@" || return 1
+ _run_sub_test_lib_test_common -eq 0 "$@"
+}
+
+write_and_run_sub_test_lib_test_err () {
+ name="$1" descr="$2" # stdin is the body of the test code
+ write_sub_test_lib_test "$@" || return 1
+ _run_sub_test_lib_test_common -eq 1 "$@"
+}
+
+run_sub_test_lib_test () {
+ _run_sub_test_lib_test_common -eq 0 "$@"
+}
+
+run_sub_test_lib_test_err () {
+ _run_sub_test_lib_test_common -eq 1 "$@"
+}
+
+_check_sub_test_lib_test_common () {
+ name="$1" &&
+ sed -e 's/^> //' -e 's/Z$//' >"$name"/expect.out &&
+ test_cmp "$name"/expect.out "$name"/out
+}
+
+check_sub_test_lib_test () {
+ name="$1" # stdin is the expected output from the test
+ _check_sub_test_lib_test_common "$name" &&
+ test_must_be_empty "$name"/err
+}
+
+check_sub_test_lib_test_err () {
+ name="$1" # stdin is the expected output from the test
+ _check_sub_test_lib_test_common "$name" &&
+ # expected error output is in descriptor 3
+ sed -e 's/^> //' -e 's/Z$//' <&3 >"$name"/expect.err &&
+ test_cmp "$name"/expect.err "$name"/err
+}
diff --git a/t/oid-info/oid b/t/oid-info/oid
index a754970523..7547d2c790 100644
--- a/t/oid-info/oid
+++ b/t/oid-info/oid
@@ -27,3 +27,5 @@ numeric sha1:0123456789012345678901234567890123456789
numeric sha256:0123456789012345678901234567890123456789012345678901234567890123
deadbeef sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
deadbeef sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
+deadbeef_short sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbee
+deadbeef_short sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbee
diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl
index 82c0df4553..575d2000cc 100755
--- a/t/perf/aggregate.perl
+++ b/t/perf/aggregate.perl
@@ -17,8 +17,8 @@ sub get_times {
my $rt = ((defined $1 ? $1 : 0.0)*60+$2)*60+$3;
return ($rt, $4, $5);
# size
- } elsif ($line =~ /^\d+$/) {
- return $&;
+ } elsif ($line =~ /^\s*(\d+)$/) {
+ return $1;
} else {
die "bad input line: $line";
}
diff --git a/t/perf/config b/t/perf/config
new file mode 100644
index 0000000000..b92768b039
--- /dev/null
+++ b/t/perf/config
@@ -0,0 +1,2 @@
+[gc]
+ auto = 0
diff --git a/t/perf/p0071-sort.sh b/t/perf/p0071-sort.sh
index 6e924f5fa3..ed366e2e12 100755
--- a/t/perf/p0071-sort.sh
+++ b/t/perf/p0071-sort.sh
@@ -11,16 +11,42 @@ test_expect_success 'setup' '
git cat-file --batch >unsorted
'
-test_perf 'sort(1)' '
- sort <unsorted >expect
+test_perf 'sort(1) unsorted' '
+ sort <unsorted >sorted
'
-test_perf 'string_list_sort()' '
- test-tool string-list sort <unsorted >actual
+test_expect_success 'reverse' '
+ sort -r <unsorted >reversed
'
-test_expect_success 'string_list_sort() sorts like sort(1)' '
- test_cmp_bin expect actual
-'
+for file in sorted reversed
+do
+ test_perf "sort(1) $file" "
+ sort <$file >actual
+ "
+done
+
+for file in unsorted sorted reversed
+do
+
+ test_perf "string_list_sort() $file" "
+ test-tool string-list sort <$file >actual
+ "
+
+ test_expect_success "string_list_sort() $file sorts like sort(1)" "
+ test_cmp_bin sorted actual
+ "
+done
+
+for file in unsorted sorted reversed
+do
+ test_perf "llist_mergesort() $file" "
+ test-tool mergesort sort <$file >actual
+ "
+
+ test_expect_success "llist_mergesort() $file sorts like sort(1)" "
+ test_cmp_bin sorted actual
+ "
+done
test_done
diff --git a/t/perf/p2000-sparse-operations.sh b/t/perf/p2000-sparse-operations.sh
index 597626276f..bfd332120c 100755
--- a/t/perf/p2000-sparse-operations.sh
+++ b/t/perf/p2000-sparse-operations.sh
@@ -110,5 +110,8 @@ test_perf_on_all git add -A
test_perf_on_all git add .
test_perf_on_all git commit -a -m A
test_perf_on_all git checkout -f -
+test_perf_on_all git reset
+test_perf_on_all git reset --hard
+test_perf_on_all git reset -- does-not-exist
test_done
diff --git a/t/perf/p3400-rebase.sh b/t/perf/p3400-rebase.sh
index 7a0bb29448..43d5a34e8c 100755
--- a/t/perf/p3400-rebase.sh
+++ b/t/perf/p3400-rebase.sh
@@ -18,7 +18,7 @@ test_expect_success 'setup rebasing on top of a lot of changes' '
test_tick &&
git commit -m commit$i unrelated-file$i &&
echo change$i >unrelated-file$i &&
- test_seq 1000 | tac >>unrelated-file$i &&
+ test_seq 1000 | sort -nr >>unrelated-file$i &&
git add unrelated-file$i &&
test_tick &&
git commit -m commit$i-reverse unrelated-file$i ||
diff --git a/t/perf/p5326-multi-pack-bitmaps.sh b/t/perf/p5326-multi-pack-bitmaps.sh
index 5845109ac7..f2fa228f16 100755
--- a/t/perf/p5326-multi-pack-bitmaps.sh
+++ b/t/perf/p5326-multi-pack-bitmaps.sh
@@ -6,15 +6,24 @@ test_description='Tests performance using midx bitmaps'
test_perf_large_repo
-test_expect_success 'enable multi-pack index' '
- git config core.multiPackIndex true
+# we need to create the tag up front such that it is covered by the repack and
+# thus by generated bitmaps.
+test_expect_success 'create tags' '
+ git tag --message="tag pointing to HEAD" perf-tag HEAD
+'
+
+test_expect_success 'start with bitmapped pack' '
+ git repack -adb
'
test_perf 'setup multi-pack index' '
- git repack -ad &&
git multi-pack-index write --bitmap
'
+test_expect_success 'drop pack bitmap' '
+ rm -f .git/objects/pack/pack-*.bitmap
+'
+
test_full_bitmap
test_expect_success 'create partial bitmap state' '
diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index f5ed092ee5..780a7402d5 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -27,6 +27,10 @@ TEST_NO_MALLOC_CHECK=t
. ../test-lib.sh
+unset GIT_CONFIG_NOSYSTEM
+GIT_CONFIG_SYSTEM="$TEST_DIRECTORY/perf/config"
+export GIT_CONFIG_SYSTEM
+
if test -n "$GIT_TEST_INSTALLED" -a -z "$PERF_SET_GIT_TEST_INSTALLED"
then
error "Do not use GIT_TEST_INSTALLED with the perf tests.
@@ -230,6 +234,7 @@ test_perf_ () {
test_ok_ "$1"
fi
"$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".result
+ rm test_time.*
}
test_perf () {
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 5c342de713..b007f0efef 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -19,6 +19,7 @@ modification *should* take notice and update the test vectors here.
'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-subtest.sh
try_local_xy () {
local x="local" y="alsolocal" &&
@@ -66,95 +67,8 @@ test_expect_success 'success is reported like this' '
:
'
-_run_sub_test_lib_test_common () {
- neg="$1" name="$2" descr="$3" # stdin is the body of the test code
- shift 3
-
- # intercept pseudo-options at the front of the argument list that we
- # will not pass to child script
- skip=
- while test $# -gt 0
- do
- case "$1" in
- --skip=*)
- skip=${1#--*=}
- shift
- ;;
- *)
- break
- ;;
- esac
- done
-
- mkdir "$name" &&
- (
- # Pretend we're not running under a test harness, whether we
- # are or not. The test-lib output depends on the setting of
- # this variable, so we need a stable setting under which to run
- # the sub-test.
- sane_unset HARNESS_ACTIVE &&
- cd "$name" &&
- write_script "$name.sh" "$TEST_SHELL_PATH" <<-EOF &&
- test_description='$descr (run in sub test-lib)
-
- This is run in a sub test-lib so that we do not get incorrect
- passing metrics
- '
-
- # Point to the t/test-lib.sh, which isn't in ../ as usual
- . "\$TEST_DIRECTORY"/test-lib.sh
- EOF
- cat >>"$name.sh" &&
- export TEST_DIRECTORY &&
- # The child test re-sources GIT-BUILD-OPTIONS and may thus
- # override the test output directory. We thus pass it as an
- # explicit override to the child.
- TEST_OUTPUT_DIRECTORY_OVERRIDE=$(pwd) &&
- export TEST_OUTPUT_DIRECTORY_OVERRIDE &&
- GIT_SKIP_TESTS=$skip &&
- export GIT_SKIP_TESTS &&
- sane_unset GIT_TEST_FAIL_PREREQS &&
- if test -z "$neg"
- then
- ./"$name.sh" "$@" >out 2>err
- else
- ! ./"$name.sh" "$@" >out 2>err
- fi
- )
-}
-
-run_sub_test_lib_test () {
- _run_sub_test_lib_test_common '' "$@"
-}
-
-run_sub_test_lib_test_err () {
- _run_sub_test_lib_test_common '!' "$@"
-}
-
-check_sub_test_lib_test () {
- name="$1" # stdin is the expected output from the test
- (
- cd "$name" &&
- test_must_be_empty err &&
- sed -e 's/^> //' -e 's/Z$//' >expect &&
- test_cmp expect out
- )
-}
-
-check_sub_test_lib_test_err () {
- name="$1" # stdin is the expected output from the test
- # expected error output is in descriptor 3
- (
- cd "$name" &&
- sed -e 's/^> //' -e 's/Z$//' >expect.out &&
- test_cmp expect.out out &&
- sed -e 's/^> //' -e 's/Z$//' <&3 >expect.err &&
- test_cmp expect.err err
- )
-}
-
-test_expect_success 'pretend we have a fully passing test suite' '
- run_sub_test_lib_test full-pass "3 passing tests" <<-\EOF &&
+test_expect_success 'subtest: 3 passing tests' '
+ write_and_run_sub_test_lib_test full-pass <<-\EOF &&
for i in 1 2 3
do
test_expect_success "passing test #$i" "true"
@@ -170,9 +84,8 @@ test_expect_success 'pretend we have a fully passing test suite' '
EOF
'
-test_expect_success 'pretend we have a partially passing test suite' '
- run_sub_test_lib_test_err \
- partial-pass "2/3 tests passing" <<-\EOF &&
+test_expect_success 'subtest: 2/3 tests passing' '
+ write_and_run_sub_test_lib_test_err partial-pass <<-\EOF &&
test_expect_success "passing test #1" "true"
test_expect_success "failing test #2" "false"
test_expect_success "passing test #3" "true"
@@ -188,8 +101,8 @@ test_expect_success 'pretend we have a partially passing test suite' '
EOF
'
-test_expect_success 'pretend we have a known breakage' '
- run_sub_test_lib_test failing-todo "A failing TODO test" <<-\EOF &&
+test_expect_success 'subtest: a failing TODO test' '
+ write_and_run_sub_test_lib_test failing-todo <<-\EOF &&
test_expect_success "passing test" "true"
test_expect_failure "pretend we have a known breakage" "false"
test_done
@@ -203,8 +116,8 @@ test_expect_success 'pretend we have a known breakage' '
EOF
'
-test_expect_success 'pretend we have fixed a known breakage' '
- run_sub_test_lib_test passing-todo "A passing TODO test" <<-\EOF &&
+test_expect_success 'subtest: a passing TODO test' '
+ write_and_run_sub_test_lib_test passing-todo <<-\EOF &&
test_expect_failure "pretend we have fixed a known breakage" "true"
test_done
EOF
@@ -215,9 +128,8 @@ test_expect_success 'pretend we have fixed a known breakage' '
EOF
'
-test_expect_success 'pretend we have fixed one of two known breakages (run in sub test-lib)' '
- run_sub_test_lib_test partially-passing-todos \
- "2 TODO tests, one passing" <<-\EOF &&
+test_expect_success 'subtest: 2 TODO tests, one passin' '
+ write_and_run_sub_test_lib_test 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"
@@ -234,9 +146,8 @@ test_expect_success 'pretend we have fixed one of two known breakages (run in su
EOF
'
-test_expect_success 'pretend we have a pass, fail, and known breakage' '
- run_sub_test_lib_test_err \
- mixed-results1 "mixed results #1" <<-\EOF &&
+test_expect_success 'subtest: mixed results: pass, failure and a TODO test' '
+ write_and_run_sub_test_lib_test_err mixed-results1 <<-\EOF &&
test_expect_success "passing test" "true"
test_expect_success "failing test" "false"
test_expect_failure "pretend we have a known breakage" "false"
@@ -253,9 +164,8 @@ test_expect_success 'pretend we have a pass, fail, and known breakage' '
EOF
'
-test_expect_success 'pretend we have a mix of all possible results' '
- run_sub_test_lib_test_err \
- mixed-results2 "mixed results #2" <<-\EOF &&
+test_expect_success 'subtest: mixed results: a mixture of all possible results' '
+ write_and_run_sub_test_lib_test_err mixed-results2 <<-\EOF &&
test_expect_success "passing test" "true"
test_expect_success "passing test" "true"
test_expect_success "passing test" "true"
@@ -289,9 +199,8 @@ test_expect_success 'pretend we have a mix of all possible results' '
EOF
'
-test_expect_success 'test --verbose' '
- run_sub_test_lib_test_err \
- t1234-verbose "test verbose" --verbose <<-\EOF &&
+test_expect_success 'subtest: --verbose option' '
+ write_and_run_sub_test_lib_test_err t1234-verbose --verbose <<-\EOF &&
test_expect_success "passing test" true
test_expect_success "test with output" "echo foo"
test_expect_success "failing test" false
@@ -316,19 +225,14 @@ test_expect_success 'test --verbose' '
EOF
'
-test_expect_success 'test --verbose-only' '
+test_expect_success 'subtest: --verbose-only option' '
run_sub_test_lib_test_err \
- t2345-verbose-only-2 "test verbose-only=2" \
- --verbose-only=2 <<-\EOF &&
- test_expect_success "passing test" true
- test_expect_success "test with output" "echo foo"
- test_expect_success "failing test" false
- test_done
- EOF
- check_sub_test_lib_test t2345-verbose-only-2 <<-\EOF
+ t1234-verbose \
+ --verbose-only=2 &&
+ check_sub_test_lib_test t1234-verbose <<-\EOF
> ok 1 - passing test
> Z
- > expecting success of 2345.2 '\''test with output'\'': echo foo
+ > expecting success of 1234.2 '\''test with output'\'': echo foo
> foo
> ok 2 - test with output
> Z
@@ -339,18 +243,11 @@ test_expect_success 'test --verbose-only' '
EOF
'
-test_expect_success 'GIT_SKIP_TESTS' '
+test_expect_success 'subtest: skip one with GIT_SKIP_TESTS' '
(
- run_sub_test_lib_test git-skip-tests-basic \
- "GIT_SKIP_TESTS" \
- --skip="git.2" <<-\EOF &&
- for i in 1 2 3
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test git-skip-tests-basic <<-\EOF
+ run_sub_test_lib_test full-pass \
+ --skip="full.2" &&
+ check_sub_test_lib_test full-pass <<-\EOF
> ok 1 - passing test #1
> ok 2 # skip passing test #2 (GIT_SKIP_TESTS)
> ok 3 - passing test #3
@@ -360,10 +257,9 @@ test_expect_success 'GIT_SKIP_TESTS' '
)
'
-test_expect_success 'GIT_SKIP_TESTS several tests' '
+test_expect_success 'subtest: skip several with GIT_SKIP_TESTS' '
(
- run_sub_test_lib_test git-skip-tests-several \
- "GIT_SKIP_TESTS several tests" \
+ write_and_run_sub_test_lib_test git-skip-tests-several \
--skip="git.2 git.5" <<-\EOF &&
for i in 1 2 3 4 5 6
do
@@ -384,18 +280,11 @@ test_expect_success 'GIT_SKIP_TESTS several tests' '
)
'
-test_expect_success 'GIT_SKIP_TESTS sh pattern' '
+test_expect_success 'subtest: sh pattern skipping with GIT_SKIP_TESTS' '
(
- run_sub_test_lib_test git-skip-tests-sh-pattern \
- "GIT_SKIP_TESTS sh pattern" \
- --skip="git.[2-5]" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test git-skip-tests-sh-pattern <<-\EOF
+ run_sub_test_lib_test git-skip-tests-several \
+ --skip="git.[2-5]" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 # skip passing test #2 (GIT_SKIP_TESTS)
> ok 3 # skip passing test #3 (GIT_SKIP_TESTS)
@@ -408,35 +297,23 @@ test_expect_success 'GIT_SKIP_TESTS sh pattern' '
)
'
-test_expect_success 'GIT_SKIP_TESTS entire suite' '
+test_expect_success 'subtest: skip entire test suite with GIT_SKIP_TESTS' '
(
- run_sub_test_lib_test git-skip-tests-entire-suite \
- "GIT_SKIP_TESTS entire suite" \
- --skip="git" <<-\EOF &&
- for i in 1 2 3
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test git-skip-tests-entire-suite <<-\EOF
+ GIT_SKIP_TESTS="git" && export GIT_SKIP_TESTS &&
+ run_sub_test_lib_test git-skip-tests-several \
+ --skip="git" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> 1..0 # SKIP skip all tests in git
EOF
)
'
-test_expect_success 'GIT_SKIP_TESTS does not skip unmatched suite' '
+test_expect_success 'subtest: GIT_SKIP_TESTS does not skip unmatched suite' '
(
- run_sub_test_lib_test git-skip-tests-unmatched-suite \
- "GIT_SKIP_TESTS does not skip unmatched suite" \
- --skip="notgit" <<-\EOF &&
- for i in 1 2 3
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test git-skip-tests-unmatched-suite <<-\EOF
+ GIT_SKIP_TESTS="notgit" && export GIT_SKIP_TESTS &&
+ run_sub_test_lib_test full-pass \
+ --skip="notfull" &&
+ check_sub_test_lib_test full-pass <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 - passing test #3
@@ -446,16 +323,9 @@ test_expect_success 'GIT_SKIP_TESTS does not skip unmatched suite' '
)
'
-test_expect_success '--run basic' '
- run_sub_test_lib_test run-basic \
- "--run basic" --run="1,3,5" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-basic <<-\EOF
+test_expect_success 'subtest: --run basic' '
+ run_sub_test_lib_test git-skip-tests-several --run="1,3,5" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 # skip passing test #2 (--run)
> ok 3 - passing test #3
@@ -467,16 +337,10 @@ test_expect_success '--run basic' '
EOF
'
-test_expect_success '--run with a range' '
- run_sub_test_lib_test run-range \
- "--run with a range" --run="1-3" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-range <<-\EOF
+test_expect_success 'subtest: --run with a range' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="1-3" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 - passing test #3
@@ -488,16 +352,10 @@ test_expect_success '--run with a range' '
EOF
'
-test_expect_success '--run with two ranges' '
- run_sub_test_lib_test run-two-ranges \
- "--run with two ranges" --run="1-2,5-6" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-two-ranges <<-\EOF
+test_expect_success 'subtest: --run with two ranges' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="1-2,5-6" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -509,16 +367,10 @@ test_expect_success '--run with two ranges' '
EOF
'
-test_expect_success '--run with a left open range' '
- run_sub_test_lib_test run-left-open-range \
- "--run with a left open range" --run="-3" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-left-open-range <<-\EOF
+test_expect_success 'subtest: --run with a left open range' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="-3" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 - passing test #3
@@ -530,16 +382,10 @@ test_expect_success '--run with a left open range' '
EOF
'
-test_expect_success '--run with a right open range' '
- run_sub_test_lib_test run-right-open-range \
- "--run with a right open range" --run="4-" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-right-open-range <<-\EOF
+test_expect_success 'subtest: --run with a right open range' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="4-" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 # skip passing test #1 (--run)
> ok 2 # skip passing test #2 (--run)
> ok 3 # skip passing test #3 (--run)
@@ -551,16 +397,10 @@ test_expect_success '--run with a right open range' '
EOF
'
-test_expect_success '--run with basic negation' '
- run_sub_test_lib_test run-basic-neg \
- "--run with basic negation" --run="!3" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-basic-neg <<-\EOF
+test_expect_success 'subtest: --run with basic negation' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="!3" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -572,16 +412,10 @@ test_expect_success '--run with basic negation' '
EOF
'
-test_expect_success '--run with two negations' '
- run_sub_test_lib_test run-two-neg \
- "--run with two negations" --run="!3,!6" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-two-neg <<-\EOF
+test_expect_success 'subtest: --run with two negations' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="!3,!6" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -593,16 +427,10 @@ test_expect_success '--run with two negations' '
EOF
'
-test_expect_success '--run a range and negation' '
- run_sub_test_lib_test run-range-and-neg \
- "--run a range and negation" --run="-4,!2" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-range-and-neg <<-\EOF
+test_expect_success 'subtest: --run a range and negation' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="-4,!2" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 # skip passing test #2 (--run)
> ok 3 - passing test #3
@@ -614,16 +442,10 @@ test_expect_success '--run a range and negation' '
EOF
'
-test_expect_success '--run range negation' '
- run_sub_test_lib_test run-range-neg \
- "--run range negation" --run="!1-3" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-range-neg <<-\EOF
+test_expect_success 'subtest: --run range negation' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="!1-3" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 # skip passing test #1 (--run)
> ok 2 # skip passing test #2 (--run)
> ok 3 # skip passing test #3 (--run)
@@ -635,17 +457,10 @@ test_expect_success '--run range negation' '
EOF
'
-test_expect_success '--run include, exclude and include' '
- run_sub_test_lib_test run-inc-neg-inc \
- "--run include, exclude and include" \
- --run="1-5,!1-3,2" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-inc-neg-inc <<-\EOF
+test_expect_success 'subtest: --run include, exclude and include' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="1-5,!1-3,2" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 # skip passing test #1 (--run)
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -657,17 +472,10 @@ test_expect_success '--run include, exclude and include' '
EOF
'
-test_expect_success '--run include, exclude and include, comma separated' '
- run_sub_test_lib_test run-inc-neg-inc-comma \
- "--run include, exclude and include, comma separated" \
- --run=1-5,!1-3,2 <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-inc-neg-inc-comma <<-\EOF
+test_expect_success 'subtest: --run include, exclude and include, comma separated' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run=1-5,!1-3,2 &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 # skip passing test #1 (--run)
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -679,17 +487,10 @@ test_expect_success '--run include, exclude and include, comma separated' '
EOF
'
-test_expect_success '--run exclude and include' '
- run_sub_test_lib_test run-neg-inc \
- "--run exclude and include" \
- --run="!3-,5" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-neg-inc <<-\EOF
+test_expect_success 'subtest: --run exclude and include' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="!3-,5" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 - passing test #2
> ok 3 # skip passing test #3 (--run)
@@ -701,17 +502,10 @@ test_expect_success '--run exclude and include' '
EOF
'
-test_expect_success '--run empty selectors' '
- run_sub_test_lib_test run-empty-sel \
- "--run empty selectors" \
- --run="1,,3,,,5" <<-\EOF &&
- for i in 1 2 3 4 5 6
- do
- test_expect_success "passing test #$i" "true"
- done
- test_done
- EOF
- check_sub_test_lib_test run-empty-sel <<-\EOF
+test_expect_success 'subtest: --run empty selectors' '
+ run_sub_test_lib_test git-skip-tests-several \
+ --run="1,,3,,,5" &&
+ check_sub_test_lib_test git-skip-tests-several <<-\EOF
> ok 1 - passing test #1
> ok 2 # skip passing test #2 (--run)
> ok 3 - passing test #3
@@ -723,9 +517,8 @@ test_expect_success '--run empty selectors' '
EOF
'
-test_expect_success '--run substring selector' '
- run_sub_test_lib_test run-substring-selector \
- "--run empty selectors" \
+test_expect_success 'subtest: --run substring selector' '
+ write_and_run_sub_test_lib_test run-substring-selector \
--run="relevant" <<-\EOF &&
test_expect_success "relevant test" "true"
for i in 1 2 3 4 5 6
@@ -747,9 +540,8 @@ test_expect_success '--run substring selector' '
EOF
'
-test_expect_success '--run keyword selection' '
- run_sub_test_lib_test_err run-inv-range-start \
- "--run invalid range start" \
+test_expect_success 'subtest: --run keyword selection' '
+ write_and_run_sub_test_lib_test_err run-inv-range-start \
--run="a-5" <<-\EOF &&
test_expect_success "passing test #1" "true"
test_done
@@ -762,14 +554,10 @@ test_expect_success '--run keyword selection' '
EOF_ERR
'
-test_expect_success '--run invalid range end' '
- run_sub_test_lib_test_err run-inv-range-end \
- "--run invalid range end" \
- --run="1-z" <<-\EOF &&
- test_expect_success "passing test #1" "true"
- test_done
- EOF
- check_sub_test_lib_test_err run-inv-range-end \
+test_expect_success 'subtest: --run invalid range end' '
+ run_sub_test_lib_test_err run-inv-range-start \
+ --run="1-z" &&
+ check_sub_test_lib_test_err run-inv-range-start \
<<-\EOF_OUT 3<<-EOF_ERR
> FATAL: Unexpected exit with code 1
EOF_OUT
@@ -777,8 +565,8 @@ test_expect_success '--run invalid range end' '
EOF_ERR
'
-test_expect_success 'tests respect prerequisites' '
- run_sub_test_lib_test prereqs "tests respect prereqs" <<-\EOF &&
+test_expect_success 'subtest: tests respect prerequisites' '
+ write_and_run_sub_test_lib_test prereqs <<-\EOF &&
test_set_prereq HAVEIT
test_expect_success HAVEIT "prereq is satisfied" "true"
@@ -807,8 +595,8 @@ test_expect_success 'tests respect prerequisites' '
EOF
'
-test_expect_success 'tests respect lazy prerequisites' '
- run_sub_test_lib_test lazy-prereqs "respect lazy prereqs" <<-\EOF &&
+test_expect_success 'subtest: tests respect lazy prerequisites' '
+ write_and_run_sub_test_lib_test lazy-prereqs <<-\EOF &&
test_lazy_prereq LAZY_TRUE true
test_expect_success LAZY_TRUE "lazy prereq is satisifed" "true"
@@ -831,8 +619,8 @@ test_expect_success 'tests respect lazy prerequisites' '
EOF
'
-test_expect_success 'nested lazy prerequisites' '
- run_sub_test_lib_test nested-lazy "nested lazy prereqs" <<-\EOF &&
+test_expect_success 'subtest: nested lazy prerequisites' '
+ write_and_run_sub_test_lib_test nested-lazy <<-\EOF &&
test_lazy_prereq NESTED_INNER "
>inner &&
@@ -857,9 +645,9 @@ test_expect_success 'nested lazy prerequisites' '
EOF
'
-test_expect_success 'lazy prereqs do not turn off tracing' '
- run_sub_test_lib_test lazy-prereq-and-tracing \
- "lazy prereqs and -x" -v -x <<-\EOF &&
+test_expect_success 'subtest: lazy prereqs do not turn off tracing' '
+ write_and_run_sub_test_lib_test lazy-prereq-and-tracing \
+ -v -x <<-\EOF &&
test_lazy_prereq LAZY true
test_expect_success lazy "test_have_prereq LAZY && echo trace"
@@ -870,8 +658,8 @@ test_expect_success 'lazy prereqs do not turn off tracing' '
grep "echo trace" lazy-prereq-and-tracing/err
'
-test_expect_success 'tests clean up after themselves' '
- run_sub_test_lib_test cleanup "test with cleanup" <<-\EOF &&
+test_expect_success 'subtest: tests clean up after themselves' '
+ write_and_run_sub_test_lib_test cleanup <<-\EOF &&
clean=no
test_expect_success "do cleanup" "
test_when_finished clean=yes
@@ -890,9 +678,9 @@ test_expect_success 'tests clean up after themselves' '
EOF
'
-test_expect_success 'tests clean up even on failures' '
- run_sub_test_lib_test_err \
- failing-cleanup "Failing tests with cleanup commands" <<-\EOF &&
+test_expect_success 'subtest: tests clean up even on failures' '
+ write_and_run_sub_test_lib_test_err \
+ failing-cleanup <<-\EOF &&
test_expect_success "tests clean up even after a failure" "
touch clean-after-failure &&
test_when_finished rm clean-after-failure &&
@@ -919,9 +707,9 @@ test_expect_success 'tests clean up even on failures' '
EOF
'
-test_expect_success 'test_atexit is run' '
- run_sub_test_lib_test_err \
- atexit-cleanup "Run atexit commands" -i <<-\EOF &&
+test_expect_success 'subtest: test_atexit is run' '
+ write_and_run_sub_test_lib_test_err \
+ atexit-cleanup -i <<-\EOF &&
test_expect_success "tests clean up even after a failure" "
> ../../clean-atexit &&
test_atexit rm ../../clean-atexit &&
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index df544bb321..7603ad2f82 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -2,6 +2,7 @@
test_description='git init'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_config () {
diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh
index 8440e6add1..76052cb562 100755
--- a/t/t0002-gitfile.sh
+++ b/t/t0002-gitfile.sh
@@ -7,6 +7,7 @@ Verify that plumbing commands work when .git is a file
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
objpath() {
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index 1e4c672b84..b9ed612af1 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -2,6 +2,7 @@
test_description=gitattributes
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
attr_check_basic () {
diff --git a/t/t0004-unwritable.sh b/t/t0004-unwritable.sh
index e3137d638e..2e9d652d82 100755
--- a/t/t0004-unwritable.sh
+++ b/t/t0004-unwritable.sh
@@ -2,6 +2,7 @@
test_description='detect unwritable repository and fail correctly'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
@@ -18,27 +19,66 @@ test_expect_success setup '
test_expect_success POSIXPERM,SANITY 'write-tree should notice unwritable repository' '
test_when_finished "chmod 775 .git/objects .git/objects/??" &&
chmod a-w .git/objects .git/objects/?? &&
- test_must_fail git write-tree
+ test_must_fail git write-tree 2>out.write-tree
'
-test_expect_success POSIXPERM,SANITY 'commit should notice unwritable repository' '
+test_lazy_prereq WRITE_TREE_OUT 'test -e "$TRASH_DIRECTORY"/out.write-tree'
+test_expect_success WRITE_TREE_OUT 'write-tree output on unwritable repository' '
+ cat >expect <<-\EOF &&
+ error: insufficient permission for adding an object to repository database .git/objects
+ fatal: git-write-tree: error building trees
+ EOF
+ test_cmp expect out.write-tree
+'
+
+test_expect_success POSIXPERM,SANITY,!SANITIZE_LEAK 'commit should notice unwritable repository' '
test_when_finished "chmod 775 .git/objects .git/objects/??" &&
chmod a-w .git/objects .git/objects/?? &&
- test_must_fail git commit -m second
+ test_must_fail git commit -m second 2>out.commit
+'
+
+test_lazy_prereq COMMIT_OUT 'test -e "$TRASH_DIRECTORY"/out.commit'
+test_expect_success COMMIT_OUT 'commit output on unwritable repository' '
+ cat >expect <<-\EOF &&
+ error: insufficient permission for adding an object to repository database .git/objects
+ error: Error building trees
+ EOF
+ test_cmp expect out.commit
'
test_expect_success POSIXPERM,SANITY 'update-index should notice unwritable repository' '
test_when_finished "chmod 775 .git/objects .git/objects/??" &&
echo 6O >file &&
chmod a-w .git/objects .git/objects/?? &&
- test_must_fail git update-index file
+ test_must_fail git update-index file 2>out.update-index
+'
+
+test_lazy_prereq UPDATE_INDEX_OUT 'test -e "$TRASH_DIRECTORY"/out.update-index'
+test_expect_success UPDATE_INDEX_OUT 'update-index output on unwritable repository' '
+ cat >expect <<-\EOF &&
+ error: insufficient permission for adding an object to repository database .git/objects
+ error: file: failed to insert into database
+ fatal: Unable to process path file
+ EOF
+ test_cmp expect out.update-index
'
test_expect_success POSIXPERM,SANITY 'add should notice unwritable repository' '
test_when_finished "chmod 775 .git/objects .git/objects/??" &&
echo b >file &&
chmod a-w .git/objects .git/objects/?? &&
- test_must_fail git add file
+ test_must_fail git add file 2>out.add
+'
+
+test_lazy_prereq ADD_OUT 'test -e "$TRASH_DIRECTORY"/out.add'
+test_expect_success ADD_OUT 'add output on unwritable repository' '
+ cat >expect <<-\EOF &&
+ error: insufficient permission for adding an object to repository database .git/objects
+ error: file: failed to insert into database
+ error: unable to index file '\''file'\''
+ fatal: updating files failed
+ EOF
+ test_cmp expect out.add
'
test_done
diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh
index 4c214bd11c..a5ec6a0315 100755
--- a/t/t0005-signals.sh
+++ b/t/t0005-signals.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='signals work as we expect'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >expect <<EOF
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index 6b757d7169..794186961e 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -63,6 +63,10 @@ check_show 'format-local:%%z' "$TIME" '%z'
check_show 'format:%Y-%m-%d %H:%M:%S' "$TIME" '2016-06-15 16:13:20'
check_show 'format-local:%Y-%m-%d %H:%M:%S' "$TIME" '2016-06-15 09:13:20' '' EST5
+check_show 'format:%s' '123456789 +1234' 123456789
+check_show 'format:%s' '123456789 -1234' 123456789
+check_show 'format-local:%s' '123456789 -1234' 123456789
+
# arbitrary time absurdly far in the future
FUTURE="5758122296 -0400"
check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" TIME_IS_64BIT,TIME_T_IS_64BIT
diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh
index 88b9ae8158..e56f4b9ac5 100755
--- a/t/t0007-git-var.sh
+++ b/t/t0007-git-var.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='basic sanity checks for git var'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'get GIT_AUTHOR_IDENT' '
@@ -25,6 +27,26 @@ test_expect_success !FAIL_PREREQS,!AUTOIDENT 'requested identities are strict' '
)
'
+test_expect_success 'get GIT_DEFAULT_BRANCH without configuration' '
+ (
+ sane_unset GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+ git init defbranch &&
+ git -C defbranch symbolic-ref --short HEAD >expect &&
+ git var GIT_DEFAULT_BRANCH >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'get GIT_DEFAULT_BRANCH with configuration' '
+ test_config init.defaultbranch foo &&
+ (
+ sane_unset GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+ echo foo >expect &&
+ git var GIT_DEFAULT_BRANCH >actual &&
+ test_cmp expect actual
+ )
+'
+
# For git var -l, we check only a representative variable;
# testing the whole output would make our test too brittle with
# respect to unrelated changes in the test suite's environment.
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index a594b4aa7d..42d2314804 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -2,6 +2,7 @@
test_description=check-ignore
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
init_vars () {
@@ -802,6 +803,49 @@ test_expect_success 'existing directory and file' '
grep top-level-dir actual
'
+test_expect_success 'exact prefix matching (with root)' '
+ test_when_finished rm -r a &&
+ mkdir -p a/git a/git-foo &&
+ touch a/git/foo a/git-foo/bar &&
+ echo /git/ >a/.gitignore &&
+ git check-ignore a/git a/git/foo a/git-foo a/git-foo/bar >actual &&
+ cat >expect <<-\EOF &&
+ a/git
+ a/git/foo
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'exact prefix matching (without root)' '
+ test_when_finished rm -r a &&
+ mkdir -p a/git a/git-foo &&
+ touch a/git/foo a/git-foo/bar &&
+ echo git/ >a/.gitignore &&
+ git check-ignore a/git a/git/foo a/git-foo a/git-foo/bar >actual &&
+ cat >expect <<-\EOF &&
+ a/git
+ a/git/foo
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'directories and ** matches' '
+ cat >.gitignore <<-\EOF &&
+ data/**
+ !data/**/
+ !data/**/*.txt
+ EOF
+ git check-ignore file \
+ data/file data/data1/file1 data/data1/file1.txt \
+ data/data2/file2 data/data2/file2.txt >actual &&
+ cat >expect <<-\EOF &&
+ data/file
+ data/data1/file1
+ data/data2/file2
+ EOF
+ test_cmp expect actual
+'
+
############################################################################
#
# test whitespace handling
diff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh
index 3941ad2528..eea99107a4 100755
--- a/t/t0009-prio-queue.sh
+++ b/t/t0009-prio-queue.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='basic tests for priority queue implementation'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >expect <<'EOF'
diff --git a/t/t0010-racy-git.sh b/t/t0010-racy-git.sh
index 5657c5a87b..837c8b7228 100755
--- a/t/t0010-racy-git.sh
+++ b/t/t0010-racy-git.sh
@@ -2,6 +2,7 @@
test_description='racy GIT'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# This test can give false success if your machine is sufficiently
diff --git a/t/t0011-hashmap.sh b/t/t0011-hashmap.sh
index 5343ffd3f9..e094975b13 100755
--- a/t/t0011-hashmap.sh
+++ b/t/t0011-hashmap.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test hashmap and string hash functions'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_hashmap() {
diff --git a/t/t0012-help.sh b/t/t0012-help.sh
index 913f34c8e9..91b68c74a1 100755
--- a/t/t0012-help.sh
+++ b/t/t0012-help.sh
@@ -34,6 +34,18 @@ test_expect_success 'basic help commands' '
git help -a >/dev/null
'
+test_expect_success 'invalid usage' '
+ test_expect_code 129 git help -g add &&
+ test_expect_code 129 git help -a -c &&
+
+ test_expect_code 129 git help -g add &&
+ test_expect_code 129 git help -a -g &&
+
+ test_expect_code 129 git help -g -c &&
+ test_expect_code 129 git help --config-for-completion add &&
+ test_expect_code 129 git help --config-sections-for-completion add
+'
+
test_expect_success "works for commands and guides by default" '
configure_help &&
git help status &&
@@ -89,6 +101,43 @@ test_expect_success 'git help succeeds without git.html' '
test_cmp expect test-browser.log
'
+test_expect_success 'git help -c' '
+ git help -c >help.output &&
+ cat >expect <<-\EOF &&
+
+ '\''git help config'\'' for more information
+ EOF
+ grep -v -E \
+ -e "^[^.]+\.[^.]+$" \
+ -e "^[^.]+\.[^.]+\.[^.]+$" \
+ help.output >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git help --config-for-completion' '
+ git help -c >human &&
+ grep -E \
+ -e "^[^.]+\.[^.]+$" \
+ -e "^[^.]+\.[^.]+\.[^.]+$" human |
+ sed -e "s/\*.*//" -e "s/<.*//" |
+ sort -u >human.munged &&
+
+ git help --config-for-completion >vars &&
+ test_cmp human.munged vars
+'
+
+test_expect_success 'git help --config-sections-for-completion' '
+ git help -c >human &&
+ grep -E \
+ -e "^[^.]+\.[^.]+$" \
+ -e "^[^.]+\.[^.]+\.[^.]+$" human |
+ sed -e "s/\..*//" |
+ sort -u >human.munged &&
+
+ git help --config-sections-for-completion >sections &&
+ test_cmp human.munged sections
+'
+
test_expect_success 'generate builtin list' '
git --list-cmds=builtins >builtins
'
diff --git a/t/t0013-sha1dc.sh b/t/t0013-sha1dc.sh
index 419f31a8f7..9ad76080aa 100755
--- a/t/t0013-sha1dc.sh
+++ b/t/t0013-sha1dc.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test sha1 collision detection'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
TEST_DATA="$TEST_DIRECTORY/t0013"
diff --git a/t/t0016-oidmap.sh b/t/t0016-oidmap.sh
index 31f8276ba8..0faef1f4f1 100755
--- a/t/t0016-oidmap.sh
+++ b/t/t0016-oidmap.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test oidmap'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# This purposefully is very similar to t0011-hashmap.sh
diff --git a/t/t0017-env-helper.sh b/t/t0017-env-helper.sh
index 4a159f99e4..2e42fba956 100755
--- a/t/t0017-env-helper.sh
+++ b/t/t0017-env-helper.sh
@@ -2,6 +2,7 @@
test_description='test env--helper'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
diff --git a/t/t0018-advice.sh b/t/t0018-advice.sh
index 39e5e4b34f..c13057a4ca 100755
--- a/t/t0018-advice.sh
+++ b/t/t0018-advice.sh
@@ -2,6 +2,7 @@
test_description='Test advise_if_enabled functionality'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'advice should be printed when config variable is unset' '
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index f25ae8b5e1..4125ab8b88 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -5,6 +5,7 @@ test_description='CRLF conversion'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
has_cr() {
diff --git a/t/t0022-crlf-rename.sh b/t/t0022-crlf-rename.sh
index 7af3fbcc7b..c1a331e9e9 100755
--- a/t/t0022-crlf-rename.sh
+++ b/t/t0022-crlf-rename.sh
@@ -2,6 +2,7 @@
test_description='ignore CR in CRLF sequence while computing similiarity'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t0024-crlf-archive.sh b/t/t0024-crlf-archive.sh
index 4e9fa3cd68..a34de56420 100755
--- a/t/t0024-crlf-archive.sh
+++ b/t/t0024-crlf-archive.sh
@@ -2,6 +2,7 @@
test_description='respect crlf in git archive'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t0025-crlf-renormalize.sh b/t/t0025-crlf-renormalize.sh
index e13363ade5..81447978b7 100755
--- a/t/t0025-crlf-renormalize.sh
+++ b/t/t0025-crlf-renormalize.sh
@@ -2,6 +2,7 @@
test_description='CRLF renormalization'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t0026-eol-config.sh b/t/t0026-eol-config.sh
index c5203e232c..cdcafcdff7 100755
--- a/t/t0026-eol-config.sh
+++ b/t/t0026-eol-config.sh
@@ -2,6 +2,7 @@
test_description='CRLF conversion'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
has_cr() {
diff --git a/t/t0029-core-unsetenvvars.sh b/t/t0029-core-unsetenvvars.sh
index 24ce46a6ea..b138e1d9cb 100755
--- a/t/t0029-core-unsetenvvars.sh
+++ b/t/t0029-core-unsetenvvars.sh
@@ -2,6 +2,7 @@
test_description='test the Windows-only core.unsetenvvars setting'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
if ! test_have_prereq MINGW
diff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh
index 0c24a0f9a3..ae1ca380c1 100755
--- a/t/t0030-stripspace.sh
+++ b/t/t0030-stripspace.sh
@@ -5,6 +5,7 @@
test_description='git stripspace'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
t40='A quick brown fox jumps over the lazy do'
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index da310ed29b..ed2fb620a9 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -5,6 +5,7 @@
test_description='our own option parser'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >expect <<\EOF
@@ -168,9 +169,45 @@ test_expect_success 'long options' '
'
test_expect_success 'missing required value' '
- test_expect_code 129 test-tool parse-options -s &&
- test_expect_code 129 test-tool parse-options --string &&
- test_expect_code 129 test-tool parse-options --file
+ cat >expect <<-\EOF &&
+ error: switch `s'\'' requires a value
+ EOF
+ test_expect_code 129 test-tool parse-options -s 2>actual &&
+ test_cmp expect actual &&
+
+ cat >expect <<-\EOF &&
+ error: option `string'\'' requires a value
+ EOF
+ test_expect_code 129 test-tool parse-options --string 2>actual &&
+ test_cmp expect actual &&
+
+ cat >expect <<-\EOF &&
+ error: option `file'\'' requires a value
+ EOF
+ test_expect_code 129 test-tool parse-options --file 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'superfluous value provided: boolean' '
+ cat >expect <<-\EOF &&
+ error: option `yes'\'' takes no value
+ EOF
+ test_expect_code 129 test-tool parse-options --yes=hi 2>actual &&
+ test_cmp expect actual &&
+
+ cat >expect <<-\EOF &&
+ error: option `no-yes'\'' takes no value
+ EOF
+ test_expect_code 129 test-tool parse-options --no-yes=hi 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'superfluous value provided: cmdmode' '
+ cat >expect <<-\EOF &&
+ error: option `mode1'\'' takes no value
+ EOF
+ test_expect_code 129 test-tool parse-options --mode1=hi 2>actual &&
+ test_cmp expect actual
'
cat >expect <<\EOF
diff --git a/t/t0052-simple-ipc.sh b/t/t0052-simple-ipc.sh
index ff98be31a5..1a36a53574 100755
--- a/t/t0052-simple-ipc.sh
+++ b/t/t0052-simple-ipc.sh
@@ -2,6 +2,7 @@
test_description='simple command server'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test-tool simple-ipc SUPPORTS_SIMPLE_IPC || {
diff --git a/t/t0055-beyond-symlinks.sh b/t/t0055-beyond-symlinks.sh
index 0c6ff567a1..6bada37022 100755
--- a/t/t0055-beyond-symlinks.sh
+++ b/t/t0055-beyond-symlinks.sh
@@ -2,6 +2,7 @@
test_description='update-index and add refuse to add beyond symlinks'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success SYMLINKS setup '
diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh
index 7d599675e3..ee281909bc 100755
--- a/t/t0061-run-command.sh
+++ b/t/t0061-run-command.sh
@@ -5,6 +5,7 @@
test_description='Test run command'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >hello-script <<-EOF
diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh
index c6ee9f66b1..46d4839194 100755
--- a/t/t0063-string-list.sh
+++ b/t/t0063-string-list.sh
@@ -5,6 +5,7 @@
test_description='Test string list functionality'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_split () {
diff --git a/t/t0064-oid-array.sh b/t/t0064-oid-array.sh
index 2e5438ccda..88c89e8f48 100755
--- a/t/t0064-oid-array.sh
+++ b/t/t0064-oid-array.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='basic tests for the oid array implementation'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
echoid () {
diff --git a/t/t0065-strcmp-offset.sh b/t/t0065-strcmp-offset.sh
index 91fa639c4a..94e34c83ed 100755
--- a/t/t0065-strcmp-offset.sh
+++ b/t/t0065-strcmp-offset.sh
@@ -2,6 +2,7 @@
test_description='Test strcmp_offset functionality'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
while read s1 s2 expect
diff --git a/t/t0066-dir-iterator.sh b/t/t0066-dir-iterator.sh
index 92910e4e6c..63a1a45cd3 100755
--- a/t/t0066-dir-iterator.sh
+++ b/t/t0066-dir-iterator.sh
@@ -2,6 +2,7 @@
test_description='Test the dir-iterator functionality'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t0067-parse_pathspec_file.sh b/t/t0067-parse_pathspec_file.sh
index 7bab49f361..0188d0423a 100755
--- a/t/t0067-parse_pathspec_file.sh
+++ b/t/t0067-parse_pathspec_file.sh
@@ -2,6 +2,7 @@
test_description='Test parse_pathspec_file()'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'one item from stdin' '
diff --git a/t/t0069-oidtree.sh b/t/t0069-oidtree.sh
index bfb1397d7b..74cc59bf8a 100755
--- a/t/t0069-oidtree.sh
+++ b/t/t0069-oidtree.sh
@@ -1,6 +1,7 @@
#!/bin/sh
test_description='basic tests for the oidtree implementation'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
maxhexsz=$(test_oid hexsz)
diff --git a/t/t0071-sort.sh b/t/t0071-sort.sh
new file mode 100755
index 0000000000..a8ab174879
--- /dev/null
+++ b/t/t0071-sort.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+test_description='verify sort functions'
+
+. ./test-lib.sh
+
+test_expect_success 'llist_mergesort()' '
+ test-tool mergesort test
+'
+
+test_done
diff --git a/t/t0091-bugreport.sh b/t/t0091-bugreport.sh
index 526304ff95..eeedbfa919 100755
--- a/t/t0091-bugreport.sh
+++ b/t/t0091-bugreport.sh
@@ -2,6 +2,7 @@
test_description='git bugreport'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Headers "[System Info]" will be followed by a non-empty line if we put some
diff --git a/t/t0110-urlmatch-normalization.sh b/t/t0110-urlmatch-normalization.sh
index f99529d838..4dc9fecf72 100755
--- a/t/t0110-urlmatch-normalization.sh
+++ b/t/t0110-urlmatch-normalization.sh
@@ -47,7 +47,7 @@ test_expect_success 'url authority' '
test-tool urlmatch-normalization "scheme://@host" &&
test-tool urlmatch-normalization "scheme://%00@host" &&
! test-tool urlmatch-normalization "scheme://%%@host" &&
- ! test-tool urlmatch-normalization "scheme://host_" &&
+ test-tool urlmatch-normalization "scheme://host_" &&
test-tool urlmatch-normalization "scheme://user:pass@host/" &&
test-tool urlmatch-normalization "scheme://@host/" &&
test-tool urlmatch-normalization "scheme://host/" &&
diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh
index 0cf3a63b75..37c359bd5a 100755
--- a/t/t0210-trace2-normal.sh
+++ b/t/t0210-trace2-normal.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test trace2 facility (normal target)'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Turn off any inherited trace2 settings for this test.
diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh
index 6ee8ee3b67..22d0845544 100755
--- a/t/t0211-trace2-perf.sh
+++ b/t/t0211-trace2-perf.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test trace2 facility (perf target)'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Turn off any inherited trace2 settings for this test.
diff --git a/t/t0212-trace2-event.sh b/t/t0212-trace2-event.sh
index 1529155cf0..6d3374ff77 100755
--- a/t/t0212-trace2-event.sh
+++ b/t/t0212-trace2-event.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test trace2 facility'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Turn off any inherited trace2 settings for this test.
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index bba679685f..c76485b1b6 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -6,6 +6,10 @@ test_description='partial clone'
# missing promisor objects cause repacks which write bitmaps to fail
GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
+# When enabled, some commands will write commit-graphs. This causes fsck
+# to fail when delete_object() is called because fsck will attempt to
+# verify the out-of-sync commit graph.
+GIT_TEST_COMMIT_GRAPH=0
delete_object () {
rm $1/.git/objects/$(echo $2 | sed -e 's|^..|&/|')
@@ -322,7 +326,7 @@ test_expect_success 'rev-list stops traversal at missing and promised commit' '
git -C repo config core.repositoryformatversion 1 &&
git -C repo config extensions.partialclone "arbitrary string" &&
- GIT_TEST_COMMIT_GRAPH=0 git -C repo -c core.commitGraph=false rev-list --exclude-promisor-objects --objects bar >out &&
+ git -C repo rev-list --exclude-promisor-objects --objects bar >out &&
grep $(git -C repo rev-parse bar) out &&
! grep $FOO out
'
diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh
index 013c5a7bc3..0e8c0dfbbe 100755
--- a/t/t1000-read-tree-m-3way.sh
+++ b/t/t1000-read-tree-m-3way.sh
@@ -71,6 +71,8 @@ In addition:
DF: a special case, where A makes a directory and B makes a file.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-read-tree.sh
. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 1057a96b24..d1115528cb 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -20,6 +20,8 @@ In the test, these paths are used:
rezrov - in H, deleted in M
yomin - not in H or M
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-read-tree.sh
diff --git a/t/t1003-read-tree-prefix.sh b/t/t1003-read-tree-prefix.sh
index b6111cd150..e0db2066f3 100755
--- a/t/t1003-read-tree-prefix.sh
+++ b/t/t1003-read-tree-prefix.sh
@@ -6,6 +6,7 @@
test_description='git read-tree --prefix test.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh
index 83b09e1310..12e30d77d0 100755
--- a/t/t1005-read-tree-reset.sh
+++ b/t/t1005-read-tree-reset.sh
@@ -2,6 +2,7 @@
test_description='read-tree -u --reset'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-read-tree.sh
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 18b3779ccb..658628375c 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -315,39 +315,238 @@ test_expect_success '%(deltabase) reports packed delta bases' '
}
'
-bogus_type="bogus"
-bogus_content="bogus"
-bogus_size=$(strlen "$bogus_content")
-bogus_sha1=$(echo_without_newline "$bogus_content" | git hash-object -t $bogus_type --literally -w --stdin)
+test_expect_success 'setup bogus data' '
+ bogus_short_type="bogus" &&
+ bogus_short_content="bogus" &&
+ bogus_short_size=$(strlen "$bogus_short_content") &&
+ bogus_short_sha1=$(echo_without_newline "$bogus_short_content" | git hash-object -t $bogus_short_type --literally -w --stdin) &&
+
+ bogus_long_type="abcdefghijklmnopqrstuvwxyz1234679" &&
+ bogus_long_content="bogus" &&
+ bogus_long_size=$(strlen "$bogus_long_content") &&
+ bogus_long_sha1=$(echo_without_newline "$bogus_long_content" | git hash-object -t $bogus_long_type --literally -w --stdin)
+'
+
+for arg1 in '' --allow-unknown-type
+do
+ for arg2 in -s -t -p
+ do
+ if test "$arg1" = "--allow-unknown-type" && test "$arg2" = "-p"
+ then
+ continue
+ fi
+
+
+ test_expect_success "cat-file $arg1 $arg2 error on bogus short OID" '
+ cat >expect <<-\EOF &&
+ fatal: invalid object type
+ EOF
+
+ if test "$arg1" = "--allow-unknown-type"
+ then
+ git cat-file $arg1 $arg2 $bogus_short_sha1
+ else
+ test_must_fail git cat-file $arg1 $arg2 $bogus_short_sha1 >out 2>actual &&
+ test_must_be_empty out &&
+ test_cmp expect actual
+ fi
+ '
+
+ test_expect_success "cat-file $arg1 $arg2 error on bogus full OID" '
+ if test "$arg2" = "-p"
+ then
+ cat >expect <<-EOF
+ error: header for $bogus_long_sha1 too long, exceeds 32 bytes
+ fatal: Not a valid object name $bogus_long_sha1
+ EOF
+ else
+ cat >expect <<-EOF
+ error: header for $bogus_long_sha1 too long, exceeds 32 bytes
+ fatal: git cat-file: could not get object info
+ EOF
+ fi &&
+
+ if test "$arg1" = "--allow-unknown-type"
+ then
+ git cat-file $arg1 $arg2 $bogus_short_sha1
+ else
+ test_must_fail git cat-file $arg1 $arg2 $bogus_long_sha1 >out 2>actual &&
+ test_must_be_empty out &&
+ test_cmp expect actual
+ fi
+ '
+
+ test_expect_success "cat-file $arg1 $arg2 error on missing short OID" '
+ cat >expect.err <<-EOF &&
+ fatal: Not a valid object name $(test_oid deadbeef_short)
+ EOF
+ test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef_short) >out 2>err.actual &&
+ test_must_be_empty out
+ '
+
+ test_expect_success "cat-file $arg1 $arg2 error on missing full OID" '
+ if test "$arg2" = "-p"
+ then
+ cat >expect.err <<-EOF
+ fatal: Not a valid object name $(test_oid deadbeef)
+ EOF
+ else
+ cat >expect.err <<-\EOF
+ fatal: git cat-file: could not get object info
+ EOF
+ fi &&
+ test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef) >out 2>err.actual &&
+ test_must_be_empty out &&
+ test_cmp expect.err err.actual
+ '
+ done
+done
+
+test_expect_success '-e is OK with a broken object without --allow-unknown-type' '
+ git cat-file -e $bogus_short_sha1
+'
+
+test_expect_success '-e can not be combined with --allow-unknown-type' '
+ test_expect_code 128 git cat-file -e --allow-unknown-type $bogus_short_sha1
+'
+
+test_expect_success '-p cannot print a broken object even with --allow-unknown-type' '
+ test_must_fail git cat-file -p $bogus_short_sha1 &&
+ test_expect_code 128 git cat-file -p --allow-unknown-type $bogus_short_sha1
+'
+
+test_expect_success '<type> <hash> does not work with objects of broken types' '
+ cat >err.expect <<-\EOF &&
+ fatal: invalid object type "bogus"
+ EOF
+ test_must_fail git cat-file $bogus_short_type $bogus_short_sha1 2>err.actual &&
+ test_cmp err.expect err.actual
+'
+
+test_expect_success 'broken types combined with --batch and --batch-check' '
+ echo $bogus_short_sha1 >bogus-oid &&
+
+ cat >err.expect <<-\EOF &&
+ fatal: invalid object type
+ EOF
+
+ test_must_fail git cat-file --batch <bogus-oid 2>err.actual &&
+ test_cmp err.expect err.actual &&
+
+ test_must_fail git cat-file --batch-check <bogus-oid 2>err.actual &&
+ test_cmp err.expect err.actual
+'
+
+test_expect_success 'the --batch and --batch-check options do not combine with --allow-unknown-type' '
+ test_expect_code 128 git cat-file --batch --allow-unknown-type <bogus-oid &&
+ test_expect_code 128 git cat-file --batch-check --allow-unknown-type <bogus-oid
+'
+
+test_expect_success 'the --allow-unknown-type option does not consider replacement refs' '
+ cat >expect <<-EOF &&
+ $bogus_short_type
+ EOF
+ git cat-file -t --allow-unknown-type $bogus_short_sha1 >actual &&
+ test_cmp expect actual &&
+
+ # Create it manually, as "git replace" will die on bogus
+ # types.
+ head=$(git rev-parse --verify HEAD) &&
+ test_when_finished "rm -rf .git/refs/replace" &&
+ mkdir -p .git/refs/replace &&
+ echo $head >.git/refs/replace/$bogus_short_sha1 &&
+
+ cat >expect <<-EOF &&
+ commit
+ EOF
+ git cat-file -t --allow-unknown-type $bogus_short_sha1 >actual &&
+ test_cmp expect actual
+'
test_expect_success "Type of broken object is correct" '
- echo $bogus_type >expect &&
- git cat-file -t --allow-unknown-type $bogus_sha1 >actual &&
+ echo $bogus_short_type >expect &&
+ git cat-file -t --allow-unknown-type $bogus_short_sha1 >actual &&
test_cmp expect actual
'
test_expect_success "Size of broken object is correct" '
- echo $bogus_size >expect &&
- git cat-file -s --allow-unknown-type $bogus_sha1 >actual &&
+ echo $bogus_short_size >expect &&
+ git cat-file -s --allow-unknown-type $bogus_short_sha1 >actual &&
test_cmp expect actual
'
-bogus_type="abcdefghijklmnopqrstuvwxyz1234679"
-bogus_content="bogus"
-bogus_size=$(strlen "$bogus_content")
-bogus_sha1=$(echo_without_newline "$bogus_content" | git hash-object -t $bogus_type --literally -w --stdin)
+
+test_expect_success 'clean up broken object' '
+ rm .git/objects/$(test_oid_to_path $bogus_short_sha1)
+'
test_expect_success "Type of broken object is correct when type is large" '
- echo $bogus_type >expect &&
- git cat-file -t --allow-unknown-type $bogus_sha1 >actual &&
+ echo $bogus_long_type >expect &&
+ git cat-file -t --allow-unknown-type $bogus_long_sha1 >actual &&
test_cmp expect actual
'
test_expect_success "Size of large broken object is correct when type is large" '
- echo $bogus_size >expect &&
- git cat-file -s --allow-unknown-type $bogus_sha1 >actual &&
+ echo $bogus_long_size >expect &&
+ git cat-file -s --allow-unknown-type $bogus_long_sha1 >actual &&
test_cmp expect actual
'
+test_expect_success 'clean up broken object' '
+ rm .git/objects/$(test_oid_to_path $bogus_long_sha1)
+'
+
+test_expect_success 'cat-file -t and -s on corrupt loose object' '
+ git init --bare corrupt-loose.git &&
+ (
+ cd corrupt-loose.git &&
+
+ # Setup and create the empty blob and its path
+ empty_path=$(git rev-parse --git-path objects/$(test_oid_to_path "$EMPTY_BLOB")) &&
+ git hash-object -w --stdin </dev/null &&
+
+ # Create another blob and its path
+ echo other >other.blob &&
+ other_blob=$(git hash-object -w --stdin <other.blob) &&
+ other_path=$(git rev-parse --git-path objects/$(test_oid_to_path "$other_blob")) &&
+
+ # Before the swap the size is 0
+ cat >out.expect <<-EOF &&
+ 0
+ EOF
+ git cat-file -s "$EMPTY_BLOB" >out.actual 2>err.actual &&
+ test_must_be_empty err.actual &&
+ test_cmp out.expect out.actual &&
+
+ # Swap the two to corrupt the repository
+ mv -f "$other_path" "$empty_path" &&
+ test_must_fail git fsck 2>err.fsck &&
+ grep "hash-path mismatch" err.fsck &&
+
+ # confirm that cat-file is reading the new swapped-in
+ # blob...
+ cat >out.expect <<-EOF &&
+ blob
+ EOF
+ git cat-file -t "$EMPTY_BLOB" >out.actual 2>err.actual &&
+ test_must_be_empty err.actual &&
+ test_cmp out.expect out.actual &&
+
+ # ... since it has a different size now.
+ cat >out.expect <<-EOF &&
+ 6
+ EOF
+ git cat-file -s "$EMPTY_BLOB" >out.actual 2>err.actual &&
+ test_must_be_empty err.actual &&
+ test_cmp out.expect out.actual &&
+
+ # So far "cat-file" has been happy to spew the found
+ # content out as-is. Try to make it zlib-invalid.
+ mv -f other.blob "$empty_path" &&
+ test_must_fail git fsck 2>err.fsck &&
+ grep "^error: inflate: data stream error (" err.fsck
+ )
+'
+
# Tests for git cat-file --follow-symlinks
test_expect_success 'prep for symlink tests' '
echo_without_newline "$hello_content" >morx &&
@@ -608,4 +807,70 @@ test_expect_success 'cat-file --batch="batman" with --batch-all-objects will wor
cmp expect actual
'
+test_expect_success 'set up replacement object' '
+ orig=$(git rev-parse HEAD) &&
+ git cat-file commit $orig >orig &&
+ {
+ cat orig &&
+ echo extra
+ } >fake &&
+ fake=$(git hash-object -t commit -w fake) &&
+ orig_size=$(git cat-file -s $orig) &&
+ fake_size=$(git cat-file -s $fake) &&
+ git replace $orig $fake
+'
+
+test_expect_success 'cat-file --batch respects replace objects' '
+ git cat-file --batch >actual <<-EOF &&
+ $orig
+ EOF
+ {
+ echo "$orig commit $fake_size" &&
+ cat fake &&
+ echo
+ } >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'cat-file --batch-check respects replace objects' '
+ git cat-file --batch-check >actual <<-EOF &&
+ $orig
+ EOF
+ echo "$orig commit $fake_size" >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).
+extract_batch_output () {
+ perl -ne '
+ BEGIN { $oid = shift }
+ if (/^$oid \S+ (\d+)$/) {
+ print;
+ read STDIN, my $buf, $1;
+ print $buf;
+ print "\n";
+ }
+ ' "$@"
+}
+
+test_expect_success 'cat-file --batch-all-objects --batch ignores replace' '
+ git cat-file --batch-all-objects --batch >actual.raw &&
+ extract_batch_output $orig <actual.raw >actual &&
+ {
+ echo "$orig commit $orig_size" &&
+ cat orig &&
+ echo
+ } >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'cat-file --batch-all-objects --batch-check ignores replace' '
+ git cat-file --batch-all-objects --batch-check >actual.raw &&
+ grep ^$orig actual.raw >actual &&
+ echo "$orig commit $orig_size" >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1008-read-tree-overlay.sh b/t/t1008-read-tree-overlay.sh
index 4512fb0b6e..ad5936e54d 100755
--- a/t/t1008-read-tree-overlay.sh
+++ b/t/t1008-read-tree-overlay.sh
@@ -5,6 +5,7 @@ test_description='test multi-tree read-tree without merging'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-read-tree.sh
diff --git a/t/t1009-read-tree-new-index.sh b/t/t1009-read-tree-new-index.sh
index 2935f68f8d..fc179ac5dd 100755
--- a/t/t1009-read-tree-new-index.sh
+++ b/t/t1009-read-tree-new-index.sh
@@ -5,6 +5,7 @@ test_description='test read-tree into a fresh index file'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh
index b946f87686..48bfad07ab 100755
--- a/t/t1010-mktree.sh
+++ b/t/t1010-mktree.sh
@@ -2,6 +2,7 @@
test_description='git mktree'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t1012-read-tree-df.sh b/t/t1012-read-tree-df.sh
index 57f0770df1..cde93d22cd 100755
--- a/t/t1012-read-tree-df.sh
+++ b/t/t1012-read-tree-df.sh
@@ -2,6 +2,7 @@
test_description='read-tree D/F conflict corner cases'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-read-tree.sh
diff --git a/t/t1013-read-tree-submodule.sh b/t/t1013-read-tree-submodule.sh
index b6df7444c0..bfc90d4cf2 100755
--- a/t/t1013-read-tree-submodule.sh
+++ b/t/t1013-read-tree-submodule.sh
@@ -6,7 +6,6 @@ test_description='read-tree can handle submodules'
. "$TEST_DIRECTORY"/lib-submodule-update.sh
KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
-KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1
test_submodule_switch_recursing_with_args "read-tree -u -m"
diff --git a/t/t1014-read-tree-confusing.sh b/t/t1014-read-tree-confusing.sh
index da3376b3bb..8ea8d36818 100755
--- a/t/t1014-read-tree-confusing.sh
+++ b/t/t1014-read-tree-confusing.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='check that read-tree rejects confusing paths'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create base tree' '
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 4bab6a513c..6bc1d76fb1 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -17,6 +17,14 @@ test_expect_success setup '
export GIT_ALLOC_LIMIT
'
+test_expect_success 'enter "large" codepath, with small core.bigFileThreshold' '
+ test_when_finished "rm -rf repo" &&
+
+ git init --bare repo &&
+ echo large | git -C repo hash-object -w --stdin &&
+ git -C repo -c core.bigfilethreshold=4 fsck
+'
+
# add a large file with different settings
while read expect config
do
diff --git a/t/t1051-large-conversion.sh b/t/t1051-large-conversion.sh
index 8b7640b3ba..042b0e4429 100755
--- a/t/t1051-large-conversion.sh
+++ b/t/t1051-large-conversion.sh
@@ -83,4 +83,30 @@ test_expect_success 'ident converts on output' '
test_cmp small.clean large.clean
'
+# This smudge filter prepends 5GB of zeros to the file it checks out. This
+# ensures that smudging doesn't mangle large files on 64-bit Windows.
+test_expect_success EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \
+ 'files over 4GB convert on output' '
+ test_commit test small "a small file" &&
+ small_size=$(test_file_size small) &&
+ test_config filter.makelarge.smudge \
+ "test-tool genzeros $((5*1024*1024*1024)) && cat" &&
+ echo "small filter=makelarge" >.gitattributes &&
+ rm small &&
+ git checkout -- small &&
+ size=$(test_file_size small) &&
+ test "$size" -eq $((5 * 1024 * 1024 * 1024 + $small_size))
+'
+
+# This clean filter writes down the size of input it receives. By checking against
+# the actual size, we ensure that cleaning doesn't mangle large files on 64-bit Windows.
+test_expect_success EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \
+ 'files over 4GB convert on input' '
+ test-tool genzeros $((5*1024*1024*1024)) >big &&
+ test_config filter.checklarge.clean "wc -c >big.size" &&
+ echo "big filter=checklarge" >.gitattributes &&
+ git add big &&
+ test $(test_file_size big) -eq $(cat big.size)
+'
+
test_done
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index 71236981e6..272ba1b566 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -206,16 +206,21 @@ test_expect_success 'sparse-checkout disable' '
'
test_expect_success 'sparse-index enabled and disabled' '
- git -C repo sparse-checkout init --cone --sparse-index &&
- test_cmp_config -C repo true index.sparse &&
- test-tool -C repo read-cache --table >cache &&
- grep " tree " cache &&
-
- git -C repo sparse-checkout disable &&
- test-tool -C repo read-cache --table >cache &&
- ! grep " tree " cache &&
- git -C repo config --list >config &&
- ! grep index.sparse config
+ (
+ sane_unset GIT_TEST_SPLIT_INDEX &&
+ git -C repo update-index --no-split-index &&
+
+ git -C repo sparse-checkout init --cone --sparse-index &&
+ test_cmp_config -C repo true index.sparse &&
+ test-tool -C repo read-cache --table >cache &&
+ grep " tree " cache &&
+
+ git -C repo sparse-checkout disable &&
+ test-tool -C repo read-cache --table >cache &&
+ ! grep " tree " cache &&
+ git -C repo config --list >config &&
+ ! grep index.sparse config
+ )
'
test_expect_success 'cone mode: init and set' '
@@ -406,7 +411,7 @@ test_expect_success 'sparse-checkout (init|set|disable) warns with unmerged stat
git -C unmerged sparse-checkout disable
'
-test_expect_success 'sparse-checkout reapply' '
+test_expect_failure 'sparse-checkout reapply' '
git clone repo tweak &&
echo dirty >tweak/deep/deeper2/a &&
@@ -438,6 +443,8 @@ test_expect_success 'sparse-checkout reapply' '
test_i18ngrep "warning.*The following paths are unmerged" err &&
test_path_is_file tweak/folder1/a &&
+ # NEEDSWORK: We are asking to update a file outside of the
+ # sparse-checkout cone, but this is no longer allowed.
git -C tweak add folder1/a &&
git -C tweak sparse-checkout reapply 2>err &&
test_must_be_empty err &&
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 886e78715f..0fe5b5f482 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -187,6 +187,16 @@ test_sparse_match () {
test_cmp sparse-checkout-err sparse-index-err
}
+test_sparse_unstaged () {
+ file=$1 &&
+ for repo in sparse-checkout sparse-index
+ do
+ # Skip "unmerged" paths
+ git -C $repo diff --staged --diff-filter=u -- "$file" >diff &&
+ test_must_be_empty diff || return 1
+ done
+}
+
test_expect_success 'sparse-index contents' '
init_repos &&
@@ -291,6 +301,20 @@ test_expect_success 'add, commit, checkout' '
test_all_match git checkout -
'
+test_expect_success 'add outside sparse cone' '
+ init_repos &&
+
+ run_on_sparse mkdir folder1 &&
+ run_on_sparse ../edit-contents folder1/a &&
+ run_on_sparse ../edit-contents folder1/newfile &&
+ test_sparse_match test_must_fail git add folder1/a &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/a &&
+ test_sparse_match test_must_fail git add folder1/newfile &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/newfile
+'
+
test_expect_success 'commit including unstaged changes' '
init_repos &&
@@ -339,18 +363,24 @@ test_expect_success 'status/add: outside sparse cone' '
# Adding the path outside of the sparse-checkout cone should fail.
test_sparse_match test_must_fail git add folder1/a &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/a &&
test_sparse_match test_must_fail git add --refresh folder1/a &&
-
- # NEEDSWORK: Adding a newly-tracked file outside the cone succeeds
- test_sparse_match git add folder1/new &&
-
- test_all_match git add . &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/a &&
+ test_sparse_match test_must_fail git add folder1/new &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/new &&
+ test_sparse_match git add --sparse folder1/a &&
+ test_sparse_match git add --sparse folder1/new &&
+
+ test_all_match git add --sparse . &&
test_all_match git status --porcelain=v2 &&
test_all_match git commit -m folder1/new &&
test_all_match git rev-parse HEAD^{tree} &&
run_on_all ../edit-contents folder1/newer &&
- test_all_match git add folder1/ &&
+ test_all_match git add --sparse folder1/ &&
test_all_match git status --porcelain=v2 &&
test_all_match git commit -m folder1/newer &&
test_all_match git rev-parse HEAD^{tree}
@@ -459,32 +489,124 @@ test_expect_failure 'blame with pathspec outside sparse definition' '
test_all_match git blame deep/deeper2/deepest/a
'
-# NEEDSWORK: a sparse-checkout behaves differently from a full checkout
-# in this scenario, but it shouldn't.
-test_expect_failure 'checkout and reset (mixed)' '
+test_expect_success 'checkout and reset (mixed)' '
init_repos &&
test_all_match git checkout -b reset-test update-deep &&
test_all_match git reset deepest &&
- test_all_match git reset update-folder1 &&
- test_all_match git reset update-folder2
+
+ # Because skip-worktree is preserved, resetting to update-folder1
+ # will show worktree changes for folder1/a in full-checkout, but not
+ # in sparse-checkout or sparse-index.
+ git -C full-checkout reset update-folder1 >full-checkout-out &&
+ test_sparse_match git reset update-folder1 &&
+ grep "M folder1/a" full-checkout-out &&
+ ! grep "M folder1/a" sparse-checkout-out &&
+ run_on_sparse test_path_is_missing folder1
'
-# NEEDSWORK: a sparse-checkout behaves differently from a full checkout
-# in this scenario, but it shouldn't.
-test_expect_success 'checkout and reset (mixed) [sparse]' '
+test_expect_success 'checkout and reset (merge)' '
init_repos &&
- test_sparse_match git checkout -b reset-test update-deep &&
- test_sparse_match git reset deepest &&
- test_sparse_match git reset update-folder1 &&
- test_sparse_match git reset update-folder2
+ write_script edit-contents <<-\EOF &&
+ echo text >>$1
+ EOF
+
+ test_all_match git checkout -b reset-test update-deep &&
+ run_on_all ../edit-contents a &&
+ test_all_match git reset --merge deepest &&
+ test_all_match git status --porcelain=v2 &&
+
+ test_all_match git reset --hard update-deep &&
+ run_on_all ../edit-contents deep/a &&
+ test_all_match test_must_fail git reset --merge deepest
+'
+
+test_expect_success 'checkout and reset (keep)' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>$1
+ EOF
+
+ test_all_match git checkout -b reset-test update-deep &&
+ run_on_all ../edit-contents a &&
+ test_all_match git reset --keep deepest &&
+ test_all_match git status --porcelain=v2 &&
+
+ test_all_match git reset --hard update-deep &&
+ run_on_all ../edit-contents deep/a &&
+ test_all_match test_must_fail git reset --keep deepest
+'
+
+test_expect_success 'reset with pathspecs inside sparse definition' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>$1
+ EOF
+
+ test_all_match git checkout -b reset-test update-deep &&
+ run_on_all ../edit-contents deep/a &&
+
+ test_all_match git reset base -- deep/a &&
+ test_all_match git status --porcelain=v2 &&
+
+ test_all_match git reset base -- nonexistent-file &&
+ test_all_match git status --porcelain=v2 &&
+
+ test_all_match git reset deepest -- deep &&
+ test_all_match git status --porcelain=v2
+'
+
+# Although the working tree differs between full and sparse checkouts after
+# reset, the state of the index is the same.
+test_expect_success 'reset with pathspecs outside sparse definition' '
+ init_repos &&
+ test_all_match git checkout -b reset-test base &&
+
+ test_sparse_match git reset update-folder1 -- folder1 &&
+ git -C full-checkout reset update-folder1 -- folder1 &&
+ test_sparse_match git status --porcelain=v2 &&
+ test_all_match git rev-parse HEAD:folder1 &&
+
+ test_sparse_match git reset update-folder2 -- folder2/a &&
+ git -C full-checkout reset update-folder2 -- folder2/a &&
+ test_sparse_match git status --porcelain=v2 &&
+ test_all_match git rev-parse HEAD:folder2/a
+'
+
+test_expect_success 'reset with wildcard pathspec' '
+ init_repos &&
+
+ test_all_match git reset update-deep -- deep\* &&
+ test_all_match git ls-files -s -- deep &&
+
+ test_all_match git reset deepest -- deep\*\*\* &&
+ test_all_match git ls-files -s -- deep &&
+
+ # The following `git reset`s result in updating the index on files with
+ # `skip-worktree` enabled. To avoid failing due to discrepencies in reported
+ # "modified" files, `test_sparse_match` reset is performed separately from
+ # "full-checkout" reset, then the index contents of all repos are verified.
+
+ test_sparse_match git reset update-folder1 -- \*/a &&
+ git -C full-checkout reset update-folder1 -- \*/a &&
+ test_all_match git ls-files -s -- deep/a folder1/a &&
+
+ test_sparse_match git reset update-folder2 -- folder\* &&
+ git -C full-checkout reset update-folder2 -- folder\* &&
+ test_all_match git ls-files -s -- folder10 folder1 folder2 &&
+
+ test_sparse_match git reset base -- folder1/\* &&
+ git -C full-checkout reset base -- folder1/\* &&
+ test_all_match git ls-files -s -- folder1
'
test_expect_success 'merge, cherry-pick, and rebase' '
init_repos &&
- for OPERATION in "merge -m merge" cherry-pick rebase
+ for OPERATION in "merge -m merge" cherry-pick "rebase --apply" "rebase --merge"
do
test_all_match git checkout -B temp update-deep &&
test_all_match git $OPERATION update-folder1 &&
@@ -494,11 +616,6 @@ test_expect_success 'merge, cherry-pick, and rebase' '
done
'
-# NEEDSWORK: This test is documenting current behavior, but that
-# behavior can be confusing to users so there is desire to change it.
-# Right now, users might be using this flow to work through conflicts,
-# so any solution should present advice to users who try this sequence
-# of commands to follow whatever new method we create.
test_expect_success 'merge with conflict outside cone' '
init_repos &&
@@ -513,13 +630,19 @@ test_expect_success 'merge with conflict outside cone' '
test_all_match git status --porcelain=v2 &&
# 2. Add the file with conflict markers
- test_all_match git add folder1/a &&
+ test_sparse_match test_must_fail git add folder1/a &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/a &&
+ test_all_match git add --sparse folder1/a &&
test_all_match git status --porcelain=v2 &&
# 3. Rename the file to another sparse filename and
# accept conflict markers as resolved content.
run_on_all mv folder2/a folder2/z &&
- test_all_match git add folder2 &&
+ test_sparse_match test_must_fail git add folder2 &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder2/z &&
+ test_all_match git add --sparse folder2 &&
test_all_match git status --porcelain=v2 &&
test_all_match git merge --continue &&
@@ -544,13 +667,25 @@ test_expect_success 'cherry-pick/rebase with conflict outside cone' '
test_all_match git status --porcelain=v2 &&
# 2. Add the file with conflict markers
- test_all_match git add folder1/a &&
+ # NEEDSWORK: Even though the merge conflict removed the
+ # SKIP_WORKTREE bit from the index entry for folder1/a, we should
+ # warn that this is a problematic add.
+ test_sparse_match test_must_fail git add folder1/a &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder1/a &&
+ test_all_match git add --sparse folder1/a &&
test_all_match git status --porcelain=v2 &&
# 3. Rename the file to another sparse filename and
# accept conflict markers as resolved content.
+ # NEEDSWORK: This mode now fails, because folder2/z is
+ # outside of the sparse-checkout cone and does not match an
+ # existing index entry with the SKIP_WORKTREE bit cleared.
run_on_all mv folder2/a folder2/z &&
- test_all_match git add folder2 &&
+ test_sparse_match test_must_fail git add folder2 &&
+ grep "Disable or modify the sparsity rules" sparse-checkout-err &&
+ test_sparse_unstaged folder2/z &&
+ test_all_match git add --sparse folder2 &&
test_all_match git status --porcelain=v2 &&
test_all_match git $OPERATION --continue &&
@@ -626,6 +761,7 @@ test_expect_success 'clean' '
test_expect_success 'submodule handling' '
init_repos &&
+ test_sparse_match git sparse-checkout add modules &&
test_all_match mkdir modules &&
test_all_match touch modules/a &&
test_all_match git add modules &&
@@ -635,20 +771,56 @@ test_expect_success 'submodule handling' '
test_all_match git commit -m "add submodule" &&
# having a submodule prevents "modules" from collapse
+ test_sparse_match git sparse-checkout set deep/deeper1 &&
test-tool -C sparse-index read-cache --table >cache &&
grep "100644 blob .* modules/a" cache &&
grep "160000 commit $(git -C initial-repo rev-parse HEAD) modules/sub" cache
'
+# When working with a sparse index, some commands will need to expand the
+# index to operate properly. If those commands also write the index back
+# to disk, they need to convert the index to sparse before writing.
+# This test verifies that both of these events are logged in trace2 logs.
test_expect_success 'sparse-index is expanded and converted back' '
init_repos &&
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
- git -C sparse-index -c core.fsmonitor="" reset --hard &&
+ git -C sparse-index reset -- folder1/a &&
test_region index convert_to_sparse trace2.txt &&
test_region index ensure_full_index trace2.txt
'
+test_expect_success 'index.sparse disabled inline uses full index' '
+ init_repos &&
+
+ # When index.sparse is disabled inline with `git status`, the
+ # index is expanded at the beginning of the execution then never
+ # converted back to sparse. It is then written to disk as a full index.
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ git -C sparse-index -c index.sparse=false status &&
+ ! test_region index convert_to_sparse trace2.txt &&
+ test_region index ensure_full_index trace2.txt &&
+
+ # Since index.sparse is set to true at a repo level, the index
+ # is converted from full to sparse when read, then never expanded
+ # over the course of `git status`. It is written to disk as a sparse
+ # index.
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ git -C sparse-index status &&
+ test_region index convert_to_sparse trace2.txt &&
+ ! test_region index ensure_full_index trace2.txt &&
+
+ # Now that the index has been written to disk as sparse, it is not
+ # converted to sparse (or expanded to full) when read by `git status`.
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ git -C sparse-index status &&
+ ! test_region index convert_to_sparse trace2.txt &&
+ ! test_region index ensure_full_index trace2.txt
+'
+
ensure_not_expanded () {
rm -f trace2.txt &&
echo >>sparse-index/untracked.txt &&
@@ -681,9 +853,9 @@ test_expect_success 'sparse-index is not expanded' '
ensure_not_expanded checkout - &&
ensure_not_expanded switch rename-out-to-out &&
ensure_not_expanded switch - &&
- git -C sparse-index reset --hard &&
+ ensure_not_expanded reset --hard &&
ensure_not_expanded checkout rename-out-to-out -- deep/deeper1 &&
- git -C sparse-index reset --hard &&
+ ensure_not_expanded reset --hard &&
ensure_not_expanded restore -s rename-out-to-out -- deep/deeper1 &&
echo >>sparse-index/README.md &&
@@ -693,6 +865,34 @@ test_expect_success 'sparse-index is not expanded' '
echo >>sparse-index/untracked.txt &&
ensure_not_expanded add . &&
+ for ref in update-deep update-folder1 update-folder2 update-deep
+ do
+ echo >>sparse-index/README.md &&
+ ensure_not_expanded reset --hard $ref || return 1
+ done &&
+
+ ensure_not_expanded reset --mixed base &&
+ ensure_not_expanded reset --hard update-deep &&
+ ensure_not_expanded reset --keep base &&
+ ensure_not_expanded reset --merge update-deep &&
+ ensure_not_expanded reset --hard &&
+
+ ensure_not_expanded reset base -- deep/a &&
+ ensure_not_expanded reset base -- nonexistent-file &&
+ ensure_not_expanded reset deepest -- deep &&
+
+ # Although folder1 is outside the sparse definition, it exists as a
+ # directory entry in the index, so the pathspec will not force the
+ # index to be expanded.
+ ensure_not_expanded reset deepest -- folder1 &&
+ ensure_not_expanded reset deepest -- folder1/ &&
+
+ # Wildcard identifies only in-cone files, no index expansion
+ ensure_not_expanded reset deepest -- deep/\* &&
+
+ # Wildcard identifies only full sparse directories, no index expansion
+ ensure_not_expanded reset deepest -- folder\* &&
+
ensure_not_expanded checkout -f update-deep &&
test_config -C sparse-index pull.twohead ort &&
(
diff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh
index ae66ba5bab..0f37a43fd3 100755
--- a/t/t1100-commit-tree-options.sh
+++ b/t/t1100-commit-tree-options.sh
@@ -12,6 +12,7 @@ Also make sure that command line parser understands the normal
"flags first and then non flag arguments" command line.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >expected <<EOF
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index ccbb116c01..5cde79ef8c 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -1,6 +1,7 @@
#!/bin/sh
test_description='test config file include directives'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Force setup_explicit_git_dir() to run until the end. This is needed
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
index 17d3cc1405..4d261e80c6 100755
--- a/t/t1403-show-ref.sh
+++ b/t/t1403-show-ref.sh
@@ -4,6 +4,7 @@ test_description='show-ref'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t1405-main-ref-store.sh b/t/t1405-main-ref-store.sh
index 49718b7ea7..c89cef2d26 100755
--- a/t/t1405-main-ref-store.sh
+++ b/t/t1405-main-ref-store.sh
@@ -108,7 +108,7 @@ test_expect_success 'delete_reflog(HEAD)' '
'
test_expect_success 'create-reflog(HEAD)' '
- $RUN create-reflog HEAD 1 &&
+ $RUN create-reflog HEAD &&
git reflog exists HEAD
'
diff --git a/t/t1406-submodule-ref-store.sh b/t/t1406-submodule-ref-store.sh
index 0a87058971..c95c5d47aa 100755
--- a/t/t1406-submodule-ref-store.sh
+++ b/t/t1406-submodule-ref-store.sh
@@ -5,6 +5,7 @@ test_description='test submodule ref store api'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
RUN="test-tool ref-store submodule:sub"
@@ -92,7 +93,7 @@ test_expect_success 'delete_reflog() not allowed' '
'
test_expect_success 'create-reflog() not allowed' '
- test_must_fail $RUN create-reflog HEAD 1
+ test_must_fail $RUN create-reflog HEAD
'
test_done
diff --git a/t/t1417-reflog-updateref.sh b/t/t1417-reflog-updateref.sh
new file mode 100755
index 0000000000..14f13b57c6
--- /dev/null
+++ b/t/t1417-reflog-updateref.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+test_description='git reflog --updateref'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ git init -b main repo &&
+ (
+ cd repo &&
+
+ test_commit A &&
+ test_commit B &&
+ test_commit C &&
+
+ cp .git/logs/HEAD HEAD.old &&
+ git reset --hard HEAD~ &&
+ cp HEAD.old .git/logs/HEAD
+ )
+'
+
+test_reflog_updateref () {
+ exp=$1
+ shift
+ args="$@"
+
+ test_expect_success REFFILES "get '$exp' with '$args'" '
+ test_when_finished "rm -rf copy" &&
+ cp -R repo copy &&
+
+ (
+ cd copy &&
+
+ $args &&
+ git rev-parse $exp >expect &&
+ git rev-parse HEAD >actual &&
+
+ test_cmp expect actual
+ )
+ '
+}
+
+test_reflog_updateref B git reflog delete --updateref HEAD@{0}
+test_reflog_updateref B git reflog delete --updateref HEAD@{1}
+test_reflog_updateref C git reflog delete --updateref main@{0}
+test_reflog_updateref B git reflog delete --updateref main@{1}
+test_reflog_updateref B git reflog delete --updateref --rewrite HEAD@{0}
+test_reflog_updateref B git reflog delete --updateref --rewrite HEAD@{1}
+test_reflog_updateref C git reflog delete --updateref --rewrite main@{0}
+test_reflog_updateref B git reflog delete --updateref --rewrite main@{1}
+test_reflog_updateref B test_must_fail git reflog expire HEAD@{0}
+test_reflog_updateref B test_must_fail git reflog expire HEAD@{1}
+test_reflog_updateref B test_must_fail git reflog expire main@{0}
+test_reflog_updateref B test_must_fail git reflog expire main@{1}
+test_reflog_updateref B test_must_fail git reflog expire --updateref HEAD@{0}
+test_reflog_updateref B test_must_fail git reflog expire --updateref HEAD@{1}
+test_reflog_updateref B test_must_fail git reflog expire --updateref main@{0}
+test_reflog_updateref B test_must_fail git reflog expire --updateref main@{1}
+test_reflog_updateref B test_must_fail git reflog expire --updateref --rewrite HEAD@{0}
+test_reflog_updateref B test_must_fail git reflog expire --updateref --rewrite HEAD@{1}
+test_reflog_updateref B test_must_fail git reflog expire --updateref --rewrite main@{0}
+test_reflog_updateref B test_must_fail git reflog expire --updateref --rewrite main@{1}
+
+test_done
diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh
index b1839e0877..4c77cf89a6 100755
--- a/t/t1430-bad-ref-name.sh
+++ b/t/t1430-bad-ref-name.sh
@@ -4,6 +4,7 @@ test_description='Test handling of ref names that check-ref-format rejects'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
@@ -170,7 +171,7 @@ test_expect_success 'for-each-ref emits warnings for broken names' '
! grep -e "badname" output &&
! grep -e "broken\.\.\.symref" output &&
test_i18ngrep "ignoring ref with broken name refs/heads/broken\.\.\.ref" error &&
- test_i18ngrep "ignoring broken ref refs/heads/badname" error &&
+ test_i18ngrep ! "ignoring broken ref refs/heads/badname" error &&
test_i18ngrep "ignoring ref with broken name refs/heads/broken\.\.\.symref" error
'
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 5071ac63a5..6337236fd8 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -48,24 +48,70 @@ remove_object () {
rm "$(sha1_file "$1")"
}
-test_expect_success 'object with bad sha1' '
- sha=$(echo blob | git hash-object -w --stdin) &&
- old=$(test_oid_to_path "$sha") &&
- new=$(dirname $old)/$(test_oid ff_2) &&
- sha="$(dirname $new)$(basename $new)" &&
- mv .git/objects/$old .git/objects/$new &&
- test_when_finished "remove_object $sha" &&
- git update-index --add --cacheinfo 100644 $sha foo &&
- test_when_finished "git read-tree -u --reset HEAD" &&
- tree=$(git write-tree) &&
- test_when_finished "remove_object $tree" &&
- cmt=$(echo bogus | git commit-tree $tree) &&
- test_when_finished "remove_object $cmt" &&
- git update-ref refs/heads/bogus $cmt &&
- test_when_finished "git update-ref -d refs/heads/bogus" &&
+test_expect_success 'object with hash mismatch' '
+ git init --bare hash-mismatch &&
+ (
+ cd hash-mismatch &&
- test_must_fail git fsck 2>out &&
- test_i18ngrep "$sha.*corrupt" out
+ oid=$(echo blob | git hash-object -w --stdin) &&
+ oldoid=$oid &&
+ old=$(test_oid_to_path "$oid") &&
+ new=$(dirname $old)/$(test_oid ff_2) &&
+ oid="$(dirname $new)$(basename $new)" &&
+
+ mv objects/$old objects/$new &&
+ git update-index --add --cacheinfo 100644 $oid foo &&
+ tree=$(git write-tree) &&
+ cmt=$(echo bogus | git commit-tree $tree) &&
+ git update-ref refs/heads/bogus $cmt &&
+
+ test_must_fail git fsck 2>out &&
+ grep "$oldoid: hash-path mismatch, found at: .*$new" out
+ )
+'
+
+test_expect_success 'object with hash and type mismatch' '
+ git init --bare hash-type-mismatch &&
+ (
+ cd hash-type-mismatch &&
+
+ oid=$(echo blob | git hash-object -w --stdin -t garbage --literally) &&
+ oldoid=$oid &&
+ old=$(test_oid_to_path "$oid") &&
+ new=$(dirname $old)/$(test_oid ff_2) &&
+ oid="$(dirname $new)$(basename $new)" &&
+
+ mv objects/$old objects/$new &&
+ git update-index --add --cacheinfo 100644 $oid foo &&
+ tree=$(git write-tree) &&
+ cmt=$(echo bogus | git commit-tree $tree) &&
+ git update-ref refs/heads/bogus $cmt &&
+
+
+ test_must_fail git fsck 2>out &&
+ grep "^error: $oldoid: hash-path mismatch, found at: .*$new" out &&
+ grep "^error: $oldoid: object is of unknown type '"'"'garbage'"'"'" out
+ )
+'
+
+test_expect_success POSIXPERM 'zlib corrupt loose object output ' '
+ git init --bare corrupt-loose-output &&
+ (
+ cd corrupt-loose-output &&
+ oid=$(git hash-object -w --stdin --literally </dev/null) &&
+ oidf=objects/$(test_oid_to_path "$oid") &&
+ chmod 755 $oidf &&
+ echo extra garbage >>$oidf &&
+
+ cat >expect.error <<-EOF &&
+ error: garbage at end of loose object '\''$oid'\''
+ error: unable to unpack contents of ./$oidf
+ error: $oid: object corrupt or missing: ./$oidf
+ EOF
+ test_must_fail git fsck 2>actual &&
+ grep ^error: actual >error &&
+ test_cmp expect.error error
+ )
'
test_expect_success 'branch pointing to non-commit' '
@@ -865,4 +911,21 @@ test_expect_success 'detect corrupt index file in fsck' '
test_i18ngrep "bad index file" errors
'
+test_expect_success 'fsck error and recovery on invalid object type' '
+ git init --bare garbage-type &&
+ (
+ cd garbage-type &&
+
+ garbage_blob=$(git hash-object --stdin -w -t garbage --literally </dev/null) &&
+
+ cat >err.expect <<-\EOF &&
+ fatal: invalid object type
+ EOF
+ test_must_fail git fsck >out 2>err &&
+ grep -e "^error" -e "^fatal" err >errors &&
+ test_line_count = 1 errors &&
+ grep "$garbage_blob: object is of unknown type '"'"'garbage'"'"':" err
+ )
+'
+
test_done
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index b29563fc99..284fe18e72 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -282,4 +282,58 @@ test_expect_success 'test --parseopt --stuck-long and short option with unset op
test_cmp expect output
'
+test_expect_success 'test --parseopt help output: "wrapped" options normal "or:" lines' '
+ sed -e "s/^|//" >spec <<-\EOF &&
+ |cmd [--some-option]
+ | [--another-option]
+ |cmd [--yet-another-option]
+ |--
+ |h,help show the help
+ EOF
+
+ sed -e "s/^|//" >expect <<-\END_EXPECT &&
+ |cat <<\EOF
+ |usage: cmd [--some-option]
+ | or: [--another-option]
+ | or: cmd [--yet-another-option]
+ |
+ | -h, --help show the help
+ |
+ |EOF
+ END_EXPECT
+
+ test_must_fail git rev-parse --parseopt -- -h >out <spec >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'test --parseopt help output: multi-line blurb after empty line' '
+ sed -e "s/^|//" >spec <<-\EOF &&
+ |cmd [--some-option]
+ | [--another-option]
+ |
+ |multi
+ |line
+ |blurb
+ |--
+ |h,help show the help
+ EOF
+
+ sed -e "s/^|//" >expect <<-\END_EXPECT &&
+ |cat <<\EOF
+ |usage: cmd [--some-option]
+ | or: [--another-option]
+ |
+ | multi
+ | line
+ | blurb
+ |
+ | -h, --help show the help
+ |
+ |EOF
+ END_EXPECT
+
+ test_must_fail git rev-parse --parseopt -- -h >out <spec >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh
index 3d51615e42..0fafcf9dde 100755
--- a/t/t1504-ceiling-dirs.sh
+++ b/t/t1504-ceiling-dirs.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test GIT_CEILING_DIRECTORIES'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_prefix() {
diff --git a/t/t1505-rev-parse-last.sh b/t/t1505-rev-parse-last.sh
index 2803ca9489..4a5758f08a 100755
--- a/t/t1505-rev-parse-last.sh
+++ b/t/t1505-rev-parse-last.sh
@@ -5,6 +5,7 @@ test_description='test @{-N} syntax'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
diff --git a/t/t1510-repo-setup.sh b/t/t1510-repo-setup.sh
index bbfe05b8e4..591505a39c 100755
--- a/t/t1510-repo-setup.sh
+++ b/t/t1510-repo-setup.sh
@@ -43,6 +43,7 @@ A few rules for repo setup:
# This test heavily relies on the standard error of nested function calls.
test_untraceable=UnfortunatelyYes
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
here=$(pwd)
diff --git a/t/t1600-index.sh b/t/t1600-index.sh
index c9b9e718b8..46329c488b 100755
--- a/t/t1600-index.sh
+++ b/t/t1600-index.sh
@@ -4,6 +4,8 @@ test_description='index file specific tests'
. ./test-lib.sh
+sane_unset GIT_TEST_SPLIT_INDEX
+
test_expect_success 'setup' '
echo 1 >a
'
@@ -13,7 +15,8 @@ test_expect_success 'bogus GIT_INDEX_VERSION issues warning' '
rm -f .git/index &&
GIT_INDEX_VERSION=2bogus &&
export GIT_INDEX_VERSION &&
- git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ git add a 2>err &&
+ sed "s/[0-9]//" err >actual.err &&
sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
warning: GIT_INDEX_VERSION set, but the value is invalid.
Using version Z
@@ -27,7 +30,8 @@ test_expect_success 'out of bounds GIT_INDEX_VERSION issues warning' '
rm -f .git/index &&
GIT_INDEX_VERSION=1 &&
export GIT_INDEX_VERSION &&
- git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ git add a 2>err &&
+ sed "s/[0-9]//" err >actual.err &&
sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
warning: GIT_INDEX_VERSION set, but the value is invalid.
Using version Z
@@ -50,7 +54,8 @@ test_expect_success 'out of bounds index.version issues warning' '
sane_unset GIT_INDEX_VERSION &&
rm -f .git/index &&
git config --add index.version 1 &&
- git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ git add a 2>err &&
+ sed "s/[0-9]//" err >actual.err &&
sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
warning: index.version set, but the value is invalid.
Using version Z
@@ -79,7 +84,7 @@ test_index_version () {
else
unset GIT_INDEX_VERSION
fi &&
- git add a 2>&1 &&
+ git add a &&
echo $EXPECTED_OUTPUT_VERSION >expect &&
test-tool index-version <.git/index >actual &&
test_cmp expect actual
diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh
index 986baa612e..decd2527ed 100755
--- a/t/t1700-split-index.sh
+++ b/t/t1700-split-index.sh
@@ -510,4 +510,38 @@ test_expect_success 'do not refresh null base index' '
)
'
+test_expect_success 'reading split index at alternate location' '
+ git init reading-alternate-location &&
+ (
+ cd reading-alternate-location &&
+ >file-in-alternate &&
+ git update-index --split-index --add file-in-alternate
+ ) &&
+ echo file-in-alternate >expect &&
+
+ # Should be able to find the shared index both right next to
+ # the specified split index file ...
+ GIT_INDEX_FILE=./reading-alternate-location/.git/index \
+ git ls-files --cached >actual &&
+ test_cmp expect actual &&
+
+ # ... and, for backwards compatibility, in the current GIT_DIR
+ # as well.
+ mv -v ./reading-alternate-location/.git/sharedindex.* .git &&
+ GIT_INDEX_FILE=./reading-alternate-location/.git/index \
+ git ls-files --cached >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'GIT_TEST_SPLIT_INDEX works' '
+ git init git-test-split-index &&
+ (
+ cd git-test-split-index &&
+ >file &&
+ GIT_TEST_SPLIT_INDEX=1 git update-index --add file &&
+ ls -l .git/sharedindex.* >actual &&
+ test_line_count = 1 actual
+ )
+'
+
test_done
diff --git a/t/t2002-checkout-cache-u.sh b/t/t2002-checkout-cache-u.sh
index 70361c806e..fc95cf9048 100755
--- a/t/t2002-checkout-cache-u.sh
+++ b/t/t2002-checkout-cache-u.sh
@@ -8,6 +8,7 @@ test_description='git checkout-index -u test.
With -u flag, git checkout-index internally runs the equivalent of
git update-index --refresh on the checked out entry.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success \
diff --git a/t/t2003-checkout-cache-mkdir.sh b/t/t2003-checkout-cache-mkdir.sh
index ff163cf675..f0fd441d81 100755
--- a/t/t2003-checkout-cache-mkdir.sh
+++ b/t/t2003-checkout-cache-mkdir.sh
@@ -10,6 +10,7 @@ also verifies that such leading path may contain symlinks, unlike
the GIT controlled paths.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh
index a9352b08a8..9bb503a975 100755
--- a/t/t2004-checkout-cache-temp.sh
+++ b/t/t2004-checkout-cache-temp.sh
@@ -8,6 +8,7 @@ test_description='git checkout-index --temp test.
With --temp flag, git checkout-index writes to temporary merge files
rather than the tracked path.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2005-checkout-index-symlinks.sh b/t/t2005-checkout-index-symlinks.sh
index 9fa5610474..112682a45a 100755
--- a/t/t2005-checkout-index-symlinks.sh
+++ b/t/t2005-checkout-index-symlinks.sh
@@ -8,6 +8,7 @@ test_description='git checkout-index on filesystem w/o symlinks test.
This tests that git checkout-index creates a symbolic link as a plain
file if core.symlinks is false.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success \
diff --git a/t/t2007-checkout-symlink.sh b/t/t2007-checkout-symlink.sh
index 6f0b90ce12..bd9e9e7530 100755
--- a/t/t2007-checkout-symlink.sh
+++ b/t/t2007-checkout-symlink.sh
@@ -7,6 +7,7 @@ test_description='git checkout to switch between branches with symlink<->dir'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t2008-checkout-subdir.sh b/t/t2008-checkout-subdir.sh
index eadb9434ae..8a518a44ea 100755
--- a/t/t2008-checkout-subdir.sh
+++ b/t/t2008-checkout-subdir.sh
@@ -4,6 +4,7 @@
test_description='git checkout from subdirectories'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t2009-checkout-statinfo.sh b/t/t2009-checkout-statinfo.sh
index b0540636ae..71195dd28f 100755
--- a/t/t2009-checkout-statinfo.sh
+++ b/t/t2009-checkout-statinfo.sh
@@ -5,6 +5,7 @@ test_description='checkout should leave clean stat info'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2010-checkout-ambiguous.sh b/t/t2010-checkout-ambiguous.sh
index 6e8757387d..9d4b37526a 100755
--- a/t/t2010-checkout-ambiguous.sh
+++ b/t/t2010-checkout-ambiguous.sh
@@ -5,6 +5,7 @@ test_description='checkout and pathspecs/refspecs ambiguities'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh
index e52022e152..d9997e7b6b 100755
--- a/t/t2011-checkout-invalid-head.sh
+++ b/t/t2011-checkout-invalid-head.sh
@@ -5,6 +5,7 @@ test_description='checkout switching away from an invalid branch'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2014-checkout-switch.sh b/t/t2014-checkout-switch.sh
index ccfb147113..c138bdde4f 100755
--- a/t/t2014-checkout-switch.sh
+++ b/t/t2014-checkout-switch.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='Peter MacMillan'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh
index 88d6992a5e..f3371e2646 100755
--- a/t/t2017-checkout-orphan.sh
+++ b/t/t2017-checkout-orphan.sh
@@ -10,6 +10,7 @@ Main Tests for --orphan functionality.'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
TEST_FILE=foo
diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh
index b99d5192a9..2c8c926b4d 100755
--- a/t/t2019-checkout-ambiguous-ref.sh
+++ b/t/t2019-checkout-ambiguous-ref.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='checkout handling of ambiguous (branch/tag) refs'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup ambiguous refs' '
diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh
index 660132ff8d..713c3fa603 100755
--- a/t/t2021-checkout-overwrite.sh
+++ b/t/t2021-checkout-overwrite.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='checkout must not overwrite an untracked objects'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2022-checkout-paths.sh b/t/t2022-checkout-paths.sh
index c49ba7f9bd..f1b709d58b 100755
--- a/t/t2022-checkout-paths.sh
+++ b/t/t2022-checkout-paths.sh
@@ -4,6 +4,7 @@ test_description='checkout $tree -- $paths'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t2026-checkout-pathspec-file.sh b/t/t2026-checkout-pathspec-file.sh
index 43d31d7948..9db11f86dd 100755
--- a/t/t2026-checkout-pathspec-file.sh
+++ b/t/t2026-checkout-pathspec-file.sh
@@ -2,6 +2,7 @@
test_description='checkout --pathspec-from-file'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_tick
diff --git a/t/t2050-git-dir-relative.sh b/t/t2050-git-dir-relative.sh
index 21f4659a9d..1f193cde96 100755
--- a/t/t2050-git-dir-relative.sh
+++ b/t/t2050-git-dir-relative.sh
@@ -12,6 +12,7 @@ into the subdir while keeping the worktree location,
and tries commits from the top and the subdir, checking
that the commit-hook still gets called.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
COMMIT_FILE="$(pwd)/output"
diff --git a/t/t2081-parallel-checkout-collisions.sh b/t/t2081-parallel-checkout-collisions.sh
index f6fcfc0c1e..6acdb89d12 100755
--- a/t/t2081-parallel-checkout-collisions.sh
+++ b/t/t2081-parallel-checkout-collisions.sh
@@ -11,6 +11,7 @@ The tests in this file exercise parallel checkout's collision detection code in
both these mechanics.
"
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-parallel-checkout.sh"
diff --git a/t/t2106-update-index-assume-unchanged.sh b/t/t2106-update-index-assume-unchanged.sh
index 2d450daf5c..d943ddf47e 100755
--- a/t/t2106-update-index-assume-unchanged.sh
+++ b/t/t2106-update-index-assume-unchanged.sh
@@ -3,6 +3,7 @@
test_description='git update-index --assume-unchanged test.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
index 45ca35d60a..94c4cb0672 100755
--- a/t/t2200-add-update.sh
+++ b/t/t2200-add-update.sh
@@ -129,12 +129,15 @@ test_expect_success 'add -n -u should not add but just report' '
echo "remove '\''top'\''"
) >expect &&
before=$(git ls-files -s check top) &&
+ git count-objects -v >objects_before &&
echo changed >>check &&
rm -f top &&
git add -n -u >actual &&
after=$(git ls-files -s check top) &&
+ git count-objects -v >objects_after &&
test "$before" = "$after" &&
+ test_cmp objects_before objects_after &&
test_cmp expect actual
'
diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh
index c8de6d8a19..b40eeb263f 100755
--- a/t/t2300-cd-to-toplevel.sh
+++ b/t/t2300-cd-to-toplevel.sh
@@ -2,6 +2,7 @@
test_description='cd_to_toplevel'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
EXEC_PATH="$(git --exec-path)"
diff --git a/t/t2500-untracked-overwriting.sh b/t/t2500-untracked-overwriting.sh
new file mode 100755
index 0000000000..5c0bf4d21f
--- /dev/null
+++ b/t/t2500-untracked-overwriting.sh
@@ -0,0 +1,244 @@
+#!/bin/sh
+
+test_description='Test handling of overwriting untracked files'
+
+. ./test-lib.sh
+
+test_setup_reset () {
+ git init reset_$1 &&
+ (
+ cd reset_$1 &&
+ test_commit init &&
+
+ git branch stable &&
+ git branch work &&
+
+ git checkout work &&
+ test_commit foo &&
+
+ git checkout stable
+ )
+}
+
+test_expect_success 'reset --hard will nuke untracked files/dirs' '
+ test_setup_reset hard &&
+ (
+ cd reset_hard &&
+ git ls-tree -r stable &&
+ git log --all --name-status --oneline &&
+ git ls-tree -r work &&
+
+ mkdir foo.t &&
+ echo precious >foo.t/file &&
+ echo foo >expect &&
+
+ git reset --hard work &&
+
+ # check that untracked directory foo.t/ was nuked
+ test_path_is_file foo.t &&
+ test_cmp expect foo.t
+ )
+'
+
+test_expect_success 'reset --merge will preserve untracked files/dirs' '
+ test_setup_reset merge &&
+ (
+ cd reset_merge &&
+
+ mkdir foo.t &&
+ echo precious >foo.t/file &&
+ cp foo.t/file expect &&
+
+ test_must_fail git reset --merge work 2>error &&
+ test_cmp expect foo.t/file &&
+ grep "Updating .foo.t. would lose untracked files" error
+ )
+'
+
+test_expect_success 'reset --keep will preserve untracked files/dirs' '
+ test_setup_reset keep &&
+ (
+ cd reset_keep &&
+
+ mkdir foo.t &&
+ echo precious >foo.t/file &&
+ cp foo.t/file expect &&
+
+ test_must_fail git reset --merge work 2>error &&
+ test_cmp expect foo.t/file &&
+ grep "Updating.*foo.t.*would lose untracked files" error
+ )
+'
+
+test_setup_checkout_m () {
+ git init checkout &&
+ (
+ cd checkout &&
+ test_commit init &&
+
+ test_write_lines file has some >filler &&
+ git add filler &&
+ git commit -m filler &&
+
+ git branch stable &&
+
+ git switch -c work &&
+ echo stuff >notes.txt &&
+ test_write_lines file has some words >filler &&
+ git add notes.txt filler &&
+ git commit -m filler &&
+
+ git checkout stable
+ )
+}
+
+test_expect_success 'checkout -m does not nuke untracked file' '
+ test_setup_checkout_m &&
+ (
+ cd checkout &&
+
+ # Tweak filler
+ test_write_lines this file has some >filler &&
+ # Make an untracked file, save its contents in "expect"
+ echo precious >notes.txt &&
+ cp notes.txt expect &&
+
+ test_must_fail git checkout -m work &&
+ test_cmp expect notes.txt
+ )
+'
+
+test_setup_sequencing () {
+ git init sequencing_$1 &&
+ (
+ cd sequencing_$1 &&
+ test_commit init &&
+
+ test_write_lines this file has some words >filler &&
+ git add filler &&
+ git commit -m filler &&
+
+ mkdir -p foo/bar &&
+ test_commit foo/bar/baz &&
+
+ git branch simple &&
+ git branch fooey &&
+
+ git checkout fooey &&
+ git rm foo/bar/baz.t &&
+ echo stuff >>filler &&
+ git add -u &&
+ git commit -m "changes" &&
+
+ git checkout simple &&
+ echo items >>filler &&
+ echo newstuff >>newfile &&
+ git add filler newfile &&
+ git commit -m another
+ )
+}
+
+test_expect_success 'git rebase --abort and untracked files' '
+ test_setup_sequencing rebase_abort_and_untracked &&
+ (
+ cd sequencing_rebase_abort_and_untracked &&
+ git checkout fooey &&
+ test_must_fail git rebase simple &&
+
+ cat init.t &&
+ git rm init.t &&
+ echo precious >init.t &&
+ cp init.t expect &&
+ git status --porcelain &&
+ test_must_fail git rebase --abort &&
+ test_cmp expect init.t
+ )
+'
+
+test_expect_success 'git rebase fast forwarding and untracked files' '
+ test_setup_sequencing rebase_fast_forward_and_untracked &&
+ (
+ cd sequencing_rebase_fast_forward_and_untracked &&
+ git checkout init &&
+ echo precious >filler &&
+ cp filler expect &&
+ test_must_fail git rebase init simple &&
+ test_cmp expect filler
+ )
+'
+
+test_expect_failure 'git rebase --autostash and untracked files' '
+ test_setup_sequencing rebase_autostash_and_untracked &&
+ (
+ cd sequencing_rebase_autostash_and_untracked &&
+ git checkout simple &&
+ git rm filler &&
+ mkdir filler &&
+ echo precious >filler/file &&
+ cp filler/file expect &&
+ git rebase --autostash init &&
+ test_path_is_file filler/file
+ )
+'
+
+test_expect_failure 'git stash and untracked files' '
+ test_setup_sequencing stash_and_untracked_files &&
+ (
+ cd sequencing_stash_and_untracked_files &&
+ git checkout simple &&
+ git rm filler &&
+ mkdir filler &&
+ echo precious >filler/file &&
+ cp filler/file expect &&
+ git status --porcelain &&
+ git stash push &&
+ git status --porcelain &&
+ test_path_is_file filler/file
+ )
+'
+
+test_expect_success 'git am --abort and untracked dir vs. unmerged file' '
+ test_setup_sequencing am_abort_and_untracked &&
+ (
+ cd sequencing_am_abort_and_untracked &&
+ git format-patch -1 --stdout fooey >changes.mbox &&
+ test_must_fail git am --3way changes.mbox &&
+
+ # Delete the conflicted file; we will stage and commit it later
+ rm filler &&
+
+ # Put an unrelated untracked directory there
+ mkdir filler &&
+ echo foo >filler/file1 &&
+ echo bar >filler/file2 &&
+
+ test_must_fail git am --abort 2>errors &&
+ test_path_is_dir filler &&
+ grep "Updating .filler. would lose untracked files in it" errors
+ )
+'
+
+test_expect_success 'git am --skip and untracked dir vs deleted file' '
+ test_setup_sequencing am_skip_and_untracked &&
+ (
+ cd sequencing_am_skip_and_untracked &&
+ git checkout fooey &&
+ git format-patch -1 --stdout simple >changes.mbox &&
+ test_must_fail git am --3way changes.mbox &&
+
+ # Delete newfile
+ rm newfile &&
+
+ # Put an unrelated untracked directory there
+ mkdir newfile &&
+ echo foo >newfile/file1 &&
+ echo bar >newfile/file2 &&
+
+ # Change our mind about resolutions, just skip this patch
+ test_must_fail git am --skip 2>errors &&
+ test_path_is_dir newfile &&
+ grep "Updating .newfile. would lose untracked files in it" errors
+ )
+'
+
+test_done
diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh
index 740ce56eab..11af4552f7 100755
--- a/t/t3000-ls-files-others.sh
+++ b/t/t3000-ls-files-others.sh
@@ -15,6 +15,8 @@ filesystem.
path3/file3 - a file in a directory
path4 - an empty directory
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup ' '
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index 516c95ea0e..48cec4e5f8 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -8,6 +8,7 @@ test_description='git ls-files --others --exclude
This test runs git ls-files --others and tests --exclude patterns.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
rm -fr one three
@@ -102,7 +103,7 @@ test_expect_success \
>output &&
test_cmp expect output'
-test_expect_success 'restore gitignore' '
+test_expect_success !SANITIZE_LEAK 'restore gitignore' '
git checkout --ignore-skip-worktree-bits $allignores &&
rm .git/index
'
@@ -125,7 +126,7 @@ cat > expect << EOF
# three/
EOF
-test_expect_success 'git status honors core.excludesfile' \
+test_expect_success !SANITIZE_LEAK 'git status honors core.excludesfile' \
'test_cmp expect output'
test_expect_success 'trailing slash in exclude allows directory match(1)' '
diff --git a/t/t3002-ls-files-dashpath.sh b/t/t3002-ls-files-dashpath.sh
index 8704b04e1b..54d22a45df 100755
--- a/t/t3002-ls-files-dashpath.sh
+++ b/t/t3002-ls-files-dashpath.sh
@@ -12,6 +12,8 @@ filesystem.
-foo - a file with a funny name.
-- - another file with a funny name.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success \
diff --git a/t/t3003-ls-files-exclude.sh b/t/t3003-ls-files-exclude.sh
index c41c4f046a..7933dff9b3 100755
--- a/t/t3003-ls-files-exclude.sh
+++ b/t/t3003-ls-files-exclude.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='ls-files --exclude does not affect index files'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create repo with file' '
diff --git a/t/t3004-ls-files-basic.sh b/t/t3004-ls-files-basic.sh
index 9fd5a1f188..a16e25c79b 100755
--- a/t/t3004-ls-files-basic.sh
+++ b/t/t3004-ls-files-basic.sh
@@ -6,6 +6,7 @@ This test runs git ls-files with various unusual or malformed
command-line arguments.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'ls-files in empty repository' '
diff --git a/t/t3005-ls-files-relative.sh b/t/t3005-ls-files-relative.sh
index 727e9ae1a4..6ba8b589cd 100755
--- a/t/t3005-ls-files-relative.sh
+++ b/t/t3005-ls-files-relative.sh
@@ -5,6 +5,7 @@ test_description='ls-files tests with relative paths
This test runs git ls-files with various relative path arguments.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'prepare' '
diff --git a/t/t3006-ls-files-long.sh b/t/t3006-ls-files-long.sh
index e109c3fbfb..2aaf91ebc8 100755
--- a/t/t3006-ls-files-long.sh
+++ b/t/t3006-ls-files-long.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='overly long paths'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3008-ls-files-lazy-init-name-hash.sh b/t/t3008-ls-files-lazy-init-name-hash.sh
index 85f3704958..51d3dffaa6 100755
--- a/t/t3008-ls-files-lazy-init-name-hash.sh
+++ b/t/t3008-ls-files-lazy-init-name-hash.sh
@@ -2,6 +2,7 @@
test_description='Test the lazy init name hash with various folder structures'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
if test 1 -eq $(test-tool online-cpus)
diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh
index 124e73b8e6..2cbcbc0721 100755
--- a/t/t3020-ls-files-error-unmatch.sh
+++ b/t/t3020-ls-files-error-unmatch.sh
@@ -9,6 +9,8 @@ This test runs git ls-files --error-unmatch to ensure it correctly
returns an error when a non-existent path is provided on the command
line.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t3040-subprojects-basic.sh b/t/t3040-subprojects-basic.sh
index 6abdcbbc94..bd65dfcffc 100755
--- a/t/t3040-subprojects-basic.sh
+++ b/t/t3040-subprojects-basic.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='Basic subproject functionality'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup: create superproject' '
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 56ea4bda13..72d5b014d8 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -2,6 +2,7 @@
test_description='wildmatch tests'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Disable expensive chain-lint tests; all of the tests in this script
diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh
index 18baf49a49..436de44971 100755
--- a/t/t3100-ls-tree-restrict.sh
+++ b/t/t3100-ls-tree-restrict.sh
@@ -16,6 +16,8 @@ This test runs git ls-tree with the following in a tree.
The new path restriction code should do the right thing for path2 and
path2/baz. Also path0/ should snow nothing.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success \
diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh
index 12bf31022a..05fde64225 100755
--- a/t/t3101-ls-tree-dirname.sh
+++ b/t/t3101-ls-tree-dirname.sh
@@ -19,6 +19,8 @@ This test runs git ls-tree with the following in a tree.
Test the handling of multiple directories which have matching file
entries. Also test odd filename and missing entries handling.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t3102-ls-tree-wildcards.sh b/t/t3102-ls-tree-wildcards.sh
index 1e16c6b8ea..3942db2290 100755
--- a/t/t3102-ls-tree-wildcards.sh
+++ b/t/t3102-ls-tree-wildcards.sh
@@ -2,6 +2,7 @@
test_description='ls-tree with(out) globs'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t3103-ls-tree-misc.sh b/t/t3103-ls-tree-misc.sh
index 14520913af..d18ba1bd84 100755
--- a/t/t3103-ls-tree-misc.sh
+++ b/t/t3103-ls-tree-misc.sh
@@ -7,6 +7,7 @@ Miscellaneous tests for git ls-tree.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index e575ffb4ff..8c5c1ccf33 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -731,6 +731,28 @@ test_expect_success SYMLINKS 'git branch -m u v should fail when the reflog for
test_must_fail git branch -m u v
'
+test_expect_success SYMLINKS 'git branch -m with symlinked .git/refs' '
+ test_when_finished "rm -rf subdir" &&
+ git init --bare subdir &&
+
+ rm -rfv subdir/refs subdir/objects subdir/packed-refs &&
+ ln -s ../.git/refs subdir/refs &&
+ ln -s ../.git/objects subdir/objects &&
+ ln -s ../.git/packed-refs subdir/packed-refs &&
+
+ git -C subdir rev-parse --absolute-git-dir >subdir.dir &&
+ git rev-parse --absolute-git-dir >our.dir &&
+ ! test_cmp subdir.dir our.dir &&
+
+ git -C subdir log &&
+ git -C subdir branch rename-src &&
+ git rev-parse rename-src >expect &&
+ git -C subdir branch -m rename-src rename-dest &&
+ git rev-parse rename-dest >actual &&
+ test_cmp expect actual &&
+ git branch -D rename-dest
+'
+
test_expect_success 'test tracking setup via --track' '
git config remote.local.url . &&
git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
@@ -1418,7 +1440,17 @@ test_expect_success 'invalid sort parameter in configuration' '
(
cd sort &&
git config branch.sort "v:notvalid" &&
- test_must_fail git branch
+
+ # this works in the "listing" mode, so bad sort key
+ # is a dying offence.
+ test_must_fail git branch &&
+
+ # these do not need to use sorting, and should all
+ # succeed
+ git branch newone main &&
+ git branch -c newone newerone &&
+ git branch -m newone newestone &&
+ git branch -d newerone newestone
)
'
diff --git a/t/t3205-branch-color.sh b/t/t3205-branch-color.sh
index 08bd906173..6a521c1a3e 100755
--- a/t/t3205-branch-color.sh
+++ b/t/t3205-branch-color.sh
@@ -4,6 +4,7 @@ test_description='basic branch output coloring'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'set up some sample branches' '
diff --git a/t/t3211-peel-ref.sh b/t/t3211-peel-ref.sh
index 37b9d26f4b..9cbc34fc58 100755
--- a/t/t3211-peel-ref.sh
+++ b/t/t3211-peel-ref.sh
@@ -4,6 +4,7 @@ test_description='tests for the peel_ref optimization of packed-refs'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create annotated tag in refs/tags' '
diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh
index f5bf16abcd..d3ac826283 100755
--- a/t/t3300-funny-names.sh
+++ b/t/t3300-funny-names.sh
@@ -9,6 +9,7 @@ This test tries pathnames with funny characters in the working
tree, index, and tree objects.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
HT=' '
diff --git a/t/t3305-notes-fanout.sh b/t/t3305-notes-fanout.sh
index 94c1b02251..960d0587e1 100755
--- a/t/t3305-notes-fanout.sh
+++ b/t/t3305-notes-fanout.sh
@@ -2,6 +2,7 @@
test_description='Test that adding/removing many notes triggers automatic fanout restructuring'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
path_has_fanout() {
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 972ce026bb..12eb226957 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -352,82 +352,6 @@ test_expect_success 'retain authorship when squashing' '
git show HEAD | grep "^Author: Twerp Snog"
'
-test_expect_success REBASE_P '-p handles "no changes" gracefully' '
- HEAD=$(git rev-parse HEAD) &&
- git rebase -i -p HEAD^ &&
- git update-index --refresh &&
- git diff-files --quiet &&
- git diff-index --quiet --cached HEAD -- &&
- test $HEAD = $(git rev-parse HEAD)
-'
-
-test_expect_failure REBASE_P 'exchange two commits with -p' '
- git checkout H &&
- (
- set_fake_editor &&
- FAKE_LINES="2 1" git rebase -i -p HEAD~2
- ) &&
- test H = $(git cat-file commit HEAD^ | sed -ne \$p) &&
- test G = $(git cat-file commit HEAD | sed -ne \$p)
-'
-
-test_expect_success REBASE_P 'preserve merges with -p' '
- git checkout -b to-be-preserved primary^ &&
- : > unrelated-file &&
- git add unrelated-file &&
- test_tick &&
- git commit -m "unrelated" &&
- git checkout -b another-branch primary &&
- echo B > file1 &&
- test_tick &&
- git commit -m J file1 &&
- test_tick &&
- git merge to-be-preserved &&
- echo C > file1 &&
- test_tick &&
- git commit -m K file1 &&
- echo D > file1 &&
- test_tick &&
- git commit -m L1 file1 &&
- git checkout HEAD^ &&
- echo 1 > unrelated-file &&
- test_tick &&
- git commit -m L2 unrelated-file &&
- test_tick &&
- git merge another-branch &&
- echo E > file1 &&
- test_tick &&
- git commit -m M file1 &&
- git checkout -b to-be-rebased &&
- test_tick &&
- git rebase -i -p --onto branch1 primary &&
- git update-index --refresh &&
- git diff-files --quiet &&
- git diff-index --quiet --cached HEAD -- &&
- test_cmp_rev HEAD~6 branch1 &&
- test_cmp_rev HEAD~4^2 to-be-preserved &&
- test_cmp_rev HEAD^^2^ HEAD^^^ &&
- test $(git show HEAD~5:file1) = B &&
- test $(git show HEAD~3:file1) = C &&
- test $(git show HEAD:file1) = E &&
- test $(git show HEAD:unrelated-file) = 1
-'
-
-test_expect_success REBASE_P 'edit ancestor with -p' '
- (
- set_fake_editor &&
- FAKE_LINES="1 2 edit 3 4" git rebase -i -p HEAD~3
- ) &&
- echo 2 > unrelated-file &&
- test_tick &&
- git commit -m L2-modified --amend unrelated-file &&
- git rebase --continue &&
- git update-index --refresh &&
- git diff-files --quiet &&
- git diff-index --quiet --cached HEAD -- &&
- test $(git show HEAD:unrelated-file) = 2
-'
-
test_expect_success '--continue tries to commit' '
git reset --hard D &&
test_tick &&
diff --git a/t/t3408-rebase-multi-line.sh b/t/t3408-rebase-multi-line.sh
index ab0960e6d9..cde3562e3a 100755
--- a/t/t3408-rebase-multi-line.sh
+++ b/t/t3408-rebase-multi-line.sh
@@ -55,14 +55,4 @@ test_expect_success rebase '
test_cmp expect actual
'
-test_expect_success REBASE_P rebasep '
-
- git checkout side-merge &&
- git rebase -p side &&
- git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
- git cat-file commit side-merge-original | sed -e "1,/^\$/d" >expect &&
- test_cmp expect actual
-
-'
-
test_done
diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh
deleted file mode 100755
index ec8062a66a..0000000000
--- a/t/t3409-rebase-preserve-merges.sh
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/bin/sh
-#
-# Copyright(C) 2008 Stephen Habermann & Andreas Ericsson
-#
-test_description='git rebase -p should preserve merges
-
-Run "git rebase -p" and check that merges are properly carried along
-'
-GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
-export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-
-. ./test-lib.sh
-
-if ! test_have_prereq REBASE_P; then
- skip_all='skipping git rebase -p tests, as asked for'
- test_done
-fi
-
-GIT_AUTHOR_EMAIL=bogus_email_address
-export GIT_AUTHOR_EMAIL
-
-# Clone 2 (conflicting merge):
-#
-# A1--A2--B3 <-- origin/main
-# \ \
-# B1------M <-- topic
-# \
-# B2 <-- origin/topic
-#
-# Clone 3 (no-ff merge):
-#
-# A1--A2--B3 <-- origin/main
-# \
-# B1------M <-- topic
-# \ /
-# \--A3 <-- topic2
-# \
-# B2 <-- origin/topic
-#
-# Clone 4 (same as Clone 3)
-
-test_expect_success 'setup for merge-preserving rebase' \
- 'echo First > A &&
- git add A &&
- git commit -m "Add A1" &&
- git checkout -b topic &&
- echo Second > B &&
- git add B &&
- git commit -m "Add B1" &&
- git checkout -f main &&
- echo Third >> A &&
- git commit -a -m "Modify A2" &&
- echo Fifth > B &&
- git add B &&
- git commit -m "Add different B" &&
-
- git clone ./. clone2 &&
- (
- cd clone2 &&
- git checkout -b topic origin/topic &&
- test_must_fail git merge origin/main &&
- echo Resolved >B &&
- git add B &&
- git commit -m "Merge origin/main into topic"
- ) &&
-
- git clone ./. clone3 &&
- (
- cd clone3 &&
- git checkout -b topic2 origin/topic &&
- echo Sixth > A &&
- git commit -a -m "Modify A3" &&
- git checkout -b topic origin/topic &&
- git merge --no-ff topic2
- ) &&
-
- git clone ./. clone4 &&
- (
- cd clone4 &&
- git checkout -b topic2 origin/topic &&
- echo Sixth > A &&
- git commit -a -m "Modify A3" &&
- git checkout -b topic origin/topic &&
- git merge --no-ff topic2
- ) &&
-
- git checkout topic &&
- echo Fourth >> B &&
- git commit -a -m "Modify B2"
-'
-
-test_expect_success '--continue works after a conflict' '
- (
- cd clone2 &&
- git fetch &&
- test_must_fail git rebase -p origin/topic &&
- test 2 = $(git ls-files B | wc -l) &&
- echo Resolved again > B &&
- test_must_fail git rebase --continue &&
- grep "^@@@ " .git/rebase-merge/patch &&
- git add B &&
- git rebase --continue &&
- test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) &&
- test 1 = $(git rev-list --all --pretty=oneline | grep "Add different" | wc -l) &&
- test 1 = $(git rev-list --all --pretty=oneline | grep "Merge origin" | wc -l)
- )
-'
-
-test_expect_success 'rebase -p preserves no-ff merges' '
- (
- cd clone3 &&
- git fetch &&
- git rebase -p origin/topic &&
- test 3 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) &&
- test 1 = $(git rev-list --all --pretty=oneline | grep "Merge branch" | wc -l)
- )
-'
-
-test_expect_success 'rebase -p ignores merge.log config' '
- (
- cd clone4 &&
- git fetch &&
- git -c merge.log=1 rebase -p origin/topic &&
- echo >expected &&
- git log --format="%b" -1 >current &&
- test_cmp expected current
- )
-'
-
-test_done
diff --git a/t/t3410-rebase-preserve-dropped-merges.sh b/t/t3410-rebase-preserve-dropped-merges.sh
deleted file mode 100755
index 2e29866993..0000000000
--- a/t/t3410-rebase-preserve-dropped-merges.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2008 Stephen Haberman
-#
-
-test_description='git rebase preserve merges
-
-This test runs git rebase with preserve merges and ensures commits
-dropped by the --cherry-pick flag have their childrens parents
-rewritten.
-'
-. ./test-lib.sh
-
-if ! test_have_prereq REBASE_P; then
- skip_all='skipping git rebase -p tests, as asked for'
- test_done
-fi
-
-# set up two branches like this:
-#
-# A - B - C - D - E
-# \
-# F - G - H
-# \
-# I
-#
-# where B, D and G touch the same file.
-
-test_expect_success 'setup' '
- test_commit A file1 &&
- test_commit B file1 1 &&
- test_commit C file2 &&
- test_commit D file1 2 &&
- test_commit E file3 &&
- git checkout A &&
- test_commit F file4 &&
- test_commit G file1 3 &&
- test_commit H file5 &&
- git checkout F &&
- test_commit I file6
-'
-
-# A - B - C - D - E
-# \ \ \
-# F - G - H -- L \ --> L
-# \ | \
-# I -- G2 -- J -- K I -- K
-# G2 = same changes as G
-test_expect_success 'skip same-resolution merges with -p' '
- git checkout H &&
- test_must_fail git merge E &&
- test_commit L file1 23 &&
- git checkout I &&
- test_commit G2 file1 3 &&
- test_must_fail git merge E &&
- test_commit J file1 23 &&
- test_commit K file7 file7 &&
- git rebase -i -p L &&
- test $(git rev-parse HEAD^^) = $(git rev-parse L) &&
- test "23" = "$(cat file1)" &&
- test "I" = "$(cat file6)" &&
- test "file7" = "$(cat file7)"
-'
-
-# A - B - C - D - E
-# \ \ \
-# F - G - H -- L2 \ --> L2
-# \ | \
-# I -- G3 --- J2 -- K2 I -- G3 -- K2
-# G2 = different changes as G
-test_expect_success 'keep different-resolution merges with -p' '
- git checkout H &&
- test_must_fail git merge E &&
- test_commit L2 file1 23 &&
- git checkout I &&
- test_commit G3 file1 4 &&
- test_must_fail git merge E &&
- test_commit J2 file1 24 &&
- test_commit K2 file7 file7 &&
- test_must_fail git rebase -i -p L2 &&
- echo 234 > file1 &&
- git add file1 &&
- git rebase --continue &&
- test $(git rev-parse HEAD^^^) = $(git rev-parse L2) &&
- test "234" = "$(cat file1)" &&
- test "I" = "$(cat file6)" &&
- test "file7" = "$(cat file7)"
-'
-
-test_done
diff --git a/t/t3411-rebase-preserve-around-merges.sh b/t/t3411-rebase-preserve-around-merges.sh
deleted file mode 100755
index fb45e7bf7b..0000000000
--- a/t/t3411-rebase-preserve-around-merges.sh
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2008 Stephen Haberman
-#
-
-test_description='git rebase preserve merges
-
-This test runs git rebase with -p and tries to squash a commit from after
-a merge to before the merge.
-'
-. ./test-lib.sh
-
-if ! test_have_prereq REBASE_P; then
- skip_all='skipping git rebase -p tests, as asked for'
- test_done
-fi
-
-. "$TEST_DIRECTORY"/lib-rebase.sh
-
-set_fake_editor
-
-# set up two branches like this:
-#
-# A1 - B1 - D1 - E1 - F1
-# \ /
-# -- C1 --
-
-test_expect_success 'setup' '
- test_commit A1 &&
- test_commit B1 &&
- test_commit C1 &&
- git reset --hard B1 &&
- test_commit D1 &&
- test_merge E1 C1 &&
- test_commit F1
-'
-
-# Should result in:
-#
-# A1 - B1 - D2 - E2
-# \ /
-# -- C1 --
-#
-test_expect_success 'squash F1 into D1' '
- FAKE_LINES="1 squash 4 2 3" git rebase -i -p B1 &&
- test "$(git rev-parse HEAD^2)" = "$(git rev-parse C1)" &&
- test "$(git rev-parse HEAD~2)" = "$(git rev-parse B1)" &&
- git tag E2
-'
-
-# Start with:
-#
-# A1 - B1 - D2 - E2
-# \
-# G1 ---- L1 ---- M1
-# \ /
-# H1 -- J1 -- K1
-# \ /
-# -- I1 --
-#
-# And rebase G1..M1 onto E2
-
-test_expect_success 'rebase two levels of merge' '
- git checkout A1 &&
- test_commit G1 &&
- test_commit H1 &&
- test_commit I1 &&
- git checkout -b branch3 H1 &&
- test_commit J1 &&
- test_merge K1 I1 &&
- git checkout -b branch2 G1 &&
- test_commit L1 &&
- test_merge M1 K1 &&
- GIT_EDITOR=: git rebase -i -p E2 &&
- test "$(git rev-parse HEAD~3)" = "$(git rev-parse E2)" &&
- test "$(git rev-parse HEAD~2)" = "$(git rev-parse HEAD^2^2~2)" &&
- test "$(git rev-parse HEAD^2^1^1)" = "$(git rev-parse HEAD^2^2^1)"
-'
-
-test_done
diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh
index fda62c65bd..19c6f4acbf 100755
--- a/t/t3412-rebase-root.sh
+++ b/t/t3412-rebase-root.sh
@@ -89,17 +89,6 @@ test_expect_success 'pre-rebase got correct input (4)' '
test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work4
'
-test_expect_success REBASE_P 'rebase -i -p with linear history' '
- git checkout -b work5 other &&
- git rebase -i -p --root --onto main &&
- git log --pretty=tformat:"%s" > rebased5 &&
- test_cmp expect rebased5
-'
-
-test_expect_success REBASE_P 'pre-rebase got correct input (5)' '
- test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,
-'
-
test_expect_success 'set up merge history' '
git checkout other^ &&
git checkout -b side &&
@@ -123,13 +112,6 @@ commit work6~4
1
EOF
-test_expect_success REBASE_P 'rebase -i -p with merge' '
- git checkout -b work6 other &&
- git rebase -i -p --root --onto main &&
- log_with_names work6 > rebased6 &&
- test_cmp expect-side rebased6
-'
-
test_expect_success 'set up second root and merge' '
git symbolic-ref HEAD refs/heads/third &&
rm .git/index &&
@@ -158,13 +140,6 @@ commit work7~5
1
EOF
-test_expect_success REBASE_P 'rebase -i -p with two roots' '
- git checkout -b work7 other &&
- git rebase -i -p --root --onto main &&
- log_with_names work7 > rebased7 &&
- test_cmp expect-third rebased7
-'
-
test_expect_success 'setup pre-rebase hook that fails' '
mkdir -p .git/hooks &&
cat >.git/hooks/pre-rebase <<EOF &&
@@ -264,21 +239,9 @@ commit conflict3~6
1
EOF
-test_expect_success REBASE_P 'rebase -i -p --root with conflict (first part)' '
- git checkout -b conflict3 other &&
- test_must_fail git rebase -i -p --root --onto main &&
- git ls-files -u | grep "B$"
-'
-
test_expect_success 'fix the conflict' '
echo 3 > B &&
git add B
'
-test_expect_success REBASE_P 'rebase -i -p --root with conflict (second part)' '
- git rebase --continue &&
- log_with_names conflict3 >out &&
- test_cmp expect-conflict-p out
-'
-
test_done
diff --git a/t/t3414-rebase-preserve-onto.sh b/t/t3414-rebase-preserve-onto.sh
deleted file mode 100755
index 72e04b5386..0000000000
--- a/t/t3414-rebase-preserve-onto.sh
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2009 Greg Price
-#
-
-test_description='git rebase -p should respect --onto
-
-In a rebase with --onto, we should rewrite all the commits that
-aren'"'"'t on top of $ONTO, even if they are on top of $UPSTREAM.
-'
-. ./test-lib.sh
-
-if ! test_have_prereq REBASE_P; then
- skip_all='skipping git rebase -p tests, as asked for'
- test_done
-fi
-
-. "$TEST_DIRECTORY"/lib-rebase.sh
-
-# Set up branches like this:
-# A1---B1---E1---F1---G1
-# \ \ /
-# \ \--C1---D1--/
-# H1
-
-test_expect_success 'setup' '
- test_commit A1 &&
- test_commit B1 &&
- test_commit C1 &&
- test_commit D1 &&
- git reset --hard B1 &&
- test_commit E1 &&
- test_commit F1 &&
- test_merge G1 D1 &&
- git reset --hard A1 &&
- test_commit H1
-'
-
-# Now rebase merge G1 from both branches' base B1, both should move:
-# A1---B1---E1---F1---G1
-# \ \ /
-# \ \--C1---D1--/
-# \
-# H1---E2---F2---G2
-# \ /
-# \--C2---D2--/
-
-test_expect_success 'rebase from B1 onto H1' '
- git checkout G1 &&
- git rebase -p --onto H1 B1 &&
- test "$(git rev-parse HEAD^1^1^1)" = "$(git rev-parse H1)" &&
- test "$(git rev-parse HEAD^2^1^1)" = "$(git rev-parse H1)"
-'
-
-# On the other hand if rebase from E1 which is within one branch,
-# then the other branch stays:
-# A1---B1---E1---F1---G1
-# \ \ /
-# \ \--C1---D1--/
-# \ \
-# H1-----F3-----G3
-
-test_expect_success 'rebase from E1 onto H1' '
- git checkout G1 &&
- git rebase -p --onto H1 E1 &&
- test "$(git rev-parse HEAD^1^1)" = "$(git rev-parse H1)" &&
- test "$(git rev-parse HEAD^2)" = "$(git rev-parse D1)"
-'
-
-# And the same if we rebase from a commit in the second-parent branch.
-# A1---B1---E1---F1----G1
-# \ \ \ /
-# \ \--C1---D1-\-/
-# \ \
-# H1------D3------G4
-
-test_expect_success 'rebase from C1 onto H1' '
- git checkout G1 &&
- git rev-list --first-parent --pretty=oneline C1..G1 &&
- git rebase -p --onto H1 C1 &&
- test "$(git rev-parse HEAD^2^1)" = "$(git rev-parse H1)" &&
- test "$(git rev-parse HEAD^1)" = "$(git rev-parse F1)"
-'
-
-test_done
diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index 738fbae9b2..22eca73aa3 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -119,20 +119,6 @@ test_expect_success 'rebase -i --continue handles merge strategy and options' '
test -f funny.was.run
'
-test_expect_success REBASE_P 'rebase passes merge strategy options correctly' '
- rm -fr .git/rebase-* &&
- git reset --hard commit-new-file-F3-on-topic-branch &&
- test_commit theirs-to-merge &&
- git reset --hard HEAD^ &&
- test_commit some-commit &&
- test_tick &&
- git merge --no-ff theirs-to-merge &&
- FAKE_LINES="1 edit 2 3" git rebase -i -f -p -m \
- -s recursive --strategy-option=theirs HEAD~2 &&
- test_commit force-change &&
- git rebase --continue
-'
-
test_expect_success 'rebase -r passes merge strategy options correctly' '
rm -fr .git/rebase-* &&
git reset --hard commit-new-file-F3-on-topic-branch &&
@@ -268,7 +254,6 @@ test_rerere_autoupdate --apply
test_rerere_autoupdate -m
GIT_SEQUENCE_EDITOR=: && export GIT_SEQUENCE_EDITOR
test_rerere_autoupdate -i
-test_have_prereq !REBASE_P || test_rerere_autoupdate --preserve-merges
unset GIT_SEQUENCE_EDITOR
test_expect_success 'the todo command "break" works' '
diff --git a/t/t3421-rebase-topology-linear.sh b/t/t3421-rebase-topology-linear.sh
index 4a9204b4b6..62d86d557d 100755
--- a/t/t3421-rebase-topology-linear.sh
+++ b/t/t3421-rebase-topology-linear.sh
@@ -29,7 +29,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_expect_success 'setup branches and remote tracking' '
git tag -l >tags &&
@@ -53,7 +52,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_run_rebase () {
result=$1
@@ -70,7 +68,6 @@ test_run_rebase success --apply
test_run_rebase success --fork-point
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase failure -p
test_run_rebase () {
result=$1
@@ -87,7 +84,6 @@ test_run_rebase success --apply
test_run_rebase success --fork-point
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_run_rebase () {
result=$1
@@ -102,7 +98,6 @@ test_run_rebase success --apply
test_run_rebase success --fork-point
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
# f
# /
@@ -142,7 +137,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_run_rebase () {
result=$1
@@ -157,7 +151,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_run_rebase () {
result=$1
@@ -172,7 +165,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_run_rebase () {
result=$1
@@ -187,7 +179,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
# a---b---c---j!
# \
@@ -215,7 +206,6 @@ test_run_rebase () {
test_run_rebase failure --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase failure -p
test_run_rebase () {
result=$1
@@ -229,7 +219,6 @@ test_run_rebase () {
}
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_run_rebase () {
result=$1
@@ -243,7 +232,6 @@ test_run_rebase () {
}
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_run_rebase success --rebase-merges
# m
@@ -283,7 +271,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_run_rebase () {
result=$1
@@ -298,7 +285,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase failure -p
test_run_rebase () {
result=$1
@@ -313,7 +299,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_run_rebase () {
result=$1
@@ -329,7 +314,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase failure -p
test_run_rebase () {
result=$1
@@ -344,7 +328,6 @@ test_run_rebase () {
test_run_rebase success --apply
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase failure -p
test_run_rebase () {
result=$1
@@ -358,7 +341,6 @@ test_run_rebase () {
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase failure -p
test_run_rebase () {
result=$1
@@ -373,6 +355,5 @@ test_run_rebase () {
test_run_rebase success ''
test_run_rebase success -m
test_run_rebase success -i
-test_have_prereq !REBASE_P || test_run_rebase success -p
test_done
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index c8234062c6..6dabb05a2a 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test if rebase detects and aborts on incompatible options'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
@@ -63,15 +65,4 @@ test_rebase_am_only () {
test_rebase_am_only --whitespace=fix
test_rebase_am_only -C4
-test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
- git checkout B^0 &&
- test_must_fail git rebase --preserve-merges --signoff A
-'
-
-test_expect_success REBASE_P \
- '--preserve-merges incompatible with --rebase-merges' '
- git checkout B^0 &&
- test_must_fail git rebase --preserve-merges --rebase-merges A
-'
-
test_done
diff --git a/t/t3425-rebase-topology-merges.sh b/t/t3425-rebase-topology-merges.sh
index e42faa44e7..63acc1ea4d 100755
--- a/t/t3425-rebase-topology-merges.sh
+++ b/t/t3425-rebase-topology-merges.sh
@@ -106,155 +106,4 @@ test_run_rebase success 'd n o e' --apply
test_run_rebase success 'd n o e' -m
test_run_rebase success 'd n o e' -i
-if ! test_have_prereq REBASE_P; then
- skip_all='skipping git rebase -p tests, as asked for'
- test_done
-fi
-
-test_expect_success "rebase -p is no-op in non-linear history" "
- reset_rebase &&
- git rebase -p d w &&
- test_cmp_rev w HEAD
-"
-
-test_expect_success "rebase -p is no-op when base inside second parent" "
- reset_rebase &&
- git rebase -p e w &&
- test_cmp_rev w HEAD
-"
-
-test_expect_failure "rebase -p --root on non-linear history is a no-op" "
- reset_rebase &&
- git rebase -p --root w &&
- test_cmp_rev w HEAD
-"
-
-test_expect_success "rebase -p re-creates merge from side branch" "
- reset_rebase &&
- git rebase -p z w &&
- test_cmp_rev z HEAD^ &&
- test_cmp_rev w^2 HEAD^2
-"
-
-test_expect_success "rebase -p re-creates internal merge" "
- reset_rebase &&
- git rebase -p c w &&
- test_cmp_rev c HEAD~4 &&
- test_cmp_rev HEAD^2^ HEAD~3 &&
- test_revision_subjects 'd n e o w' HEAD~3 HEAD~2 HEAD^2 HEAD^ HEAD
-"
-
-test_expect_success "rebase -p can re-create two branches on onto" "
- reset_rebase &&
- git rebase -p --onto c d w &&
- test_cmp_rev c HEAD~3 &&
- test_cmp_rev c HEAD^2^ &&
- test_revision_subjects 'n e o w' HEAD~2 HEAD^2 HEAD^ HEAD
-"
-
-# f
-# /
-# a---b---c---g---h
-# \
-# d---gp--i
-# \ \
-# e-------u
-#
-# gp = cherry-picked g
-# h = reverted g
-test_expect_success 'setup of non-linear-history for patch-equivalence tests' '
- git checkout e &&
- test_merge u i
-'
-
-test_expect_success "rebase -p re-creates history around dropped commit matching upstream" "
- reset_rebase &&
- git rebase -p h u &&
- test_cmp_rev h HEAD~3 &&
- test_cmp_rev HEAD^2^ HEAD~2 &&
- test_revision_subjects 'd i e u' HEAD~2 HEAD^2 HEAD^ HEAD
-"
-
-test_expect_success "rebase -p --onto in merged history drops patches in upstream" "
- reset_rebase &&
- git rebase -p --onto f h u &&
- test_cmp_rev f HEAD~3 &&
- test_cmp_rev HEAD^2^ HEAD~2 &&
- test_revision_subjects 'd i e u' HEAD~2 HEAD^2 HEAD^ HEAD
-"
-
-test_expect_success "rebase -p --onto in merged history does not drop patches in onto" "
- reset_rebase &&
- git rebase -p --onto h f u &&
- test_cmp_rev h HEAD~3 &&
- test_cmp_rev HEAD^2~2 HEAD~2 &&
- test_revision_subjects 'd gp i e u' HEAD~2 HEAD^2^ HEAD^2 HEAD^ HEAD
-"
-
-# a---b---c---g---h
-# \
-# d---gp--s
-# \ \ /
-# \ X
-# \ / \
-# e---t
-#
-# gp = cherry-picked g
-# h = reverted g
-test_expect_success 'setup of non-linear-history for dropping whole side' '
- git checkout gp &&
- test_merge s e &&
- git checkout e &&
- test_merge t gp
-'
-
-test_expect_failure "rebase -p drops merge commit when entire first-parent side is dropped" "
- reset_rebase &&
- git rebase -p h s &&
- test_cmp_rev h HEAD~2 &&
- test_linear_range 'd e' h..
-"
-
-test_expect_success "rebase -p drops merge commit when entire second-parent side is dropped" "
- reset_rebase &&
- git rebase -p h t &&
- test_cmp_rev h HEAD~2 &&
- test_linear_range 'd e' h..
-"
-
-# a---b---c
-# \
-# d---e
-# \ \
-# n---r
-# \
-# o
-#
-# r = tree-same with n
-test_expect_success 'setup of non-linear-history for empty commits' '
- git checkout n &&
- git merge --no-commit e &&
- git reset n . &&
- git commit -m r &&
- git reset --hard &&
- git clean -f &&
- git tag r
-'
-
-test_expect_success "rebase -p re-creates empty internal merge commit" "
- reset_rebase &&
- git rebase -p c r &&
- test_cmp_rev c HEAD~3 &&
- test_cmp_rev HEAD^2^ HEAD~2 &&
- test_revision_subjects 'd e n r' HEAD~2 HEAD^2 HEAD^ HEAD
-"
-
-test_expect_success "rebase -p re-creates empty merge commit" "
- reset_rebase &&
- git rebase -p o r &&
- test_cmp_rev e HEAD^2 &&
- test_cmp_rev o HEAD^ &&
- test_revision_subjects 'r' HEAD
-"
-
test_done
diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh
index e78c7e3796..48b76f8232 100755
--- a/t/t3427-rebase-subtree.sh
+++ b/t/t3427-rebase-subtree.sh
@@ -36,11 +36,10 @@ commit_message() {
# where the root commit adds three files: topic_1.t, topic_2.t and topic_3.t.
#
# This commit history is then rebased onto `topic_3` with the
-# `-Xsubtree=files_subtree` option in three different ways:
+# `-Xsubtree=files_subtree` option in two different ways:
#
-# 1. using `--preserve-merges`
-# 2. using `--preserve-merges` and --keep-empty
-# 3. without specifying a rebase backend
+# 1. without specifying a rebase backend
+# 2. using the `--rebase-merges` backend
test_expect_success 'setup' '
test_commit README &&
@@ -69,25 +68,6 @@ test_expect_success 'setup' '
git commit -m "Empty commit" --allow-empty
'
-# FAILURE: Does not preserve topic_4.
-test_expect_failure REBASE_P 'Rebase -Xsubtree --preserve-merges --onto commit' '
- reset_rebase &&
- git checkout -b rebase-preserve-merges to-rebase &&
- git rebase -Xsubtree=files_subtree --preserve-merges --onto files-main main &&
- verbose test "$(commit_message HEAD~)" = "topic_4" &&
- verbose test "$(commit_message HEAD)" = "files_subtree/topic_5"
-'
-
-# FAILURE: Does not preserve topic_4.
-test_expect_failure REBASE_P 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit' '
- reset_rebase &&
- git checkout -b rebase-keep-empty to-rebase &&
- git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-main main &&
- verbose test "$(commit_message HEAD~2)" = "topic_4" &&
- verbose test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
- verbose test "$(commit_message HEAD)" = "Empty commit"
-'
-
test_expect_success 'Rebase -Xsubtree --empty=ask --onto commit' '
reset_rebase &&
git checkout -b rebase-onto to-rebase &&
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 4d106642ba..94671d3c46 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -82,6 +82,20 @@ test_expect_success '--committer-date-is-author-date works with merge backend' '
test_ctime_is_atime -1
'
+test_expect_success '--committer-date-is-author-date works when rewording' '
+ GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+ (
+ set_fake_editor &&
+ FAKE_COMMIT_MESSAGE=edited \
+ FAKE_LINES="reword 1" \
+ git rebase -i --committer-date-is-author-date HEAD^
+ ) &&
+ test_write_lines edited "" >expect &&
+ git log --format="%B" -1 >actual &&
+ test_cmp expect actual &&
+ test_ctime_is_atime -1
+'
+
test_expect_success '--committer-date-is-author-date works with rebase -r' '
git checkout side &&
GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
@@ -155,6 +169,21 @@ test_expect_success '--reset-author-date with --committer-date-is-author-date wo
test_atime_is_ignored -2
'
+test_expect_success 'reset-author-date with --committer-date-is-author-date works when rewording' '
+ GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+ (
+ set_fake_editor &&
+ FAKE_COMMIT_MESSAGE=edited \
+ FAKE_LINES="reword 1" \
+ git rebase -i --committer-date-is-author-date \
+ --reset-author-date HEAD^
+ ) &&
+ test_write_lines edited "" >expect &&
+ git log --format="%B" -1 >actual &&
+ test_cmp expect actual &&
+ test_atime_is_ignored -1
+'
+
test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '
GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
PATH="./test-bin:$PATH" git rebase -i --strategy=test \
diff --git a/t/t3601-rm-pathspec-file.sh b/t/t3601-rm-pathspec-file.sh
index 7de21f8bcf..b2a8db69af 100755
--- a/t/t3601-rm-pathspec-file.sh
+++ b/t/t3601-rm-pathspec-file.sh
@@ -2,6 +2,7 @@
test_description='rm --pathspec-from-file'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_tick
diff --git a/t/t3602-rm-sparse-checkout.sh b/t/t3602-rm-sparse-checkout.sh
index e9e9a15c74..034ec01091 100755
--- a/t/t3602-rm-sparse-checkout.sh
+++ b/t/t3602-rm-sparse-checkout.sh
@@ -11,12 +11,15 @@ test_expect_success 'setup' "
git commit -m files &&
cat >sparse_error_header <<-EOF &&
- The following pathspecs didn't match any eligible path, but they do match index
- entries outside the current sparse checkout:
+ The following paths and/or pathspecs matched paths that exist
+ outside of your sparse-checkout definition, so will not be
+ updated in the index:
EOF
cat >sparse_hint <<-EOF &&
- hint: Disable or modify the sparsity rules if you intend to update such entries.
+ hint: If you intend to update such entries, try one of the following:
+ hint: * Use the --sparse option.
+ hint: * Disable or modify the sparsity rules.
hint: Disable this message with \"git config advice.updateSparsePath false\"
EOF
@@ -39,7 +42,29 @@ test_expect_success 'recursive rm does not remove sparse entries' '
git sparse-checkout set sub/dir &&
git rm -r sub &&
git status --porcelain -uno >actual &&
- echo "D sub/dir/e" >expected &&
+ cat >expected <<-\EOF &&
+ D sub/dir/e
+ EOF
+ test_cmp expected actual &&
+
+ git rm --sparse -r sub &&
+ git status --porcelain -uno >actual2 &&
+ cat >expected2 <<-\EOF &&
+ D sub/d
+ D sub/dir/e
+ EOF
+ test_cmp expected2 actual2
+'
+
+test_expect_success 'recursive rm --sparse removes sparse entries' '
+ git reset --hard &&
+ git sparse-checkout set "sub/dir" &&
+ git rm --sparse -r sub &&
+ git status --porcelain -uno >actual &&
+ cat >expected <<-\EOF &&
+ D sub/d
+ D sub/dir/e
+ EOF
test_cmp expected actual
'
@@ -75,4 +100,40 @@ test_expect_success 'do not warn about sparse entries with --ignore-unmatch' '
git ls-files --error-unmatch b
'
+test_expect_success 'refuse to rm a non-skip-worktree path outside sparse cone' '
+ git reset --hard &&
+ git sparse-checkout set a &&
+ git update-index --no-skip-worktree b &&
+ test_must_fail git rm b 2>stderr &&
+ test_cmp b_error_and_hint stderr &&
+ git rm --sparse b 2>stderr &&
+ test_must_be_empty stderr &&
+ test_path_is_missing b
+'
+
+test_expect_success 'can remove files from non-sparse dir' '
+ git reset --hard &&
+ git sparse-checkout disable &&
+ mkdir -p w x/y &&
+ test_commit w/f &&
+ test_commit x/y/f &&
+
+ git sparse-checkout set w !/x y/ &&
+ git rm w/f.t x/y/f.t 2>stderr &&
+ test_must_be_empty stderr
+'
+
+test_expect_success 'refuse to remove non-skip-worktree file from sparse dir' '
+ git reset --hard &&
+ git sparse-checkout disable &&
+ mkdir -p x/y/z &&
+ test_commit x/y/z/f &&
+ git sparse-checkout set !/x y/ !x/y/z &&
+
+ git update-index --no-skip-worktree x/y/z/f.t &&
+ test_must_fail git rm x/y/z/f.t 2>stderr &&
+ echo x/y/z/f.t | cat sparse_error_header - sparse_hint >expect &&
+ test_cmp expect stderr
+'
+
test_done
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 4086e1ebbc..283a66955d 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -5,6 +5,7 @@
test_description='Test of git add, including the -- option.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Test the file mode "$1" of the file "$2" in the index.
diff --git a/t/t3705-add-sparse-checkout.sh b/t/t3705-add-sparse-checkout.sh
index 2b1fd0d0ee..f3143c9290 100755
--- a/t/t3705-add-sparse-checkout.sh
+++ b/t/t3705-add-sparse-checkout.sh
@@ -19,6 +19,7 @@ setup_sparse_entry () {
fi &&
git add sparse_entry &&
git update-index --skip-worktree sparse_entry &&
+ git commit --allow-empty -m "ensure sparse_entry exists at HEAD" &&
SPARSE_ENTRY_BLOB=$(git rev-parse :sparse_entry)
}
@@ -36,14 +37,22 @@ setup_gitignore () {
EOF
}
+test_sparse_entry_unstaged () {
+ git diff --staged -- sparse_entry >diff &&
+ test_must_be_empty diff
+}
+
test_expect_success 'setup' "
cat >sparse_error_header <<-EOF &&
- The following pathspecs didn't match any eligible path, but they do match index
- entries outside the current sparse checkout:
+ The following paths and/or pathspecs matched paths that exist
+ outside of your sparse-checkout definition, so will not be
+ updated in the index:
EOF
cat >sparse_hint <<-EOF &&
- hint: Disable or modify the sparsity rules if you intend to update such entries.
+ hint: If you intend to update such entries, try one of the following:
+ hint: * Use the --sparse option.
+ hint: * Disable or modify the sparsity rules.
hint: Disable this message with \"git config advice.updateSparsePath false\"
EOF
@@ -55,6 +64,7 @@ test_expect_success 'git add does not remove sparse entries' '
setup_sparse_entry &&
rm sparse_entry &&
test_must_fail git add sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
test_sparse_entry_unchanged
'
@@ -73,6 +83,7 @@ test_expect_success 'git add . does not remove sparse entries' '
rm sparse_entry &&
setup_gitignore &&
test_must_fail git add . 2>stderr &&
+ test_sparse_entry_unstaged &&
cat sparse_error_header >expect &&
echo . >>expect &&
@@ -88,6 +99,7 @@ do
setup_sparse_entry &&
echo modified >sparse_entry &&
test_must_fail git add $opt sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
test_sparse_entry_unchanged
'
@@ -98,6 +110,7 @@ test_expect_success 'git add --refresh does not update sparse entries' '
git ls-files --debug sparse_entry | grep mtime >before &&
test-tool chmtime -60 sparse_entry &&
test_must_fail git add --refresh sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
git ls-files --debug sparse_entry | grep mtime >after &&
test_cmp before after
@@ -106,6 +119,7 @@ test_expect_success 'git add --refresh does not update sparse entries' '
test_expect_success 'git add --chmod does not update sparse entries' '
setup_sparse_entry &&
test_must_fail git add --chmod=+x sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
test_sparse_entry_unchanged &&
! test -x sparse_entry
@@ -116,6 +130,7 @@ test_expect_success 'git add --renormalize does not update sparse entries' '
setup_sparse_entry "LINEONE\r\nLINETWO\r\n" &&
echo "sparse_entry text=auto" >.gitattributes &&
test_must_fail git add --renormalize sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
test_sparse_entry_unchanged
'
@@ -124,6 +139,7 @@ test_expect_success 'git add --dry-run --ignore-missing warn on sparse path' '
setup_sparse_entry &&
rm sparse_entry &&
test_must_fail git add --dry-run --ignore-missing sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp error_and_hint stderr &&
test_sparse_entry_unchanged
'
@@ -145,11 +161,74 @@ test_expect_success 'do not warn when pathspec matches dense entries' '
git ls-files --error-unmatch dense_entry
'
+test_expect_success 'git add fails outside of sparse-checkout definition' '
+ test_when_finished git sparse-checkout disable &&
+ test_commit a &&
+ git sparse-checkout init &&
+ git sparse-checkout set a &&
+ echo >>sparse_entry &&
+
+ git update-index --no-skip-worktree sparse_entry &&
+ test_must_fail git add sparse_entry &&
+ test_sparse_entry_unstaged &&
+
+ test_must_fail git add --chmod=+x sparse_entry &&
+ test_sparse_entry_unstaged &&
+
+ test_must_fail git add --renormalize sparse_entry &&
+ test_sparse_entry_unstaged &&
+
+ # Avoid munging CRLFs to avoid an error message
+ git -c core.autocrlf=input add --sparse sparse_entry 2>stderr &&
+ test_must_be_empty stderr &&
+ test-tool read-cache --table >actual &&
+ grep "^100644 blob.*sparse_entry\$" actual &&
+
+ git add --sparse --chmod=+x sparse_entry 2>stderr &&
+ test_must_be_empty stderr &&
+ test-tool read-cache --table >actual &&
+ grep "^100755 blob.*sparse_entry\$" actual &&
+
+ git reset &&
+
+ # This will print a message over stderr on Windows.
+ git add --sparse --renormalize sparse_entry &&
+ git status --porcelain >actual &&
+ grep "^M sparse_entry\$" actual
+'
+
test_expect_success 'add obeys advice.updateSparsePath' '
setup_sparse_entry &&
test_must_fail git -c advice.updateSparsePath=false add sparse_entry 2>stderr &&
+ test_sparse_entry_unstaged &&
test_cmp sparse_entry_error stderr
'
+test_expect_success 'add allows sparse entries with --sparse' '
+ git sparse-checkout set a &&
+ echo modified >sparse_entry &&
+ test_must_fail git add sparse_entry &&
+ test_sparse_entry_unchanged &&
+ git add --sparse sparse_entry 2>stderr &&
+ test_must_be_empty stderr
+'
+
+test_expect_success 'can add files from non-sparse dir' '
+ git sparse-checkout set w !/x y/ &&
+ mkdir -p w x/y &&
+ touch w/f x/y/f &&
+ git add w/f x/y/f 2>stderr &&
+ test_must_be_empty stderr
+'
+
+test_expect_success 'refuse to add non-skip-worktree file from sparse dir' '
+ git sparse-checkout set !/x y/ !x/y/z &&
+ mkdir -p x/y/z &&
+ touch x/y/z/f &&
+ test_must_fail git add x/y/z/f 2>stderr &&
+ echo x/y/z/f | cat sparse_error_header - sparse_hint >expect &&
+ test_cmp expect stderr
+'
+
test_done
diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh
index f528008c36..72a5a565e9 100755
--- a/t/t3902-quoted.sh
+++ b/t/t3902-quoted.sh
@@ -5,6 +5,7 @@
test_description='quoted output'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
FN='濱野'
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index f0a82be9de..2c66cfbc3b 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -288,6 +288,17 @@ test_expect_success 'stash --no-keep-index' '
test bar,bar2 = $(cat file),$(cat file2)
'
+test_expect_success 'stash --staged' '
+ echo bar3 >file &&
+ echo bar4 >file2 &&
+ git add file2 &&
+ git stash --staged &&
+ test bar3,bar2 = $(cat file),$(cat file2) &&
+ git reset --hard &&
+ git stash pop &&
+ test bar,bar4 = $(cat file),$(cat file2)
+'
+
test_expect_success 'dont assume push with non-option args' '
test_must_fail git stash -q drop 2>err &&
test_i18ngrep -e "subcommand wasn'\''t specified; '\''push'\'' can'\''t be assumed due to unexpected token '\''drop'\''" err
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
index dd2cdcc114..5390eec4e3 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -422,4 +422,10 @@ test_expect_success 'stash show --{include,only}-untracked on stashes without un
test_must_be_empty actual
'
+test_expect_success 'stash -u ignores sub-repository' '
+ test_when_finished "rm -rf sub-repo" &&
+ git init sub-repo &&
+ git stash -u
+'
+
test_done
diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh
index 6a9f010197..ea52e5b91b 100755
--- a/t/t4002-diff-basic.sh
+++ b/t/t4002-diff-basic.sh
@@ -6,6 +6,8 @@
test_description='Test diff raw-output.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh
diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh
index db07ff3eb1..f4485a87c6 100755
--- a/t/t4003-diff-rename-1.sh
+++ b/t/t4003-diff-rename-1.sh
@@ -11,7 +11,7 @@ test_description='More rename detection
test_expect_success \
'prepare reference tree' \
- 'cat "$TEST_DIRECTORY"/lib-diff/COPYING >COPYING &&
+ 'COPYING_test_data >COPYING &&
echo frotz >rezrov &&
git update-index --add COPYING rezrov &&
tree=$(git write-tree) &&
@@ -99,7 +99,7 @@ test_expect_success \
test_expect_success \
'prepare work tree once again' \
- 'cat "$TEST_DIRECTORY"/lib-diff/COPYING >COPYING &&
+ 'COPYING_test_data >COPYING &&
git update-index --add --remove COPYING COPYING.1'
# tree has COPYING and rezrov. work tree has COPYING and COPYING.1,
diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh
index 8647906132..6f1b323f97 100755
--- a/t/t4005-diff-rename-2.sh
+++ b/t/t4005-diff-rename-2.sh
@@ -9,7 +9,7 @@ test_description='Same rename detection as t4003 but testing diff-raw.'
. "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash
test_expect_success 'setup reference tree' '
- cat "$TEST_DIRECTORY"/lib-diff/COPYING >COPYING &&
+ COPYING_test_data >COPYING &&
echo frotz >rezrov &&
git update-index --add COPYING rezrov &&
tree=$(git write-tree) &&
@@ -64,7 +64,7 @@ test_expect_success 'validate output from rename/copy detection (#2)' '
# nows how to say Copy.
test_expect_success 'validate output from rename/copy detection (#3)' '
- cat "$TEST_DIRECTORY"/lib-diff/COPYING >COPYING &&
+ COPYING_test_data >COPYING &&
git update-index --add --remove COPYING COPYING.1 &&
cat <<-EOF >expected &&
diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh
index cbb9c62f53..c634653b5b 100755
--- a/t/t4007-rename-3.sh
+++ b/t/t4007-rename-3.sh
@@ -11,13 +11,12 @@ test_description='Rename interaction with pathspec.
test_expect_success 'prepare reference tree' '
mkdir path0 path1 &&
- cp "$TEST_DIRECTORY"/lib-diff/COPYING path0/COPYING &&
+ COPYING_test_data >path0/COPYING &&
git update-index --add path0/COPYING &&
tree=$(git write-tree) &&
- echo $tree
+ blob=$(git rev-parse :path0/COPYING)
'
-blob=$(git hash-object "$TEST_DIRECTORY/lib-diff/COPYING")
test_expect_success 'prepare work tree' '
cp path0/COPYING path1/COPYING &&
git update-index --add --remove path0/COPYING path1/COPYING
diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh
index 2299f27511..562aaf3a2a 100755
--- a/t/t4008-diff-break-rewrite.sh
+++ b/t/t4008-diff-break-rewrite.sh
@@ -25,8 +25,8 @@ Further, with -B and -M together, these should turn into two renames.
. "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash
test_expect_success setup '
- cat "$TEST_DIRECTORY"/lib-diff/README >file0 &&
- cat "$TEST_DIRECTORY"/lib-diff/COPYING >file1 &&
+ echo some dissimilar content >file0 &&
+ COPYING_test_data >file1 &&
blob0_id=$(git hash-object file0) &&
blob1_id=$(git hash-object file1) &&
git update-index --add file0 file1 &&
diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh
index b1da807f16..59b7f44f05 100755
--- a/t/t4009-diff-rename-4.sh
+++ b/t/t4009-diff-rename-4.sh
@@ -11,7 +11,7 @@ test_description='Same rename detection as t4003 but testing diff-raw -z.
test_expect_success \
'prepare reference tree' \
- 'cat "$TEST_DIRECTORY"/lib-diff/COPYING >COPYING &&
+ 'COPYING_test_data >COPYING &&
echo frotz >rezrov &&
git update-index --add COPYING rezrov &&
orig=$(git hash-object COPYING) &&
@@ -81,7 +81,7 @@ test_expect_success \
test_expect_success \
'prepare work tree once again' \
- 'cat "$TEST_DIRECTORY"/lib-diff/COPYING >COPYING &&
+ 'COPYING_test_data >COPYING &&
git update-index --add --remove COPYING COPYING.1'
git diff-index -z -C --find-copies-harder $tree >current
diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh
index 876271d682..5a8d887683 100755
--- a/t/t4016-diff-quote.sh
+++ b/t/t4016-diff-quote.sh
@@ -6,6 +6,7 @@
test_description='Quoting paths in diff output.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
P0='pathname'
diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh
index c6135c7548..c68729ac09 100755
--- a/t/t4019-diff-wserror.sh
+++ b/t/t4019-diff-wserror.sh
@@ -2,6 +2,7 @@
test_description='diff whitespace error detection'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh
index 6d1c3d949c..1c89050a97 100755
--- a/t/t4022-diff-rewrite.sh
+++ b/t/t4022-diff-rewrite.sh
@@ -3,15 +3,17 @@
test_description='rewrite diff'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-diff-data.sh
test_expect_success setup '
- cat "$TEST_DIRECTORY"/../COPYING >test &&
+ COPYING_test_data >test.data &&
+ cp test.data test &&
git add test &&
tr \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM" \
- <"$TEST_DIRECTORY"/../COPYING >test &&
+ <test.data >test &&
echo "to be deleted" >test2 &&
blob=$(git hash-object test2) &&
blob=$(git rev-parse --short $blob) &&
diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh
index 8c9823765e..47d6f35dcc 100755
--- a/t/t4023-diff-rename-typechange.sh
+++ b/t/t4023-diff-rename-typechange.sh
@@ -3,25 +3,26 @@
test_description='typechange rename detection'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-diff.sh
test_expect_success setup '
rm -f foo bar &&
- cat "$TEST_DIRECTORY"/../COPYING >foo &&
+ COPYING_test_data >foo &&
test_ln_s_add linklink bar &&
git add foo &&
git commit -a -m Initial &&
git tag one &&
git rm -f foo bar &&
- cat "$TEST_DIRECTORY"/../COPYING >bar &&
+ COPYING_test_data >bar &&
test_ln_s_add linklink foo &&
git add bar &&
git commit -a -m Second &&
git tag two &&
git rm -f foo bar &&
- cat "$TEST_DIRECTORY"/../COPYING >foo &&
+ COPYING_test_data >foo &&
git add foo &&
git commit -a -m Third &&
git tag three &&
@@ -35,7 +36,7 @@ test_expect_success setup '
# This is purely for sanity check
git rm -f foo bar &&
- cat "$TEST_DIRECTORY"/../COPYING >foo &&
+ COPYING_test_data >foo &&
cat "$TEST_DIRECTORY"/../Makefile >bar &&
git add foo bar &&
git commit -a -m Fifth &&
@@ -43,7 +44,7 @@ test_expect_success setup '
git rm -f foo bar &&
cat "$TEST_DIRECTORY"/../Makefile >foo &&
- cat "$TEST_DIRECTORY"/../COPYING >bar &&
+ COPYING_test_data >bar &&
git add foo bar &&
git commit -a -m Sixth &&
git tag six
diff --git a/t/t4025-hunk-header.sh b/t/t4025-hunk-header.sh
index 35578f2bb9..6356961de4 100755
--- a/t/t4025-hunk-header.sh
+++ b/t/t4025-hunk-header.sh
@@ -2,6 +2,7 @@
test_description='diff hunk header truncation'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
N='日本語'
diff --git a/t/t4026-color.sh b/t/t4026-color.sh
index c0b642c1ab..cc73161b46 100755
--- a/t/t4026-color.sh
+++ b/t/t4026-color.sh
@@ -4,6 +4,8 @@
#
test_description='Test diff/status color escape codes'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
ESC=$(printf '\033')
diff --git a/t/t4034/cpp/expect b/t/t4034/cpp/expect
index 37d1ea2587..dc500ae092 100644
--- a/t/t4034/cpp/expect
+++ b/t/t4034/cpp/expect
@@ -1,36 +1,35 @@
<BOLD>diff --git a/pre b/post<RESET>
-<BOLD>index 23d5c8a..7e8c026 100644<RESET>
+<BOLD>index a1a09b7..f1b6f3c 100644<RESET>
<BOLD>--- a/pre<RESET>
<BOLD>+++ b/post<RESET>
-<CYAN>@@ -1,19 +1,19 @@<RESET>
-Foo() : x(0<RED>&&1<RESET><GREEN>&42<RESET>) { <GREEN>bar(x);<RESET> }
+<CYAN>@@ -1,30 +1,30 @@<RESET>
+Foo() : x(0<RED>&&1<RESET><GREEN>&42<RESET>) { <RED>foo0<RESET><GREEN>bar<RESET>(x.<RED>find<RESET><GREEN>Find<RESET>); }
cout<<"Hello World<RED>!<RESET><GREEN>?<RESET>\n"<<endl;
-<GREEN>(<RESET>1<GREEN>) (<RESET>-1e10<GREEN>) (<RESET>0xabcdef<GREEN>)<RESET> '<RED>x<RESET><GREEN>y<RESET>'
-[<RED>a<RESET><GREEN>x<RESET>] <RED>a<RESET><GREEN>x<RESET>-><RED>b a<RESET><GREEN>y x<RESET>.<RED>b<RESET><GREEN>y<RESET>
-!<RED>a<RESET><GREEN>x<RESET> ~<RED>a a<RESET><GREEN>x x<RESET>++ <RED>a<RESET><GREEN>x<RESET>-- <RED>a<RESET><GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>&<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b a<RESET><GREEN>y x<RESET>%<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET><<<RED>b a<RESET><GREEN>y x<RESET>>><RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET><<RED>b a<RESET><GREEN>y x<RESET><=<RED>b a<RESET><GREEN>y x<RESET>><RED>b a<RESET><GREEN>y x<RESET>>=<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET>==<RED>b a<RESET><GREEN>y x<RESET>!=<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET>&<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET>^<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET>|<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET>&&<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET>||<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET>?<RED>b<RESET><GREEN>y<RESET>:z
-<RED>a<RESET><GREEN>x<RESET>=<RED>b a<RESET><GREEN>y x<RESET>+=<RED>b a<RESET><GREEN>y x<RESET>-=<RED>b a<RESET><GREEN>y x<RESET>*=<RED>b a<RESET><GREEN>y x<RESET>/=<RED>b a<RESET><GREEN>y x<RESET>%=<RED>b a<RESET><GREEN>y x<RESET><<=<RED>b a<RESET><GREEN>y x<RESET>>>=<RED>b a<RESET><GREEN>y x<RESET>&=<RED>b a<RESET><GREEN>y x<RESET>^=<RED>b a<RESET><GREEN>y x<RESET>|=<RED>b<RESET>
-<RED>a<RESET><GREEN>y<RESET>
-<GREEN>x<RESET>,y
-<RED>a<RESET><GREEN>x<RESET>::<RED>b<RESET><GREEN>y<RESET>
+<GREEN>(<RESET>1 <RED>-<RESET><GREEN>+<RESET>1e10 0xabcdef<GREEN>)<RESET> '<RED>x<RESET><GREEN>2<RESET>'
+// long double<RESET>
+<RED>3.141592653e-10l<RESET><GREEN>3.141592654e+10l<RESET>
+// float<RESET>
+<RED>120E5f<RESET><GREEN>120E6f<RESET>
+// hex<RESET>
+<RED>0xdead<RESET><GREEN>0xdeaf<RESET>'1<RED>eaF<RESET><GREEN>eaf<RESET>+<RED>8ULL<RESET><GREEN>7ULL<RESET>
+// octal<RESET>
+<RED>01234567<RESET><GREEN>01234560<RESET>
+// binary<RESET>
+<RED>0b1000<RESET><GREEN>0b1100<RESET>+e1
+// expression<RESET>
+1.5-e+<RED>2<RESET><GREEN>3<RESET>+f
+// another one<RESET>
+str.e+<RED>65<RESET><GREEN>75<RESET>
+[a] b<RED>-><RESET><GREEN>->*<RESET>v d<RED>.<RESET><GREEN>.*<RESET>e
+<GREEN>~<RESET>!a <GREEN>!<RESET>~b c<RED>++<RESET><GREEN>+<RESET> d<RED>--<RESET><GREEN>-<RESET> e*<GREEN>*<RESET>f g<RED>&<RESET><GREEN>&&<RESET>h
+a<RED>*<RESET><GREEN>*=<RESET>b c<RED>/<RESET><GREEN>/=<RESET>d e<RED>%<RESET><GREEN>%=<RESET>f
+a<RED>+<RESET><GREEN>++<RESET>b c<RED>-<RESET><GREEN>--<RESET>d
+a<RED><<<RESET><GREEN><<=<RESET>b c<RED>>><RESET><GREEN>>>=<RESET>d
+a<RED><<RESET><GREEN><=<RESET>b c<RED><=<RESET><GREEN><<RESET>d e<RED>><RESET><GREEN>>=<RESET>f g<RED>>=<RESET><GREEN>><RESET>h i<RED><=<RESET><GREEN><=><RESET>j
+a<RED>==<RESET><GREEN>!=<RESET>b c<RED>!=<RESET><GREEN>=<RESET>d
+a<RED>^<RESET><GREEN>^=<RESET>b c<RED>|<RESET><GREEN>|=<RESET>d e<RED>&&<RESET><GREEN>&=<RESET>f
+a<RED>||<RESET><GREEN>|<RESET>b
+a?<GREEN>:<RESET>b
+a<RED>=<RESET><GREEN>==<RESET>b c<RED>+=<RESET><GREEN>+<RESET>d e<RED>-=<RESET><GREEN>-<RESET>f g<RED>*=<RESET><GREEN>*<RESET>h i<RED>/=<RESET><GREEN>/<RESET>j k<RED>%=<RESET><GREEN>%<RESET>l m<RED><<=<RESET><GREEN><<<RESET>n o<RED>>>=<RESET><GREEN>>><RESET>p q<RED>&=<RESET><GREEN>&<RESET>r s<RED>^=<RESET><GREEN>^<RESET>t u<RED>|=<RESET><GREEN>|<RESET>v
+a,b<RESET>
+a<RED>::<RESET><GREEN>:<RESET>b
diff --git a/t/t4034/cpp/post b/t/t4034/cpp/post
index 7e8c026cef..f1b6f3c228 100644
--- a/t/t4034/cpp/post
+++ b/t/t4034/cpp/post
@@ -1,19 +1,30 @@
-Foo() : x(0&42) { bar(x); }
+Foo() : x(0&42) { bar(x.Find); }
cout<<"Hello World?\n"<<endl;
-(1) (-1e10) (0xabcdef) 'y'
-[x] x->y x.y
-!x ~x x++ x-- x*y x&y
-x*y x/y x%y
-x+y x-y
-x<<y x>>y
-x<y x<=y x>y x>=y
-x==y x!=y
-x&y
-x^y
-x|y
-x&&y
-x||y
-x?y:z
-x=y x+=y x-=y x*=y x/=y x%=y x<<=y x>>=y x&=y x^=y x|=y
-x,y
-x::y
+(1 +1e10 0xabcdef) '2'
+// long double
+3.141592654e+10l
+// float
+120E6f
+// hex
+0xdeaf'1eaf+7ULL
+// octal
+01234560
+// binary
+0b1100+e1
+// expression
+1.5-e+3+f
+// another one
+str.e+75
+[a] b->*v d.*e
+~!a !~b c+ d- e**f g&&h
+a*=b c/=d e%=f
+a++b c--d
+a<<=b c>>=d
+a<=b c<d e>=f g>h i<=>j
+a!=b c=d
+a^=b c|=d e&=f
+a|b
+a?:b
+a==b c+d e-f g*h i/j k%l m<<n o>>p q&r s^t u|v
+a,b
+a:b
diff --git a/t/t4034/cpp/pre b/t/t4034/cpp/pre
index 23d5c8adf5..a1a09b7712 100644
--- a/t/t4034/cpp/pre
+++ b/t/t4034/cpp/pre
@@ -1,19 +1,30 @@
-Foo():x(0&&1){}
+Foo():x(0&&1){ foo0( x.find); }
cout<<"Hello World!\n"<<endl;
1 -1e10 0xabcdef 'x'
-[a] a->b a.b
-!a ~a a++ a-- a*b a&b
-a*b a/b a%b
-a+b a-b
-a<<b a>>b
-a<b a<=b a>b a>=b
-a==b a!=b
-a&b
-a^b
-a|b
-a&&b
+// long double
+3.141592653e-10l
+// float
+120E5f
+// hex
+0xdead'1eaF+8ULL
+// octal
+01234567
+// binary
+0b1000+e1
+// expression
+1.5-e+2+f
+// another one
+str.e+65
+[a] b->v d.e
+!a ~b c++ d-- e*f g&h
+a*b c/d e%f
+a+b c-d
+a<<b c>>d
+a<b c<=d e>f g>=h i<=j
+a==b c!=d
+a^b c|d e&&f
a||b
-a?b:z
-a=b a+=b a-=b a*=b a/=b a%=b a<<=b a>>=b a&=b a^=b a|=b
-a,y
+a?b
+a=b c+=d e-=f g*=h i/=j k%=l m<<=n o>>=p q&=r s^=t u|=v
+a,b
a::b
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
index 872fcda6cb..d0f3edef54 100755
--- a/t/t4115-apply-symlink.sh
+++ b/t/t4115-apply-symlink.sh
@@ -7,6 +7,7 @@ test_description='git apply symlinks and partial files
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t4121-apply-diffs.sh b/t/t4121-apply-diffs.sh
index b45454aaf4..a80cec9d11 100755
--- a/t/t4121-apply-diffs.sh
+++ b/t/t4121-apply-diffs.sh
@@ -4,6 +4,7 @@ test_description='git apply for contextually independent diffs'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
echo '1
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 9dfead936b..7884e3d46b 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -449,6 +449,57 @@ test_expect_success !FAIL_PREREQS 'log with various grep.patternType configurati
)
'
+test_expect_success 'log --author' '
+ cat >expect <<-\EOF &&
+ Author: <BOLD;RED>A U<RESET> Thor <author@example.com>
+ EOF
+ git log -1 --color=always --author="A U" >log &&
+ grep Author log >actual.raw &&
+ test_decode_color <actual.raw >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log --committer' '
+ cat >expect <<-\EOF &&
+ Commit: C O Mitter <committer@<BOLD;RED>example<RESET>.com>
+ EOF
+ git log -1 --color=always --pretty=fuller --committer="example" >log &&
+ grep "Commit:" log >actual.raw &&
+ test_decode_color <actual.raw >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log -i --grep with color' '
+ cat >expect <<-\EOF &&
+ <BOLD;RED>Sec<RESET>ond
+ <BOLD;RED>sec<RESET>ond
+ EOF
+ git log --color=always -i --grep=^sec >log &&
+ grep -i sec log >actual.raw &&
+ test_decode_color <actual.raw >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '-c color.grep.selected log --grep' '
+ cat >expect <<-\EOF &&
+ <GREEN>th<RESET><BOLD;RED>ir<RESET><GREEN>d<RESET>
+ EOF
+ git -c color.grep.selected="green" log --color=always --grep=ir >log &&
+ grep ir log >actual.raw &&
+ test_decode_color <actual.raw >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '-c color.grep.matchSelected log --grep' '
+ cat >expect <<-\EOF &&
+ <BLUE>i<RESET>n<BLUE>i<RESET>t<BLUE>i<RESET>al
+ EOF
+ git -c color.grep.matchSelected="blue" log --color=always --grep=i >log &&
+ grep al log >actual.raw &&
+ test_decode_color <actual.raw >actual &&
+ test_cmp expect actual
+'
+
cat > expect <<EOF
* Second
* sixth
@@ -1616,6 +1667,16 @@ test_expect_success GPGSM 'setup signed branch x509' '
git commit -S -m signed_commit
'
+test_expect_success GPGSSH 'setup sshkey signed branch' '
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+ test_when_finished "git reset --hard && git checkout main" &&
+ git checkout -b signed-ssh main &&
+ echo foo >foo &&
+ git add foo &&
+ git commit -S -m signed_commit
+'
+
test_expect_success GPGSM 'log x509 fingerprint' '
echo "F8BF62E0693D0694816377099909C779FA23FD65 | " >expect &&
git log -n1 --format="%GF | %GP" signed-x509 >actual &&
@@ -1628,6 +1689,13 @@ test_expect_success GPGSM 'log OpenPGP fingerprint' '
test_cmp expect actual
'
+test_expect_success GPGSSH 'log ssh key fingerprint' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2\" | \"}" >expect &&
+ git log -n1 --format="%GF | %GP" signed-ssh >actual &&
+ test_cmp expect actual
+'
+
test_expect_success GPG 'log --graph --show-signature' '
git log --graph --show-signature -n1 signed >actual &&
grep "^| gpg: Signature made" actual &&
@@ -1640,6 +1708,12 @@ test_expect_success GPGSM 'log --graph --show-signature x509' '
grep "^| gpgsm: Good signature" actual
'
+test_expect_success GPGSSH 'log --graph --show-signature ssh' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git log --graph --show-signature -n1 signed-ssh >actual &&
+ grep "${GOOD_SIGNATURE_TRUSTED}" actual
+'
+
test_expect_success GPG 'log --graph --show-signature for merged tag' '
test_when_finished "git reset --hard && git checkout main" &&
git checkout -b plain main &&
diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh
index f120857c20..e78d8097f3 100755
--- a/t/t4204-patch-id.sh
+++ b/t/t4204-patch-id.sh
@@ -5,6 +5,7 @@ test_description='git patch-id'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4210-log-i18n.sh b/t/t4210-log-i18n.sh
index 0141f36e33..d2dfcf164e 100755
--- a/t/t4210-log-i18n.sh
+++ b/t/t4210-log-i18n.sh
@@ -131,11 +131,4 @@ do
fi
done
-test_expect_success 'log shows warning when conversion fails' '
- enc=this-encoding-does-not-exist &&
- git log -1 --encoding=$enc 2>err &&
- echo "warning: unable to reencode commit to ${SQ}${enc}${SQ}" >expect &&
- test_cmp expect err
-'
-
test_done
diff --git a/t/t4300-merge-tree.sh b/t/t4300-merge-tree.sh
index e59601e5fe..c52c8a21fa 100755
--- a/t/t4300-merge-tree.sh
+++ b/t/t4300-merge-tree.sh
@@ -4,6 +4,8 @@
#
test_description='git merge-tree'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index 673baa5c3c..dcf03d324a 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -5,7 +5,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-bundle.sh
. "$TEST_DIRECTORY"/lib-bitmap.sh
# t5310 deals only with single-pack bitmaps, so don't write MIDX bitmaps in
diff --git a/t/t5312-prune-corruption.sh b/t/t5312-prune-corruption.sh
index 11423b3cb2..ea889c088a 100755
--- a/t/t5312-prune-corruption.sh
+++ b/t/t5312-prune-corruption.sh
@@ -7,6 +7,9 @@ if we see, for example, a ref with a bogus name, it is OK either to
bail out or to proceed using it as a reachable tip, but it is _not_
OK to proceed as if it did not exist. Otherwise we might silently
delete objects that cannot be recovered.
+
+Note that we do assert command failure in these cases, because that is
+what currently happens. If that changes, these tests should be revisited.
'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
@@ -18,39 +21,58 @@ test_expect_success 'disable reflogs' '
git reflog expire --expire=all --all
'
+create_bogus_ref () {
+ test_when_finished 'rm -f .git/refs/heads/bogus..name' &&
+ echo $bogus >.git/refs/heads/bogus..name
+}
+
test_expect_success 'create history reachable only from a bogus-named ref' '
test_tick && git commit --allow-empty -m main &&
base=$(git rev-parse HEAD) &&
test_tick && git commit --allow-empty -m bogus &&
bogus=$(git rev-parse HEAD) &&
git cat-file commit $bogus >saved &&
- echo $bogus >.git/refs/heads/bogus..name &&
git reset --hard HEAD^
'
test_expect_success 'pruning does not drop bogus object' '
test_when_finished "git hash-object -w -t commit saved" &&
- test_might_fail git prune --expire=now &&
- verbose git cat-file -e $bogus
+ create_bogus_ref &&
+ test_must_fail git prune --expire=now &&
+ git cat-file -e $bogus
'
test_expect_success 'put bogus object into pack' '
git tag reachable $bogus &&
git repack -ad &&
git tag -d reachable &&
- verbose git cat-file -e $bogus
+ git cat-file -e $bogus
+'
+
+test_expect_success 'non-destructive repack bails on bogus ref' '
+ create_bogus_ref &&
+ test_must_fail git repack -adk
'
+test_expect_success 'GIT_REF_PARANOIA=0 overrides safety' '
+ create_bogus_ref &&
+ GIT_REF_PARANOIA=0 git repack -adk
+'
+
+
test_expect_success 'destructive repack keeps packed object' '
- test_might_fail git repack -Ad --unpack-unreachable=now &&
- verbose git cat-file -e $bogus &&
- test_might_fail git repack -ad &&
- verbose git cat-file -e $bogus
+ create_bogus_ref &&
+ test_must_fail git repack -Ad --unpack-unreachable=now &&
+ git cat-file -e $bogus &&
+ test_must_fail git repack -ad &&
+ git cat-file -e $bogus
'
-# subsequent tests will have different corruptions
-test_expect_success 'clean up bogus ref' '
- rm .git/refs/heads/bogus..name
+test_expect_success 'destructive repack not confused by dangling symref' '
+ test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+ git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+ git repack -ad &&
+ test_must_fail git cat-file -e $bogus
'
# We create two new objects here, "one" and "two". Our
@@ -77,8 +99,8 @@ test_expect_success 'create history with missing tip commit' '
test_expect_success 'pruning with a corrupted tip does not drop history' '
test_when_finished "git hash-object -w -t commit saved" &&
- test_might_fail git prune --expire=now &&
- verbose git cat-file -e $recoverable
+ test_must_fail git prune --expire=now &&
+ git cat-file -e $recoverable
'
test_expect_success 'pack-refs does not silently delete broken loose ref' '
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index 295c5bd94d..f516fda7cc 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -70,8 +70,8 @@ test_expect_success 'create commits and repack' '
'
graph_git_two_modes() {
- git -c core.commitGraph=true $1 >output
- git -c core.commitGraph=false $1 >expect
+ git -c core.commitGraph=true $1 >output &&
+ git -c core.commitGraph=false $1 >expect &&
test_cmp expect output
}
@@ -385,6 +385,7 @@ test_expect_success 'replace-objects invalidates commit-graph' '
git commit-graph write --reachable &&
test_path_is_file .git/objects/info/commit-graph &&
git replace HEAD~1 HEAD~2 &&
+ graph_git_two_modes "commit-graph verify" &&
git -c core.commitGraph=false log >expect &&
git -c core.commitGraph=true log >actual &&
test_cmp expect actual &&
@@ -693,12 +694,33 @@ test_expect_success 'detect incorrect chunk count' '
$GRAPH_CHUNK_LOOKUP_OFFSET
'
-test_expect_success 'git fsck (checks commit-graph)' '
+test_expect_success 'git fsck (checks commit-graph when config set to true)' '
cd "$TRASH_DIRECTORY/full" &&
git fsck &&
corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
"incorrect checksum" &&
cp commit-graph-pre-write-test $objdir/info/commit-graph &&
+ test_must_fail git -c core.commitGraph=true fsck
+'
+
+test_expect_success 'git fsck (ignores commit-graph when config set to false)' '
+ cd "$TRASH_DIRECTORY/full" &&
+ git fsck &&
+ corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
+ "incorrect checksum" &&
+ cp commit-graph-pre-write-test $objdir/info/commit-graph &&
+ git -c core.commitGraph=false fsck
+'
+
+test_expect_success 'git fsck (checks commit-graph when config unset)' '
+ cd "$TRASH_DIRECTORY/full" &&
+ test_when_finished "git config core.commitGraph true" &&
+
+ git fsck &&
+ corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
+ "incorrect checksum" &&
+ test_unconfig core.commitGraph &&
+ cp commit-graph-pre-write-test $objdir/info/commit-graph &&
test_must_fail git fsck
'
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index bd17f308b3..a612e44547 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -168,6 +168,21 @@ test_expect_success 'write midx with two packs' '
compare_results_with_midx "two packs"
+test_expect_success 'write midx with --stdin-packs' '
+ rm -fr $objdir/pack/multi-pack-index &&
+
+ idx="$(find $objdir/pack -name "test-2-*.idx")" &&
+ basename "$idx" >in &&
+
+ git multi-pack-index write --stdin-packs <in &&
+
+ test-tool read-midx $objdir | grep "\.idx$" >packs &&
+
+ test_cmp packs in
+'
+
+compare_results_with_midx "mixed mode (one pack + extra)"
+
test_expect_success 'write progress off for redirected stderr' '
git multi-pack-index --object-dir=$objdir write 2>err &&
test_line_count = 0 err
@@ -452,7 +467,10 @@ test_expect_success 'verify incorrect offset' '
test_expect_success 'git-fsck incorrect offset' '
corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\377" $objdir \
"incorrect object offset" \
- "git -c core.multipackindex=true fsck"
+ "git -c core.multiPackIndex=true fsck" &&
+ test_unconfig core.multiPackIndex &&
+ test_must_fail git fsck &&
+ git -c core.multiPackIndex=false fsck
'
test_expect_success 'corrupt MIDX is not reused' '
@@ -464,8 +482,10 @@ test_expect_success 'corrupt MIDX is not reused' '
'
test_expect_success 'verify incorrect checksum' '
- pos=$(($(wc -c <$objdir/pack/multi-pack-index) - 1)) &&
- corrupt_midx_and_verify $pos "\377" $objdir "incorrect checksum"
+ pos=$(($(wc -c <$objdir/pack/multi-pack-index) - 10)) &&
+ corrupt_midx_and_verify $pos \
+ "\377\377\377\377\377\377\377\377\377\377" \
+ $objdir "incorrect checksum"
'
test_expect_success 'repack progress off for redirected stderr' '
diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh
index 587226ed10..847b809710 100755
--- a/t/t5324-split-commit-graph.sh
+++ b/t/t5324-split-commit-graph.sh
@@ -55,8 +55,8 @@ test_expect_success 'create commits and write commit-graph' '
'
graph_git_two_modes() {
- git -c core.commitGraph=true $1 >output
- git -c core.commitGraph=false $1 >expect
+ git ${2:+ -C "$2"} -c core.commitGraph=true $1 >output &&
+ git ${2:+ -C "$2"} -c core.commitGraph=false $1 >expect &&
test_cmp expect output
}
@@ -64,12 +64,13 @@ graph_git_behavior() {
MSG=$1
BRANCH=$2
COMPARE=$3
+ DIR=$4
test_expect_success "check normal git operations: $MSG" '
- graph_git_two_modes "log --oneline $BRANCH" &&
- graph_git_two_modes "log --topo-order $BRANCH" &&
- graph_git_two_modes "log --graph $COMPARE..$BRANCH" &&
- graph_git_two_modes "branch -vv" &&
- graph_git_two_modes "merge-base -a $BRANCH $COMPARE"
+ graph_git_two_modes "log --oneline $BRANCH" "$DIR" &&
+ graph_git_two_modes "log --topo-order $BRANCH" "$DIR" &&
+ graph_git_two_modes "log --graph $COMPARE..$BRANCH" "$DIR" &&
+ graph_git_two_modes "branch -vv" "$DIR" &&
+ graph_git_two_modes "merge-base -a $BRANCH $COMPARE" "$DIR"
'
}
@@ -187,7 +188,10 @@ test_expect_success 'create fork and chain across alternate' '
)
'
-graph_git_behavior 'alternate: commit 13 vs 6' commits/13 commits/6
+if test -d fork
+then
+ graph_git_behavior 'alternate: commit 13 vs 6' commits/13 origin/commits/6 "fork"
+fi
test_expect_success 'test merge stragety constants' '
git clone . merge-2 &&
diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh
index 4ad7c2c969..e187f90f29 100755
--- a/t/t5326-multi-pack-bitmaps.sh
+++ b/t/t5326-multi-pack-bitmaps.sh
@@ -283,4 +283,116 @@ test_expect_success 'pack.preferBitmapTips' '
)
'
+test_expect_success 'writing a bitmap with --refs-snapshot' '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit one &&
+ test_commit two &&
+
+ git rev-parse one >snapshot &&
+
+ git repack -ad &&
+
+ # First, write a MIDX which see both refs/tags/one and
+ # refs/tags/two (causing both of those commits to receive
+ # bitmaps).
+ git multi-pack-index write --bitmap &&
+
+ test_path_is_file $midx &&
+ test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
+
+ test-tool bitmap list-commits | sort >bitmaps &&
+ grep "$(git rev-parse one)" bitmaps &&
+ grep "$(git rev-parse two)" bitmaps &&
+
+ rm -fr $midx-$(midx_checksum $objdir).bitmap &&
+ rm -fr $midx-$(midx_checksum $objdir).rev &&
+ rm -fr $midx &&
+
+ # Then again, but with a refs snapshot which only sees
+ # refs/tags/one.
+ git multi-pack-index write --bitmap --refs-snapshot=snapshot &&
+
+ test_path_is_file $midx &&
+ test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
+
+ test-tool bitmap list-commits | sort >bitmaps &&
+ grep "$(git rev-parse one)" bitmaps &&
+ ! grep "$(git rev-parse two)" bitmaps
+ )
+'
+
+test_expect_success 'write a bitmap with --refs-snapshot (preferred tips)' '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit_bulk --message="%s" 103 &&
+
+ git log --format="%H" >commits.raw &&
+ sort <commits.raw >commits &&
+
+ git log --format="create refs/tags/%s %H" HEAD >refs &&
+ git update-ref --stdin <refs &&
+
+ git multi-pack-index write --bitmap &&
+ test_path_is_file $midx &&
+ test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
+
+ test-tool bitmap list-commits | sort >bitmaps &&
+ comm -13 bitmaps commits >before &&
+ test_line_count = 1 before &&
+
+ (
+ grep -vf before commits.raw &&
+ # mark missing commits as preferred
+ sed "s/^/+/" before
+ ) >snapshot &&
+
+ rm -fr $midx-$(midx_checksum $objdir).bitmap &&
+ rm -fr $midx-$(midx_checksum $objdir).rev &&
+ rm -fr $midx &&
+
+ git multi-pack-index write --bitmap --refs-snapshot=snapshot &&
+ test-tool bitmap list-commits | sort >bitmaps &&
+ comm -13 bitmaps commits >after &&
+
+ ! test_cmp before after
+ )
+'
+
+test_expect_success 'hash-cache values are propagated from pack bitmaps' '
+ rm -fr repo &&
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit base &&
+ test_commit base2 &&
+ git repack -adb &&
+
+ test-tool bitmap dump-hashes >pack.raw &&
+ test_file_not_empty pack.raw &&
+ sort pack.raw >pack.hashes &&
+
+ test_commit new &&
+ git repack &&
+ git multi-pack-index write --bitmap &&
+
+ test-tool bitmap dump-hashes >midx.raw &&
+ sort midx.raw >midx.hashes &&
+
+ # ensure that every namehash in the pack bitmap can be found in
+ # the midx bitmap (i.e., that there are no oid-namehash pairs
+ # unique to the pack bitmap).
+ comm -23 pack.hashes midx.hashes >dropped.hashes &&
+ test_must_be_empty dropped.hashes
+ )
+'
+
test_done
diff --git a/t/t5410-receive-pack-alternates.sh b/t/t5410-receive-pack-alternates.sh
index 0b28e4e452..7a45d4c311 100755
--- a/t/t5410-receive-pack-alternates.sh
+++ b/t/t5410-receive-pack-alternates.sh
@@ -5,6 +5,7 @@ test_description='git receive-pack with alternate ref filtering'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 4db8edd9c8..7831a38dde 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -541,6 +541,15 @@ do
done
+test_expect_success "push to remote with no explicit refspec and config remote.*.push = src:dest" '
+ mk_test testrepo heads/main &&
+ git checkout $the_first_commit &&
+ test_config remote.there.url testrepo &&
+ test_config remote.there.push refs/heads/main:refs/heads/main &&
+ git push there &&
+ check_push_result testrepo $the_commit heads/main
+'
+
test_expect_success 'push with remote.pushdefault' '
mk_test up_repo heads/main &&
mk_test down_repo heads/main &&
@@ -662,10 +671,10 @@ test_expect_success 'push does not update local refs on failure' '
test_expect_success 'allow deleting an invalid remote ref' '
- mk_test testrepo heads/main &&
+ mk_test testrepo heads/branch &&
rm -f testrepo/.git/objects/??/* &&
- git push testrepo :refs/heads/main &&
- (cd testrepo && test_must_fail git rev-parse --verify refs/heads/main)
+ git push testrepo :refs/heads/branch &&
+ (cd testrepo && test_must_fail git rev-parse --verify refs/heads/branch)
'
@@ -706,25 +715,26 @@ test_expect_success 'pushing valid refs triggers post-receive and post-update ho
'
test_expect_success 'deleting dangling ref triggers hooks with correct args' '
- mk_test_with_hooks testrepo heads/main &&
+ mk_test_with_hooks testrepo heads/branch &&
+ orig=$(git -C testrepo rev-parse refs/heads/branch) &&
rm -f testrepo/.git/objects/??/* &&
- git push testrepo :refs/heads/main &&
+ git push testrepo :refs/heads/branch &&
(
cd testrepo/.git &&
cat >pre-receive.expect <<-EOF &&
- $ZERO_OID $ZERO_OID refs/heads/main
+ $orig $ZERO_OID refs/heads/branch
EOF
cat >update.expect <<-EOF &&
- refs/heads/main $ZERO_OID $ZERO_OID
+ refs/heads/branch $orig $ZERO_OID
EOF
cat >post-receive.expect <<-EOF &&
- $ZERO_OID $ZERO_OID refs/heads/main
+ $orig $ZERO_OID refs/heads/branch
EOF
cat >post-update.expect <<-EOF &&
- refs/heads/main
+ refs/heads/branch
EOF
test_cmp pre-receive.expect pre-receive.actual &&
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 672001a18b..93ecfcdd24 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -546,15 +546,6 @@ test_expect_success 'pull.rebase=1 is treated as true and flattens keep-merge' '
test_cmp expect actual
'
-test_expect_success REBASE_P \
- 'pull.rebase=preserve rebases and merges keep-merge' '
- git reset --hard before-preserve-rebase &&
- test_config pull.rebase preserve &&
- git pull . copy &&
- test_cmp_rev HEAD^^ copy &&
- test_cmp_rev HEAD^2 keep-merge
-'
-
test_expect_success 'pull.rebase=interactive' '
write_script "$TRASH_DIRECTORY/fake-editor" <<-\EOF &&
echo I was here >fake.out &&
@@ -598,7 +589,7 @@ test_expect_success '--rebase=false create a new merge commit' '
test_expect_success '--rebase=true rebases and flattens keep-merge' '
git reset --hard before-preserve-rebase &&
- test_config pull.rebase preserve &&
+ test_config pull.rebase merges &&
git pull --rebase=true . copy &&
test_cmp_rev HEAD^^ copy &&
echo file3 >expect &&
@@ -606,23 +597,14 @@ test_expect_success '--rebase=true rebases and flattens keep-merge' '
test_cmp expect actual
'
-test_expect_success REBASE_P \
- '--rebase=preserve rebases and merges keep-merge' '
- git reset --hard before-preserve-rebase &&
- test_config pull.rebase true &&
- git pull --rebase=preserve . copy &&
- test_cmp_rev HEAD^^ copy &&
- test_cmp_rev HEAD^2 keep-merge
-'
-
test_expect_success '--rebase=invalid fails' '
git reset --hard before-preserve-rebase &&
test_must_fail git pull --rebase=invalid . copy
'
-test_expect_success '--rebase overrides pull.rebase=preserve and flattens keep-merge' '
+test_expect_success '--rebase overrides pull.rebase=merges and flattens keep-merge' '
git reset --hard before-preserve-rebase &&
- test_config pull.rebase preserve &&
+ test_config pull.rebase merges &&
git pull --rebase . copy &&
test_cmp_rev HEAD^^ copy &&
echo file3 >expect &&
diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh
index 7601c919fd..66cfcb09c5 100755
--- a/t/t5521-pull-options.sh
+++ b/t/t5521-pull-options.sh
@@ -228,4 +228,28 @@ test_expect_success 'git pull --no-signoff flag cancels --signoff flag' '
test_must_be_empty actual
'
+test_expect_success 'git pull --no-verify flag passed to merge' '
+ test_when_finished "rm -fr src dst actual" &&
+ git init src &&
+ test_commit -C src one &&
+ git clone src dst &&
+ write_script dst/.git/hooks/commit-msg <<-\EOF &&
+ false
+ EOF
+ test_commit -C src two &&
+ git -C dst pull --no-ff --no-verify
+'
+
+test_expect_success 'git pull --no-verify --verify passed to merge' '
+ test_when_finished "rm -fr src dst actual" &&
+ git init src &&
+ test_commit -C src one &&
+ git clone src dst &&
+ write_script dst/.git/hooks/commit-msg <<-\EOF &&
+ false
+ EOF
+ test_commit -C src two &&
+ test_must_fail git -C dst pull --no-ff --no-verify --verify
+'
+
test_done
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index ed11569d8d..2dc75b80db 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -6,6 +6,9 @@ test_description='Recursive "git fetch" for submodules'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
+export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+
. ./test-lib.sh
pwd=$(pwd)
diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh
index d573ca496a..3f58b515ce 100755
--- a/t/t5531-deep-submodule-push.sh
+++ b/t/t5531-deep-submodule-push.sh
@@ -5,6 +5,9 @@ test_description='test push with submodules'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
+export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5534-push-signed.sh b/t/t5534-push-signed.sh
index bba768f5de..24d374adba 100755
--- a/t/t5534-push-signed.sh
+++ b/t/t5534-push-signed.sh
@@ -137,6 +137,53 @@ test_expect_success GPG 'signed push sends push certificate' '
test_cmp expect dst/push-cert-status
'
+test_expect_success GPGSSH 'ssh signed push sends push certificate' '
+ prepare_dst &&
+ mkdir -p dst/.git/hooks &&
+ git -C dst config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git -C dst config receive.certnonceseed sekrit &&
+ write_script dst/.git/hooks/post-receive <<-\EOF &&
+ # discard the update list
+ cat >/dev/null
+ # record the push certificate
+ if test -n "${GIT_PUSH_CERT-}"
+ then
+ git cat-file blob $GIT_PUSH_CERT >../push-cert
+ fi &&
+
+ cat >../push-cert-status <<E_O_F
+ SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
+ KEY=${GIT_PUSH_CERT_KEY-nokey}
+ STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
+ NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
+ NONCE=${GIT_PUSH_CERT_NONCE-nononce}
+ E_O_F
+
+ EOF
+
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+ FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") &&
+ git push --signed dst noop ff +noff &&
+
+ (
+ cat <<-\EOF &&
+ SIGNER=principal with number 1
+ KEY=FINGERPRINT
+ STATUS=G
+ NONCE_STATUS=OK
+ EOF
+ sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
+ ) | sed -e "s|FINGERPRINT|$FINGERPRINT|" >expect &&
+
+ noop=$(git rev-parse noop) &&
+ ff=$(git rev-parse ff) &&
+ noff=$(git rev-parse noff) &&
+ grep "$noop $ff refs/heads/ff" dst/push-cert &&
+ grep "$noop $noff refs/heads/noff" dst/push-cert &&
+ test_cmp expect dst/push-cert-status
+'
+
test_expect_success GPG 'inconsistent push options in signed push not allowed' '
# First, invoke receive-pack with dummy input to obtain its preamble.
prepare_dst &&
@@ -276,6 +323,60 @@ test_expect_success GPGSM 'fail without key and heed user.signingkey x509' '
test_cmp expect dst/push-cert-status
'
+test_expect_success GPGSSH 'fail without key and heed user.signingkey ssh' '
+ test_config gpg.format ssh &&
+ prepare_dst &&
+ mkdir -p dst/.git/hooks &&
+ git -C dst config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git -C dst config receive.certnonceseed sekrit &&
+ write_script dst/.git/hooks/post-receive <<-\EOF &&
+ # discard the update list
+ cat >/dev/null
+ # record the push certificate
+ if test -n "${GIT_PUSH_CERT-}"
+ then
+ git cat-file blob $GIT_PUSH_CERT >../push-cert
+ fi &&
+
+ cat >../push-cert-status <<E_O_F
+ SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
+ KEY=${GIT_PUSH_CERT_KEY-nokey}
+ STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
+ NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
+ NONCE=${GIT_PUSH_CERT_NONCE-nononce}
+ E_O_F
+
+ EOF
+
+ test_config user.email hasnokey@nowhere.com &&
+ test_config gpg.format ssh &&
+ test_config user.signingkey "" &&
+ (
+ sane_unset GIT_COMMITTER_EMAIL &&
+ test_must_fail git push --signed dst noop ff +noff
+ ) &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+ FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") &&
+ git push --signed dst noop ff +noff &&
+
+ (
+ cat <<-\EOF &&
+ SIGNER=principal with number 1
+ KEY=FINGERPRINT
+ STATUS=G
+ NONCE_STATUS=OK
+ EOF
+ sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
+ ) | sed -e "s|FINGERPRINT|$FINGERPRINT|" >expect &&
+
+ noop=$(git rev-parse noop) &&
+ ff=$(git rev-parse ff) &&
+ noff=$(git rev-parse noff) &&
+ grep "$noop $ff refs/heads/ff" dst/push-cert &&
+ grep "$noop $noff refs/heads/noff" dst/push-cert &&
+ test_cmp expect dst/push-cert-status
+'
+
test_expect_success GPG 'failed atomic push does not execute GPG' '
prepare_dst &&
git -C dst config receive.certnonceseed sekrit &&
diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
index c024fa2818..8ca50f8b18 100755
--- a/t/t5541-http-push-smart.sh
+++ b/t/t5541-http-push-smart.sh
@@ -509,4 +509,20 @@ test_expect_success 'colorize errors/hints' '
test_i18ngrep ! "^hint: " decoded
'
+test_expect_success 'report error server does not provide ref status' '
+ git init "$HTTPD_DOCUMENT_ROOT_PATH/no_report" &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/no_report" config http.receivepack true &&
+ test_must_fail git push --porcelain \
+ $HTTPD_URL_USER_PASS/smart/no_report \
+ HEAD:refs/tags/will-fail >actual &&
+ test_must_fail git -C "$HTTPD_DOCUMENT_ROOT_PATH/no_report" \
+ rev-parse --verify refs/tags/will-fail &&
+ cat >expect <<-EOF &&
+ To $HTTPD_URL/smart/no_report
+ ! HEAD:refs/tags/will-fail [remote failure] (remote failed to report status)
+ Done
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5545-push-options.sh b/t/t5545-push-options.sh
index 58c7add7ee..214228349a 100755
--- a/t/t5545-push-options.sh
+++ b/t/t5545-push-options.sh
@@ -5,6 +5,9 @@ test_description='pushing to a repository using push options'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
+export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+
. ./test-lib.sh
mk_repo_pair () {
diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh
index 4f92a116e1..fa6b4cca65 100755
--- a/t/t5572-pull-submodule.sh
+++ b/t/t5572-pull-submodule.sh
@@ -2,6 +2,9 @@
test_description='pull can handle submodules'
+GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
+export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh
diff --git a/t/t5580-unc-paths.sh b/t/t5580-unc-paths.sh
index cd803ae8bf..cd7604fff9 100755
--- a/t/t5580-unc-paths.sh
+++ b/t/t5580-unc-paths.sh
@@ -4,6 +4,7 @@ test_description='various Windows-only path tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
if test_have_prereq CYGWIN
diff --git a/t/t5600-clone-fail-cleanup.sh b/t/t5600-clone-fail-cleanup.sh
index 5bf10261d3..34b3df4027 100755
--- a/t/t5600-clone-fail-cleanup.sh
+++ b/t/t5600-clone-fail-cleanup.sh
@@ -35,7 +35,9 @@ test_expect_success 'create a repo to clone' '
'
test_expect_success 'create objects in repo for later corruption' '
- test_commit -C foo file
+ test_commit -C foo file &&
+ git -C foo checkout --detach &&
+ test_commit -C foo detached
'
# source repository given to git clone should be relative to the
diff --git a/t/t5609-clone-branch.sh b/t/t5609-clone-branch.sh
index f86a674a03..252e1f7c20 100755
--- a/t/t5609-clone-branch.sh
+++ b/t/t5609-clone-branch.sh
@@ -4,6 +4,7 @@ test_description='clone --branch option'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_HEAD() {
diff --git a/t/t5615-alternate-env.sh b/t/t5615-alternate-env.sh
index b4905b822c..83513e46a3 100755
--- a/t/t5615-alternate-env.sh
+++ b/t/t5615-alternate-env.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='handling of alternates in environment variables'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_obj () {
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index d527cf6c49..78f85b0714 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -1107,6 +1107,57 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul
test_i18ngrep "disallowed submodule name" err
'
+test_expect_success 'packfile-uri path redacted in trace' '
+ P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
+ rm -rf "$P" http_child log &&
+
+ git init "$P" &&
+ git -C "$P" config "uploadpack.allowsidebandall" "true" &&
+
+ echo my-blob >"$P/my-blob" &&
+ git -C "$P" add my-blob &&
+ git -C "$P" commit -m x &&
+
+ git -C "$P" hash-object my-blob >objh &&
+ git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh &&
+ git -C "$P" config --add \
+ "uploadpack.blobpackfileuri" \
+ "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" &&
+
+ GIT_TRACE_PACKET="$(pwd)/log" \
+ git -c protocol.version=2 \
+ -c fetch.uriprotocols=http,https \
+ clone "$HTTPD_URL/smart/http_parent" http_child &&
+
+ grep -F "clone< \\1$(cat packh) $HTTPD_URL/<redacted>" log
+'
+
+test_expect_success 'packfile-uri path not redacted in trace when GIT_TRACE_REDACT=0' '
+ P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
+ rm -rf "$P" http_child log &&
+
+ git init "$P" &&
+ git -C "$P" config "uploadpack.allowsidebandall" "true" &&
+
+ echo my-blob >"$P/my-blob" &&
+ git -C "$P" add my-blob &&
+ git -C "$P" commit -m x &&
+
+ git -C "$P" hash-object my-blob >objh &&
+ git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh &&
+ git -C "$P" config --add \
+ "uploadpack.blobpackfileuri" \
+ "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" &&
+
+ GIT_TRACE_PACKET="$(pwd)/log" \
+ GIT_TRACE_REDACT=0 \
+ git -c protocol.version=2 \
+ -c fetch.uriprotocols=http,https \
+ clone "$HTTPD_URL/smart/http_parent" http_child &&
+
+ grep -F "clone< \\1$(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" log
+'
+
test_expect_success 'http:// --negotiate-only' '
SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" &&
URI="$HTTPD_URL/smart/server" &&
diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
index ef849e5bc8..12def7bcbf 100755
--- a/t/t6000-rev-list-misc.sh
+++ b/t/t6000-rev-list-misc.sh
@@ -169,35 +169,4 @@ test_expect_success 'rev-list --count --objects' '
test_line_count = $count actual
'
-test_expect_success 'rev-list --unsorted-input results in different sorting' '
- git rev-list --unsorted-input HEAD HEAD~ >first &&
- git rev-list --unsorted-input HEAD~ HEAD >second &&
- ! test_cmp first second &&
- sort first >first.sorted &&
- sort second >second.sorted &&
- test_cmp first.sorted second.sorted
-'
-
-test_expect_success 'rev-list --unsorted-input incompatible with --no-walk' '
- cat >expect <<-EOF &&
- fatal: --no-walk is incompatible with --unsorted-input
- EOF
- test_must_fail git rev-list --unsorted-input --no-walk HEAD 2>error &&
- test_cmp expect error &&
- test_must_fail git rev-list --unsorted-input --no-walk=sorted HEAD 2>error &&
- test_cmp expect error &&
- test_must_fail git rev-list --unsorted-input --no-walk=unsorted HEAD 2>error &&
- test_cmp expect error &&
-
- cat >expect <<-EOF &&
- fatal: --unsorted-input is incompatible with --no-walk
- EOF
- test_must_fail git rev-list --no-walk --unsorted-input HEAD 2>error &&
- test_cmp expect error &&
- test_must_fail git rev-list --no-walk=sorted --unsorted-input HEAD 2>error &&
- test_cmp expect error &&
- test_must_fail git rev-list --no-walk=unsorted --unsorted-input HEAD 2>error &&
- test_cmp expect error
-'
-
test_done
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index 44f55d93fe..06c5fb5615 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -81,6 +81,16 @@ test_expect_success GPG 'set up a signed tag' '
git tag -s -m signed-tag-msg signed-good-tag left
'
+test_expect_success GPGSSH 'created ssh signed commit and tag' '
+ test_config gpg.format ssh &&
+ git checkout -b signed-ssh &&
+ touch file &&
+ git add file &&
+ git commit -m "ssh signed" -S"${GPGSSH_KEY_PRIMARY}" &&
+ git tag -s -u"${GPGSSH_KEY_PRIMARY}" -m signed-ssh-tag-msg signed-good-ssh-tag left &&
+ git tag -s -u"${GPGSSH_KEY_UNTRUSTED}" -m signed-ssh-tag-msg-untrusted signed-untrusted-ssh-tag left
+'
+
test_expect_success 'message for merging local branch' '
echo "Merge branch ${apos}left${apos}" >expected &&
@@ -109,6 +119,24 @@ test_expect_success GPG 'message for merging local tag signed by unknown key' '
grep -E "^# gpg: Can${apos}t check signature: (public key not found|No public key)" actual
'
+test_expect_success GPGSSH 'message for merging local tag signed by good ssh key' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git checkout main &&
+ git fetch . signed-good-ssh-tag &&
+ git fmt-merge-msg <.git/FETCH_HEAD >actual 2>&1 &&
+ grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual
+'
+
+test_expect_success GPGSSH 'message for merging local tag signed by unknown ssh key' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git checkout main &&
+ git fetch . signed-untrusted-ssh-tag &&
+ git fmt-merge-msg <.git/FETCH_HEAD >actual 2>&1 &&
+ grep "${GPGSSH_GOOD_SIGNATURE_UNTRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ grep "${GPGSSH_KEY_NOT_TRUSTED}" actual
+'
test_expect_success 'message for merging external branch' '
echo "Merge branch ${apos}left${apos} of $(pwd)" >expected &&
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 80679d5e12..9f2c706c12 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -419,6 +419,11 @@ test_expect_success 'Verify descending sort' '
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
@@ -1019,6 +1024,27 @@ test_expect_success 'equivalent sorts fall back on refname' '
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 '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 &&
diff --git a/t/t6407-merge-binary.sh b/t/t6407-merge-binary.sh
index d4273f2575..e34676c204 100755
--- a/t/t6407-merge-binary.sh
+++ b/t/t6407-merge-binary.sh
@@ -5,6 +5,7 @@ test_description='ask merge-recursive to merge binary files'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t6414-merge-rename-nocruft.sh b/t/t6414-merge-rename-nocruft.sh
index d7e3c1fa6e..69fc1c9e69 100755
--- a/t/t6414-merge-rename-nocruft.sh
+++ b/t/t6414-merge-rename-nocruft.sh
@@ -4,6 +4,7 @@ test_description='Merge-recursive merging renames'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t6437-submodule-merge.sh b/t/t6437-submodule-merge.sh
index e5e89c2045..178413c22f 100755
--- a/t/t6437-submodule-merge.sh
+++ b/t/t6437-submodule-merge.sh
@@ -5,6 +5,9 @@ test_description='merging with submodules'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
+export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-merge.sh
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 25bb9bbb89..963356ba5f 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -2,10 +2,11 @@
test_description='git mv in subdirs'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-diff-data.sh
test_expect_success 'prepare reference tree' '
mkdir path0 path1 &&
- cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
+ COPYING_test_data >path0/COPYING &&
git add path0/COPYING &&
git commit -m add -a
'
@@ -107,7 +108,7 @@ test_expect_success 'clean up' '
'
test_expect_success 'adding another file' '
- cp "$TEST_DIRECTORY"/../README.md path0/README &&
+ COPYING_test_data | tr A-Za-z N-ZA-Mn-za-m >path0/README &&
git add path0/README &&
git commit -m add2 -a
'
diff --git a/t/t7002-mv-sparse-checkout.sh b/t/t7002-mv-sparse-checkout.sh
new file mode 100755
index 0000000000..1d3d2aca21
--- /dev/null
+++ b/t/t7002-mv-sparse-checkout.sh
@@ -0,0 +1,209 @@
+#!/bin/sh
+
+test_description='git mv in sparse working trees'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' "
+ mkdir -p sub/dir sub/dir2 &&
+ touch a b c sub/d sub/dir/e sub/dir2/e &&
+ git add -A &&
+ git commit -m files &&
+
+ cat >sparse_error_header <<-EOF &&
+ The following paths and/or pathspecs matched paths that exist
+ outside of your sparse-checkout definition, so will not be
+ updated in the index:
+ EOF
+
+ cat >sparse_hint <<-EOF
+ hint: If you intend to update such entries, try one of the following:
+ hint: * Use the --sparse option.
+ hint: * Disable or modify the sparsity rules.
+ hint: Disable this message with \"git config advice.updateSparsePath false\"
+ EOF
+"
+
+test_expect_success 'mv refuses to move sparse-to-sparse' '
+ test_when_finished rm -f e &&
+ git reset --hard &&
+ git sparse-checkout set a &&
+ touch b &&
+ test_must_fail git mv b e 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo b >>expect &&
+ echo e >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse b e 2>stderr &&
+ test_must_be_empty stderr
+'
+
+test_expect_success 'mv refuses to move sparse-to-sparse, ignores failure' '
+ test_when_finished rm -f b c e &&
+ git reset --hard &&
+ git sparse-checkout set a &&
+
+ # tracked-to-untracked
+ touch b &&
+ git mv -k b e 2>stderr &&
+ test_path_exists b &&
+ test_path_is_missing e &&
+ cat sparse_error_header >expect &&
+ echo b >>expect &&
+ echo e >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse b e 2>stderr &&
+ test_must_be_empty stderr &&
+ test_path_is_missing b &&
+ test_path_exists e &&
+
+ # tracked-to-tracked
+ git reset --hard &&
+ touch b &&
+ git mv -k b c 2>stderr &&
+ test_path_exists b &&
+ test_path_is_missing c &&
+ cat sparse_error_header >expect &&
+ echo b >>expect &&
+ echo c >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+
+ git mv --sparse b c 2>stderr &&
+ test_must_be_empty stderr &&
+ test_path_is_missing b &&
+ test_path_exists c
+'
+
+test_expect_success 'mv refuses to move non-sparse-to-sparse' '
+ test_when_finished rm -f b c e &&
+ git reset --hard &&
+ git sparse-checkout set a &&
+
+ # tracked-to-untracked
+ test_must_fail git mv a e 2>stderr &&
+ test_path_exists a &&
+ test_path_is_missing e &&
+ cat sparse_error_header >expect &&
+ echo e >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse a e 2>stderr &&
+ test_must_be_empty stderr &&
+ test_path_is_missing a &&
+ test_path_exists e &&
+
+ # tracked-to-tracked
+ rm e &&
+ git reset --hard &&
+ test_must_fail git mv a c 2>stderr &&
+ test_path_exists a &&
+ test_path_is_missing c &&
+ cat sparse_error_header >expect &&
+ echo c >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse a c 2>stderr &&
+ test_must_be_empty stderr &&
+ test_path_is_missing a &&
+ test_path_exists c
+'
+
+test_expect_success 'mv refuses to move sparse-to-non-sparse' '
+ test_when_finished rm -f b c e &&
+ git reset --hard &&
+ git sparse-checkout set a e &&
+
+ # tracked-to-untracked
+ touch b &&
+ test_must_fail git mv b e 2>stderr &&
+ cat sparse_error_header >expect &&
+ echo b >>expect &&
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse b e 2>stderr &&
+ test_must_be_empty stderr
+'
+
+test_expect_success 'recursive mv refuses to move (possible) sparse' '
+ test_when_finished rm -rf b c e sub2 &&
+ git reset --hard &&
+ # Without cone mode, "sub" and "sub2" do not match
+ git sparse-checkout set sub/dir sub2/dir &&
+
+ # Add contained contents to ensure we avoid non-existence errors
+ mkdir sub/dir2 &&
+ touch sub/d sub/dir2/e &&
+
+ test_must_fail git mv sub sub2 2>stderr &&
+ cat sparse_error_header >expect &&
+ cat >>expect <<-\EOF &&
+ sub/d
+ sub2/d
+ sub/dir2/e
+ sub2/dir2/e
+ EOF
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse sub sub2 2>stderr &&
+ test_must_be_empty stderr &&
+ git commit -m "moved sub to sub2" &&
+ git rev-parse HEAD~1:sub >expect &&
+ git rev-parse HEAD:sub2 >actual &&
+ test_cmp expect actual &&
+ git reset --hard HEAD~1
+'
+
+test_expect_success 'recursive mv refuses to move sparse' '
+ git reset --hard &&
+ # Use cone mode so "sub/" matches the sparse-checkout patterns
+ git sparse-checkout init --cone &&
+ git sparse-checkout set sub/dir sub2/dir &&
+
+ # Add contained contents to ensure we avoid non-existence errors
+ mkdir sub/dir2 &&
+ touch sub/dir2/e &&
+
+ test_must_fail git mv sub sub2 2>stderr &&
+ cat sparse_error_header >expect &&
+ cat >>expect <<-\EOF &&
+ sub/dir2/e
+ sub2/dir2/e
+ EOF
+ cat sparse_hint >>expect &&
+ test_cmp expect stderr &&
+ git mv --sparse sub sub2 2>stderr &&
+ test_must_be_empty stderr &&
+ git commit -m "moved sub to sub2" &&
+ git rev-parse HEAD~1:sub >expect &&
+ git rev-parse HEAD:sub2 >actual &&
+ test_cmp expect actual &&
+ git reset --hard HEAD~1
+'
+
+test_expect_success 'can move files to non-sparse dir' '
+ git reset --hard &&
+ git sparse-checkout init --no-cone &&
+ git sparse-checkout set a b c w !/x y/ &&
+ mkdir -p w x/y &&
+
+ git mv a w/new-a 2>stderr &&
+ git mv b x/y/new-b 2>stderr &&
+ test_must_be_empty stderr
+'
+
+test_expect_success 'refuse to move file to non-skip-worktree sparse path' '
+ git reset --hard &&
+ git sparse-checkout init --no-cone &&
+ git sparse-checkout set a !/x y/ !x/y/z &&
+ mkdir -p x/y/z &&
+
+ test_must_fail git mv a x/y/z/new-a 2>stderr &&
+ echo x/y/z/new-a | cat sparse_error_header - sparse_hint >expect &&
+ test_cmp expect stderr
+'
+
+test_done
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 0e7cf75435..a87ef37803 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -661,6 +661,13 @@ test_expect_success 'setup trace2' '
export GIT_TRACE2_BRIEF
'
+test_expect_success 'setup large log output' '
+ perl -e "
+ print \"this is a long commit message\" x 50000
+ " >commit-msg &&
+ git commit --allow-empty -F commit-msg
+'
+
test_expect_success TTY 'git returns SIGPIPE on early pager exit' '
test_when_finished "rm pager-used trace.normal" &&
test_config core.pager ">pager-used; head -n 1; exit 0" &&
@@ -670,7 +677,7 @@ test_expect_success TTY 'git returns SIGPIPE on early pager exit' '
if test_have_prereq !MINGW
then
- OUT=$( ((test_terminal git log; echo $? 1>&3) | :) 3>&1 ) &&
+ { test_terminal git log >/dev/null; OUT=$?; } &&
test_match_signal 13 "$OUT"
else
test_terminal git log
@@ -691,7 +698,7 @@ test_expect_success TTY 'git returns SIGPIPE on early pager non-zero exit' '
if test_have_prereq !MINGW
then
- OUT=$( ((test_terminal git log; echo $? 1>&3) | :) 3>&1 ) &&
+ { test_terminal git log >/dev/null; OUT=$?; } &&
test_match_signal 13 "$OUT"
else
test_terminal git log
@@ -710,13 +717,7 @@ test_expect_success TTY 'git discards pager non-zero exit without SIGPIPE' '
export GIT_TRACE2 &&
test_when_finished "unset GIT_TRACE2" &&
- if test_have_prereq !MINGW
- then
- OUT=$( ((test_terminal git log; echo $? 1>&3) | :) 3>&1 ) &&
- test "$OUT" -eq 0
- else
- test_terminal git log
- fi &&
+ test_terminal git log &&
grep child_exit trace.normal >child-exits &&
test_line_count = 1 child-exits &&
@@ -724,41 +725,14 @@ test_expect_success TTY 'git discards pager non-zero exit without SIGPIPE' '
test_path_is_file pager-used
'
-test_expect_success TTY 'git discards nonexisting pager without SIGPIPE' '
- test_when_finished "rm pager-used trace.normal" &&
- test_config core.pager "wc >pager-used; does-not-exist" &&
- GIT_TRACE2="$(pwd)/trace.normal" &&
- export GIT_TRACE2 &&
- test_when_finished "unset GIT_TRACE2" &&
-
- if test_have_prereq !MINGW
- then
- OUT=$( ((test_terminal git log; echo $? 1>&3) | :) 3>&1 ) &&
- test "$OUT" -eq 0
- else
- test_terminal git log
- fi &&
-
- grep child_exit trace.normal >child-exits &&
- test_line_count = 1 child-exits &&
- grep " code:127 " child-exits &&
- test_path_is_file pager-used
-'
-
-test_expect_success TTY 'git attempts to page to nonexisting pager command, gets SIGPIPE' '
+test_expect_success TTY 'git skips paging nonexisting command' '
test_when_finished "rm trace.normal" &&
test_config core.pager "does-not-exist" &&
GIT_TRACE2="$(pwd)/trace.normal" &&
export GIT_TRACE2 &&
test_when_finished "unset GIT_TRACE2" &&
- if test_have_prereq !MINGW
- then
- OUT=$( ((test_terminal git log; echo $? 1>&3) | :) 3>&1 ) &&
- test_match_signal 13 "$OUT"
- else
- test_terminal git log
- fi &&
+ test_terminal git log &&
grep child_exit trace.normal >child-exits &&
test_line_count = 1 child-exits &&
@@ -767,14 +741,14 @@ test_expect_success TTY 'git attempts to page to nonexisting pager command, gets
test_expect_success TTY 'git returns SIGPIPE on propagated signals from pager' '
test_when_finished "rm pager-used trace.normal" &&
- test_config core.pager ">pager-used; test-tool sigchain" &&
+ test_config core.pager ">pager-used; exec test-tool sigchain" &&
GIT_TRACE2="$(pwd)/trace.normal" &&
export GIT_TRACE2 &&
test_when_finished "unset GIT_TRACE2" &&
if test_have_prereq !MINGW
then
- OUT=$( ((test_terminal git log; echo $? 1>&3) | :) 3>&1 ) &&
+ { test_terminal git log >/dev/null; OUT=$?; } &&
test_match_signal 13 "$OUT"
else
test_terminal git log
diff --git a/t/t7031-verify-tag-signed-ssh.sh b/t/t7031-verify-tag-signed-ssh.sh
new file mode 100755
index 0000000000..06c9dd6c93
--- /dev/null
+++ b/t/t7031-verify-tag-signed-ssh.sh
@@ -0,0 +1,161 @@
+#!/bin/sh
+
+test_description='signed tag tests'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-gpg.sh"
+
+test_expect_success GPGSSH 'create signed tags ssh' '
+ test_when_finished "test_unconfig commit.gpgsign" &&
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+
+ echo 1 >file && git add file &&
+ test_tick && git commit -m initial &&
+ git tag -s -m initial initial &&
+ git branch side &&
+
+ echo 2 >file && test_tick && git commit -a -m second &&
+ git tag -s -m second second &&
+
+ git checkout side &&
+ echo 3 >elif && git add elif &&
+ test_tick && git commit -m "third on side" &&
+
+ git checkout main &&
+ test_tick && git merge -S side &&
+ git tag -s -m merge merge &&
+
+ echo 4 >file && test_tick && git commit -a -S -m "fourth unsigned" &&
+ git tag -a -m fourth-unsigned fourth-unsigned &&
+
+ test_tick && git commit --amend -S -m "fourth signed" &&
+ git tag -s -m fourth fourth-signed &&
+
+ echo 5 >file && test_tick && git commit -a -m "fifth" &&
+ git tag fifth-unsigned &&
+
+ git config commit.gpgsign true &&
+ echo 6 >file && test_tick && git commit -a -m "sixth" &&
+ git tag -a -m sixth sixth-unsigned &&
+
+ test_tick && git rebase -f HEAD^^ && git tag -s -m 6th sixth-signed HEAD^ &&
+ git tag -m seventh -s seventh-signed &&
+
+ echo 8 >file && test_tick && git commit -a -m eighth &&
+ git tag -u"${GPGSSH_KEY_UNTRUSTED}" -m eighth eighth-signed-alt
+'
+
+test_expect_success GPGSSH 'verify and show ssh signatures' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ (
+ for tag in initial second merge fourth-signed sixth-signed seventh-signed
+ do
+ git verify-tag $tag 2>actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo $tag OK || exit 1
+ done
+ ) &&
+ (
+ for tag in fourth-unsigned fifth-unsigned sixth-unsigned
+ do
+ test_must_fail git verify-tag $tag 2>actual &&
+ ! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo $tag OK || exit 1
+ done
+ ) &&
+ (
+ for tag in eighth-signed-alt
+ do
+ test_must_fail git verify-tag $tag 2>actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_UNTRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ grep "${GPGSSH_KEY_NOT_TRUSTED}" actual &&
+ echo $tag OK || exit 1
+ done
+ )
+'
+
+test_expect_success GPGSSH 'detect fudged ssh signature' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git cat-file tag seventh-signed >raw &&
+ sed -e "/^tag / s/seventh/7th forged/" raw >forged1 &&
+ git hash-object -w -t tag forged1 >forged1.tag &&
+ test_must_fail git verify-tag $(cat forged1.tag) 2>actual1 &&
+ grep "${GPGSSH_BAD_SIGNATURE}" actual1 &&
+ ! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual1 &&
+ ! grep "${GPGSSH_GOOD_SIGNATURE_UNTRUSTED}" actual1
+'
+
+test_expect_success GPGSSH 'verify ssh signatures with --raw' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ (
+ for tag in initial second merge fourth-signed sixth-signed seventh-signed
+ do
+ git verify-tag --raw $tag 2>actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo $tag OK || exit 1
+ done
+ ) &&
+ (
+ for tag in fourth-unsigned fifth-unsigned sixth-unsigned
+ do
+ test_must_fail git verify-tag --raw $tag 2>actual &&
+ ! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo $tag OK || exit 1
+ done
+ ) &&
+ (
+ for tag in eighth-signed-alt
+ do
+ test_must_fail git verify-tag --raw $tag 2>actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_UNTRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo $tag OK || exit 1
+ done
+ )
+'
+
+test_expect_success GPGSSH 'verify signatures with --raw ssh' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git verify-tag --raw sixth-signed 2>actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo sixth-signed OK
+'
+
+test_expect_success GPGSSH 'verify multiple tags ssh' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ tags="seventh-signed sixth-signed" &&
+ for i in $tags
+ do
+ git verify-tag -v --raw $i || return 1
+ done >expect.stdout 2>expect.stderr.1 &&
+ grep "^${GPGSSH_GOOD_SIGNATURE_TRUSTED}" <expect.stderr.1 >expect.stderr &&
+ git verify-tag -v --raw $tags >actual.stdout 2>actual.stderr.1 &&
+ grep "^${GPGSSH_GOOD_SIGNATURE_TRUSTED}" <actual.stderr.1 >actual.stderr &&
+ test_cmp expect.stdout actual.stdout &&
+ test_cmp expect.stderr actual.stderr
+'
+
+test_expect_success GPGSSH 'verifying tag with --format - ssh' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ cat >expect <<-\EOF &&
+ tagname : fourth-signed
+ EOF
+ git verify-tag --format="tagname : %(tag)" "fourth-signed" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPGSSH 'verifying a forged tag with --format should fail silently - ssh' '
+ test_must_fail git verify-tag --format="tagname : %(tag)" $(cat forged1.tag) >actual-forged &&
+ test_must_be_empty actual-forged
+'
+
+test_done
diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh
index eeb0534163..47fc21d962 100755
--- a/t/t7064-wtstatus-pv2.sh
+++ b/t/t7064-wtstatus-pv2.sh
@@ -113,6 +113,21 @@ test_expect_success 'after first commit, create unstaged changes' '
test_cmp expect actual
'
+test_expect_success 'after first commit, stash existing changes' '
+ cat >expect <<-EOF &&
+ # branch.oid $H0
+ # branch.head initial-branch
+ # stash 2
+ EOF
+
+ test_when_finished "git stash pop && git stash pop" &&
+
+ git stash -- file_x &&
+ git stash &&
+ git status --porcelain=v2 --branch --show-stash --untracked-files=no >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'after first commit but omit untracked files and branch' '
cat >expect <<-EOF &&
1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
diff --git a/t/t7101-reset-empty-subdirs.sh b/t/t7101-reset-empty-subdirs.sh
index bfce05ac5d..5530651eea 100755
--- a/t/t7101-reset-empty-subdirs.sh
+++ b/t/t7101-reset-empty-subdirs.sh
@@ -5,10 +5,11 @@
test_description='git reset should cull empty subdirs'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-diff-data.sh
test_expect_success 'creating initial files' '
mkdir path0 &&
- cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
+ COPYING_test_data >path0/COPYING &&
git add path0/COPYING &&
git commit -m add -a
'
@@ -16,10 +17,10 @@ test_expect_success 'creating initial files' '
test_expect_success 'creating second files' '
mkdir path1 &&
mkdir path1/path2 &&
- cp "$TEST_DIRECTORY"/../COPYING path1/path2/COPYING &&
- cp "$TEST_DIRECTORY"/../COPYING path1/COPYING &&
- cp "$TEST_DIRECTORY"/../COPYING COPYING &&
- cp "$TEST_DIRECTORY"/../COPYING path0/COPYING-TOO &&
+ COPYING_test_data >path1/path2/COPYING &&
+ COPYING_test_data >path1/COPYING &&
+ COPYING_test_data >COPYING &&
+ COPYING_test_data >path0/COPYING-TOO &&
git add path1/path2/COPYING &&
git add path1/COPYING &&
git add COPYING &&
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index 601b2bf97f..d05426062e 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -472,6 +472,23 @@ test_expect_success '--mixed refreshes the index' '
test_cmp expect output
'
+test_expect_success '--mixed preserves skip-worktree' '
+ echo 123 >>file2 &&
+ git add file2 &&
+ git update-index --skip-worktree file2 &&
+ git reset --mixed HEAD >output &&
+ test_must_be_empty output &&
+
+ cat >expect <<-\EOF &&
+ Unstaged changes after reset:
+ M file2
+ EOF
+ git update-index --no-skip-worktree file2 &&
+ git add file2 &&
+ git reset --mixed HEAD >output &&
+ test_cmp expect output
+'
+
test_expect_success 'resetting specific path that is unmerged' '
git rm --cached file2 &&
F1=$(git rev-parse HEAD:file1) &&
diff --git a/t/t7104-reset-hard.sh b/t/t7104-reset-hard.sh
index 7948ec392b..cf9697eba9 100755
--- a/t/t7104-reset-hard.sh
+++ b/t/t7104-reset-hard.sh
@@ -2,6 +2,7 @@
test_description='reset --hard unmerged'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t7112-reset-submodule.sh b/t/t7112-reset-submodule.sh
index 19830d9036..a3e2413bc3 100755
--- a/t/t7112-reset-submodule.sh
+++ b/t/t7112-reset-submodule.sh
@@ -6,7 +6,6 @@ test_description='reset can handle submodules'
. "$TEST_DIRECTORY"/lib-submodule-update.sh
KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
-KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1
test_submodule_switch_recursing_with_args "reset --keep"
diff --git a/t/t7113-post-index-change-hook.sh b/t/t7113-post-index-change-hook.sh
index 688fa995c9..a21781d68a 100755
--- a/t/t7113-post-index-change-hook.sh
+++ b/t/t7113-post-index-change-hook.sh
@@ -5,6 +5,7 @@ test_description='post index change hook'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7418-submodule-sparse-gitmodules.sh b/t/t7418-submodule-sparse-gitmodules.sh
index 3f7f271883..f87e524d6d 100755
--- a/t/t7418-submodule-sparse-gitmodules.sh
+++ b/t/t7418-submodule-sparse-gitmodules.sh
@@ -12,6 +12,9 @@ The test setup uses a sparse checkout, however the same scenario can be set up
also by committing .gitmodules and then just removing it from the filesystem.
'
+GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
+export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+
. ./test-lib.sh
test_expect_success 'sparse checkout setup which hides .gitmodules' '
diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh
index 4e7592522a..bba58f0480 100755
--- a/t/t7504-commit-msg-hook.sh
+++ b/t/t7504-commit-msg-hook.sh
@@ -133,6 +133,14 @@ test_expect_success '--no-verify with failing hook' '
'
+test_expect_success '-n followed by --verify with failing hook' '
+
+ echo "even more" >> file &&
+ git add file &&
+ test_must_fail git commit -n --verify -m "even more"
+
+'
+
test_expect_success '--no-verify with failing hook (editor)' '
echo "more stuff" >> file &&
diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh
index 7a8194ce72..2a07c70867 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -250,7 +250,6 @@ test_rebase () {
}
test_rebase success
-test_have_prereq !REBASE_P || test_rebase success -p
test_expect_success 'with hook (cherry-pick)' '
test_when_finished "git checkout -f main" &&
diff --git a/t/t7509-commit-authorship.sh b/t/t7509-commit-authorship.sh
index d568593382..21c668f75e 100755
--- a/t/t7509-commit-authorship.sh
+++ b/t/t7509-commit-authorship.sh
@@ -5,6 +5,7 @@
test_description='commit tests of various authorhip options. '
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
author_header () {
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 8df5a74f1d..d65a0171f2 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -71,7 +71,25 @@ test_expect_success GPG 'create signed commits' '
git tag eleventh-signed $(cat oid) &&
echo 12 | git commit-tree --gpg-sign=B7227189 HEAD^{tree} >oid &&
test_line_count = 1 oid &&
- git tag twelfth-signed-alt $(cat oid)
+ git tag twelfth-signed-alt $(cat oid) &&
+
+ cat >keydetails <<-\EOF &&
+ Key-Type: RSA
+ Key-Length: 2048
+ Subkey-Type: RSA
+ Subkey-Length: 2048
+ Name-Real: Unknown User
+ Name-Email: unknown@git.com
+ Expire-Date: 0
+ %no-ask-passphrase
+ %no-protection
+ EOF
+ gpg --batch --gen-key keydetails &&
+ echo 13 >file && git commit -a -S"unknown@git.com" -m thirteenth &&
+ git tag thirteenth-signed &&
+ DELETE_FINGERPRINT=$(gpg -K --with-colons --fingerprint --batch unknown@git.com | grep "^fpr" | head -n 1 | awk -F ":" "{print \$10;}") &&
+ gpg --batch --yes --delete-secret-keys $DELETE_FINGERPRINT &&
+ gpg --batch --yes --delete-keys unknown@git.com
'
test_expect_success GPG 'verify and show signatures' '
@@ -110,6 +128,13 @@ test_expect_success GPG 'verify and show signatures' '
)
'
+test_expect_success GPG 'verify-commit exits failure on unknown signature' '
+ test_must_fail git verify-commit thirteenth-signed 2>actual &&
+ ! grep "Good signature from" actual &&
+ ! grep "BAD signature from" actual &&
+ grep -q -F -e "No public key" -e "public key not found" actual
+'
+
test_expect_success GPG 'verify-commit exits success on untrusted signature' '
git verify-commit eighth-signed-alt 2>actual &&
grep "Good signature from" actual &&
@@ -338,6 +363,8 @@ test_expect_success GPG 'show double signature with custom format' '
'
+# NEEDSWORK: This test relies on the test_tick commit/author dates from the first
+# 'create signed commits' test even though it creates its own
test_expect_success GPG 'verify-commit verifies multiply signed commits' '
git init multiply-signed &&
cd multiply-signed &&
diff --git a/t/t7517-per-repo-email.sh b/t/t7517-per-repo-email.sh
index 405420ae4d..163ae80468 100755
--- a/t/t7517-per-repo-email.sh
+++ b/t/t7517-per-repo-email.sh
@@ -75,19 +75,6 @@ test_expect_success 'noop interactive rebase does not care about ident' '
git rebase -i HEAD^
'
-test_expect_success REBASE_P \
- 'fast-forward rebase does not care about ident (preserve)' '
- git checkout -B tmp side-without-commit &&
- git rebase -p main
-'
-
-test_expect_success REBASE_P \
- 'non-fast-forward rebase refuses to write commits (preserve)' '
- test_when_finished "git rebase --abort || true" &&
- git checkout -B tmp side-with-commit &&
- test_must_fail git rebase -p main
-'
-
test_expect_success 'author.name overrides user.name' '
test_config user.name user &&
test_config user.email user@example.com &&
diff --git a/t/t7518-ident-corner-cases.sh b/t/t7518-ident-corner-cases.sh
index 905957bd0a..fffdb6ff2e 100755
--- a/t/t7518-ident-corner-cases.sh
+++ b/t/t7518-ident-corner-cases.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='corner cases in ident strings'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# confirm that we do not segfault _and_ that we do not say "(null)", as
diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
index f1463197b9..f488d930df 100755
--- a/t/t7519-status-fsmonitor.sh
+++ b/t/t7519-status-fsmonitor.sh
@@ -399,41 +399,45 @@ check_sparse_index_behavior () {
}
test_expect_success 'status succeeds with sparse index' '
- git clone . full &&
- git clone --sparse . sparse &&
- git -C sparse sparse-checkout init --cone --sparse-index &&
- git -C sparse sparse-checkout set dir1 dir2 &&
+ (
+ sane_unset GIT_TEST_SPLIT_INDEX &&
- write_script .git/hooks/fsmonitor-test <<-\EOF &&
- printf "last_update_token\0"
- EOF
- git -C full config core.fsmonitor ../.git/hooks/fsmonitor-test &&
- git -C sparse config core.fsmonitor ../.git/hooks/fsmonitor-test &&
- check_sparse_index_behavior ! &&
+ git clone . full &&
+ git clone --sparse . sparse &&
+ git -C sparse sparse-checkout init --cone --sparse-index &&
+ git -C sparse sparse-checkout set dir1 dir2 &&
- write_script .git/hooks/fsmonitor-test <<-\EOF &&
- printf "last_update_token\0"
- printf "dir1/modified\0"
- EOF
- check_sparse_index_behavior ! &&
-
- git -C sparse sparse-checkout add dir1a &&
+ write_script .git/hooks/fsmonitor-test <<-\EOF &&
+ printf "last_update_token\0"
+ EOF
+ git -C full config core.fsmonitor ../.git/hooks/fsmonitor-test &&
+ git -C sparse config core.fsmonitor ../.git/hooks/fsmonitor-test &&
+ check_sparse_index_behavior ! &&
- for repo in full sparse
- do
- cp -r $repo/dir1 $repo/dir1a &&
- git -C $repo add dir1a &&
- git -C $repo commit -m "add dir1a" || return 1
- done &&
- git -C sparse sparse-checkout set dir1 dir2 &&
-
- # This one modifies outside the sparse-checkout definition
- # and hence we expect to expand the sparse-index.
- write_script .git/hooks/fsmonitor-test <<-\EOF &&
- printf "last_update_token\0"
- printf "dir1a/modified\0"
- EOF
- check_sparse_index_behavior
+ write_script .git/hooks/fsmonitor-test <<-\EOF &&
+ printf "last_update_token\0"
+ printf "dir1/modified\0"
+ EOF
+ check_sparse_index_behavior ! &&
+
+ git -C sparse sparse-checkout add dir1a &&
+
+ for repo in full sparse
+ do
+ cp -r $repo/dir1 $repo/dir1a &&
+ git -C $repo add dir1a &&
+ git -C $repo commit -m "add dir1a" || return 1
+ done &&
+ git -C sparse sparse-checkout set dir1 dir2 &&
+
+ # This one modifies outside the sparse-checkout definition
+ # and hence we expect to expand the sparse-index.
+ write_script .git/hooks/fsmonitor-test <<-\EOF &&
+ printf "last_update_token\0"
+ printf "dir1a/modified\0"
+ EOF
+ check_sparse_index_behavior
+ )
'
test_done
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
new file mode 100755
index 0000000000..badf3ed320
--- /dev/null
+++ b/t/t7528-signed-commit-ssh.sh
@@ -0,0 +1,398 @@
+#!/bin/sh
+
+test_description='ssh signed commit tests'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+GNUPGHOME_NOT_USED=$GNUPGHOME
+. "$TEST_DIRECTORY/lib-gpg.sh"
+
+test_expect_success GPGSSH 'create signed commits' '
+ test_oid_cache <<-\EOF &&
+ header sha1:gpgsig
+ header sha256:gpgsig-sha256
+ EOF
+
+ test_when_finished "test_unconfig commit.gpgsign" &&
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+
+ echo 1 >file && git add file &&
+ test_tick && git commit -S -m initial &&
+ git tag initial &&
+ git branch side &&
+
+ echo 2 >file && test_tick && git commit -a -S -m second &&
+ git tag second &&
+
+ git checkout side &&
+ echo 3 >elif && git add elif &&
+ test_tick && git commit -m "third on side" &&
+
+ git checkout main &&
+ test_tick && git merge -S side &&
+ git tag merge &&
+
+ echo 4 >file && test_tick && git commit -a -m "fourth unsigned" &&
+ git tag fourth-unsigned &&
+
+ test_tick && git commit --amend -S -m "fourth signed" &&
+ git tag fourth-signed &&
+
+ git config commit.gpgsign true &&
+ echo 5 >file && test_tick && git commit -a -m "fifth signed" &&
+ git tag fifth-signed &&
+
+ git config commit.gpgsign false &&
+ echo 6 >file && test_tick && git commit -a -m "sixth" &&
+ git tag sixth-unsigned &&
+
+ git config commit.gpgsign true &&
+ echo 7 >file && test_tick && git commit -a -m "seventh" --no-gpg-sign &&
+ git tag seventh-unsigned &&
+
+ test_tick && git rebase -f HEAD^^ && git tag sixth-signed HEAD^ &&
+ git tag seventh-signed &&
+
+ echo 8 >file && test_tick && git commit -a -m eighth -S"${GPGSSH_KEY_UNTRUSTED}" &&
+ git tag eighth-signed-alt &&
+
+ # commit.gpgsign is still on but this must not be signed
+ echo 9 | git commit-tree HEAD^{tree} >oid &&
+ test_line_count = 1 oid &&
+ git tag ninth-unsigned $(cat oid) &&
+ # explicit -S of course must sign.
+ echo 10 | git commit-tree -S HEAD^{tree} >oid &&
+ test_line_count = 1 oid &&
+ git tag tenth-signed $(cat oid) &&
+
+ # --gpg-sign[=<key-id>] must sign.
+ echo 11 | git commit-tree --gpg-sign HEAD^{tree} >oid &&
+ test_line_count = 1 oid &&
+ git tag eleventh-signed $(cat oid) &&
+ echo 12 | git commit-tree --gpg-sign="${GPGSSH_KEY_UNTRUSTED}" HEAD^{tree} >oid &&
+ test_line_count = 1 oid &&
+ git tag twelfth-signed-alt $(cat oid)
+'
+
+test_expect_success GPGSSH 'verify and show signatures' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ test_config gpg.mintrustlevel UNDEFINED &&
+ (
+ for commit in initial second merge fourth-signed \
+ fifth-signed sixth-signed seventh-signed tenth-signed \
+ eleventh-signed
+ do
+ git verify-commit $commit &&
+ git show --pretty=short --show-signature $commit >actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo $commit OK || exit 1
+ done
+ ) &&
+ (
+ for commit in merge^2 fourth-unsigned sixth-unsigned \
+ seventh-unsigned ninth-unsigned
+ do
+ test_must_fail git verify-commit $commit &&
+ git show --pretty=short --show-signature $commit >actual &&
+ ! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo $commit OK || exit 1
+ done
+ ) &&
+ (
+ for commit in eighth-signed-alt twelfth-signed-alt
+ do
+ git show --pretty=short --show-signature $commit >actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_UNTRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ grep "${GPGSSH_KEY_NOT_TRUSTED}" actual &&
+ echo $commit OK || exit 1
+ done
+ )
+'
+
+test_expect_success GPGSSH 'verify-commit exits failure on untrusted signature' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ test_must_fail git verify-commit eighth-signed-alt 2>actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_UNTRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ grep "${GPGSSH_KEY_NOT_TRUSTED}" actual
+'
+
+test_expect_success GPGSSH 'verify-commit exits success with matching minTrustLevel' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ test_config gpg.minTrustLevel fully &&
+ git verify-commit sixth-signed
+'
+
+test_expect_success GPGSSH 'verify-commit exits success with low minTrustLevel' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ test_config gpg.minTrustLevel marginal &&
+ git verify-commit sixth-signed
+'
+
+test_expect_success GPGSSH 'verify-commit exits failure with high minTrustLevel' '
+ test_config gpg.minTrustLevel ultimate &&
+ test_must_fail git verify-commit eighth-signed-alt
+'
+
+test_expect_success GPGSSH 'verify signatures with --raw' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ (
+ for commit in initial second merge fourth-signed fifth-signed sixth-signed seventh-signed
+ do
+ git verify-commit --raw $commit 2>actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo $commit OK || exit 1
+ done
+ ) &&
+ (
+ for commit in merge^2 fourth-unsigned sixth-unsigned seventh-unsigned
+ do
+ test_must_fail git verify-commit --raw $commit 2>actual &&
+ ! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo $commit OK || exit 1
+ done
+ ) &&
+ (
+ for commit in eighth-signed-alt
+ do
+ test_must_fail git verify-commit --raw $commit 2>actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_UNTRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual &&
+ echo $commit OK || exit 1
+ done
+ )
+'
+
+test_expect_success GPGSSH 'proper header is used for hash algorithm' '
+ git cat-file commit fourth-signed >output &&
+ grep "^$(test_oid header) -----BEGIN SSH SIGNATURE-----" output
+'
+
+test_expect_success GPGSSH 'show signed commit with signature' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git show -s initial >commit &&
+ git show -s --show-signature initial >show &&
+ git verify-commit -v initial >verify.1 2>verify.2 &&
+ git cat-file commit initial >cat &&
+ grep -v -e "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" -e "Warning: " show >show.commit &&
+ grep -e "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" -e "Warning: " show >show.gpg &&
+ grep -v "^ " cat | grep -v "^gpgsig.* " >cat.commit &&
+ test_cmp show.commit commit &&
+ test_cmp show.gpg verify.2 &&
+ test_cmp cat.commit verify.1
+'
+
+test_expect_success GPGSSH 'detect fudged signature' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git cat-file commit seventh-signed >raw &&
+ sed -e "s/^seventh/7th forged/" raw >forged1 &&
+ git hash-object -w -t commit forged1 >forged1.commit &&
+ test_must_fail git verify-commit $(cat forged1.commit) &&
+ git show --pretty=short --show-signature $(cat forged1.commit) >actual1 &&
+ grep "${GPGSSH_BAD_SIGNATURE}" actual1 &&
+ ! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual1 &&
+ ! grep "${GPGSSH_GOOD_SIGNATURE_UNTRUSTED}" actual1
+'
+
+test_expect_success GPGSSH 'detect fudged signature with NUL' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git cat-file commit seventh-signed >raw &&
+ cat raw >forged2 &&
+ echo Qwik | tr "Q" "\000" >>forged2 &&
+ git hash-object -w -t commit forged2 >forged2.commit &&
+ test_must_fail git verify-commit $(cat forged2.commit) &&
+ git show --pretty=short --show-signature $(cat forged2.commit) >actual2 &&
+ grep "${GPGSSH_BAD_SIGNATURE}" actual2 &&
+ ! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual2
+'
+
+test_expect_success GPGSSH 'amending already signed commit' '
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ git checkout fourth-signed^0 &&
+ git commit --amend -S --no-edit &&
+ git verify-commit HEAD &&
+ git show -s --show-signature HEAD >actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
+ ! grep "${GPGSSH_BAD_SIGNATURE}" actual
+'
+
+test_expect_success GPGSSH 'show good signature with custom format' '
+ 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 log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPGSSH 'show bad signature with custom format' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ cat >expect <<-\EOF &&
+ B
+
+
+
+
+ EOF
+ git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPGSSH 'show untrusted signature with custom format' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ cat >expect.tmpl <<-\EOF &&
+ U
+ FINGERPRINT
+
+ FINGERPRINT
+
+ EOF
+ git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_UNTRUSTED}" | awk "{print \$2;}") &&
+ sed "s|FINGERPRINT|$FINGERPRINT|g" expect.tmpl >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success GPGSSH 'show untrusted signature with undefined trust level' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ cat >expect.tmpl <<-\EOF &&
+ undefined
+ FINGERPRINT
+
+ FINGERPRINT
+
+ EOF
+ git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_UNTRUSTED}" | awk "{print \$2;}") &&
+ sed "s|FINGERPRINT|$FINGERPRINT|g" expect.tmpl >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success GPGSSH 'show untrusted signature with ultimate trust level' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ cat >expect.tmpl <<-\EOF &&
+ fully
+ FINGERPRINT
+ principal with number 1
+ FINGERPRINT
+
+ EOF
+ git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
+ FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") &&
+ sed "s|FINGERPRINT|$FINGERPRINT|g" expect.tmpl >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success GPGSSH 'show lack of signature with custom format' '
+ cat >expect <<-\EOF &&
+ N
+
+
+
+
+ EOF
+ git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPGSSH 'log.showsignature behaves like --show-signature' '
+ test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
+ test_config log.showsignature true &&
+ git show initial >actual &&
+ grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual
+'
+
+test_expect_success GPGSSH 'check config gpg.format values' '
+ test_config gpg.format ssh &&
+ test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+ test_config gpg.format ssh &&
+ git commit -S --amend -m "success" &&
+ test_config gpg.format OpEnPgP &&
+ test_must_fail git commit -S --amend -m "fail"
+'
+
+test_expect_failure GPGSSH 'detect fudged commit with double signature (TODO)' '
+ sed -e "/gpgsig/,/END PGP/d" forged1 >double-base &&
+ sed -n -e "/gpgsig/,/END PGP/p" forged1 | \
+ sed -e "s/^$(test_oid header)//;s/^ //" | gpg --dearmor >double-sig1.sig &&
+ gpg -o double-sig2.sig -u 29472784 --detach-sign double-base &&
+ cat double-sig1.sig double-sig2.sig | gpg --enarmor >double-combined.asc &&
+ sed -e "s/^\(-.*\)ARMORED FILE/\1SIGNATURE/;1s/^/$(test_oid header) /;2,\$s/^/ /" \
+ double-combined.asc > double-gpgsig &&
+ sed -e "/committer/r double-gpgsig" double-base >double-commit &&
+ git hash-object -w -t commit double-commit >double-commit.commit &&
+ test_must_fail git verify-commit $(cat double-commit.commit) &&
+ git show --pretty=short --show-signature $(cat double-commit.commit) >double-actual &&
+ grep "BAD signature from" double-actual &&
+ grep "Good signature from" double-actual
+'
+
+test_expect_failure GPGSSH 'show double signature with custom format (TODO)' '
+ cat >expect <<-\EOF &&
+ E
+
+
+
+
+ EOF
+ git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat double-commit.commit) >actual &&
+ test_cmp expect actual
+'
+
+
+test_expect_failure GPGSSH 'verify-commit verifies multiply signed commits (TODO)' '
+ git init multiply-signed &&
+ cd multiply-signed &&
+ test_commit first &&
+ echo 1 >second &&
+ git add second &&
+ tree=$(git write-tree) &&
+ parent=$(git rev-parse HEAD^{commit}) &&
+ git commit --gpg-sign -m second &&
+ git cat-file commit HEAD &&
+ # Avoid trailing whitespace.
+ sed -e "s/^Q//" -e "s/^Z/ /" >commit <<-EOF &&
+ Qtree $tree
+ Qparent $parent
+ Qauthor A U Thor <author@example.com> 1112912653 -0700
+ Qcommitter C O Mitter <committer@example.com> 1112912653 -0700
+ Qgpgsig -----BEGIN PGP SIGNATURE-----
+ QZ
+ Q iHQEABECADQWIQRz11h0S+chaY7FTocTtvUezd5DDQUCX/uBDRYcY29tbWl0dGVy
+ Q QGV4YW1wbGUuY29tAAoJEBO29R7N3kMNd+8AoK1I8mhLHviPH+q2I5fIVgPsEtYC
+ Q AKCTqBh+VabJceXcGIZuF0Ry+udbBQ==
+ Q =tQ0N
+ Q -----END PGP SIGNATURE-----
+ Qgpgsig-sha256 -----BEGIN PGP SIGNATURE-----
+ QZ
+ Q iHQEABECADQWIQRz11h0S+chaY7FTocTtvUezd5DDQUCX/uBIBYcY29tbWl0dGVy
+ Q QGV4YW1wbGUuY29tAAoJEBO29R7N3kMN/NEAn0XO9RYSBj2dFyozi0JKSbssYMtO
+ Q AJwKCQ1BQOtuwz//IjU8TiS+6S4iUw==
+ Q =pIwP
+ Q -----END PGP SIGNATURE-----
+ Q
+ Qsecond
+ EOF
+ head=$(git hash-object -t commit -w commit) &&
+ git reset --hard $head &&
+ git verify-commit $head 2>actual &&
+ grep "Good signature from" actual &&
+ ! grep "BAD signature from" actual
+'
+
+test_done
diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh
index 1f652f433e..bd238d89b0 100755
--- a/t/t7601-merge-pull-config.sh
+++ b/t/t7601-merge-pull-config.sh
@@ -2,7 +2,7 @@
test_description='git merge
-Testing pull.* configuration parsing.'
+Testing pull.* configuration parsing and other things.'
. ./test-lib.sh
@@ -387,6 +387,26 @@ test_expect_success 'pull prevents non-fast-forward with "only" in pull.ff' '
test_must_fail git pull . c3
'
+test_expect_success 'already-up-to-date pull succeeds with unspecified pull.ff' '
+ git reset --hard c1 &&
+ git pull . c0 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
+'
+
+test_expect_success 'already-up-to-date pull succeeds with "only" in pull.ff' '
+ git reset --hard c1 &&
+ test_config pull.ff only &&
+ git pull . c0 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
+'
+
+test_expect_success 'already-up-to-date pull/rebase succeeds with "only" in pull.ff' '
+ git reset --hard c1 &&
+ test_config pull.ff only &&
+ git -c pull.rebase=true pull . c0 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
+'
+
test_expect_success 'merge c1 with c2 (ours in pull.twohead)' '
git reset --hard c1 &&
git config pull.twohead ours &&
diff --git a/t/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh
index cd4f9607dc..eca7555101 100755
--- a/t/t7604-merge-custom-message.sh
+++ b/t/t7604-merge-custom-message.sh
@@ -4,6 +4,7 @@ test_description='git merge
Testing merge when using a custom message for the merge commit.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
create_merge_msgs() {
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index 98eda3bfeb..0260ad6f0e 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -3,6 +3,8 @@
test_description='git repack works correctly'
. ./test-lib.sh
+. "${TEST_DIRECTORY}/lib-bitmap.sh"
+. "${TEST_DIRECTORY}/lib-midx.sh"
commit_and_pack () {
test_commit "$@" 1>&2 &&
@@ -234,4 +236,140 @@ test_expect_success 'auto-bitmaps do not complain if unavailable' '
test_must_be_empty actual
'
+objdir=.git/objects
+midx=$objdir/pack/multi-pack-index
+
+test_expect_success 'setup for --write-midx tests' '
+ git init midx &&
+ (
+ cd midx &&
+ git config core.multiPackIndex true &&
+
+ test_commit base
+ )
+'
+
+test_expect_success '--write-midx unchanged' '
+ (
+ cd midx &&
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack &&
+ test_path_is_missing $midx &&
+ test_path_is_missing $midx-*.bitmap &&
+
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack --write-midx &&
+
+ test_path_is_file $midx &&
+ test_path_is_missing $midx-*.bitmap &&
+ test_midx_consistent $objdir
+ )
+'
+
+test_expect_success '--write-midx with a new pack' '
+ (
+ cd midx &&
+ test_commit loose &&
+
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack --write-midx &&
+
+ test_path_is_file $midx &&
+ test_path_is_missing $midx-*.bitmap &&
+ test_midx_consistent $objdir
+ )
+'
+
+test_expect_success '--write-midx with -b' '
+ (
+ cd midx &&
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack -mb &&
+
+ test_path_is_file $midx &&
+ test_path_is_file $midx-*.bitmap &&
+ test_midx_consistent $objdir
+ )
+'
+
+test_expect_success '--write-midx with -d' '
+ (
+ cd midx &&
+ test_commit repack &&
+
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack -Ad --write-midx &&
+
+ test_path_is_file $midx &&
+ test_path_is_missing $midx-*.bitmap &&
+ test_midx_consistent $objdir
+ )
+'
+
+test_expect_success 'cleans up MIDX when appropriate' '
+ (
+ cd midx &&
+
+ test_commit repack-2 &&
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adb --write-midx &&
+
+ checksum=$(midx_checksum $objdir) &&
+ test_path_is_file $midx &&
+ test_path_is_file $midx-$checksum.bitmap &&
+ test_path_is_file $midx-$checksum.rev &&
+
+ test_commit repack-3 &&
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adb --write-midx &&
+
+ test_path_is_file $midx &&
+ test_path_is_missing $midx-$checksum.bitmap &&
+ test_path_is_missing $midx-$checksum.rev &&
+ test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
+ test_path_is_file $midx-$(midx_checksum $objdir).rev &&
+
+ test_commit repack-4 &&
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adb &&
+
+ find $objdir/pack -type f -name "multi-pack-index*" >files &&
+ test_must_be_empty files
+ )
+'
+
+test_expect_success '--write-midx with preferred bitmap tips' '
+ git init midx-preferred-tips &&
+ test_when_finished "rm -fr midx-preferred-tips" &&
+ (
+ cd midx-preferred-tips &&
+
+ test_commit_bulk --message="%s" 103 &&
+
+ git log --format="%H" >commits.raw &&
+ sort <commits.raw >commits &&
+
+ git log --format="create refs/tags/%s/%s %H" HEAD >refs &&
+ git update-ref --stdin <refs &&
+
+ git repack --write-midx --write-bitmap-index &&
+ test_path_is_file $midx &&
+ test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
+
+ test-tool bitmap list-commits | sort >bitmaps &&
+ comm -13 bitmaps commits >before &&
+ test_line_count = 1 before &&
+
+ rm -fr $midx-$(midx_checksum $objdir).bitmap &&
+ rm -fr $midx-$(midx_checksum $objdir).rev &&
+ rm -fr $midx &&
+
+ # instead of constructing the snapshot ourselves (c.f., the test
+ # "write a bitmap with --refs-snapshot (preferred tips)" in
+ # t5326), mark the missing commit as preferred by adding it to
+ # the pack.preferBitmapTips configuration.
+ git for-each-ref --format="%(refname:rstrip=1)" \
+ --points-at="$(cat before)" >missing &&
+ git config pack.preferBitmapTips "$(cat missing)" &&
+ git repack --write-midx --write-bitmap-index &&
+
+ test-tool bitmap list-commits | sort >bitmaps &&
+ comm -13 bitmaps commits >after &&
+
+ ! test_cmp before after
+ )
+'
+
test_done
diff --git a/t/t7703-repack-geometric.sh b/t/t7703-repack-geometric.sh
index 5ccaa440e0..bdbbcbf1ec 100755
--- a/t/t7703-repack-geometric.sh
+++ b/t/t7703-repack-geometric.sh
@@ -15,7 +15,7 @@ test_expect_success '--geometric with no packs' '
(
cd geometric &&
- git repack --geometric 2 >out &&
+ git repack --write-midx --geometric 2 >out &&
test_i18ngrep "Nothing new to pack" out
)
'
@@ -180,4 +180,26 @@ test_expect_success '--geometric ignores kept packs' '
)
'
+test_expect_success '--geometric chooses largest MIDX preferred pack' '
+ git init geometric &&
+ test_when_finished "rm -fr geometric" &&
+ (
+ cd geometric &&
+
+ # These packs already form a geometric progression.
+ test_commit_bulk --start=1 1 && # 3 objects
+ test_commit_bulk --start=2 2 && # 6 objects
+ ls $objdir/pack/pack-*.idx >before &&
+ test_commit_bulk --start=4 4 && # 12 objects
+ ls $objdir/pack/pack-*.idx >after &&
+
+ git repack --geometric 2 -dbm &&
+
+ comm -3 before after | xargs -n 1 basename >expect &&
+ test-tool read-midx --preferred-pack $objdir >actual &&
+
+ test_cmp expect actual
+ )
+'
+
test_done
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 528e0dabf0..096456292c 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -453,6 +453,13 @@ run_dir_diff_test 'difftool --dir-diff' '
grep "^file$" output
'
+run_dir_diff_test 'difftool --dir-diff avoids repeated slashes in TMPDIR' '
+ TMPDIR="${TMPDIR:-/tmp}////" \
+ git difftool --dir-diff $symlinks --extcmd echo branch >output &&
+ grep -v // output >actual &&
+ test_line_count = 1 actual
+'
+
run_dir_diff_test 'difftool --dir-diff ignores --prompt' '
git difftool --dir-diff $symlinks --prompt --extcmd ls branch >output &&
grep "^sub$" output &&
diff --git a/t/t7811-grep-open.sh b/t/t7811-grep-open.sh
index a98785da79..1dd07141a7 100755
--- a/t/t7811-grep-open.sh
+++ b/t/t7811-grep-open.sh
@@ -3,6 +3,7 @@
test_description='git grep --open-files-in-pager
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-pager.sh
unset PAGER GIT_PAGER
@@ -114,8 +115,8 @@ test_expect_success 'modified file' '
unrelated
EOF
+ test_when_finished "git reset --hard" &&
echo "enum grep_pat_token" >unrelated &&
- test_when_finished "git checkout HEAD unrelated" &&
GIT_PAGER=./less git grep -F -O "enum grep_pat_token" >out &&
test_cmp expect actual &&
test_must_be_empty out
diff --git a/t/t7813-grep-icase-iso.sh b/t/t7813-grep-icase-iso.sh
index 701e08a8e5..1227885737 100755
--- a/t/t7813-grep-icase-iso.sh
+++ b/t/t7813-grep-icase-iso.sh
@@ -2,6 +2,7 @@
test_description='grep icase on non-English locales'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-gettext.sh
test_expect_success GETTEXT_ISO_LOCALE 'setup' '
diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh
index 3172f5b936..058e5d0c96 100755
--- a/t/t7814-grep-recurse-submodules.sh
+++ b/t/t7814-grep-recurse-submodules.sh
@@ -441,4 +441,107 @@ test_expect_success 'grep --recurse-submodules with --cached ignores worktree mo
test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 &&
test_must_be_empty actual
'
+
+test_expect_failure 'grep --textconv: superproject .gitattributes does not affect submodules' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+ echo "a diff=d2x" >.gitattributes &&
+
+ cat >expect <<-\EOF &&
+ a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'grep --textconv: superproject .gitattributes (from index) does not affect submodules' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+ echo "a diff=d2x" >.gitattributes &&
+ git add .gitattributes &&
+ rm .gitattributes &&
+
+ cat >expect <<-\EOF &&
+ a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'grep --textconv: superproject .git/info/attributes does not affect submodules' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+ super_attr="$(git rev-parse --git-path info/attributes)" &&
+ test_when_finished "rm -f \"$super_attr\"" &&
+ echo "a diff=d2x" >"$super_attr" &&
+
+ cat >expect <<-\EOF &&
+ a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+# Note: what currently prevents this test from passing is not that the
+# .gitattributes file from "./submodule" is being ignored, but that it is being
+# propagated to the nested "./submodule/sub" files.
+#
+test_expect_failure 'grep --textconv correctly reads submodule .gitattributes' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+ echo "a diff=d2x" >submodule/.gitattributes &&
+
+ cat >expect <<-\EOF &&
+ submodule/a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'grep --textconv correctly reads submodule .gitattributes (from index)' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+ echo "a diff=d2x" >submodule/.gitattributes &&
+ git -C submodule add .gitattributes &&
+ rm submodule/.gitattributes &&
+
+ cat >expect <<-\EOF &&
+ submodule/a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'grep --textconv correctly reads submodule .git/info/attributes' '
+ reset_and_clean &&
+ test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
+
+ submodule_attr="$(git -C submodule rev-parse --path-format=absolute --git-path info/attributes)" &&
+ test_when_finished "rm -f \"$submodule_attr\"" &&
+ echo "a diff=d2x" >"$submodule_attr" &&
+
+ cat >expect <<-\EOF &&
+ submodule/a:(1|2)x(3|4)
+ EOF
+ git grep --textconv --recurse-submodules x >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'grep saves textconv cache in the appropriate repository' '
+ reset_and_clean &&
+ test_config_global diff.d2x_cached.textconv "sed -e \"s/d/x/\"" &&
+ test_config_global diff.d2x_cached.cachetextconv true &&
+ echo "a diff=d2x_cached" >submodule/.gitattributes &&
+
+ # We only read/write to the textconv cache when grepping from an OID,
+ # as the working tree file might have modifications.
+ git grep --textconv --cached --recurse-submodules x &&
+
+ super_textconv_cache="$(git rev-parse --git-path refs/notes/textconv/d2x_cached)" &&
+ sub_textconv_cache="$(git -C submodule rev-parse \
+ --path-format=absolute --git-path refs/notes/textconv/d2x_cached)" &&
+ test_path_is_missing "$super_textconv_cache" &&
+ test_path_is_file "$sub_textconv_cache"
+'
+
test_done
diff --git a/t/t7815-grep-binary.sh b/t/t7815-grep-binary.sh
index 90ebb64f46..ac871287c0 100755
--- a/t/t7815-grep-binary.sh
+++ b/t/t7815-grep-binary.sh
@@ -2,6 +2,7 @@
test_description='git grep in binary files'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' "
diff --git a/t/t7816-grep-binary-pattern.sh b/t/t7816-grep-binary-pattern.sh
index 9d67a5fc4c..fdb2355649 100755
--- a/t/t7816-grep-binary-pattern.sh
+++ b/t/t7816-grep-binary-pattern.sh
@@ -2,6 +2,7 @@
test_description='git grep with a binary pattern files'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-gettext.sh
nul_match_internal () {
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 6b4941980c..74aa638475 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -276,7 +276,7 @@ test_expect_success 'incremental-repack task' '
# Delete refs that have not been repacked in these packs.
git for-each-ref --format="delete %(refname)" \
- refs/prefetch refs/tags >refs &&
+ refs/prefetch refs/tags refs/remotes >refs &&
git update-ref --stdin <refs &&
# Replace the object directory with this pack layout.
@@ -285,6 +285,10 @@ test_expect_success 'incremental-repack task' '
ls $packDir/*.pack >packs-before &&
test_line_count = 3 packs-before &&
+ # make sure we do not have any broken refs that were
+ # missed in the deletion above
+ git for-each-ref &&
+
# the job repacks the two into a new pack, but does not
# delete the old ones.
git maintenance run --task=incremental-repack &&
@@ -332,15 +336,15 @@ test_expect_success EXPENSIVE 'incremental-repack 2g limit' '
--no-progress --batch-size=2147483647 <run-2g.txt
'
-test_expect_success 'maintenance.incremental-repack.auto' '
+run_incremental_repack_and_verify () {
+ test_commit A &&
git repack -adk &&
- git config core.multiPackIndex true &&
git multi-pack-index write &&
GIT_TRACE2_EVENT="$(pwd)/midx-init.txt" git \
-c maintenance.incremental-repack.auto=1 \
maintenance run --auto --task=incremental-repack 2>/dev/null &&
test_subcommand ! git multi-pack-index write --no-progress <midx-init.txt &&
- test_commit A &&
+ test_commit B &&
git pack-objects --revs .git/objects/pack/pack <<-\EOF &&
HEAD
^HEAD~1
@@ -349,7 +353,7 @@ test_expect_success 'maintenance.incremental-repack.auto' '
-c maintenance.incremental-repack.auto=2 \
maintenance run --auto --task=incremental-repack 2>/dev/null &&
test_subcommand ! git multi-pack-index write --no-progress <trace-A &&
- test_commit B &&
+ test_commit C &&
git pack-objects --revs .git/objects/pack/pack <<-\EOF &&
HEAD
^HEAD~1
@@ -358,6 +362,26 @@ test_expect_success 'maintenance.incremental-repack.auto' '
-c maintenance.incremental-repack.auto=2 \
maintenance run --auto --task=incremental-repack 2>/dev/null &&
test_subcommand git multi-pack-index write --no-progress <trace-B
+}
+
+test_expect_success 'maintenance.incremental-repack.auto' '
+ rm -rf incremental-repack-true &&
+ git init incremental-repack-true &&
+ (
+ cd incremental-repack-true &&
+ git config core.multiPackIndex true &&
+ run_incremental_repack_and_verify
+ )
+'
+
+test_expect_success 'maintenance.incremental-repack.auto (when config is unset)' '
+ rm -rf incremental-repack-unset &&
+ git init incremental-repack-unset &&
+ (
+ cd incremental-repack-unset &&
+ test_unconfig core.multiPackIndex &&
+ run_incremental_repack_and_verify
+ )
'
test_expect_success 'pack-refs task' '
diff --git a/t/t9102-git-svn-deep-rmdir.sh b/t/t9102-git-svn-deep-rmdir.sh
index 66cd51102c..7b2049caa0 100755
--- a/t/t9102-git-svn-deep-rmdir.sh
+++ b/t/t9102-git-svn-deep-rmdir.sh
@@ -1,5 +1,7 @@
#!/bin/sh
test_description='git svn rmdir'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-svn.sh
test_expect_success 'initialize repo' '
diff --git a/t/t9123-git-svn-rebuild-with-rewriteroot.sh b/t/t9123-git-svn-rebuild-with-rewriteroot.sh
index ead404589e..3320b1f39c 100755
--- a/t/t9123-git-svn-rebuild-with-rewriteroot.sh
+++ b/t/t9123-git-svn-rebuild-with-rewriteroot.sh
@@ -5,6 +5,7 @@
test_description='git svn respects rewriteRoot during rebuild'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-svn.sh
mkdir import
diff --git a/t/t9128-git-svn-cmd-branch.sh b/t/t9128-git-svn-cmd-branch.sh
index 4e95f791db..9871f5abc9 100755
--- a/t/t9128-git-svn-cmd-branch.sh
+++ b/t/t9128-git-svn-cmd-branch.sh
@@ -4,6 +4,8 @@
#
test_description='git svn partial-rebuild tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-svn.sh
test_expect_success 'initialize svnrepo' '
diff --git a/t/t9167-git-svn-cmd-branch-subproject.sh b/t/t9167-git-svn-cmd-branch-subproject.sh
index ba35fc06fc..d9fd111c10 100755
--- a/t/t9167-git-svn-cmd-branch-subproject.sh
+++ b/t/t9167-git-svn-cmd-branch-subproject.sh
@@ -4,6 +4,8 @@
#
test_description='git svn branch for subproject clones'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-svn.sh
test_expect_success 'initialize svnrepo' '
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 5decc3b269..518203fbe0 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2148,6 +2148,9 @@ test_expect_success PERL 'send-email' '
--cover-from-description=Z
--cover-letter Z
EOF
+ test_completion "git send-email --val" <<-\EOF &&
+ --validate Z
+ EOF
test_completion "git send-email ma" "main "
'
diff --git a/t/test-lib.sh b/t/test-lib.sh
index aa1ad8180e..57efcc5e97 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -589,17 +589,33 @@ USER_TERM="$TERM"
TERM=dumb
export TERM USER_TERM
-error () {
- say_color error "error: $*"
+_error_exit () {
finalize_junit_xml
GIT_EXIT_OK=t
exit 1
}
+error () {
+ say_color error "error: $*"
+ _error_exit
+}
+
BUG () {
error >&7 "bug in the test script: $*"
}
+BAIL_OUT () {
+ test $# -ne 1 && BUG "1 param"
+
+ # Do not change "Bail out! " string. It's part of TAP syntax:
+ # https://testanything.org/tap-specification.html
+ local bail_out="Bail out! "
+ local message="$1"
+
+ say_color error $bail_out "$message"
+ _error_exit
+}
+
say () {
say_color info "$*"
}
@@ -608,9 +624,7 @@ if test -n "$HARNESS_ACTIVE"
then
if test "$verbose" = t || test -n "$verbose_only"
then
- printf 'Bail out! %s\n' \
- 'verbose mode forbidden under TAP harness; try --verbose-log'
- exit 1
+ BAIL_OUT 'verbose mode forbidden under TAP harness; try --verbose-log'
fi
fi
@@ -720,7 +734,7 @@ test_failure_ () {
say_color error "not ok $test_count - $1"
shift
printf '%s\n' "$*" | sed -e 's/^/# /'
- test "$immediate" = "" || { finalize_junit_xml; GIT_EXIT_OK=t; exit 1; }
+ test "$immediate" = "" || _error_exit
}
test_known_broken_ok_ () {
@@ -1381,14 +1395,46 @@ then
test_done
fi
+# skip non-whitelisted tests when compiled with SANITIZE=leak
+if test -n "$SANITIZE_LEAK"
+then
+ if test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
+ then
+ # We need to see it in "git env--helper" (via
+ # test_bool_env)
+ export TEST_PASSES_SANITIZE_LEAK
+
+ if ! test_bool_env TEST_PASSES_SANITIZE_LEAK false
+ then
+ skip_all="skipping $this_test under GIT_TEST_PASSING_SANITIZE_LEAK=true"
+ test_done
+ fi
+ fi
+elif test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
+then
+ BAIL_OUT "GIT_TEST_PASSING_SANITIZE_LEAK=true has no effect except when compiled with SANITIZE=leak"
+fi
+
# Last-minute variable setup
USER_HOME="$HOME"
HOME="$TRASH_DIRECTORY"
GNUPGHOME="$HOME/gnupg-home-not-used"
export HOME GNUPGHOME USER_HOME
+# "rm -rf" existing trash directory, even if a previous run left it
+# with bad permissions.
+remove_trash_directory () {
+ dir="$1"
+ if ! rm -rf "$dir" 2>/dev/null
+ then
+ chmod -R u+rwx "$dir"
+ rm -rf "$dir"
+ fi
+ ! test -d "$dir"
+}
+
# Test repository
-rm -fr "$TRASH_DIRECTORY" || {
+remove_trash_directory "$TRASH_DIRECTORY" || {
GIT_EXIT_OK=t
echo >&5 "FATAL: Cannot prepare test area"
exit 1
@@ -1534,6 +1580,7 @@ test -z "$NO_PYTHON" && test_set_prereq PYTHON
test -n "$USE_LIBPCRE2" && test_set_prereq PCRE
test -n "$USE_LIBPCRE2" && test_set_prereq LIBPCRE2
test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
+test -n "$SANITIZE_LEAK" && test_set_prereq SANITIZE_LEAK
if test -z "$GIT_TEST_CHECK_CACHE_TREE"
then
@@ -1687,6 +1734,10 @@ build_option () {
sed -ne "s/^$1: //p"
}
+test_lazy_prereq SIZE_T_IS_64BIT '
+ test 8 -eq "$(build_option sizeof-size_t)"
+'
+
test_lazy_prereq LONG_IS_64BIT '
test 8 -le "$(build_option sizeof-long)"
'
@@ -1709,10 +1760,6 @@ test_lazy_prereq SHA1 '
esac
'
-test_lazy_prereq REBASE_P '
- test -z "$GIT_TEST_SKIP_REBASE_P"
-'
-
# Ensure that no test accidentally triggers a Git command
# that runs the actual maintenance scheduler, affecting a user's
# system permanently.