aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/helper/test-bitmap.c36
-rw-r--r--t/helper/test-bloom.c11
-rw-r--r--t/helper/test-bundle-uri.c2
-rw-r--r--t/helper/test-cache-tree.c2
-rw-r--r--t/helper/test-dump-cache-tree.c2
-rw-r--r--t/helper/test-dump-fsmonitor.c2
-rw-r--r--t/helper/test-dump-split-index.c2
-rw-r--r--t/helper/test-dump-untracked-cache.c2
-rw-r--r--t/helper/test-example-decorate.c78
-rw-r--r--t/helper/test-find-pack.c2
-rw-r--r--t/helper/test-fsmonitor-client.c2
-rw-r--r--t/helper/test-hash-speed.c2
-rw-r--r--t/helper/test-hashmap.c3
-rw-r--r--t/helper/test-json-writer.c10
-rw-r--r--t/helper/test-lazy-init-name-hash.c2
-rw-r--r--t/helper/test-match-trees.c2
-rw-r--r--t/helper/test-oid-array.c4
-rw-r--r--t/helper/test-oidmap.c2
-rw-r--r--t/helper/test-oidtree.c54
-rw-r--r--t/helper/test-pack-mtimes.c2
-rw-r--r--t/helper/test-partial-clone.c2
-rw-r--r--t/helper/test-proc-receive.c9
-rw-r--r--t/helper/test-reach.c2
-rw-r--r--t/helper/test-read-cache.c2
-rw-r--r--t/helper/test-read-graph.c67
-rw-r--r--t/helper/test-read-midx.c2
-rw-r--r--t/helper/test-ref-store.c3
-rw-r--r--t/helper/test-reftable.c1
-rw-r--r--t/helper/test-regex.c4
-rw-r--r--t/helper/test-repository.c2
-rw-r--r--t/helper/test-revision-walking.c2
-rw-r--r--t/helper/test-rot13-filter.c5
-rw-r--r--t/helper/test-scrap-cache-tree.c2
-rw-r--r--t/helper/test-sha1.c2
-rw-r--r--t/helper/test-sha256.c2
-rw-r--r--t/helper/test-submodule-config.c4
-rw-r--r--t/helper/test-submodule-nested-repo-config.c2
-rw-r--r--t/helper/test-submodule.c2
-rw-r--r--t/helper/test-tool.c2
-rw-r--r--t/helper/test-tool.h2
-rw-r--r--t/helper/test-trace2.c2
-rw-r--r--t/helper/test-write-cache.c2
-rwxr-xr-xt/perf/p5333-pseudo-merge-bitmaps.sh32
-rwxr-xr-xt/t0001-init.sh101
-rwxr-xr-xt/t0006-date.sh51
-rwxr-xr-xt/t0008-ignores.sh8
-rwxr-xr-xt/t0014-alias.sh11
-rwxr-xr-xt/t0015-hash.sh56
-rwxr-xr-xt/t0033-safe-directory.sh15
-rwxr-xr-xt/t0064-oid-array.sh18
-rwxr-xr-xt/t0069-oidtree.sh50
-rwxr-xr-xt/t0095-bloom.sh8
-rwxr-xr-xt/t0410-partial-clone.sh62
-rwxr-xr-xt/t0600-reffiles-backend.sh32
-rwxr-xr-xt/t1006-cat-file.sh30
-rwxr-xr-xt/t1090-sparse-checkout-scope.sh1
-rwxr-xr-xt/t1091-sparse-checkout-builtin.sh1
-rwxr-xr-xt/t1400-update-ref.sh430
-rwxr-xr-xt/t1403-show-ref.sh24
-rwxr-xr-xt/t1416-ref-transaction-hooks.sh54
-rwxr-xr-xt/t1460-refs-migrate.sh243
-rwxr-xr-xt/t1517-outside-repo.sh52
-rwxr-xr-xt/t3206-range-diff.sh14
-rwxr-xr-xt/t3404-rebase-interactive.sh45
-rwxr-xr-xt/t3602-rm-sparse-checkout.sh1
-rwxr-xr-xt/t3701-add-interactive.sh15
-rwxr-xr-xt/t3900-i18n-commit.sh1
-rwxr-xr-xt/t3901-i18n-patch.sh1
-rwxr-xr-xt/t3910-mac-os-precompose.sh39
-rwxr-xr-xt/t4014-format-patch.sh61
-rwxr-xr-xt/t4015-diff-whitespace.sh9
-rwxr-xr-xt/t4020-diff-external.sh66
-rwxr-xr-xt/t4153-am-resume-override-opts.sh14
-rwxr-xr-xt/t4202-log.sh24
-rwxr-xr-xt/t4216-log-bloom.sh325
-rwxr-xr-xt/t5319-multi-pack-index.sh23
-rwxr-xr-xt/t5324-split-commit-graph.sh26
-rwxr-xr-xt/t5326-multi-pack-bitmaps.sh30
-rwxr-xr-xt/t5332-multi-pack-reuse.sh26
-rwxr-xr-xt/t5333-pseudo-merge-bitmaps.sh393
-rwxr-xr-xt/t5500-fetch-pack.sh12
-rwxr-xr-xt/t5505-remote.sh36
-rwxr-xr-xt/t5512-ls-remote.sh32
-rwxr-xr-xt/t5550-http-fetch-dumb.sh6
-rwxr-xr-xt/t5601-clone.sh7
-rwxr-xr-xt/t5605-clone-local.sh2
-rwxr-xr-xt/t5801-remote-helpers.sh23
-rwxr-xr-xt/t5801/git-remote-nourl3
-rwxr-xr-xt/t5801/git-remote-testgit3
-rwxr-xr-xt/t6112-rev-list-filters-objects.sh12
-rwxr-xr-xt/t6500-gc.sh2
-rwxr-xr-xt/t7002-mv-sparse-checkout.sh1
-rwxr-xr-xt/t7006-pager.sh17
-rwxr-xr-xt/t7600-merge.sh10
-rwxr-xr-xt/t9004-example.sh12
-rw-r--r--t/test-lib-functions.sh14
-rwxr-xr-xt/test-terminal.perl29
-rw-r--r--t/unit-tests/lib-oid.c52
-rw-r--r--t/unit-tests/lib-oid.h17
-rw-r--r--t/unit-tests/t-example-decorate.c82
-rw-r--r--t/unit-tests/t-hash.c84
-rw-r--r--t/unit-tests/t-oidtree.c122
-rw-r--r--t/unit-tests/t-reftable-basics.c160
-rw-r--r--t/unit-tests/t-strbuf.c10
-rw-r--r--t/unit-tests/t-strvec.c3
105 files changed, 3076 insertions, 412 deletions
diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c
index af43ee1cb5..3f23f21072 100644
--- a/t/helper/test-bitmap.c
+++ b/t/helper/test-bitmap.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "git-compat-util.h"
#include "pack-bitmap.h"
@@ -13,21 +15,41 @@ static int bitmap_dump_hashes(void)
return test_bitmap_hashes(the_repository);
}
+static int bitmap_dump_pseudo_merges(void)
+{
+ return test_bitmap_pseudo_merges(the_repository);
+}
+
+static int bitmap_dump_pseudo_merge_commits(uint32_t n)
+{
+ return test_bitmap_pseudo_merge_commits(the_repository, n);
+}
+
+static int bitmap_dump_pseudo_merge_objects(uint32_t n)
+{
+ return test_bitmap_pseudo_merge_objects(the_repository, n);
+}
+
int cmd__bitmap(int argc, const char **argv)
{
setup_git_directory();
- if (argc != 2)
- goto usage;
-
- if (!strcmp(argv[1], "list-commits"))
+ if (argc == 2 && !strcmp(argv[1], "list-commits"))
return bitmap_list_commits();
- if (!strcmp(argv[1], "dump-hashes"))
+ if (argc == 2 && !strcmp(argv[1], "dump-hashes"))
return bitmap_dump_hashes();
+ if (argc == 2 && !strcmp(argv[1], "dump-pseudo-merges"))
+ return bitmap_dump_pseudo_merges();
+ if (argc == 3 && !strcmp(argv[1], "dump-pseudo-merge-commits"))
+ return bitmap_dump_pseudo_merge_commits(atoi(argv[2]));
+ if (argc == 3 && !strcmp(argv[1], "dump-pseudo-merge-objects"))
+ return bitmap_dump_pseudo_merge_objects(atoi(argv[2]));
-usage:
usage("\ttest-tool bitmap list-commits\n"
- "\ttest-tool bitmap dump-hashes");
+ "\ttest-tool bitmap dump-hashes\n"
+ "\ttest-tool bitmap dump-pseudo-merges\n"
+ "\ttest-tool bitmap dump-pseudo-merge-commits <n>\n"
+ "\ttest-tool bitmap dump-pseudo-merge-objects <n>");
return -1;
}
diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c
index 1281e66876..97541daf71 100644
--- a/t/helper/test-bloom.c
+++ b/t/helper/test-bloom.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "bloom.h"
#include "hex.h"
@@ -49,6 +51,7 @@ static void get_bloom_filter_for_commit(const struct object_id *commit_oid)
static const char *bloom_usage = "\n"
" test-tool bloom get_murmur3 <string>\n"
+" test-tool bloom get_murmur3_seven_highbit\n"
" test-tool bloom generate_filter <string> [<string>...]\n"
" test-tool bloom get_filter_for_commit <commit-hex>\n";
@@ -63,7 +66,13 @@ int cmd__bloom(int argc, const char **argv)
uint32_t hashed;
if (argc < 3)
usage(bloom_usage);
- hashed = murmur3_seeded(0, argv[2], strlen(argv[2]));
+ hashed = murmur3_seeded_v2(0, argv[2], strlen(argv[2]));
+ printf("Murmur3 Hash with seed=0:0x%08x\n", hashed);
+ }
+
+ if (!strcmp(argv[1], "get_murmur3_seven_highbit")) {
+ uint32_t hashed;
+ hashed = murmur3_seeded_v2(0, "\x99\xaa\xbb\xcc\xdd\xee\xff", 7);
printf("Murmur3 Hash with seed=0:0x%08x\n", hashed);
}
diff --git a/t/helper/test-bundle-uri.c b/t/helper/test-bundle-uri.c
index 09dc78733c..0c5fa723d8 100644
--- a/t/helper/test-bundle-uri.c
+++ b/t/helper/test-bundle-uri.c
@@ -88,8 +88,6 @@ static int cmd_ls_remote(int argc, const char **argv)
die(_("bad repository '%s'"), dest);
die(_("no remote configured to get bundle URIs from"));
}
- if (!remote->url_nr)
- die(_("remote '%s' has no configured URL"), dest);
transport = transport_get(remote, NULL);
if (transport_get_remote_bundle_uri(transport) < 0) {
diff --git a/t/helper/test-cache-tree.c b/t/helper/test-cache-tree.c
index dc89ecfd71..5cdef3ebef 100644
--- a/t/helper/test-cache-tree.c
+++ b/t/helper/test-cache-tree.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "gettext.h"
#include "hex.h"
diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c
index 02b0b46c3f..3f0c7d0ed0 100644
--- a/t/helper/test-dump-cache-tree.c
+++ b/t/helper/test-dump-cache-tree.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "hash.h"
#include "hex.h"
diff --git a/t/helper/test-dump-fsmonitor.c b/t/helper/test-dump-fsmonitor.c
index 4f215fea02..1b7f37a84f 100644
--- a/t/helper/test-dump-fsmonitor.c
+++ b/t/helper/test-dump-fsmonitor.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "read-cache-ll.h"
#include "repository.h"
diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c
index f472691a3c..a6720faf9c 100644
--- a/t/helper/test-dump-split-index.c
+++ b/t/helper/test-dump-split-index.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "hex.h"
#include "read-cache-ll.h"
diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index 9ff67c3967..4f010d5324 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "dir.h"
#include "hex.h"
diff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c
deleted file mode 100644
index 8f59f6be4c..0000000000
--- a/t/helper/test-example-decorate.c
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "test-tool.h"
-#include "git-compat-util.h"
-#include "object.h"
-#include "decorate.h"
-#include "repository.h"
-
-int cmd__example_decorate(int argc UNUSED, const char **argv UNUSED)
-{
- struct decoration n;
- struct object_id one_oid = { {1} };
- struct object_id two_oid = { {2} };
- struct object_id three_oid = { {3} };
- struct object *one, *two, *three;
-
- int decoration_a, decoration_b;
-
- void *ret;
-
- int i, objects_noticed = 0;
-
- /*
- * The struct must be zero-initialized.
- */
- memset(&n, 0, sizeof(n));
-
- /*
- * Add 2 objects, one with a non-NULL decoration and one with a NULL
- * decoration.
- */
- one = lookup_unknown_object(the_repository, &one_oid);
- two = lookup_unknown_object(the_repository, &two_oid);
- ret = add_decoration(&n, one, &decoration_a);
- if (ret)
- BUG("when adding a brand-new object, NULL should be returned");
- ret = add_decoration(&n, two, NULL);
- if (ret)
- BUG("when adding a brand-new object, NULL should be returned");
-
- /*
- * When re-adding an already existing object, the old decoration is
- * returned.
- */
- ret = add_decoration(&n, one, NULL);
- if (ret != &decoration_a)
- BUG("when readding an already existing object, existing decoration should be returned");
- ret = add_decoration(&n, two, &decoration_b);
- if (ret)
- BUG("when readding an already existing object, existing decoration should be returned");
-
- /*
- * Lookup returns the added declarations, or NULL if the object was
- * never added.
- */
- ret = lookup_decoration(&n, one);
- if (ret)
- BUG("lookup should return added declaration");
- ret = lookup_decoration(&n, two);
- if (ret != &decoration_b)
- BUG("lookup should return added declaration");
- three = lookup_unknown_object(the_repository, &three_oid);
- ret = lookup_decoration(&n, three);
- if (ret)
- BUG("lookup for unknown object should return NULL");
-
- /*
- * The user can also loop through all entries.
- */
- for (i = 0; i < n.size; i++) {
- if (n.entries[i].base)
- objects_noticed++;
- }
- if (objects_noticed != 2)
- BUG("should have 2 objects");
-
- clear_decoration(&n, NULL);
-
- return 0;
-}
diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c
index e8bd793e58..14b2b0c12c 100644
--- a/t/helper/test-find-pack.c
+++ b/t/helper/test-find-pack.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "object-name.h"
#include "object-store.h"
diff --git a/t/helper/test-fsmonitor-client.c b/t/helper/test-fsmonitor-client.c
index 8280984d08..02bfe92e8d 100644
--- a/t/helper/test-fsmonitor-client.c
+++ b/t/helper/test-fsmonitor-client.c
@@ -3,6 +3,8 @@
* a `git fsmonitor--daemon` daemon.
*/
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "parse-options.h"
#include "fsmonitor-ipc.h"
diff --git a/t/helper/test-hash-speed.c b/t/helper/test-hash-speed.c
index b235da594f..7de822af51 100644
--- a/t/helper/test-hash-speed.c
+++ b/t/helper/test-hash-speed.c
@@ -1,5 +1,5 @@
#include "test-tool.h"
-#include "hash-ll.h"
+#include "hash.h"
#define NUM_SECONDS 3
diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c
index 0eb0b3d49c..2912899558 100644
--- a/t/helper/test-hashmap.c
+++ b/t/helper/test-hashmap.c
@@ -36,7 +36,8 @@ static int test_entry_cmp(const void *cmp_data,
}
static struct test_entry *alloc_test_entry(unsigned int hash,
- char *key, char *value)
+ const char *key,
+ const char *value)
{
size_t klen = strlen(key);
size_t vlen = strlen(value);
diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c
index afe393f597..ed52eb76bf 100644
--- a/t/helper/test-json-writer.c
+++ b/t/helper/test-json-writer.c
@@ -174,7 +174,7 @@ static void make_arr4(int pretty)
jw_end(&arr4);
}
-static char *expect_nest1 =
+static const char *expect_nest1 =
"{\"obj1\":{\"a\":\"abc\",\"b\":42,\"c\":true},\"arr1\":[\"abc\",42,true]}";
static struct json_writer nest1 = JSON_WRITER_INIT;
@@ -195,10 +195,10 @@ static void make_nest1(int pretty)
jw_release(&arr1);
}
-static char *expect_inline1 =
+static const char *expect_inline1 =
"{\"obj1\":{\"a\":\"abc\",\"b\":42,\"c\":true},\"arr1\":[\"abc\",42,true]}";
-static char *pretty_inline1 =
+static const char *pretty_inline1 =
("{\n"
" \"obj1\": {\n"
" \"a\": \"abc\",\n"
@@ -236,10 +236,10 @@ static void make_inline1(int pretty)
jw_end(&inline1);
}
-static char *expect_inline2 =
+static const char *expect_inline2 =
"[[1,2],[3,4],{\"a\":\"abc\"}]";
-static char *pretty_inline2 =
+static const char *pretty_inline2 =
("[\n"
" [\n"
" 1,\n"
diff --git a/t/helper/test-lazy-init-name-hash.c b/t/helper/test-lazy-init-name-hash.c
index 5f33bb7b8f..40f5df4412 100644
--- a/t/helper/test-lazy-init-name-hash.c
+++ b/t/helper/test-lazy-init-name-hash.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "environment.h"
#include "name-hash.h"
diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c
index d0db5ff26f..e0e2048320 100644
--- a/t/helper/test-match-trees.c
+++ b/t/helper/test-match-trees.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "hex.h"
#include "match-trees.h"
diff --git a/t/helper/test-oid-array.c b/t/helper/test-oid-array.c
index aafe398ef0..076b849cbf 100644
--- a/t/helper/test-oid-array.c
+++ b/t/helper/test-oid-array.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "hex.h"
#include "oid-array.h"
@@ -17,6 +19,8 @@ int cmd__oid_array(int argc UNUSED, const char **argv UNUSED)
int nongit_ok;
setup_git_directory_gently(&nongit_ok);
+ if (nongit_ok)
+ repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
while (strbuf_getline(&line, stdin) != EOF) {
const char *arg;
diff --git a/t/helper/test-oidmap.c b/t/helper/test-oidmap.c
index bd30244a54..c03cfa5ecf 100644
--- a/t/helper/test-oidmap.c
+++ b/t/helper/test-oidmap.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "hex.h"
#include "object-name.h"
diff --git a/t/helper/test-oidtree.c b/t/helper/test-oidtree.c
deleted file mode 100644
index c7a1d4c642..0000000000
--- a/t/helper/test-oidtree.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "test-tool.h"
-#include "hex.h"
-#include "oidtree.h"
-#include "setup.h"
-#include "strbuf.h"
-
-static enum cb_next print_oid(const struct object_id *oid, void *data UNUSED)
-{
- puts(oid_to_hex(oid));
- return CB_CONTINUE;
-}
-
-int cmd__oidtree(int argc UNUSED, const char **argv UNUSED)
-{
- struct oidtree ot;
- struct strbuf line = STRBUF_INIT;
- int nongit_ok;
- int algo = GIT_HASH_UNKNOWN;
-
- oidtree_init(&ot);
- setup_git_directory_gently(&nongit_ok);
-
- while (strbuf_getline(&line, stdin) != EOF) {
- const char *arg;
- struct object_id oid;
-
- if (skip_prefix(line.buf, "insert ", &arg)) {
- if (get_oid_hex_any(arg, &oid) == GIT_HASH_UNKNOWN)
- die("insert not a hexadecimal oid: %s", arg);
- algo = oid.algo;
- oidtree_insert(&ot, &oid);
- } else if (skip_prefix(line.buf, "contains ", &arg)) {
- if (get_oid_hex(arg, &oid))
- die("contains not a hexadecimal oid: %s", arg);
- printf("%d\n", oidtree_contains(&ot, &oid));
- } else if (skip_prefix(line.buf, "each ", &arg)) {
- char buf[GIT_MAX_HEXSZ + 1] = { '0' };
- memset(&oid, 0, sizeof(oid));
- memcpy(buf, arg, strlen(arg));
- buf[hash_algos[algo].hexsz] = '\0';
- get_oid_hex_any(buf, &oid);
- oid.algo = algo;
- oidtree_each(&ot, &oid, strlen(arg), print_oid, NULL);
- } else if (!strcmp(line.buf, "clear")) {
- oidtree_clear(&ot);
- } else {
- die("unknown command: %s", line.buf);
- }
- }
-
- strbuf_release(&line);
-
- return 0;
-}
diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c
index 67a964ef90..f8f9afbb5b 100644
--- a/t/helper/test-pack-mtimes.c
+++ b/t/helper/test-pack-mtimes.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "hex.h"
#include "strbuf.h"
diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c
index 910a128614..0ead529167 100644
--- a/t/helper/test-partial-clone.c
+++ b/t/helper/test-partial-clone.c
@@ -21,7 +21,7 @@ static void object_info(const char *gitdir, const char *oid_hex)
if (repo_init(&r, gitdir, NULL))
die("could not init repo");
- if (parse_oid_hex(oid_hex, &oid, &p))
+ if (parse_oid_hex_algop(oid_hex, &oid, &p, r.hash_algo))
die("could not parse oid");
if (oid_object_info_extended(&r, &oid, &oi, 0))
die("could not obtain object info");
diff --git a/t/helper/test-proc-receive.c b/t/helper/test-proc-receive.c
index f30022d222..29361c7aab 100644
--- a/t/helper/test-proc-receive.c
+++ b/t/helper/test-proc-receive.c
@@ -3,8 +3,8 @@
#include "hex.h"
#include "parse-options.h"
#include "pkt-line.h"
-#include "setup.h"
#include "sigchain.h"
+#include "string-list.h"
static const char *proc_receive_usage[] = {
"test-tool proc-receive [<options>]",
@@ -92,9 +92,9 @@ static void proc_receive_read_commands(struct packet_reader *reader,
if (die_read_commands)
die("die with the --die-read-commands option");
- if (parse_oid_hex(reader->line, &old_oid, &p) ||
+ if (parse_oid_hex_any(reader->line, &old_oid, &p) == GIT_HASH_UNKNOWN ||
*p++ != ' ' ||
- parse_oid_hex(p, &new_oid, &p) ||
+ parse_oid_hex_any(p, &new_oid, &p) == GIT_HASH_UNKNOWN ||
*p++ != ' ')
die("protocol error: expected 'old new ref', got '%s'",
reader->line);
@@ -128,7 +128,6 @@ static void proc_receive_read_push_options(struct packet_reader *reader,
int cmd__proc_receive(int argc, const char **argv)
{
- int nongit_ok = 0;
struct packet_reader reader;
struct command *commands = NULL;
struct string_list push_options = STRING_LIST_INIT_DUP;
@@ -154,8 +153,6 @@ int cmd__proc_receive(int argc, const char **argv)
OPT_END()
};
- setup_git_directory_gently(&nongit_ok);
-
argc = parse_options(argc, argv, "test-tools", options, proc_receive_usage, 0);
if (argc > 0)
usage_msg_opt("Too many arguments.", proc_receive_usage, options);
diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index 1ba226f1f9..5dd374379c 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "commit.h"
#include "commit-reach.h"
diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index e803c43ece..d285c656bd 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "config.h"
#include "read-cache-ll.h"
diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c
index 8c7a83f578..9018c9f541 100644
--- a/t/helper/test-read-graph.c
+++ b/t/helper/test-read-graph.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "commit-graph.h"
#include "repository.h"
@@ -5,20 +7,8 @@
#include "bloom.h"
#include "setup.h"
-int cmd__read_graph(int argc UNUSED, const char **argv UNUSED)
+static void dump_graph_info(struct commit_graph *graph)
{
- struct commit_graph *graph = NULL;
- struct object_directory *odb;
-
- setup_git_directory();
- odb = the_repository->objects->odb;
-
- prepare_repo_settings(the_repository);
-
- graph = read_commit_graph_one(the_repository, odb);
- if (!graph)
- return 1;
-
printf("header: %08x %d %d %d %d\n",
ntohl(*(uint32_t*)graph->data),
*(unsigned char*)(graph->data + 4),
@@ -57,8 +47,57 @@ int cmd__read_graph(int argc UNUSED, const char **argv UNUSED)
if (graph->topo_levels)
printf(" topo_levels");
printf("\n");
+}
+
+static void dump_graph_bloom_filters(struct commit_graph *graph)
+{
+ uint32_t i;
+
+ for (i = 0; i < graph->num_commits + graph->num_commits_in_base; i++) {
+ struct bloom_filter filter = { 0 };
+ size_t j;
+
+ if (load_bloom_filter_from_graph(graph, &filter, i) < 0) {
+ fprintf(stderr, "missing Bloom filter for graph "
+ "position %"PRIu32"\n", i);
+ continue;
+ }
+
+ for (j = 0; j < filter.len; j++)
+ printf("%02x", filter.data[j]);
+ if (filter.len)
+ printf("\n");
+ }
+}
+
+int cmd__read_graph(int argc, const char **argv)
+{
+ struct commit_graph *graph = NULL;
+ struct object_directory *odb;
+ int ret = 0;
+
+ setup_git_directory();
+ odb = the_repository->objects->odb;
+
+ prepare_repo_settings(the_repository);
+
+ graph = read_commit_graph_one(the_repository, odb);
+ if (!graph) {
+ ret = 1;
+ goto done;
+ }
+
+ if (argc <= 1)
+ dump_graph_info(graph);
+ else if (!strcmp(argv[1], "bloom-filters"))
+ dump_graph_bloom_filters(graph);
+ else {
+ fprintf(stderr, "unknown sub-command: '%s'\n", argv[1]);
+ ret = 1;
+ }
+done:
UNLEAK(graph);
- return 0;
+ return ret;
}
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
index 4acae41bb9..83effc2b5f 100644
--- a/t/helper/test-read-midx.c
+++ b/t/helper/test-read-midx.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "hex.h"
#include "midx.h"
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index c9efd74c2b..637b8b294e 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "hex.h"
#include "refs.h"
@@ -126,6 +128,7 @@ static struct flag_definition transaction_flags[] = {
FLAG_DEF(REF_FORCE_CREATE_REFLOG),
FLAG_DEF(REF_SKIP_OID_VERIFICATION),
FLAG_DEF(REF_SKIP_REFNAME_VERIFICATION),
+ FLAG_DEF(REF_SKIP_CREATE_REFLOG),
{ NULL, 0 }
};
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index bae731669c..9160bc5da6 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -5,7 +5,6 @@
int cmd__reftable(int argc, const char **argv)
{
/* test from simple to complex. */
- basics_test_main(argc, argv);
record_test_main(argc, argv);
block_test_main(argc, argv);
tree_test_main(argc, argv);
diff --git a/t/helper/test-regex.c b/t/helper/test-regex.c
index 80042eafc2..366bd70976 100644
--- a/t/helper/test-regex.c
+++ b/t/helper/test-regex.c
@@ -20,8 +20,8 @@ static struct reg_flag reg_flags[] = {
static int test_regex_bug(void)
{
- char *pat = "[^={} \t]+";
- char *str = "={}\nfred";
+ const char *pat = "[^={} \t]+";
+ const char *str = "={}\nfred";
regex_t r;
regmatch_t m[1];
diff --git a/t/helper/test-repository.c b/t/helper/test-repository.c
index 0c7c5aa4dd..c6a074df3d 100644
--- a/t/helper/test-repository.c
+++ b/t/helper/test-repository.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "commit-graph.h"
#include "commit.h"
diff --git a/t/helper/test-revision-walking.c b/t/helper/test-revision-walking.c
index f346951bc2..071f5bd1e2 100644
--- a/t/helper/test-revision-walking.c
+++ b/t/helper/test-revision-walking.c
@@ -8,6 +8,8 @@
* published by the Free Software Foundation.
*/
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "commit.h"
#include "diff.h"
diff --git a/t/helper/test-rot13-filter.c b/t/helper/test-rot13-filter.c
index f8d564c622..7e1d9e0ee4 100644
--- a/t/helper/test-rot13-filter.c
+++ b/t/helper/test-rot13-filter.c
@@ -136,7 +136,7 @@ static void free_delay_entries(void)
strmap_clear(&delay, 0);
}
-static void add_delay_entry(char *pathname, int count, int requested)
+static void add_delay_entry(const char *pathname, int count, int requested)
{
struct delay_entry *entry = xcalloc(1, sizeof(*entry));
entry->count = count;
@@ -189,7 +189,8 @@ static void reply_list_available_blobs_cmd(void)
static void command_loop(void)
{
for (;;) {
- char *buf, *output;
+ char *buf;
+ const char *output;
char *pathname;
struct delay_entry *entry;
struct strbuf input = STRBUF_INIT;
diff --git a/t/helper/test-scrap-cache-tree.c b/t/helper/test-scrap-cache-tree.c
index 737cbe475b..64fff6e9e3 100644
--- a/t/helper/test-scrap-cache-tree.c
+++ b/t/helper/test-scrap-cache-tree.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "lockfile.h"
#include "read-cache-ll.h"
diff --git a/t/helper/test-sha1.c b/t/helper/test-sha1.c
index dcb7f6c003..e60d000c03 100644
--- a/t/helper/test-sha1.c
+++ b/t/helper/test-sha1.c
@@ -1,5 +1,5 @@
#include "test-tool.h"
-#include "hash-ll.h"
+#include "hash.h"
int cmd__sha1(int ac, const char **av)
{
diff --git a/t/helper/test-sha256.c b/t/helper/test-sha256.c
index 08cf149001..2fb20438f3 100644
--- a/t/helper/test-sha256.c
+++ b/t/helper/test-sha256.c
@@ -1,5 +1,5 @@
#include "test-tool.h"
-#include "hash-ll.h"
+#include "hash.h"
int cmd__sha256(int ac, const char **av)
{
diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index 9df2f03ac8..cbe93f2f9e 100644
--- a/t/helper/test-submodule-config.c
+++ b/t/helper/test-submodule-config.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "config.h"
#include "hash.h"
@@ -44,7 +46,7 @@ int cmd__submodule_config(int argc, const char **argv)
path_or_name = arg[1];
if (commit[0] == '\0')
- oidclr(&commit_oid);
+ oidclr(&commit_oid, the_repository->hash_algo);
else if (repo_get_oid(the_repository, commit, &commit_oid) < 0)
die_usage(argc, argv, "Commit not found.");
diff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c
index ecd40ded99..6ca069ce63 100644
--- a/t/helper/test-submodule-nested-repo-config.c
+++ b/t/helper/test-submodule-nested-repo-config.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "repository.h"
#include "setup.h"
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index 7197969a08..22e518d229 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "test-tool-utils.h"
#include "parse-options.h"
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 7ad7d07018..93436a82ae 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -29,7 +29,6 @@ static struct test_cmd cmds[] = {
{ "dump-split-index", cmd__dump_split_index },
{ "dump-untracked-cache", cmd__dump_untracked_cache },
{ "env-helper", cmd__env_helper },
- { "example-decorate", cmd__example_decorate },
{ "example-tap", cmd__example_tap },
{ "find-pack", cmd__find_pack },
{ "fsmonitor-client", cmd__fsmonitor_client },
@@ -46,7 +45,6 @@ static struct test_cmd cmds[] = {
{ "mktemp", cmd__mktemp },
{ "oid-array", cmd__oid_array },
{ "oidmap", cmd__oidmap },
- { "oidtree", cmd__oidtree },
{ "online-cpus", cmd__online_cpus },
{ "pack-mtimes", cmd__pack_mtimes },
{ "parse-options", cmd__parse_options },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index d14b3072bd..d9033d14e1 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -23,7 +23,6 @@ int cmd__dump_split_index(int argc, const char **argv);
int cmd__dump_untracked_cache(int argc, const char **argv);
int cmd__dump_reftable(int argc, const char **argv);
int cmd__env_helper(int argc, const char **argv);
-int cmd__example_decorate(int argc, const char **argv);
int cmd__example_tap(int argc, const char **argv);
int cmd__find_pack(int argc, const char **argv);
int cmd__fsmonitor_client(int argc, const char **argv);
@@ -39,7 +38,6 @@ int cmd__match_trees(int argc, const char **argv);
int cmd__mergesort(int argc, const char **argv);
int cmd__mktemp(int argc, const char **argv);
int cmd__oidmap(int argc, const char **argv);
-int cmd__oidtree(int argc, const char **argv);
int cmd__online_cpus(int argc, const char **argv);
int cmd__pack_mtimes(int argc, const char **argv);
int cmd__parse_options(int argc, const char **argv);
diff --git a/t/helper/test-trace2.c b/t/helper/test-trace2.c
index 1adac29a57..cd955ec63e 100644
--- a/t/helper/test-trace2.c
+++ b/t/helper/test-trace2.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "strvec.h"
#include "run-command.h"
diff --git a/t/helper/test-write-cache.c b/t/helper/test-write-cache.c
index 7e3da380a9..b37dd2c5d6 100644
--- a/t/helper/test-write-cache.c
+++ b/t/helper/test-write-cache.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "lockfile.h"
#include "read-cache-ll.h"
diff --git a/t/perf/p5333-pseudo-merge-bitmaps.sh b/t/perf/p5333-pseudo-merge-bitmaps.sh
new file mode 100755
index 0000000000..2e8b1d2635
--- /dev/null
+++ b/t/perf/p5333-pseudo-merge-bitmaps.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+test_description='pseudo-merge bitmaps'
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+test_expect_success 'setup' '
+ git \
+ -c bitmapPseudoMerge.all.pattern="refs/" \
+ -c bitmapPseudoMerge.all.threshold=now \
+ -c bitmapPseudoMerge.all.stableThreshold=never \
+ -c bitmapPseudoMerge.all.maxMerges=64 \
+ -c pack.writeBitmapLookupTable=true \
+ repack -adb
+'
+
+test_perf 'git rev-list --count --all --objects (no bitmaps)' '
+ git rev-list --objects --all
+'
+
+test_perf 'git rev-list --count --all --objects (no pseudo-merges)' '
+ GIT_TEST_USE_PSEUDO_MERGES=0 \
+ git rev-list --objects --all --use-bitmap-index
+'
+
+test_perf 'git rev-list --count --all --objects (with pseudo-merges)' '
+ GIT_TEST_USE_PSEUDO_MERGES=1 \
+ git rev-list --objects --all --use-bitmap-index
+'
+
+test_done
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index b131d665db..49e9bf77c6 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -584,14 +584,39 @@ test_expect_success 'init with --ref-format=files' '
test_cmp expect actual
'
-test_expect_success 're-init with same format' '
- test_when_finished "rm -rf refformat" &&
- git init --ref-format=files refformat &&
- git init --ref-format=files refformat &&
- echo files >expect &&
- git -C refformat rev-parse --show-ref-format >actual &&
- test_cmp expect actual
-'
+backends="files reftable"
+for from_format in $backends
+do
+ test_expect_success "re-init with same format ($from_format)" '
+ test_when_finished "rm -rf refformat" &&
+ git init --ref-format=$from_format refformat &&
+ git init --ref-format=$from_format refformat &&
+ echo $from_format >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+ '
+
+ for to_format in $backends
+ do
+ if test "$from_format" = "$to_format"
+ then
+ continue
+ fi
+
+ test_expect_success "re-init with different format fails ($from_format -> $to_format)" '
+ test_when_finished "rm -rf refformat" &&
+ git init --ref-format=$from_format refformat &&
+ cat >expect <<-EOF &&
+ fatal: attempt to reinitialize repository with different reference storage format
+ EOF
+ test_must_fail git init --ref-format=$to_format refformat 2>err &&
+ test_cmp expect err &&
+ echo $from_format >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+ '
+ done
+done
test_expect_success 'init with --ref-format=garbage' '
test_when_finished "rm -rf refformat" &&
@@ -678,4 +703,64 @@ test_expect_success 'branch -m with the initial branch' '
test_cmp expect actual
'
+test_expect_success 'init with includeIf.onbranch condition' '
+ test_when_finished "rm -rf repo" &&
+ git -c includeIf.onbranch:main.path=nonexistent init repo &&
+ echo $GIT_DEFAULT_REF_FORMAT >expect &&
+ git -C repo rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'init with includeIf.onbranch condition with existing directory' '
+ test_when_finished "rm -rf repo" &&
+ mkdir repo &&
+ git -c includeIf.onbranch:nonexistent.path=/does/not/exist init repo &&
+ echo $GIT_DEFAULT_REF_FORMAT >expect &&
+ git -C repo rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 're-init with includeIf.onbranch condition' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ git -c includeIf.onbranch:nonexistent.path=/does/not/exist init repo &&
+ echo $GIT_DEFAULT_REF_FORMAT >expect &&
+ git -C repo rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 're-init with includeIf.onbranch condition' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ git -c includeIf.onbranch:nonexistent.path=/does/not/exist init repo &&
+ echo $GIT_DEFAULT_REF_FORMAT >expect &&
+ git -C repo rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 're-init skips non-matching includeIf.onbranch' '
+ test_when_finished "rm -rf repo config" &&
+ cat >config <<-EOF &&
+ [
+ garbage
+ EOF
+ git init repo &&
+ git -c includeIf.onbranch:nonexistent.path="$(test-tool path-utils absolute_path config)" init repo
+'
+
+test_expect_success 're-init reads matching includeIf.onbranch' '
+ test_when_finished "rm -rf repo config" &&
+ cat >config <<-EOF &&
+ [
+ garbage
+ EOF
+ path="$(test-tool path-utils absolute_path config)" &&
+ git init --initial-branch=branch repo &&
+ cat >expect <<-EOF &&
+ fatal: bad config line 1 in file $path
+ EOF
+ test_must_fail git -c includeIf.onbranch:branch.path="$path" init repo 2>err &&
+ test_cmp expect err
+'
+
test_done
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index 3031256d14..fd373e1b39 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -8,6 +8,11 @@ TEST_PASSES_SANITIZE_LEAK=true
# arbitrary reference time: 2009-08-30 19:20:00
GIT_TEST_DATE_NOW=1251660000; export GIT_TEST_DATE_NOW
+if test_have_prereq TIME_IS_64BIT,TIME_T_IS_64BIT
+then
+ test_set_prereq HAVE_64BIT_TIME
+fi
+
check_relative() {
t=$(($GIT_TEST_DATE_NOW - $1))
echo "$t -> $2" >expect
@@ -80,14 +85,15 @@ check_show raw "$TIME" '1466000000 -0200'
# 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
-check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +0000" TIME_IS_64BIT,TIME_T_IS_64BIT
+check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" HAVE_64BIT_TIME
+check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +0000" HAVE_64BIT_TIME
-check_parse() {
+REQUIRE_64BIT_TIME=
+check_parse () {
echo "$1 -> $2" >expect
- test_expect_${4:-success} "parse date ($1${3:+ TZ=$3})" "
- TZ=${3:-$TZ} test-tool date parse '$1' >actual &&
- test_cmp expect actual
+ test_expect_success $REQUIRE_64BIT_TIME "parse date ($1${3:+ TZ=$3}) -> $2" "
+ TZ=${3:-$TZ} test-tool date parse '$1' >actual &&
+ test_cmp expect actual
"
}
@@ -117,6 +123,39 @@ check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
check_parse 'Thu, 7 Apr 2005 15:14:13 -0700' '2005-04-07 15:14:13 -0700'
+check_parse '1970-01-01 00:00:00' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 +00' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 Z' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 -01' '1970-01-01 00:00:00 -0100'
+check_parse '1970-01-01 00:00:00 +01' bad
+check_parse '1970-01-01 00:00:00 +11' bad
+check_parse '1970-01-01 00:59:59 +01' bad
+check_parse '1970-01-01 01:00:00 +01' '1970-01-01 01:00:00 +0100'
+check_parse '1970-01-01 01:00:00 +11' bad
+check_parse '1970-01-02 00:00:00 +11' '1970-01-02 00:00:00 +1100'
+check_parse '1969-12-31 23:59:59' bad
+check_parse '1969-12-31 23:59:59 +00' bad
+check_parse '1969-12-31 23:59:59 Z' bad
+check_parse '1969-12-31 23:59:59 +11' bad
+check_parse '1969-12-31 23:59:59 -11' bad
+
+REQUIRE_64BIT_TIME=HAVE_64BIT_TIME
+check_parse '2099-12-31 23:59:59' '2099-12-31 23:59:59 +0000'
+check_parse '2099-12-31 23:59:59 +00' '2099-12-31 23:59:59 +0000'
+check_parse '2099-12-31 23:59:59 Z' '2099-12-31 23:59:59 +0000'
+check_parse '2099-12-31 23:59:59 +01' '2099-12-31 23:59:59 +0100'
+check_parse '2099-12-31 23:59:59 -01' bad
+check_parse '2099-12-31 23:59:59 -11' bad
+check_parse '2099-12-31 23:00:00 -01' bad
+check_parse '2099-12-31 22:59:59 -01' '2099-12-31 22:59:59 -0100'
+check_parse '2100-00-00 00:00:00' bad
+check_parse '2099-12-30 00:00:00 -11' '2099-12-30 00:00:00 -1100'
+check_parse '2100-00-00 00:00:00 +00' bad
+check_parse '2100-00-00 00:00:00 Z' bad
+check_parse '2100-00-00 00:00:00 -11' bad
+check_parse '2100-00-00 00:00:00 +11' bad
+REQUIRE_64BIT_TIME=
+
check_approxidate() {
echo "$1 -> $2 +0000" >expect
test_expect_${3:-success} "parse approxidate ($1)" "
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index 361446b2f4..02a18d4fdb 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -945,4 +945,12 @@ test_expect_success SYMLINKS 'symlinks not respected in-tree' '
test_grep "unable to access.*gitignore" err
'
+test_expect_success EXPENSIVE 'large exclude file ignored in tree' '
+ test_when_finished "rm .gitignore" &&
+ dd if=/dev/zero of=.gitignore bs=101M count=1 &&
+ git ls-files -o --exclude-standard 2>err &&
+ echo "warning: ignoring excessively large pattern file: .gitignore" >expect &&
+ test_cmp expect err
+'
+
test_done
diff --git a/t/t0014-alias.sh b/t/t0014-alias.sh
index 95568342be..854d59ec58 100755
--- a/t/t0014-alias.sh
+++ b/t/t0014-alias.sh
@@ -44,4 +44,15 @@ test_expect_success 'run-command formats empty args properly' '
test_cmp expect actual
'
+test_expect_success 'tracing a shell alias with arguments shows trace of prepared command' '
+ cat >expect <<-EOF &&
+ trace: start_command: SHELL -c ${SQ}echo \$* "\$@"${SQ} ${SQ}echo \$*${SQ} arg
+ EOF
+ git config alias.echo "!echo \$*" &&
+ env GIT_TRACE=1 git echo arg 2>output &&
+ # redact platform differences
+ sed -n -e "s/^\(trace: start_command:\) .* -c /\1 SHELL -c /p" output >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t0015-hash.sh b/t/t0015-hash.sh
deleted file mode 100755
index 0a087a1983..0000000000
--- a/t/t0015-hash.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/sh
-
-test_description='test basic hash implementation'
-
-TEST_PASSES_SANITIZE_LEAK=true
-. ./test-lib.sh
-
-test_expect_success 'test basic SHA-1 hash values' '
- test-tool sha1 </dev/null >actual &&
- grep da39a3ee5e6b4b0d3255bfef95601890afd80709 actual &&
- printf "a" | test-tool sha1 >actual &&
- grep 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 actual &&
- printf "abc" | test-tool sha1 >actual &&
- grep a9993e364706816aba3e25717850c26c9cd0d89d actual &&
- printf "message digest" | test-tool sha1 >actual &&
- grep c12252ceda8be8994d5fa0290a47231c1d16aae3 actual &&
- printf "abcdefghijklmnopqrstuvwxyz" | test-tool sha1 >actual &&
- grep 32d10c7b8cf96570ca04ce37f2a19d84240d3a89 actual &&
- perl -e "$| = 1; print q{aaaaaaaaaa} for 1..100000;" |
- test-tool sha1 >actual &&
- grep 34aa973cd4c4daa4f61eeb2bdbad27316534016f actual &&
- printf "blob 0\0" | test-tool sha1 >actual &&
- grep e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 actual &&
- printf "blob 3\0abc" | test-tool sha1 >actual &&
- grep f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f actual &&
- printf "tree 0\0" | test-tool sha1 >actual &&
- grep 4b825dc642cb6eb9a060e54bf8d69288fbee4904 actual
-'
-
-test_expect_success 'test basic SHA-256 hash values' '
- test-tool sha256 </dev/null >actual &&
- grep e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 actual &&
- printf "a" | test-tool sha256 >actual &&
- grep ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb actual &&
- printf "abc" | test-tool sha256 >actual &&
- grep ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad actual &&
- printf "message digest" | test-tool sha256 >actual &&
- grep f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650 actual &&
- printf "abcdefghijklmnopqrstuvwxyz" | test-tool sha256 >actual &&
- grep 71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 actual &&
- # Try to exercise the chunking code by turning autoflush on.
- perl -e "$| = 1; print q{aaaaaaaaaa} for 1..100000;" |
- test-tool sha256 >actual &&
- grep cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0 actual &&
- perl -e "$| = 1; print q{abcdefghijklmnopqrstuvwxyz} for 1..100000;" |
- test-tool sha256 >actual &&
- grep e406ba321ca712ad35a698bf0af8d61fc4dc40eca6bdcea4697962724ccbde35 actual &&
- printf "blob 0\0" | test-tool sha256 >actual &&
- grep 473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813 actual &&
- printf "blob 3\0abc" | test-tool sha256 >actual &&
- grep c1cf6e465077930e88dc5136641d402f72a229ddd996f627d60e9639eaba35a6 actual &&
- printf "tree 0\0" | test-tool sha256 >actual &&
- grep 6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321 actual
-'
-
-test_done
diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh
index 11c3e8f28e..5fe61f1291 100755
--- a/t/t0033-safe-directory.sh
+++ b/t/t0033-safe-directory.sh
@@ -71,7 +71,22 @@ test_expect_success 'safe.directory=*, but is reset' '
expect_rejected_dir
'
+test_expect_success 'safe.directory with matching glob' '
+ git config --global --unset-all safe.directory &&
+ p=$(pwd) &&
+ git config --global safe.directory "${p%/*}/*" &&
+ git status
+'
+
+test_expect_success 'safe.directory with unmatching glob' '
+ git config --global --unset-all safe.directory &&
+ p=$(pwd) &&
+ git config --global safe.directory "${p%/*}no/*" &&
+ expect_rejected_dir
+'
+
test_expect_success 'safe.directory in included file' '
+ git config --global --unset-all safe.directory &&
cat >gitconfig-include <<-EOF &&
[safe]
directory = "$(pwd)"
diff --git a/t/t0064-oid-array.sh b/t/t0064-oid-array.sh
index 88c89e8f48..de74b692d0 100755
--- a/t/t0064-oid-array.sh
+++ b/t/t0064-oid-array.sh
@@ -15,6 +15,24 @@ echoid () {
done
}
+test_expect_success 'without repository' '
+ cat >expect <<-EOF &&
+ 4444444444444444444444444444444444444444
+ 5555555555555555555555555555555555555555
+ 8888888888888888888888888888888888888888
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ EOF
+ cat >input <<-EOF &&
+ append 4444444444444444444444444444444444444444
+ append 5555555555555555555555555555555555555555
+ append 8888888888888888888888888888888888888888
+ append aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ for_each_unique
+ EOF
+ nongit test-tool oid-array <input >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'ordered enumeration' '
echoid "" 44 55 88 aa >expect &&
{
diff --git a/t/t0069-oidtree.sh b/t/t0069-oidtree.sh
deleted file mode 100755
index 889db50818..0000000000
--- a/t/t0069-oidtree.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/sh
-
-test_description='basic tests for the oidtree implementation'
-TEST_PASSES_SANITIZE_LEAK=true
-. ./test-lib.sh
-
-maxhexsz=$(test_oid hexsz)
-echoid () {
- prefix="${1:+$1 }"
- shift
- while test $# -gt 0
- do
- shortoid="$1"
- shift
- difference=$(($maxhexsz - ${#shortoid}))
- printf "%s%s%0${difference}d\\n" "$prefix" "$shortoid" "0"
- done
-}
-
-test_expect_success 'oidtree insert and contains' '
- cat >expect <<-\EOF &&
- 0
- 0
- 0
- 1
- 1
- 0
- EOF
- {
- echoid insert 444 1 2 3 4 5 a b c d e &&
- echoid contains 44 441 440 444 4440 4444 &&
- echo clear
- } | test-tool oidtree >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'oidtree each' '
- echoid "" 123 321 321 >expect &&
- {
- echoid insert f 9 8 123 321 a b c d e &&
- echo each 12300 &&
- echo each 3211 &&
- echo each 3210 &&
- echo each 32100 &&
- echo clear
- } | test-tool oidtree >actual &&
- test_cmp expect actual
-'
-
-test_done
diff --git a/t/t0095-bloom.sh b/t/t0095-bloom.sh
index b567383eb8..c8d84ab606 100755
--- a/t/t0095-bloom.sh
+++ b/t/t0095-bloom.sh
@@ -29,6 +29,14 @@ test_expect_success 'compute unseeded murmur3 hash for test string 2' '
test_cmp expect actual
'
+test_expect_success 'compute unseeded murmur3 hash for test string 3' '
+ cat >expect <<-\EOF &&
+ Murmur3 Hash with seed=0:0xa183ccfd
+ EOF
+ test-tool bloom get_murmur3_seven_highbit >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'compute bloom key for empty string' '
cat >expect <<-\EOF &&
Hashes:0x5615800c|0x5b966560|0x61174ab4|0x66983008|0x6c19155c|0x7199fab0|0x771ae004|
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index 88a66f0904..2c30c86e7b 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -3,6 +3,7 @@
test_description='partial clone'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
# missing promisor objects cause repacks which write bitmaps to fail
GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
@@ -689,6 +690,67 @@ test_expect_success 'lazy-fetch when accessing object not in the_repository' '
! grep "[?]$FILE_HASH" out
'
+test_expect_success 'push should not fetch new commit objects' '
+ rm -rf server client &&
+ test_create_repo server &&
+ test_config -C server uploadpack.allowfilter 1 &&
+ test_config -C server uploadpack.allowanysha1inwant 1 &&
+ test_commit -C server server1 &&
+
+ git clone --filter=blob:none "file://$(pwd)/server" client &&
+ test_commit -C client client1 &&
+
+ test_commit -C server server2 &&
+ COMMIT=$(git -C server rev-parse server2) &&
+
+ test_must_fail git -C client push 2>err &&
+ grep "fetch first" err &&
+ git -C client rev-list --objects --missing=print "$COMMIT" >objects &&
+ grep "^[?]$COMMIT" objects
+'
+
+test_expect_success 'setup for promisor.quiet tests' '
+ rm -rf server &&
+ test_create_repo server &&
+ test_commit -C server foo &&
+ git -C server rm foo.t &&
+ git -C server commit -m remove &&
+ git -C server config uploadpack.allowanysha1inwant 1 &&
+ git -C server config uploadpack.allowfilter 1
+'
+
+test_expect_success TTY 'promisor.quiet=false shows progress messages' '
+ rm -rf repo &&
+ git clone --filter=blob:none "file://$(pwd)/server" repo &&
+ git -C repo config promisor.quiet "false" &&
+
+ test_terminal git -C repo cat-file -p foo:foo.t 2>err &&
+
+ # Ensure that progress messages are written
+ grep "Receiving objects" err
+'
+
+test_expect_success TTY 'promisor.quiet=true does not show progress messages' '
+ rm -rf repo &&
+ git clone --filter=blob:none "file://$(pwd)/server" repo &&
+ git -C repo config promisor.quiet "true" &&
+
+ test_terminal git -C repo cat-file -p foo:foo.t 2>err &&
+
+ # Ensure that no progress messages are written
+ ! grep "Receiving objects" err
+'
+
+test_expect_success TTY 'promisor.quiet=unconfigured shows progress messages' '
+ rm -rf repo &&
+ git clone --filter=blob:none "file://$(pwd)/server" repo &&
+
+ test_terminal git -C repo cat-file -p foo:foo.t 2>err &&
+
+ # Ensure that progress messages are written
+ grep "Receiving objects" err
+'
+
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
diff --git a/t/t0600-reffiles-backend.sh b/t/t0600-reffiles-backend.sh
index 92f570313d..b2a771ff2b 100755
--- a/t/t0600-reffiles-backend.sh
+++ b/t/t0600-reffiles-backend.sh
@@ -468,4 +468,36 @@ test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' '
esac
'
+test_expect_success SYMLINKS 'symref transaction supports symlinks' '
+ test_when_finished "git symbolic-ref -d TEST_SYMREF_HEAD" &&
+ git update-ref refs/heads/new @ &&
+ test_config core.prefersymlinkrefs true &&
+ cat >stdin <<-EOF &&
+ start
+ symref-create TEST_SYMREF_HEAD refs/heads/new
+ prepare
+ commit
+ EOF
+ git update-ref --no-deref --stdin <stdin &&
+ test_path_is_symlink .git/TEST_SYMREF_HEAD &&
+ test "$(test_readlink .git/TEST_SYMREF_HEAD)" = refs/heads/new
+'
+
+test_expect_success 'symref transaction supports false symlink config' '
+ test_when_finished "git symbolic-ref -d TEST_SYMREF_HEAD" &&
+ git update-ref refs/heads/new @ &&
+ test_config core.prefersymlinkrefs false &&
+ cat >stdin <<-EOF &&
+ start
+ symref-create TEST_SYMREF_HEAD refs/heads/new
+ prepare
+ commit
+ EOF
+ git update-ref --no-deref --stdin <stdin &&
+ test_path_is_file .git/TEST_SYMREF_HEAD &&
+ git symbolic-ref TEST_SYMREF_HEAD >actual &&
+ echo refs/heads/new >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index e12b221972..ff9bf213aa 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -1294,4 +1294,34 @@ test_expect_success 'batch-command flush without --buffer' '
grep "^fatal:.*flush is only for --buffer mode.*" err
'
+script='
+use warnings;
+use strict;
+use IPC::Open2;
+my ($opt, $oid, $expect, @pfx) = @ARGV;
+my @cmd = (qw(git cat-file), $opt);
+my $pid = open2(my $out, my $in, @cmd) or die "open2: @cmd";
+print $in @pfx, $oid, "\n" or die "print $!";
+my $rvec = "";
+vec($rvec, fileno($out), 1) = 1;
+select($rvec, undef, undef, 30) or die "no response to `@pfx $oid` from @cmd";
+my $info = <$out>;
+chop($info) eq "\n" or die "no LF";
+$info eq $expect or die "`$info` != `$expect`";
+close $in or die "close in $!";
+close $out or die "close out $!";
+waitpid $pid, 0;
+$? == 0 or die "\$?=$?";
+'
+
+expect="$hello_oid blob $hello_size"
+
+test_expect_success PERL '--batch-check is unbuffered by default' '
+ perl -e "$script" -- --batch-check $hello_oid "$expect"
+'
+
+test_expect_success PERL '--batch-command info is unbuffered by default' '
+ perl -e "$script" -- --batch-command $hello_oid "$expect" "info "
+'
+
test_done
diff --git a/t/t1090-sparse-checkout-scope.sh b/t/t1090-sparse-checkout-scope.sh
index 3a14218b24..da0e7714d5 100755
--- a/t/t1090-sparse-checkout-scope.sh
+++ b/t/t1090-sparse-checkout-scope.sh
@@ -6,6 +6,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index ab3a105fff..8c5cd651b4 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -8,6 +8,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
GIT_TEST_SPLIT_INDEX=false
export GIT_TEST_SPLIT_INDEX
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
list_files() {
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index bbee2783ab..eb1691860d 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -892,17 +892,23 @@ test_expect_success 'stdin update/create/verify combination works' '
'
test_expect_success 'stdin verify succeeds for correct value' '
+ test-tool ref-store main for-each-reflog-ent $m >before &&
git rev-parse $m >expect &&
echo "verify $m $m" >stdin &&
git update-ref --stdin <stdin &&
git rev-parse $m >actual &&
- test_cmp expect actual
+ test_cmp expect actual &&
+ test-tool ref-store main for-each-reflog-ent $m >after &&
+ test_cmp before after
'
test_expect_success 'stdin verify succeeds for missing reference' '
+ test-tool ref-store main for-each-reflog-ent $m >before &&
echo "verify refs/heads/missing $Z" >stdin &&
git update-ref --stdin <stdin &&
- test_must_fail git rev-parse --verify -q refs/heads/missing
+ test_must_fail git rev-parse --verify -q refs/heads/missing &&
+ test-tool ref-store main for-each-reflog-ent $m >after &&
+ test_cmp before after
'
test_expect_success 'stdin verify treats no value as missing' '
@@ -1356,6 +1362,7 @@ test_expect_success 'fails with duplicate HEAD update' '
'
test_expect_success 'fails with duplicate ref update via symref' '
+ test_when_finished "git symbolic-ref -d refs/heads/symref2" &&
git branch target2 $A &&
git symbolic-ref refs/heads/symref2 refs/heads/target2 &&
cat >stdin <<-EOF &&
@@ -1643,4 +1650,423 @@ test_expect_success PIPE 'transaction flushes status updates' '
test_cmp expected actual
'
+format_command () {
+ if test "$1" = "-z"
+ then
+ shift
+ printf "$F" "$@"
+ else
+ echo "$@"
+ fi
+}
+
+for type in "" "-z"
+do
+
+ test_expect_success "stdin $type symref-verify fails without --no-deref" '
+ git symbolic-ref refs/heads/symref $a &&
+ format_command $type "symref-verify refs/heads/symref" "$a" >stdin &&
+ test_must_fail git update-ref --stdin $type <stdin 2>err &&
+ grep "fatal: symref-verify: cannot operate with deref mode" err
+ '
+
+ test_expect_success "stdin $type symref-verify fails with too many arguments" '
+ format_command $type "symref-verify refs/heads/symref" "$a" "$a" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err &&
+ if test "$type" = "-z"
+ then
+ grep "fatal: unknown command: $a" err
+ else
+ grep "fatal: symref-verify refs/heads/symref: extra input: $a" err
+ fi
+ '
+
+ test_expect_success "stdin $type symref-verify succeeds for correct value" '
+ git symbolic-ref refs/heads/symref >expect &&
+ test-tool ref-store main for-each-reflog-ent refs/heads/symref >before &&
+ format_command $type "symref-verify refs/heads/symref" "$a" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual &&
+ test-tool ref-store main for-each-reflog-ent refs/heads/symref >after &&
+ test_cmp before after
+ '
+
+ test_expect_success "stdin $type symref-verify fails with no value" '
+ git symbolic-ref refs/heads/symref >expect &&
+ format_command $type "symref-verify refs/heads/symref" "" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin
+ '
+
+ test_expect_success "stdin $type symref-verify succeeds for dangling reference" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref2" &&
+ test_must_fail git symbolic-ref refs/heads/nonexistent &&
+ git symbolic-ref refs/heads/symref2 refs/heads/nonexistent &&
+ format_command $type "symref-verify refs/heads/symref2" "refs/heads/nonexistent" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin
+ '
+
+ test_expect_success "stdin $type symref-verify fails for missing reference" '
+ test-tool ref-store main for-each-reflog-ent refs/heads/symref >before &&
+ format_command $type "symref-verify refs/heads/missing" "refs/heads/unknown" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err &&
+ grep "fatal: cannot lock ref ${SQ}refs/heads/missing${SQ}: unable to resolve reference ${SQ}refs/heads/missing${SQ}" err &&
+ test_must_fail git rev-parse --verify -q refs/heads/missing &&
+ test-tool ref-store main for-each-reflog-ent refs/heads/symref >after &&
+ test_cmp before after
+ '
+
+ test_expect_success "stdin $type symref-verify fails for wrong value" '
+ git symbolic-ref refs/heads/symref >expect &&
+ format_command $type "symref-verify refs/heads/symref" "$b" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-verify fails for mistaken null value" '
+ git symbolic-ref refs/heads/symref >expect &&
+ format_command $type "symref-verify refs/heads/symref" "$Z" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-delete fails without --no-deref" '
+ git symbolic-ref refs/heads/symref $a &&
+ format_command $type "symref-delete refs/heads/symref" "$a" >stdin &&
+ test_must_fail git update-ref --stdin $type <stdin 2>err &&
+ grep "fatal: symref-delete: cannot operate with deref mode" err
+ '
+
+ test_expect_success "stdin $type symref-delete fails with no ref" '
+ format_command $type "symref-delete " >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err &&
+ grep "fatal: symref-delete: missing <ref>" err
+ '
+
+ test_expect_success "stdin $type symref-delete fails deleting regular ref" '
+ test_when_finished "git update-ref -d refs/heads/regularref" &&
+ git update-ref refs/heads/regularref $a &&
+ format_command $type "symref-delete refs/heads/regularref" "$a" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err &&
+ grep "fatal: cannot lock ref ${SQ}refs/heads/regularref${SQ}: expected symref with target ${SQ}$a${SQ}: but is a regular ref" err
+ '
+
+ test_expect_success "stdin $type symref-delete fails with too many arguments" '
+ format_command $type "symref-delete refs/heads/symref" "$a" "$a" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err &&
+ if test "$type" = "-z"
+ then
+ grep "fatal: unknown command: $a" err
+ else
+ grep "fatal: symref-delete refs/heads/symref: extra input: $a" err
+ fi
+ '
+
+ test_expect_success "stdin $type symref-delete fails with wrong old value" '
+ format_command $type "symref-delete refs/heads/symref" "$m" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err &&
+ grep "fatal: verifying symref target: ${SQ}refs/heads/symref${SQ}: is at $a but expected refs/heads/main" err &&
+ git symbolic-ref refs/heads/symref >expect &&
+ echo $a >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-delete works with right old value" '
+ format_command $type "symref-delete refs/heads/symref" "$a" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ test_must_fail git rev-parse --verify -q refs/heads/symref
+ '
+
+ test_expect_success "stdin $type symref-delete works with empty old value" '
+ git symbolic-ref refs/heads/symref $a >stdin &&
+ format_command $type "symref-delete refs/heads/symref" "" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ test_must_fail git rev-parse --verify -q $b
+ '
+
+ test_expect_success "stdin $type symref-delete succeeds for dangling reference" '
+ test_must_fail git symbolic-ref refs/heads/nonexistent &&
+ git symbolic-ref refs/heads/symref2 refs/heads/nonexistent &&
+ format_command $type "symref-delete refs/heads/symref2" "refs/heads/nonexistent" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ test_must_fail git symbolic-ref -d refs/heads/symref2
+ '
+
+ test_expect_success "stdin $type symref-delete deletes regular ref without target" '
+ git update-ref refs/heads/regularref $a &&
+ format_command $type "symref-delete refs/heads/regularref" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin
+ '
+
+ test_expect_success "stdin $type symref-create fails with too many arguments" '
+ format_command $type "symref-create refs/heads/symref" "$a" "$a" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err &&
+ if test "$type" = "-z"
+ then
+ grep "fatal: unknown command: $a" err
+ else
+ grep "fatal: symref-create refs/heads/symref: extra input: $a" err
+ fi
+ '
+
+ test_expect_success "stdin $type symref-create fails with no target" '
+ format_command $type "symref-create refs/heads/symref" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin
+ '
+
+ test_expect_success "stdin $type symref-create fails with empty target" '
+ format_command $type "symref-create refs/heads/symref" "" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin
+ '
+
+ test_expect_success "stdin $type symref-create works" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ format_command $type "symref-create refs/heads/symref" "$a" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ git symbolic-ref refs/heads/symref >expect &&
+ echo $a >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-create works with --no-deref" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ format_command $type "symref-create refs/heads/symref" "$a" &&
+ git update-ref --stdin $type <stdin 2>err
+ '
+
+ test_expect_success "stdin $type create dangling symref ref works" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ format_command $type "symref-create refs/heads/symref" "refs/heads/unkown" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ git symbolic-ref refs/heads/symref >expect &&
+ echo refs/heads/unkown >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-create does not create reflogs by default" '
+ test_when_finished "git symbolic-ref -d refs/symref" &&
+ format_command $type "symref-create refs/symref" "$a" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ git symbolic-ref refs/symref >expect &&
+ echo $a >actual &&
+ test_cmp expect actual &&
+ test_must_fail git reflog exists refs/symref
+ '
+
+ test_expect_success "stdin $type symref-create reflogs with --create-reflog" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ format_command $type "symref-create refs/heads/symref" "$a" >stdin &&
+ git update-ref --create-reflog --stdin $type --no-deref <stdin &&
+ git symbolic-ref refs/heads/symref >expect &&
+ echo $a >actual &&
+ test_cmp expect actual &&
+ git reflog exists refs/heads/symref
+ '
+
+ test_expect_success "stdin $type symref-update fails with too many arguments" '
+ format_command $type "symref-update refs/heads/symref" "$a" "ref" "$a" "$a" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err &&
+ if test "$type" = "-z"
+ then
+ grep "fatal: unknown command: $a" err
+ else
+ grep "fatal: symref-update refs/heads/symref: extra input: $a" err
+ fi
+ '
+
+ test_expect_success "stdin $type symref-update fails with wrong old value argument" '
+ format_command $type "symref-update refs/heads/symref" "$a" "foo" "$a" "$a" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err &&
+ grep "fatal: symref-update refs/heads/symref: invalid arg ${SQ}foo${SQ} for old value" err
+ '
+
+ test_expect_success "stdin $type symref-update creates with zero old value" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ format_command $type "symref-update refs/heads/symref" "$a" "oid" "$Z" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ echo $a >expect &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update creates with no old value" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ format_command $type "symref-update refs/heads/symref" "$a" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ echo $a >expect &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update creates dangling" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ test_must_fail git rev-parse refs/heads/nonexistent &&
+ format_command $type "symref-update refs/heads/symref" "refs/heads/nonexistent" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ echo refs/heads/nonexistent >expect &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update fails with wrong old value" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ git symbolic-ref refs/heads/symref $a &&
+ format_command $type "symref-update refs/heads/symref" "$m" "ref" "$b" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err &&
+ grep "fatal: verifying symref target: ${SQ}refs/heads/symref${SQ}: is at $a but expected $b" err &&
+ test_must_fail git rev-parse --verify -q $c
+ '
+
+ test_expect_success "stdin $type symref-update updates dangling ref" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ test_must_fail git rev-parse refs/heads/nonexistent &&
+ git symbolic-ref refs/heads/symref refs/heads/nonexistent &&
+ format_command $type "symref-update refs/heads/symref" "$a" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ echo $a >expect &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update updates dangling ref with old value" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ test_must_fail git rev-parse refs/heads/nonexistent &&
+ git symbolic-ref refs/heads/symref refs/heads/nonexistent &&
+ format_command $type "symref-update refs/heads/symref" "$a" "ref" "refs/heads/nonexistent" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ echo $a >expect &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update fails update dangling ref with wrong old value" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ test_must_fail git rev-parse refs/heads/nonexistent &&
+ git symbolic-ref refs/heads/symref refs/heads/nonexistent &&
+ format_command $type "symref-update refs/heads/symref" "$a" "ref" "refs/heads/wrongref" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin &&
+ echo refs/heads/nonexistent >expect &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update works with right old value" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ git symbolic-ref refs/heads/symref $a &&
+ format_command $type "symref-update refs/heads/symref" "$m" "ref" "$a" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ echo $m >expect &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update works with no old value" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ git symbolic-ref refs/heads/symref $a &&
+ format_command $type "symref-update refs/heads/symref" "$m" >stdin &&
+ git update-ref --stdin $type --no-deref <stdin &&
+ echo $m >expect &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update fails with empty old ref-target" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ git symbolic-ref refs/heads/symref $a &&
+ format_command $type "symref-update refs/heads/symref" "$m" "ref" "" >stdin &&
+ test_must_fail git update-ref --stdin $type --no-deref <stdin &&
+ echo $a >expect &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update creates (with deref)" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ format_command $type "symref-update refs/heads/symref" "$a" >stdin &&
+ git update-ref --stdin $type <stdin &&
+ echo $a >expect &&
+ git symbolic-ref --no-recurse refs/heads/symref >actual &&
+ test_cmp expect actual &&
+ test-tool ref-store main for-each-reflog-ent refs/heads/symref >actual &&
+ grep "$Z $(git rev-parse $a)" actual
+ '
+
+ test_expect_success "stdin $type symref-update regular ref to symref with correct old-oid" '
+ test_when_finished "git symbolic-ref -d --no-recurse refs/heads/regularref" &&
+ git update-ref --no-deref refs/heads/regularref $a &&
+ format_command $type "symref-update refs/heads/regularref" "$a" "oid" "$(git rev-parse $a)" >stdin &&
+ git update-ref --stdin $type <stdin &&
+ echo $a >expect &&
+ git symbolic-ref --no-recurse refs/heads/regularref >actual &&
+ test_cmp expect actual &&
+ test-tool ref-store main for-each-reflog-ent refs/heads/regularref >actual &&
+ grep "$(git rev-parse $a) $(git rev-parse $a)" actual
+ '
+
+ test_expect_success "stdin $type symref-update regular ref to symref fails with wrong old-oid" '
+ test_when_finished "git update-ref -d refs/heads/regularref" &&
+ git update-ref --no-deref refs/heads/regularref $a &&
+ format_command $type "symref-update refs/heads/regularref" "$a" "oid" "$(git rev-parse refs/heads/target2)" >stdin &&
+ test_must_fail git update-ref --stdin $type <stdin 2>err &&
+ grep "fatal: cannot lock ref ${SQ}refs/heads/regularref${SQ}: is at $(git rev-parse $a) but expected $(git rev-parse refs/heads/target2)" err &&
+ echo $(git rev-parse $a) >expect &&
+ git rev-parse refs/heads/regularref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update regular ref to symref fails with invalid old-oid" '
+ test_when_finished "git update-ref -d refs/heads/regularref" &&
+ git update-ref --no-deref refs/heads/regularref $a &&
+ format_command $type "symref-update refs/heads/regularref" "$a" "oid" "not-a-ref-oid" >stdin &&
+ test_must_fail git update-ref --stdin $type <stdin 2>err &&
+ grep "fatal: symref-update refs/heads/regularref: invalid oid: not-a-ref-oid" err &&
+ echo $(git rev-parse $a) >expect &&
+ git rev-parse refs/heads/regularref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update existing symref with zero old-oid" '
+ test_when_finished "git symbolic-ref -d --no-recurse refs/heads/symref" &&
+ git symbolic-ref refs/heads/symref refs/heads/target2 &&
+ format_command $type "symref-update refs/heads/symref" "$a" "oid" "$Z" >stdin &&
+ test_must_fail git update-ref --stdin $type <stdin 2>err &&
+ grep "fatal: cannot lock ref ${SQ}refs/heads/symref${SQ}: reference already exists" err &&
+ echo refs/heads/target2 >expect &&
+ git symbolic-ref refs/heads/symref >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "stdin $type symref-update regular ref to symref (with deref)" '
+ test_when_finished "git symbolic-ref -d refs/heads/symref" &&
+ test_when_finished "git update-ref -d --no-deref refs/heads/symref2" &&
+ git update-ref refs/heads/symref2 $a &&
+ git symbolic-ref --no-recurse refs/heads/symref refs/heads/symref2 &&
+ format_command $type "symref-update refs/heads/symref" "$a" >stdin &&
+ git update-ref $type --stdin <stdin &&
+ echo $a >expect &&
+ git symbolic-ref --no-recurse refs/heads/symref2 >actual &&
+ test_cmp expect actual &&
+ echo refs/heads/symref2 >expect &&
+ git symbolic-ref --no-recurse refs/heads/symref >actual &&
+ test_cmp expect actual &&
+ test-tool ref-store main for-each-reflog-ent refs/heads/symref >actual &&
+ grep "$(git rev-parse $a) $(git rev-parse $a)" actual
+ '
+
+ test_expect_success "stdin $type symref-update regular ref to symref" '
+ test_when_finished "git symbolic-ref -d --no-recurse refs/heads/regularref" &&
+ git update-ref --no-deref refs/heads/regularref $a &&
+ format_command $type "symref-update refs/heads/regularref" "$a" >stdin &&
+ git update-ref $type --stdin <stdin &&
+ echo $a >expect &&
+ git symbolic-ref --no-recurse refs/heads/regularref >actual &&
+ test_cmp expect actual &&
+ test-tool ref-store main for-each-reflog-ent refs/heads/regularref >actual &&
+ grep "$(git rev-parse $a) $(git rev-parse $a)" actual
+ '
+
+done
+
test_done
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
index 33fb7a38ff..403f6b8f7d 100755
--- a/t/t1403-show-ref.sh
+++ b/t/t1403-show-ref.sh
@@ -121,13 +121,13 @@ test_expect_success 'show-ref -d' '
'
-test_expect_success 'show-ref --heads, --tags, --head, pattern' '
+test_expect_success 'show-ref --branches, --tags, --head, pattern' '
for branch in B main side
do
echo $(git rev-parse refs/heads/$branch) refs/heads/$branch || return 1
- done >expect.heads &&
- git show-ref --heads >actual &&
- test_cmp expect.heads actual &&
+ done >expect.branches &&
+ git show-ref --branches >actual &&
+ test_cmp expect.branches actual &&
for tag in A B C
do
@@ -136,15 +136,15 @@ test_expect_success 'show-ref --heads, --tags, --head, pattern' '
git show-ref --tags >actual &&
test_cmp expect.tags actual &&
- cat expect.heads expect.tags >expect &&
- git show-ref --heads --tags >actual &&
+ cat expect.branches expect.tags >expect &&
+ git show-ref --branches --tags >actual &&
test_cmp expect actual &&
{
echo $(git rev-parse HEAD) HEAD &&
- cat expect.heads expect.tags
+ cat expect.branches expect.tags
} >expect &&
- git show-ref --heads --tags --head >actual &&
+ git show-ref --branches --tags --head >actual &&
test_cmp expect actual &&
{
@@ -165,6 +165,14 @@ test_expect_success 'show-ref --heads, --tags, --head, pattern' '
test_cmp expect actual
'
+test_expect_success 'show-ref --heads is deprecated and hidden' '
+ test_expect_code 129 git show-ref -h >short-help &&
+ test_grep ! -e --heads short-help &&
+ git show-ref --heads >actual 2>warning &&
+ test_grep ! deprecated warning &&
+ test_cmp expect.branches actual
+'
+
test_expect_success 'show-ref --verify HEAD' '
echo $(git rev-parse HEAD) HEAD >expect &&
git show-ref --verify HEAD >actual &&
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 067fd57290..5a812ca3c0 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -157,4 +157,58 @@ test_expect_success 'hook captures git-symbolic-ref updates' '
test_cmp expect actual
'
+test_expect_success 'hook gets all queued symref updates' '
+ test_when_finished "rm actual" &&
+
+ git update-ref refs/heads/branch $POST_OID &&
+ git symbolic-ref refs/heads/symref refs/heads/main &&
+ git symbolic-ref refs/heads/symrefd refs/heads/main &&
+ git symbolic-ref refs/heads/symrefu refs/heads/main &&
+
+ test_hook reference-transaction <<-\EOF &&
+ echo "$*" >>actual
+ while read -r line
+ do
+ printf "%s\n" "$line"
+ done >>actual
+ EOF
+
+ # In the files backend, "delete" also triggers an additional transaction
+ # update on the packed-refs backend, which constitutes additional reflog
+ # entries.
+ if test_have_prereq REFFILES
+ then
+ cat >expect <<-EOF
+ aborted
+ $ZERO_OID $ZERO_OID refs/heads/symrefd
+ EOF
+ else
+ >expect
+ fi &&
+
+ cat >>expect <<-EOF &&
+ prepared
+ ref:refs/heads/main $ZERO_OID refs/heads/symref
+ ref:refs/heads/main $ZERO_OID refs/heads/symrefd
+ $ZERO_OID ref:refs/heads/main refs/heads/symrefc
+ ref:refs/heads/main ref:refs/heads/branch refs/heads/symrefu
+ committed
+ ref:refs/heads/main $ZERO_OID refs/heads/symref
+ ref:refs/heads/main $ZERO_OID refs/heads/symrefd
+ $ZERO_OID ref:refs/heads/main refs/heads/symrefc
+ ref:refs/heads/main ref:refs/heads/branch refs/heads/symrefu
+ EOF
+
+ git update-ref --no-deref --stdin <<-EOF &&
+ start
+ symref-verify refs/heads/symref refs/heads/main
+ symref-delete refs/heads/symrefd refs/heads/main
+ symref-create refs/heads/symrefc refs/heads/main
+ symref-update refs/heads/symrefu refs/heads/branch ref refs/heads/main
+ prepare
+ commit
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh
new file mode 100755
index 0000000000..f7c0783d30
--- /dev/null
+++ b/t/t1460-refs-migrate.sh
@@ -0,0 +1,243 @@
+#!/bin/sh
+
+test_description='migration of ref storage backends'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_migration () {
+ git -C "$1" for-each-ref --include-root-refs \
+ --format='%(refname) %(objectname) %(symref)' >expect &&
+ git -C "$1" refs migrate --ref-format="$2" &&
+ git -C "$1" for-each-ref --include-root-refs \
+ --format='%(refname) %(objectname) %(symref)' >actual &&
+ test_cmp expect actual &&
+
+ git -C "$1" rev-parse --show-ref-format >actual &&
+ echo "$2" >expect &&
+ test_cmp expect actual
+}
+
+test_expect_success 'setup' '
+ rm -rf .git &&
+ # The migration does not yet support reflogs.
+ git config --global core.logAllRefUpdates false
+'
+
+test_expect_success "superfluous arguments" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_must_fail git -C repo refs migrate foo 2>err &&
+ cat >expect <<-EOF &&
+ usage: too many arguments
+ EOF
+ test_cmp expect err
+'
+
+test_expect_success "missing ref storage format" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_must_fail git -C repo refs migrate 2>err &&
+ cat >expect <<-EOF &&
+ usage: missing --ref-format=<format>
+ EOF
+ test_cmp expect err
+'
+
+test_expect_success "unknown ref storage format" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_must_fail git -C repo refs migrate \
+ --ref-format=unknown 2>err &&
+ cat >expect <<-EOF &&
+ error: unknown ref storage format ${SQ}unknown${SQ}
+ EOF
+ test_cmp expect err
+'
+
+ref_formats="files reftable"
+for from_format in $ref_formats
+do
+ for to_format in $ref_formats
+ do
+ if test "$from_format" = "$to_format"
+ then
+ continue
+ fi
+
+ test_expect_success "$from_format: migration to same format fails" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ test_must_fail git -C repo refs migrate \
+ --ref-format=$from_format 2>err &&
+ cat >expect <<-EOF &&
+ error: repository already uses ${SQ}$from_format${SQ} format
+ EOF
+ test_cmp expect err
+ '
+
+ test_expect_success "$from_format -> $to_format: migration with reflog fails" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ test_config -C repo core.logAllRefUpdates true &&
+ test_commit -C repo logged &&
+ test_must_fail git -C repo refs migrate \
+ --ref-format=$to_format 2>err &&
+ cat >expect <<-EOF &&
+ error: migrating reflogs is not supported yet
+ EOF
+ test_cmp expect err
+ '
+
+ test_expect_success "$from_format -> $to_format: migration with worktree fails" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ git -C repo worktree add wt &&
+ test_must_fail git -C repo refs migrate \
+ --ref-format=$to_format 2>err &&
+ cat >expect <<-EOF &&
+ error: migrating repositories with worktrees is not supported yet
+ EOF
+ test_cmp expect err
+ '
+
+ test_expect_success "$from_format -> $to_format: unborn HEAD" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ test_migration repo "$to_format"
+ '
+
+ test_expect_success "$from_format -> $to_format: single ref" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ test_commit -C repo initial &&
+ test_migration repo "$to_format"
+ '
+
+ test_expect_success "$from_format -> $to_format: bare repository" '
+ test_when_finished "rm -rf repo repo.git" &&
+ git init --ref-format=$from_format repo &&
+ test_commit -C repo initial &&
+ git clone --ref-format=$from_format --mirror repo repo.git &&
+ test_migration repo.git "$to_format"
+ '
+
+ test_expect_success "$from_format -> $to_format: dangling symref" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ test_commit -C repo initial &&
+ git -C repo symbolic-ref BROKEN_HEAD refs/heads/nonexistent &&
+ test_migration repo "$to_format" &&
+ echo refs/heads/nonexistent >expect &&
+ git -C repo symbolic-ref BROKEN_HEAD >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "$from_format -> $to_format: broken ref" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ test_commit -C repo initial &&
+ test-tool -C repo ref-store main update-ref "" refs/heads/broken \
+ "$(test_oid 001)" "$ZERO_OID" REF_SKIP_CREATE_REFLOG,REF_SKIP_OID_VERIFICATION &&
+ test_migration repo "$to_format" &&
+ test_oid 001 >expect &&
+ git -C repo rev-parse refs/heads/broken >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "$from_format -> $to_format: pseudo-refs" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ test_commit -C repo initial &&
+ git -C repo update-ref FOO_HEAD HEAD &&
+ test_migration repo "$to_format"
+ '
+
+ test_expect_success "$from_format -> $to_format: special refs are left alone" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ test_commit -C repo initial &&
+ git -C repo rev-parse HEAD >repo/.git/MERGE_HEAD &&
+ git -C repo rev-parse MERGE_HEAD &&
+ test_migration repo "$to_format" &&
+ test_path_is_file repo/.git/MERGE_HEAD
+ '
+
+ test_expect_success "$from_format -> $to_format: a bunch of refs" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+
+ test_commit -C repo initial &&
+ cat >input <<-EOF &&
+ create FOO_HEAD HEAD
+ create refs/heads/branch-1 HEAD
+ create refs/heads/branch-2 HEAD
+ create refs/heads/branch-3 HEAD
+ create refs/heads/branch-4 HEAD
+ create refs/tags/tag-1 HEAD
+ create refs/tags/tag-2 HEAD
+ EOF
+ git -C repo update-ref --stdin <input &&
+ test_migration repo "$to_format"
+ '
+
+ test_expect_success "$from_format -> $to_format: dry-run migration does not modify repository" '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=$from_format repo &&
+ test_commit -C repo initial &&
+ git -C repo refs migrate --dry-run \
+ --ref-format=$to_format >output &&
+ grep "Finished dry-run migration of refs" output &&
+ test_path_is_dir repo/.git/ref_migration.* &&
+ echo $from_format >expect &&
+ git -C repo rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+ '
+ done
+done
+
+test_expect_success 'migrating from files format deletes backend files' '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=files repo &&
+ test_commit -C repo first &&
+ git -C repo pack-refs --all &&
+ test_commit -C repo second &&
+ git -C repo update-ref ORIG_HEAD HEAD &&
+ git -C repo rev-parse HEAD >repo/.git/FETCH_HEAD &&
+
+ test_path_is_file repo/.git/HEAD &&
+ test_path_is_file repo/.git/ORIG_HEAD &&
+ test_path_is_file repo/.git/refs/heads/main &&
+ test_path_is_file repo/.git/packed-refs &&
+
+ test_migration repo reftable &&
+
+ echo "ref: refs/heads/.invalid" >expect &&
+ test_cmp expect repo/.git/HEAD &&
+ echo "this repository uses the reftable format" >expect &&
+ test_cmp expect repo/.git/refs/heads &&
+ test_path_is_file repo/.git/FETCH_HEAD &&
+ test_path_is_missing repo/.git/ORIG_HEAD &&
+ test_path_is_missing repo/.git/refs/heads/main &&
+ test_path_is_missing repo/.git/logs &&
+ test_path_is_missing repo/.git/packed-refs
+'
+
+test_expect_success 'migrating from reftable format deletes backend files' '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=reftable repo &&
+ test_commit -C repo first &&
+
+ test_path_is_dir repo/.git/reftable &&
+ test_migration repo files &&
+
+ test_path_is_missing repo/.git/reftable &&
+ echo "ref: refs/heads/main" >expect &&
+ test_cmp expect repo/.git/HEAD &&
+ test_path_is_file repo/.git/refs/heads/main
+'
+
+test_done
diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh
index 557808ffa7..990a036582 100755
--- a/t/t1517-outside-repo.sh
+++ b/t/t1517-outside-repo.sh
@@ -56,4 +56,56 @@ test_expect_success 'grep outside repository' '
test_cmp expect actual
'
+test_expect_success 'imap-send outside repository' '
+ test_config_global imap.host imaps://localhost &&
+ test_config_global imap.folder Drafts &&
+
+ echo nothing to send >expect &&
+ test_must_fail git imap-send -v </dev/null 2>actual &&
+ test_cmp expect actual &&
+
+ (
+ cd non-repo &&
+ test_must_fail git imap-send -v </dev/null 2>../actual
+ ) &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check-ref-format outside repository' '
+ git check-ref-format --branch refs/heads/xyzzy >expect &&
+ nongit git check-ref-format --branch refs/heads/xyzzy >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'diff outside repository' '
+ echo one >one &&
+ echo two >two &&
+ test_must_fail git diff --no-index one two >expect.raw &&
+ (
+ cd non-repo &&
+ cp ../one . &&
+ cp ../two . &&
+ test_must_fail git diff one two >../actual.raw
+ ) &&
+ # outside repository diff falls back to SHA-1 but
+ # GIT_DEFAULT_HASH may be set to sha256 on the in-repo side.
+ sed -e "/^index /d" expect.raw >expect &&
+ sed -e "/^index /d" actual.raw >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stripspace outside repository' '
+ nongit git stripspace -s </dev/null
+'
+
+test_expect_success 'remote-http outside repository' '
+ test_must_fail git remote-http 2>actual &&
+ test_grep "^error: remote-curl" actual &&
+ (
+ cd non-repo &&
+ test_must_fail git remote-http 2>../actual
+ ) &&
+ test_grep "^error: remote-curl" actual
+'
+
test_done
diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh
index 7b05bf3961..a767c3520e 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -545,6 +545,20 @@ do
'
done
+test_expect_success "--range-diff implies --cover-letter for multi-patch series" '
+ test_when_finished "rm -f v2-000?-*" &&
+ git format-patch -v2 --range-diff=topic main..unmodified &&
+ test_grep "^Range-diff against v1:$" v2-0000-cover-letter.patch
+'
+
+test_expect_success "explicit --no-cover-letter defeats implied --cover-letter" '
+ test_when_finished "rm -f v2-000?-*" &&
+ test_must_fail git format-patch --no-cover-letter \
+ -v2 --range-diff=topic main..unmodified &&
+ test_must_fail git -c format.coverLetter=no format-patch \
+ -v2 --range-diff=topic main..unmodified
+'
+
test_expect_success 'format-patch --range-diff as commentary' '
git format-patch --range-diff=HEAD~1 HEAD~1 >actual &&
test_when_finished "rm 0001-*" &&
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index d1bead61fa..f92baad138 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -2215,6 +2215,51 @@ test_expect_success 'bad labels and refs rejected when parsing todo list' '
test_path_is_missing execed
'
+test_expect_success 'non-merge commands reject merge commits' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git checkout E &&
+ git merge I &&
+ oid=$(git rev-parse HEAD) &&
+ cat >todo <<-EOF &&
+ pick $oid
+ reword $oid
+ edit $oid
+ fixup $oid
+ squash $oid
+ EOF
+ (
+ set_replace_editor todo &&
+ test_must_fail git rebase -i HEAD 2>actual
+ ) &&
+ cat >expect <<-EOF &&
+ error: ${SQ}pick${SQ} does not accept merge commits
+ hint: ${SQ}pick${SQ} does not take a merge commit. If you wanted to
+ hint: replay the merge, use ${SQ}merge -C${SQ} on the commit.
+ hint: Disable this message with "git config advice.rebaseTodoError false"
+ error: invalid line 1: pick $oid
+ error: ${SQ}reword${SQ} does not accept merge commits
+ hint: ${SQ}reword${SQ} does not take a merge commit. If you wanted to
+ hint: replay the merge and reword the commit message, use
+ hint: ${SQ}merge -c${SQ} on the commit
+ hint: Disable this message with "git config advice.rebaseTodoError false"
+ error: invalid line 2: reword $oid
+ error: ${SQ}edit${SQ} does not accept merge commits
+ hint: ${SQ}edit${SQ} does not take a merge commit. If you wanted to
+ hint: replay the merge, use ${SQ}merge -C${SQ} on the commit, and then
+ hint: ${SQ}break${SQ} to give the control back to you so that you can
+ hint: do ${SQ}git commit --amend && git rebase --continue${SQ}.
+ hint: Disable this message with "git config advice.rebaseTodoError false"
+ error: invalid line 3: edit $oid
+ error: cannot squash merge commit into another commit
+ error: invalid line 4: fixup $oid
+ error: cannot squash merge commit into another commit
+ error: invalid line 5: squash $oid
+ You can fix this with ${SQ}git rebase --edit-todo${SQ} and then run ${SQ}git rebase --continue${SQ}.
+ Or you can abort the rebase with ${SQ}git rebase --abort${SQ}.
+ EOF
+ test_cmp expect actual
+'
+
# This must be the last test in this file
test_expect_success '$EDITOR and friends are unchanged' '
test_editor_unchanged
diff --git a/t/t3602-rm-sparse-checkout.sh b/t/t3602-rm-sparse-checkout.sh
index 08580fd3dc..fcdefba48c 100755
--- a/t/t3602-rm-sparse-checkout.sh
+++ b/t/t3602-rm-sparse-checkout.sh
@@ -2,6 +2,7 @@
test_description='git rm in sparse checked out working trees'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' "
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 6624a4f7c0..5d78868ac1 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -43,21 +43,6 @@ force_color () {
)
}
-test_expect_success 'warn about add.interactive.useBuiltin' '
- cat >expect <<-\EOF &&
- warning: the add.interactive.useBuiltin setting has been removed!
- See its entry in '\''git help config'\'' for details.
- EOF
- echo "No changes." >expect.out &&
-
- for v in = =true =false
- do
- git -c "add.interactive.useBuiltin$v" add -p >out 2>actual &&
- test_cmp expect.out out &&
- test_cmp expect actual || return 1
- done
-'
-
test_expect_success 'unknown command' '
test_when_finished "git reset --hard; rm -f command" &&
echo W >command &&
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index f27d09cfd9..db7b403bc1 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -5,6 +5,7 @@
test_description='commit and log output encodings'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
compare_with () {
diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh
index 4b37f78829..5f0b9afc3f 100755
--- a/t/t3901-i18n-patch.sh
+++ b/t/t3901-i18n-patch.sh
@@ -8,6 +8,7 @@ test_description='i18n settings and format-patch | am pipe'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_encoding () {
diff --git a/t/t3910-mac-os-precompose.sh b/t/t3910-mac-os-precompose.sh
index 898267a6bd..6d5918c8fe 100755
--- a/t/t3910-mac-os-precompose.sh
+++ b/t/t3910-mac-os-precompose.sh
@@ -37,6 +37,27 @@ Alongc=$Alongc$Alongc$Alongc$Alongc$Alongc #50 Byte
Alongc=$Alongc$Alongc$Alongc$Alongc$Alongc #250 Byte
Alongc=$Alongc$AEligatu$AEligatu #254 Byte
+
+ls_files_nfc_nfd () {
+ test_when_finished "git config --global --unset core.precomposeunicode" &&
+ prglbl=$1
+ prlocl=$2
+ aumlcreat=$3
+ aumllist=$4
+ git config --global core.precomposeunicode $prglbl &&
+ (
+ rm -rf .git &&
+ mkdir -p "somewhere/$prglbl/$prlocl/$aumlcreat" &&
+ mypwd=$PWD &&
+ cd "somewhere/$prglbl/$prlocl/$aumlcreat" &&
+ git init &&
+ git config core.precomposeunicode $prlocl &&
+ git --literal-pathspecs ls-files "$mypwd/somewhere/$prglbl/$prlocl/$aumllist" 2>err &&
+ >expected &&
+ test_cmp expected err
+ )
+}
+
test_expect_success "detect if nfd needed" '
precomposeunicode=$(git config core.precomposeunicode) &&
test "$precomposeunicode" = true &&
@@ -211,8 +232,8 @@ test_expect_success "unicode decomposed: git restore -p . " '
'
# Test if the global core.precomposeunicode stops autosensing
-# Must be the last test case
test_expect_success "respect git config --global core.precomposeunicode" '
+ test_when_finished "git config --global --unset core.precomposeunicode" &&
git config --global core.precomposeunicode true &&
rm -rf .git &&
git init &&
@@ -220,4 +241,20 @@ test_expect_success "respect git config --global core.precomposeunicode" '
test "$precomposeunicode" = "true"
'
+test_expect_success "ls-files false false nfd nfd" '
+ ls_files_nfc_nfd false false $Adiarnfd $Adiarnfd
+'
+
+test_expect_success "ls-files false true nfd nfd" '
+ ls_files_nfc_nfd false true $Adiarnfd $Adiarnfd
+'
+
+test_expect_success "ls-files true false nfd nfd" '
+ ls_files_nfc_nfd true false $Adiarnfd $Adiarnfd
+'
+
+test_expect_success "ls-files true true nfd nfd" '
+ ls_files_nfc_nfd true true $Adiarnfd $Adiarnfd
+'
+
test_done
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index ba85b582c5..884f83fb8a 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -820,8 +820,8 @@ test_expect_success 'format-patch --notes --signoff' '
'
test_expect_success 'format-patch notes output control' '
+ test_when_finished "git notes remove HEAD || :" &&
git notes add -m "notes config message" HEAD &&
- test_when_finished git notes remove HEAD &&
git format-patch -1 --stdout >out &&
! grep "notes config message" out &&
@@ -848,10 +848,10 @@ test_expect_success 'format-patch notes output control' '
'
test_expect_success 'format-patch with multiple notes refs' '
+ test_when_finished "git notes --ref note1 remove HEAD;
+ git notes --ref note2 remove HEAD || :" &&
git notes --ref note1 add -m "this is note 1" HEAD &&
- test_when_finished git notes --ref note1 remove HEAD &&
git notes --ref note2 add -m "this is note 2" HEAD &&
- test_when_finished git notes --ref note2 remove HEAD &&
git format-patch -1 --stdout >out &&
! grep "this is note 1" out &&
@@ -892,10 +892,10 @@ test_expect_success 'format-patch with multiple notes refs' '
test_expect_success 'format-patch with multiple notes refs in config' '
test_when_finished "test_unconfig format.notes" &&
+ test_when_finished "git notes --ref note1 remove HEAD;
+ git notes --ref note2 remove HEAD || :" &&
git notes --ref note1 add -m "this is note 1" HEAD &&
- test_when_finished git notes --ref note1 remove HEAD &&
git notes --ref note2 add -m "this is note 2" HEAD &&
- test_when_finished git notes --ref note2 remove HEAD &&
git config format.notes note1 &&
git format-patch -1 --stdout >out &&
@@ -2482,16 +2482,55 @@ test_expect_success 'interdiff: reroll-count with a integer' '
'
test_expect_success 'interdiff: solo-patch' '
- cat >expect <<-\EOF &&
- +fleep
-
- EOF
git format-patch --interdiff=boop~2 -1 boop &&
- test_grep "^Interdiff:$" 0001-fleep.patch &&
- sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual &&
+
+ # remove up to the last "patch" output line,
+ # and remove everything below the signature mark.
+ sed -e "1,/^+fleep\$/d" -e "/^-- /,\$d" 0001-fleep.patch >actual &&
+
+ # fabricate Interdiff output.
+ git diff boop~2 boop >inter &&
+ {
+ echo &&
+ echo "Interdiff:" &&
+ sed -e "s/^/ /" inter
+ } >expect &&
test_cmp expect actual
'
+test_expect_success 'range-diff: solo-patch' '
+ git format-patch --creation-factor=999 \
+ --range-diff=boop~2..boop~1 -1 boop &&
+
+ # remove up to the last "patch" output line,
+ # and remove everything below the signature mark.
+ sed -e "1,/^+fleep\$/d" -e "/^-- /,\$d" 0001-fleep.patch >actual &&
+
+ # fabricate range-diff output.
+ {
+ echo &&
+ echo "Range-diff:" &&
+ git range-diff --creation-factor=999 \
+ boop~2..boop~1 boop~1..boop
+ } >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'interdiff: multi-patch, implicit --cover-letter' '
+ test_when_finished "rm -f v23-0*.patch" &&
+ git format-patch --interdiff=boop~2 -2 -v23 &&
+ test_grep "^Interdiff against v22:$" v23-0000-cover-letter.patch &&
+ test_cmp expect actual
+'
+
+test_expect_success 'interdiff: explicit --no-cover-letter defeats implied --cover-letter' '
+ test_when_finished "rm -f v23-0*.patch" &&
+ test_must_fail git format-patch --no-cover-letter \
+ --interdiff=boop~2 -2 -v23 &&
+ test_must_fail git -c format.coverLetter=no format-patch \
+ --interdiff=boop~2 -2 -v23
+'
+
test_expect_success 'format-patch does not respect diff.noprefix' '
git -c diff.noprefix format-patch -1 --stdout >actual &&
grep "^--- a/blorp" actual
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index b443626afd..851cfe4f32 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -1184,6 +1184,15 @@ test_expect_success 'detect moved code, complete file' '
test_cmp expected actual
'
+test_expect_success '--color-moved with --no-ext-diff' '
+ test_config color.diff.oldMoved "yellow" &&
+ test_config color.diff.newMoved "blue" &&
+ args="--color --color-moved=zebra --no-renames HEAD" &&
+ git diff $args >expect &&
+ git -c diff.external=echo diff --no-ext-diff $args >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'detect malicious moved code, inside file' '
test_config color.diff.oldMoved "normal red" &&
test_config color.diff.newMoved "normal green" &&
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index fdd865f7c3..3baa52a9bf 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -172,6 +172,72 @@ test_expect_success 'no diff with -diff' '
grep Binary out
'
+check_external_diff () {
+ expect_code=$1
+ expect_out=$2
+ expect_err=$3
+ command_code=$4
+ trust_exit_code=$5
+ shift 5
+ options="$@"
+
+ command="echo output; exit $command_code;"
+ desc="external diff '$command' with trustExitCode=$trust_exit_code"
+ with_options="${options:+ with }$options"
+
+ test_expect_success "$desc via attribute$with_options" "
+ test_config diff.foo.command \"$command\" &&
+ test_config diff.foo.trustExitCode $trust_exit_code &&
+ echo \"file diff=foo\" >.gitattributes &&
+ test_expect_code $expect_code git diff $options >out 2>err &&
+ test_cmp $expect_out out &&
+ test_cmp $expect_err err
+ "
+
+ test_expect_success "$desc via diff.external$with_options" "
+ test_config diff.external \"$command\" &&
+ test_config diff.trustExitCode $trust_exit_code &&
+ >.gitattributes &&
+ test_expect_code $expect_code git diff $options >out 2>err &&
+ test_cmp $expect_out out &&
+ test_cmp $expect_err err
+ "
+
+ test_expect_success "$desc via GIT_EXTERNAL_DIFF$with_options" "
+ >.gitattributes &&
+ test_expect_code $expect_code env \
+ GIT_EXTERNAL_DIFF=\"$command\" \
+ GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE=$trust_exit_code \
+ git diff $options >out 2>err &&
+ test_cmp $expect_out out &&
+ test_cmp $expect_err err
+ "
+}
+
+test_expect_success 'setup output files' '
+ : >empty &&
+ echo output >output &&
+ echo "fatal: external diff died, stopping at file" >error
+'
+
+check_external_diff 0 output empty 0 off
+check_external_diff 128 output error 1 off
+check_external_diff 0 output empty 0 on
+check_external_diff 0 output empty 1 on
+check_external_diff 128 output error 2 on
+
+check_external_diff 1 output empty 0 off --exit-code
+check_external_diff 128 output error 1 off --exit-code
+check_external_diff 0 output empty 0 on --exit-code
+check_external_diff 1 output empty 1 on --exit-code
+check_external_diff 128 output error 2 on --exit-code
+
+check_external_diff 1 empty empty 0 off --quiet
+check_external_diff 1 empty empty 1 off --quiet # we don't even call the program
+check_external_diff 0 empty empty 0 on --quiet
+check_external_diff 1 empty empty 1 on --quiet
+check_external_diff 128 empty error 2 on --quiet
+
echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file
test_expect_success 'force diff with "diff"' '
diff --git a/t/t4153-am-resume-override-opts.sh b/t/t4153-am-resume-override-opts.sh
index 6bc377b917..a4d0c03ca6 100755
--- a/t/t4153-am-resume-override-opts.sh
+++ b/t/t4153-am-resume-override-opts.sh
@@ -4,7 +4,6 @@ test_description='git-am command-line options override saved options'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-terminal.sh
format_patch () {
git format-patch --stdout -1 "$1" >"$1".eml
@@ -28,7 +27,12 @@ test_expect_success 'setup' '
format_patch side2
'
-test_expect_success TTY '--3way overrides --no-3way' '
+test_expect_success '--retry fails without in-progress operation' '
+ test_must_fail git am --retry 2>err &&
+ test_grep "operation not in progress" err
+'
+
+test_expect_success '--3way overrides --no-3way' '
rm -fr .git/rebase-apply &&
git reset --hard &&
git checkout renamed-file &&
@@ -41,7 +45,7 @@ test_expect_success TTY '--3way overrides --no-3way' '
# Applying side1 with am --3way will succeed due to the threeway-merge.
# Applying side2 will fail as --3way does not apply to it.
- test_must_fail test_terminal git am --3way </dev/zero &&
+ test_must_fail git am --retry --3way &&
test_path_is_dir .git/rebase-apply &&
test side1 = "$(cat file2)"
'
@@ -85,7 +89,7 @@ test_expect_success '--signoff overrides --no-signoff' '
test $(git cat-file commit HEAD | grep -c "Signed-off-by:") -eq 0
'
-test_expect_success TTY '--reject overrides --no-reject' '
+test_expect_success '--reject overrides --no-reject' '
rm -fr .git/rebase-apply &&
git reset --hard &&
git checkout first &&
@@ -95,7 +99,7 @@ test_expect_success TTY '--reject overrides --no-reject' '
test_path_is_dir .git/rebase-apply &&
test_path_is_missing file.rej &&
- test_must_fail test_terminal git am --reject </dev/zero &&
+ test_must_fail git am --retry --reject </dev/zero &&
test_path_is_dir .git/rebase-apply &&
test_path_is_file file.rej
'
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 86c695eb0a..51f7beb59f 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -1237,6 +1237,30 @@ test_expect_success 'log.abbrevCommit configuration' '
test_cmp expect.whatchanged.full actual
'
+test_expect_success '--abbrev-commit with core.abbrev=false' '
+ git log --no-abbrev >expect &&
+ git -c core.abbrev=false log --abbrev-commit >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--abbrev-commit with --no-abbrev' '
+ git log --no-abbrev >expect &&
+ git log --abbrev-commit --no-abbrev >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--abbrev-commit with core.abbrev=9000' '
+ git log --no-abbrev >expect &&
+ git -c core.abbrev=9000 log --abbrev-commit >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--abbrev-commit with --abbrev=9000' '
+ git log --no-abbrev >expect &&
+ git log --abbrev-commit --abbrev=9000 >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'show added path under "--follow -M"' '
# This tests for a regression introduced in v1.7.2-rc0~103^2~2
test_create_repo regression &&
diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index 2ba0324a69..3f163dc396 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -82,7 +82,23 @@ test_bloom_filters_used () {
test_bloom_filters_not_used () {
log_args=$1
setup "$log_args" &&
- ! grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf" &&
+
+ if grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf"
+ then
+ # if the Bloom filter system is initialized, ensure that no
+ # filters were used
+ data="statistics:{"
+ # unusable filters (e.g., those computed with a
+ # different value of commitGraph.changedPathsVersion)
+ # are counted in the filter_not_present bucket, so any
+ # value is OK there.
+ data="$data\"filter_not_present\":[0-9][0-9]*,"
+ data="$data\"maybe\":0,"
+ data="$data\"definitely_not\":0,"
+ data="$data\"false_positive\":0}"
+
+ grep -q "$data" "$TRASH_DIRECTORY/trace.perf"
+ fi &&
test_cmp log_wo_bloom log_w_bloom
}
@@ -163,7 +179,7 @@ test_expect_success 'setup - add commit-graph to the chain with Bloom filters' '
test_bloom_filters_used_when_some_filters_are_missing () {
log_args=$1
- bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":9"
+ bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":10"
setup "$log_args" &&
grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" &&
test_cmp log_wo_bloom log_w_bloom
@@ -206,6 +222,10 @@ test_filter_trunc_large () {
grep "\"key\":\"filter-trunc-large\",\"value\":\"$1\"" $2
}
+test_filter_upgraded () {
+ grep "\"key\":\"filter-upgraded\",\"value\":\"$1\"" $2
+}
+
test_expect_success 'correctly report changes over limit' '
git init limits &&
(
@@ -405,8 +425,307 @@ test_expect_success 'Bloom generation backfills empty commits' '
)
'
+graph=.git/objects/info/commit-graph
+graphdir=.git/objects/info/commit-graphs
+chain=$graphdir/commit-graph-chain
+
+test_expect_success 'setup for mixed Bloom setting tests' '
+ repo=mixed-bloom-settings &&
+
+ git init $repo &&
+ for i in one two three
+ do
+ test_commit -C $repo $i file || return 1
+ done
+'
+
+test_expect_success 'ensure Bloom filters with incompatible settings are ignored' '
+ # Compute Bloom filters with "unusual" settings.
+ git -C $repo rev-parse one >in &&
+ GIT_TEST_BLOOM_SETTINGS_NUM_HASHES=3 git -C $repo commit-graph write \
+ --stdin-commits --changed-paths --split <in &&
+ layer=$(head -n 1 $repo/$chain) &&
+
+ # A commit-graph layer without Bloom filters "hides" the layers
+ # below ...
+ git -C $repo rev-parse two >in &&
+ git -C $repo commit-graph write --stdin-commits --no-changed-paths \
+ --split=no-merge <in &&
+
+ # Another commit-graph layer that has Bloom filters, but with
+ # standard settings, and is thus incompatible with the base
+ # layer written above.
+ git -C $repo rev-parse HEAD >in &&
+ git -C $repo commit-graph write --stdin-commits --changed-paths \
+ --split=no-merge <in &&
+
+ test_line_count = 3 $repo/$chain &&
+
+ # Ensure that incompatible Bloom filters are ignored.
+ git -C $repo -c core.commitGraph=false log --oneline --no-decorate -- file \
+ >expect 2>err &&
+ git -C $repo log --oneline --no-decorate -- file >actual 2>err &&
+ test_cmp expect actual &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err
+'
+
+test_expect_success 'merge graph layers with incompatible Bloom settings' '
+ # Ensure that incompatible Bloom filters are ignored when
+ # merging existing layers.
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C $repo commit-graph write --reachable --changed-paths 2>err &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err &&
+ grep "{\"hash_version\":1,\"num_hashes\":7,\"bits_per_entry\":10,\"max_changed_paths\":512" trace2.txt &&
+
+ test_path_is_file $repo/$graph &&
+ test_dir_is_empty $repo/$graphdir &&
+
+ git -C $repo -c core.commitGraph=false log --oneline --no-decorate -- \
+ file >expect &&
+ trace_out="$(pwd)/trace.perf" &&
+ GIT_TRACE2_PERF="$trace_out" \
+ git -C $repo log --oneline --no-decorate -- file >actual 2>err &&
+
+ test_cmp expect actual &&
+ grep "statistics:{\"filter_not_present\":0," trace.perf &&
+ test_must_be_empty err
+'
+
+# chosen to be the same under all Unicode normalization forms
+CENT=$(printf "\302\242")
+
+test_expect_success 'ensure Bloom filter with incompatible versions are ignored' '
+ rm "$repo/$graph" &&
+
+ git -C $repo log --oneline --no-decorate -- $CENT >expect &&
+
+ # Compute v1 Bloom filters for commits at the bottom.
+ git -C $repo rev-parse HEAD^ >in &&
+ git -C $repo commit-graph write --stdin-commits --changed-paths \
+ --split <in &&
+
+ # Compute v2 Bloomfilters for the rest of the commits at the top.
+ git -C $repo rev-parse HEAD >in &&
+ git -C $repo -c commitGraph.changedPathsVersion=2 commit-graph write \
+ --stdin-commits --changed-paths --split=no-merge <in &&
+
+ test_line_count = 2 $repo/$chain &&
+
+ git -C $repo log --oneline --no-decorate -- $CENT >actual 2>err &&
+ test_cmp expect actual &&
+
+ layer="$(head -n 1 $repo/$chain)" &&
+ cat >expect.err <<-EOF &&
+ warning: disabling Bloom filters for commit-graph layer $SQ$layer$SQ due to incompatible settings
+ EOF
+ test_cmp expect.err err &&
+
+ # Merge the two layers with incompatible bloom filter versions,
+ # ensuring that the v2 filters are used.
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C $repo -c commitGraph.changedPathsVersion=2 commit-graph write --reachable --changed-paths 2>err &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err &&
+ grep "{\"hash_version\":2,\"num_hashes\":7,\"bits_per_entry\":10,\"max_changed_paths\":512" trace2.txt
+'
+
+get_first_changed_path_filter () {
+ test-tool read-graph bloom-filters >filters.dat &&
+ head -n 1 filters.dat
+}
+
+test_expect_success 'set up repo with high bit path, version 1 changed-path' '
+ git init highbit1 &&
+ test_commit -C highbit1 c1 "$CENT" &&
+ git -C highbit1 commit-graph write --reachable --changed-paths
+'
+
+test_expect_success 'setup check value of version 1 changed-path' '
+ (
+ cd highbit1 &&
+ echo "52a9" >expect &&
+ get_first_changed_path_filter >actual
+ )
+'
+
+# expect will not match actual if char is unsigned by default. Write the test
+# in this way, so that a user running this test script can still see if the two
+# files match. (It will appear as an ordinary success if they match, and a skip
+# if not.)
+if test_cmp highbit1/expect highbit1/actual
+then
+ test_set_prereq SIGNED_CHAR_BY_DEFAULT
+fi
+test_expect_success SIGNED_CHAR_BY_DEFAULT 'check value of version 1 changed-path' '
+ # Only the prereq matters for this test.
+ true
+'
+
+test_expect_success 'setup make another commit' '
+ # "git log" does not use Bloom filters for root commits - see how, in
+ # revision.c, rev_compare_tree() (the only code path that eventually calls
+ # get_bloom_filter()) is only called by try_to_simplify_commit() when the commit
+ # has one parent. Therefore, make another commit so that we perform the tests on
+ # a non-root commit.
+ test_commit -C highbit1 anotherc1 "another$CENT"
+'
+
+test_expect_success 'version 1 changed-path used when version 1 requested' '
+ (
+ cd highbit1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 1 changed-path not used when version 2 requested' '
+ (
+ cd highbit1 &&
+ git config --add commitGraph.changedPathsVersion 2 &&
+ test_bloom_filters_not_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 1 changed-path used when autodetect requested' '
+ (
+ cd highbit1 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'when writing another commit graph, preserve existing version 1 of changed-path' '
+ test_commit -C highbit1 c1double "$CENT$CENT" &&
+ git -C highbit1 commit-graph write --reachable --changed-paths &&
+ (
+ cd highbit1 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ echo "options: bloom(1,10,7) read_generation_data" >expect &&
+ test-tool read-graph >full &&
+ grep options full >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'set up repo with high bit path, version 2 changed-path' '
+ git init highbit2 &&
+ git -C highbit2 config --add commitGraph.changedPathsVersion 2 &&
+ test_commit -C highbit2 c2 "$CENT" &&
+ git -C highbit2 commit-graph write --reachable --changed-paths
+'
+
+test_expect_success 'check value of version 2 changed-path' '
+ (
+ cd highbit2 &&
+ echo "c01f" >expect &&
+ get_first_changed_path_filter >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'setup make another commit' '
+ # "git log" does not use Bloom filters for root commits - see how, in
+ # revision.c, rev_compare_tree() (the only code path that eventually calls
+ # get_bloom_filter()) is only called by try_to_simplify_commit() when the commit
+ # has one parent. Therefore, make another commit so that we perform the tests on
+ # a non-root commit.
+ test_commit -C highbit2 anotherc2 "another$CENT"
+'
+
+test_expect_success 'version 2 changed-path used when version 2 requested' '
+ (
+ cd highbit2 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 2 changed-path not used when version 1 requested' '
+ (
+ cd highbit2 &&
+ git config --add commitGraph.changedPathsVersion 1 &&
+ test_bloom_filters_not_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 2 changed-path used when autodetect requested' '
+ (
+ cd highbit2 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'when writing another commit graph, preserve existing version 2 of changed-path' '
+ test_commit -C highbit2 c2double "$CENT$CENT" &&
+ git -C highbit2 commit-graph write --reachable --changed-paths &&
+ (
+ cd highbit2 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ echo "options: bloom(2,10,7) read_generation_data" >expect &&
+ test-tool read-graph >full &&
+ grep options full >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'when writing commit graph, do not reuse changed-path of another version' '
+ git init doublewrite &&
+ test_commit -C doublewrite c "$CENT" &&
+
+ git -C doublewrite config --add commitGraph.changedPathsVersion 1 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ for v in -2 3
+ do
+ git -C doublewrite config --add commitGraph.changedPathsVersion $v &&
+ git -C doublewrite commit-graph write --reachable --changed-paths 2>err &&
+ cat >expect <<-EOF &&
+ warning: attempting to write a commit-graph, but ${SQ}commitGraph.changedPathsVersion${SQ} ($v) is not supported
+ EOF
+ test_cmp expect err || return 1
+ done &&
+
+ git -C doublewrite config --add commitGraph.changedPathsVersion 2 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ (
+ cd doublewrite &&
+ echo "c01f" >expect &&
+ get_first_changed_path_filter >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'when writing commit graph, reuse changed-path of another version where possible' '
+ git init upgrade &&
+
+ test_commit -C upgrade base no-high-bits &&
+
+ git -C upgrade config --add commitGraph.changedPathsVersion 1 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C upgrade commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ git -C upgrade config --add commitGraph.changedPathsVersion 2 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C upgrade commit-graph write --reachable --changed-paths &&
+ test_filter_computed 0 trace2.txt &&
+ test_filter_upgraded 1 trace2.txt
+'
+
corrupt_graph () {
- graph=.git/objects/info/commit-graph &&
test_when_finished "rm -rf $graph" &&
git commit-graph write --reachable --changed-paths &&
corrupt_chunk_file $graph "$@"
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index dd09134db0..10d2a6bf92 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -350,6 +350,29 @@ test_expect_success 'preferred packs must be non-empty' '
)
'
+test_expect_success 'preferred pack from existing MIDX without bitmaps' '
+ git init preferred-without-bitmaps &&
+ (
+ cd preferred-without-bitmaps &&
+
+ test_commit one &&
+ pack="$(git pack-objects --all $objdir/pack/pack </dev/null)" &&
+
+ git multi-pack-index write &&
+
+ # make another pack so that the subsequent MIDX write
+ # has something to do
+ test_commit two &&
+ git repack -d &&
+
+ # write a new MIDX without bitmaps reusing the singular
+ # pack from the existing MIDX as the preferred pack in
+ # the new MIDX
+ git multi-pack-index write --preferred-pack=pack-$pack.pack
+ )
+
+'
+
test_expect_success 'verify multi-pack-index success' '
git multi-pack-index verify --object-dir=$objdir
'
diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh
index 281266f788..77e91547ea 100755
--- a/t/t5324-split-commit-graph.sh
+++ b/t/t5324-split-commit-graph.sh
@@ -13,7 +13,8 @@ test_expect_success 'setup repo' '
git init &&
git config core.commitGraph true &&
git config gc.writeCommitGraph false &&
- infodir=".git/objects/info" &&
+ objdir=".git/objects" &&
+ infodir="$objdir/info" &&
graphdir="$infodir/commit-graphs" &&
test_oid_cache <<-EOM
shallow sha1:2132
@@ -718,4 +719,27 @@ test_expect_success 'write generation data chunk when commit-graph chain is repl
)
'
+test_expect_success 'temporary graph layer is discarded upon failure' '
+ git init layer-discard &&
+ (
+ cd layer-discard &&
+
+ test_commit A &&
+ test_commit B &&
+
+ # Intentionally remove commit "A" from the object store
+ # so that the commit-graph machinery fails to parse the
+ # parents of "B".
+ #
+ # This takes place after the commit-graph machinery has
+ # initialized a new temporary file to store the contents
+ # of the new graph layer, so will allow us to ensure
+ # that the temporary file is discarded upon failure.
+ rm $objdir/$(test_oid_to_path $(git rev-parse HEAD^)) &&
+
+ test_must_fail git commit-graph write --reachable --split &&
+ test_dir_is_empty $graphdir
+ )
+'
+
test_done
diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh
index cc7220b6c0..916da389b6 100755
--- a/t/t5326-multi-pack-bitmaps.sh
+++ b/t/t5326-multi-pack-bitmaps.sh
@@ -551,4 +551,34 @@ do
'
done
+test_expect_success 'remove one packfile between MIDX bitmap writes' '
+ git init remove-pack-between-writes &&
+ (
+ cd remove-pack-between-writes &&
+
+ test_commit A &&
+ test_commit B &&
+ test_commit C &&
+
+ # Create packs with the prefix "pack-A", "pack-B",
+ # "pack-C" to impose a lexicographic order on these
+ # packs so the pack being removed is always from the
+ # middle.
+ packdir=.git/objects/pack &&
+ A="$(echo A | git pack-objects $packdir/pack-A --revs)" &&
+ B="$(echo B | git pack-objects $packdir/pack-B --revs)" &&
+ C="$(echo C | git pack-objects $packdir/pack-C --revs)" &&
+
+ git multi-pack-index write --bitmap &&
+
+ cat >in <<-EOF &&
+ pack-A-$A.idx
+ pack-C-$C.idx
+ EOF
+ git multi-pack-index write --bitmap --stdin-packs <in &&
+
+ git rev-list --test-bitmap HEAD
+ )
+'
+
test_done
diff --git a/t/t5332-multi-pack-reuse.sh b/t/t5332-multi-pack-reuse.sh
index 3c20738bce..ed823f37bc 100755
--- a/t/t5332-multi-pack-reuse.sh
+++ b/t/t5332-multi-pack-reuse.sh
@@ -204,4 +204,30 @@ test_expect_success 'omit delta from uninteresting base (cross pack)' '
test_pack_objects_reused_all $(($objects_nr - 1)) $packs_nr
'
+test_expect_success 'non-omitted delta in MIDX preferred pack' '
+ test_config pack.allowPackReuse single &&
+
+ cat >p1.objects <<-EOF &&
+ $(git rev-parse $base)
+ ^$(git rev-parse $delta^)
+ EOF
+ cat >p2.objects <<-EOF &&
+ $(git rev-parse F)
+ EOF
+
+ p1="$(git pack-objects --revs $packdir/pack <p1.objects)" &&
+ p2="$(git pack-objects --revs $packdir/pack <p2.objects)" &&
+
+ cat >in <<-EOF &&
+ pack-$p1.idx
+ pack-$p2.idx
+ EOF
+ git multi-pack-index write --bitmap --stdin-packs \
+ --preferred-pack=pack-$p1.pack <in &&
+
+ git show-index <$packdir/pack-$p1.idx >expect &&
+
+ test_pack_objects_reused_all $(wc -l <expect) 1
+'
+
test_done
diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh
new file mode 100755
index 0000000000..f052f395a7
--- /dev/null
+++ b/t/t5333-pseudo-merge-bitmaps.sh
@@ -0,0 +1,393 @@
+#!/bin/sh
+
+test_description='pseudo-merge bitmaps'
+
+GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
+
+. ./test-lib.sh
+
+test_pseudo_merges () {
+ test-tool bitmap dump-pseudo-merges
+}
+
+test_pseudo_merge_commits () {
+ test-tool bitmap dump-pseudo-merge-commits "$1"
+}
+
+test_pseudo_merges_satisfied () {
+ test_trace2_data bitmap pseudo_merges_satisfied "$1"
+}
+
+test_pseudo_merges_cascades () {
+ test_trace2_data bitmap pseudo_merges_cascades "$1"
+}
+
+test_pseudo_merges_reused () {
+ test_trace2_data pack-bitmap-write building_bitmaps_pseudo_merge_reused "$1"
+}
+
+tag_everything () {
+ git rev-list --all --no-object-names >in &&
+ perl -lne '
+ print "create refs/tags/" . $. . " " . $1 if /([0-9a-f]+)/
+ ' <in | git update-ref --stdin
+}
+
+test_expect_success 'setup' '
+ test_commit_bulk 512 &&
+ tag_everything
+'
+
+test_expect_success 'bitmap traversal without pseudo-merges' '
+ git repack -adb &&
+
+ git rev-list --count --all --objects >expect &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt \
+ git rev-list --count --all --objects --use-bitmap-index >actual &&
+
+ test_pseudo_merges_satisfied 0 <trace2.txt &&
+ test_pseudo_merges_cascades 0 <trace2.txt &&
+ test_pseudo_merges >merges &&
+ test_must_be_empty merges &&
+ test_cmp expect actual
+'
+
+test_expect_success 'pseudo-merges accurately represent their objects' '
+ test_config bitmapPseudoMerge.test.pattern "refs/tags/" &&
+ test_config bitmapPseudoMerge.test.maxMerges 8 &&
+ test_config bitmapPseudoMerge.test.stableThreshold never &&
+
+ git repack -adb &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 8 merges &&
+
+ for i in $(test_seq 0 $(($(wc -l <merges)-1)))
+ do
+ test-tool bitmap dump-pseudo-merge-commits $i >commits &&
+
+ git rev-list --objects --no-object-names --stdin <commits >expect.raw &&
+ test-tool bitmap dump-pseudo-merge-objects $i >actual.raw &&
+
+ sort -u <expect.raw >expect &&
+ sort -u <actual.raw >actual &&
+
+ test_cmp expect actual || return 1
+ done
+'
+
+test_expect_success 'bitmap traversal with pseudo-merges' '
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt \
+ git rev-list --count --all --objects --use-bitmap-index >actual &&
+ git rev-list --count --all --objects >expect &&
+
+ test_pseudo_merges_satisfied 8 <trace2.txt &&
+ test_pseudo_merges_cascades 1 <trace2.txt &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stale bitmap traversal with pseudo-merges' '
+ test_commit other &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt \
+ git rev-list --count --all --objects --use-bitmap-index >actual &&
+ git rev-list --count --all --objects >expect &&
+
+ test_pseudo_merges_satisfied 8 <trace2.txt &&
+ test_pseudo_merges_cascades 1 <trace2.txt &&
+ test_cmp expect actual
+'
+
+test_expect_success 'bitmapPseudoMerge.sampleRate adjusts commit selection rate' '
+ test_config bitmapPseudoMerge.test.pattern "refs/tags/" &&
+ test_config bitmapPseudoMerge.test.maxMerges 1 &&
+ test_config bitmapPseudoMerge.test.stableThreshold never &&
+
+ commits_nr=$(git rev-list --all --count) &&
+
+ for rate in 1.0 0.5 0.25
+ do
+ git -c bitmapPseudoMerge.test.sampleRate=$rate repack -adb &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 1 merges &&
+ test_pseudo_merge_commits 0 >commits &&
+
+ test-tool bitmap list-commits >bitmaps &&
+ bitmaps_nr="$(wc -l <bitmaps)" &&
+
+ perl -MPOSIX -e "print ceil(\$ARGV[0]*(\$ARGV[1]-\$ARGV[2]))" \
+ "$rate" "$commits_nr" "$bitmaps_nr" >expect &&
+
+ test $(cat expect) -eq $(wc -l <commits) || return 1
+ done
+'
+
+test_expect_success 'bitmapPseudoMerge.threshold excludes newer commits' '
+ git init pseudo-merge-threshold &&
+ (
+ cd pseudo-merge-threshold &&
+
+ new="1672549200" && # 2023-01-01
+ old="1641013200" && # 2022-01-01
+
+ GIT_COMMITTER_DATE="$new +0000" &&
+ export GIT_COMMITTER_DATE &&
+ test_commit_bulk --message="new" --notick 128 &&
+
+ GIT_COMMITTER_DATE="$old +0000" &&
+ export GIT_COMMITTER_DATE &&
+ test_commit_bulk --message="old" --notick 128 &&
+
+ tag_everything &&
+
+ git \
+ -c bitmapPseudoMerge.test.pattern="refs/tags/" \
+ -c bitmapPseudoMerge.test.maxMerges=1 \
+ -c bitmapPseudoMerge.test.threshold=$(($new - 1)) \
+ -c bitmapPseudoMerge.test.stableThreshold=never \
+ repack -adb &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 1 merges &&
+
+ test_pseudo_merge_commits 0 >oids &&
+ git cat-file --batch <oids >commits &&
+
+ test $(wc -l <oids) = $(grep -c "^committer.*$old +0000$" commits)
+ )
+'
+
+test_expect_success 'bitmapPseudoMerge.stableThreshold creates stable groups' '
+ (
+ cd pseudo-merge-threshold &&
+
+ new="1672549200" && # 2023-01-01
+ mid="1654059600" && # 2022-06-01
+ old="1641013200" && # 2022-01-01
+
+ GIT_COMMITTER_DATE="$mid +0000" &&
+ export GIT_COMMITTER_DATE &&
+ test_commit_bulk --message="mid" --notick 128 &&
+
+ git for-each-ref --format="delete %(refname)" refs/tags >in &&
+ git update-ref --stdin <in &&
+
+ tag_everything &&
+
+ git \
+ -c bitmapPseudoMerge.test.pattern="refs/tags/" \
+ -c bitmapPseudoMerge.test.maxMerges=1 \
+ -c bitmapPseudoMerge.test.threshold=$(($new - 1)) \
+ -c bitmapPseudoMerge.test.stableThreshold=$(($mid - 1)) \
+ -c bitmapPseudoMerge.test.stableSize=10 \
+ repack -adb &&
+
+ test_pseudo_merges >merges &&
+ merges_nr="$(wc -l <merges)" &&
+
+ for i in $(test_seq $(($merges_nr - 1)))
+ do
+ test_pseudo_merge_commits 0 >oids &&
+ git cat-file --batch <oids >commits &&
+
+ expect="$(grep -c "^committer.*$old +0000$" commits)" &&
+ actual="$(wc -l <oids)" &&
+
+ test $expect = $actual || return 1
+ done &&
+
+ test_pseudo_merge_commits $(($merges_nr - 1)) >oids &&
+ git cat-file --batch <oids >commits &&
+ test $(wc -l <oids) = $(grep -c "^committer.*$mid +0000$" commits)
+ )
+'
+
+test_expect_success 'out of order thresholds are rejected' '
+ test_must_fail git \
+ -c bitmapPseudoMerge.test.pattern="refs/*" \
+ -c bitmapPseudoMerge.test.threshold=1.month.ago \
+ -c bitmapPseudoMerge.test.stableThreshold=1.week.ago \
+ repack -adb 2>err &&
+
+ cat >expect <<-EOF &&
+ fatal: pseudo-merge group ${SQ}test${SQ} has unstable threshold before stable one
+ EOF
+
+ test_cmp expect err
+'
+
+test_expect_success 'pseudo-merge pattern with capture groups' '
+ git init pseudo-merge-captures &&
+ (
+ cd pseudo-merge-captures &&
+
+ test_commit_bulk 128 &&
+ tag_everything &&
+
+ for r in $(test_seq 8)
+ do
+ test_commit_bulk 16 &&
+
+ git rev-list HEAD~16.. >in &&
+
+ perl -lne "print \"create refs/remotes/$r/tags/\$. \$_\"" <in |
+ git update-ref --stdin || return 1
+ done &&
+
+ git \
+ -c bitmapPseudoMerge.tags.pattern="refs/remotes/([0-9]+)/tags/" \
+ -c bitmapPseudoMerge.tags.maxMerges=1 \
+ repack -adb &&
+
+ git for-each-ref --format="%(objectname) %(refname)" >refs &&
+
+ test_pseudo_merges >merges &&
+ for m in $(test_seq 0 $(($(wc -l <merges) - 1)))
+ do
+ test_pseudo_merge_commits $m >oids &&
+ grep -f oids refs |
+ perl -lne "print \$1 if /refs\/remotes\/([0-9]+)/" |
+ sort -u || return 1
+ done >remotes &&
+
+ test $(wc -l <remotes) -eq $(sort -u <remotes | wc -l)
+ )
+'
+
+test_expect_success 'pseudo-merge overlap setup' '
+ git init pseudo-merge-overlap &&
+ (
+ cd pseudo-merge-overlap &&
+
+ test_commit_bulk 256 &&
+ tag_everything &&
+
+ git \
+ -c bitmapPseudoMerge.all.pattern="refs/" \
+ -c bitmapPseudoMerge.all.maxMerges=1 \
+ -c bitmapPseudoMerge.all.stableThreshold=never \
+ -c bitmapPseudoMerge.tags.pattern="refs/tags/" \
+ -c bitmapPseudoMerge.tags.maxMerges=1 \
+ -c bitmapPseudoMerge.tags.stableThreshold=never \
+ repack -adb
+ )
+'
+
+test_expect_success 'pseudo-merge overlap generates overlapping groups' '
+ (
+ cd pseudo-merge-overlap &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 2 merges &&
+
+ test_pseudo_merge_commits 0 >commits-0.raw &&
+ test_pseudo_merge_commits 1 >commits-1.raw &&
+
+ sort commits-0.raw >commits-0 &&
+ sort commits-1.raw >commits-1 &&
+
+ comm -12 commits-0 commits-1 >overlap &&
+
+ test_line_count -gt 0 overlap
+ )
+'
+
+test_expect_success 'pseudo-merge overlap traversal' '
+ (
+ cd pseudo-merge-overlap &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt \
+ git rev-list --count --all --objects --use-bitmap-index >actual &&
+ git rev-list --count --all --objects >expect &&
+
+ test_pseudo_merges_satisfied 2 <trace2.txt &&
+ test_pseudo_merges_cascades 1 <trace2.txt &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'pseudo-merge overlap stale traversal' '
+ (
+ cd pseudo-merge-overlap &&
+
+ test_commit other &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt \
+ git rev-list --count --all --objects --use-bitmap-index >actual &&
+ git rev-list --count --all --objects >expect &&
+
+ test_pseudo_merges_satisfied 2 <trace2.txt &&
+ test_pseudo_merges_cascades 1 <trace2.txt &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'pseudo-merge reuse' '
+ git init pseudo-merge-reuse &&
+ (
+ cd pseudo-merge-reuse &&
+
+ stable="1641013200" && # 2022-01-01
+ unstable="1672549200" && # 2023-01-01
+
+ GIT_COMMITTER_DATE="$stable +0000" &&
+ export GIT_COMMITTER_DATE &&
+ test_commit_bulk --notick 128 &&
+ GIT_COMMITTER_DATE="$unstable +0000" &&
+ export GIT_COMMITTER_DATE &&
+ test_commit_bulk --notick 128 &&
+
+ tag_everything &&
+
+ git \
+ -c bitmapPseudoMerge.test.pattern="refs/tags/" \
+ -c bitmapPseudoMerge.test.maxMerges=1 \
+ -c bitmapPseudoMerge.test.threshold=now \
+ -c bitmapPseudoMerge.test.stableThreshold=$(($unstable - 1)) \
+ -c bitmapPseudoMerge.test.stableSize=512 \
+ repack -adb &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 2 merges &&
+
+ test_pseudo_merge_commits 0 >stable-oids.before &&
+ test_pseudo_merge_commits 1 >unstable-oids.before &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt git \
+ -c bitmapPseudoMerge.test.pattern="refs/tags/" \
+ -c bitmapPseudoMerge.test.maxMerges=2 \
+ -c bitmapPseudoMerge.test.threshold=now \
+ -c bitmapPseudoMerge.test.stableThreshold=$(($unstable - 1)) \
+ -c bitmapPseudoMerge.test.stableSize=512 \
+ repack -adb &&
+
+ test_pseudo_merges_reused 1 <trace2.txt &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 3 merges &&
+
+ test_pseudo_merge_commits 0 >stable-oids.after &&
+ for i in 1 2
+ do
+ test_pseudo_merge_commits $i || return 1
+ done >unstable-oids.after &&
+
+ sort -u <stable-oids.before >expect &&
+ sort -u <stable-oids.after >actual &&
+ test_cmp expect actual &&
+
+ sort -u <unstable-oids.before >expect &&
+ sort -u <unstable-oids.after >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_done
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 1bc15a3f08..585ea0ee16 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -993,6 +993,16 @@ test_expect_success 'ensure bogus fetch.negotiationAlgorithm yields error' '
fetch origin server_has both_have_2
'
+test_expect_success 'fetch-pack with fsckObjects and keep-file does not segfault' '
+ rm -rf server client &&
+ test_create_repo server &&
+ test_commit -C server one &&
+
+ test_create_repo client &&
+ git -c fetch.fsckObjects=true \
+ -C client fetch-pack -k -k ../server HEAD
+'
+
test_expect_success 'filtering by size' '
rm -rf server client &&
test_create_repo server &&
@@ -1046,7 +1056,7 @@ fetch_filter_blob_limit_zero () {
# Ensure that commit is fetched, but blob is not
commit=$(git -C "$SERVER" rev-parse two) &&
- blob=$(git hash-object server/two.t) &&
+ blob=$(git hash-object "$SERVER/two.t") &&
git -C client rev-list --objects --missing=allow-any "$commit" >oids &&
grep "$commit" oids &&
! grep "$blob" oids
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 7789ff12c4..08424e878e 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -1492,4 +1492,40 @@ test_expect_success 'refs/remotes/* <src> refspec and unqualified <dst> DWIM and
)
'
+test_expect_success 'empty config clears remote.*.url list' '
+ test_when_finished "git config --remove-section remote.multi" &&
+ git config --add remote.multi.url wrong-one &&
+ git config --add remote.multi.url wrong-two &&
+ git -c remote.multi.url= \
+ -c remote.multi.url=right-one \
+ -c remote.multi.url=right-two \
+ remote show -n multi >actual.raw &&
+ grep URL actual.raw >actual &&
+ cat >expect <<-\EOF &&
+ Fetch URL: right-one
+ Push URL: right-one
+ Push URL: right-two
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'empty config clears remote.*.pushurl list' '
+ test_when_finished "git config --remove-section remote.multi" &&
+ git config --add remote.multi.url right &&
+ git config --add remote.multi.url will-be-ignored &&
+ git config --add remote.multi.pushurl wrong-push-one &&
+ git config --add remote.multi.pushurl wrong-push-two &&
+ git -c remote.multi.pushurl= \
+ -c remote.multi.pushurl=right-push-one \
+ -c remote.multi.pushurl=right-push-two \
+ remote show -n multi >actual.raw &&
+ grep URL actual.raw >actual &&
+ cat >expect <<-\EOF &&
+ Fetch URL: right
+ Push URL: right-push-one
+ Push URL: right-push-two
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 5dbe107ce8..42e77eb5a9 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -47,6 +47,7 @@ test_expect_success setup '
git show-ref -d >refs &&
sed -e "s/ / /" refs >>expected.all &&
+ grep refs/heads/ expected.all >expected.branches &&
git remote add self "$(pwd)/.git" &&
git remote add self2 "."
'
@@ -71,6 +72,27 @@ test_expect_success 'ls-remote self' '
test_cmp expected.all actual
'
+test_expect_success 'ls-remote --branches self' '
+ git ls-remote --branches self >actual &&
+ test_cmp expected.branches actual &&
+ git ls-remote -b self >actual &&
+ test_cmp expected.branches actual
+'
+
+test_expect_success 'ls-remote -h is deprecated w/o warning' '
+ git ls-remote -h self >actual 2>warning &&
+ test_cmp expected.branches actual &&
+ test_grep ! deprecated warning
+'
+
+test_expect_success 'ls-remote --heads is deprecated and hidden w/o warning' '
+ test_expect_code 129 git ls-remote -h >short-help &&
+ test_grep ! -e --head short-help &&
+ git ls-remote --heads self >actual 2>warning &&
+ test_cmp expected.branches actual &&
+ test_grep ! deprecated warning
+'
+
test_expect_success 'ls-remote --sort="version:refname" --tags self' '
generate_references \
refs/tags/mark \
@@ -275,7 +297,7 @@ test_expect_success 'ls-remote with filtered symref (refname)' '
test_cmp expect actual
'
-test_expect_success 'ls-remote with filtered symref (--heads)' '
+test_expect_success 'ls-remote with filtered symref (--branches)' '
git symbolic-ref refs/heads/foo refs/tags/mark &&
cat >expect.v2 <<-EOF &&
ref: refs/tags/mark refs/heads/foo
@@ -283,9 +305,9 @@ test_expect_success 'ls-remote with filtered symref (--heads)' '
$rev refs/heads/main
EOF
grep -v "^ref: refs/tags/" <expect.v2 >expect.v0 &&
- git -c protocol.version=0 ls-remote --symref --heads . >actual.v0 &&
+ git -c protocol.version=0 ls-remote --symref --branches . >actual.v0 &&
test_cmp expect.v0 actual.v0 &&
- git -c protocol.version=2 ls-remote --symref --heads . >actual.v2 &&
+ git -c protocol.version=2 ls-remote --symref --branches . >actual.v2 &&
test_cmp expect.v2 actual.v2
'
@@ -335,9 +357,9 @@ test_expect_success 'ls-remote patterns work with all protocol versions' '
test_expect_success 'ls-remote prefixes work with all protocol versions' '
git for-each-ref --format="%(objectname) %(refname)" \
refs/heads/ refs/tags/ >expect &&
- git -c protocol.version=0 ls-remote --heads --tags . >actual.v0 &&
+ git -c protocol.version=0 ls-remote --branches --tags . >actual.v0 &&
test_cmp expect actual.v0 &&
- git -c protocol.version=2 ls-remote --heads --tags . >actual.v2 &&
+ git -c protocol.version=2 ls-remote --branches --tags . >actual.v2 &&
test_cmp expect actual.v2
'
diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
index 5f16cbc58d..ea8e48f627 100755
--- a/t/t5550-http-fetch-dumb.sh
+++ b/t/t5550-http-fetch-dumb.sh
@@ -25,6 +25,12 @@ test_expect_success 'setup repository' '
git commit -m two
'
+test_expect_success 'packfile without repository does not crash' '
+ echo "fatal: not a git repository" >expect &&
+ test_must_fail nongit git http-fetch --packfile=abc 2>err &&
+ test_cmp expect err
+'
+
setup_post_update_server_info_hook () {
test_hook --setup -C "$1" post-update <<-\EOF &&
exec git update-server-info
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index cc0b953f14..5d7ea147f1 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -46,6 +46,13 @@ test_expect_success 'output from clone' '
test $(grep Clon output | wc -l) = 1
'
+test_expect_success 'output from clone with core.abbrev does not crash' '
+ rm -fr dst &&
+ echo "Cloning into ${SQ}dst${SQ}..." >expect &&
+ git -c core.abbrev=12 clone -n "file://$(pwd)/src" dst >actual 2>&1 &&
+ test_cmp expect actual
+'
+
test_expect_success 'clone does not keep pack' '
rm -fr dst &&
diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh
index 9a1390a98f..d9a320abd2 100755
--- a/t/t5605-clone-local.sh
+++ b/t/t5605-clone-local.sh
@@ -164,7 +164,7 @@ test_expect_success REFFILES 'local clone from repo with corrupt refs fails grac
echo a >corrupt/.git/refs/heads/topic &&
test_must_fail git clone corrupt working 2>err &&
- grep "has a null OID" err
+ grep "has neither a valid OID nor a target" err
'
test_done
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index 4e0a77f985..20f43f7b7d 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -38,6 +38,29 @@ test_expect_success 'cloning from local repo' '
test_cmp server/file local/file
'
+test_expect_success 'clone with remote.*.vcs config' '
+ GIT_TRACE=$PWD/vcs-clone.trace \
+ git clone --no-local -c remote.origin.vcs=testgit "$PWD/server" vcs-clone &&
+ test_grep remote-testgit vcs-clone.trace
+'
+
+test_expect_success 'fetch with configured remote.*.vcs' '
+ git init vcs-fetch &&
+ git -C vcs-fetch config remote.origin.vcs testgit &&
+ git -C vcs-fetch config remote.origin.url "$PWD/server" &&
+ GIT_TRACE=$PWD/vcs-fetch.trace \
+ git -C vcs-fetch fetch origin &&
+ test_grep remote-testgit vcs-fetch.trace
+'
+
+test_expect_success 'vcs remote with no url' '
+ NOURL_UPSTREAM=$PWD/server &&
+ export NOURL_UPSTREAM &&
+ git init vcs-nourl &&
+ git -C vcs-nourl config remote.origin.vcs nourl &&
+ git -C vcs-nourl fetch origin
+'
+
test_expect_success 'create new commit on remote' '
(cd server &&
echo content >>file &&
diff --git a/t/t5801/git-remote-nourl b/t/t5801/git-remote-nourl
new file mode 100755
index 0000000000..09be6013c5
--- /dev/null
+++ b/t/t5801/git-remote-nourl
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec git-remote-testgit "$1" "$NOURL_UPSTREAM"
diff --git a/t/t5801/git-remote-testgit b/t/t5801/git-remote-testgit
index c5b10f5775..f8b476499f 100755
--- a/t/t5801/git-remote-testgit
+++ b/t/t5801/git-remote-testgit
@@ -26,7 +26,8 @@ then
t_refspec=""
fi
-GIT_DIR="$url/.git"
+unset $(git rev-parse --local-env-vars)
+GIT_DIR=$(git -C "$url" rev-parse --absolute-git-dir)
export GIT_DIR
force=
diff --git a/t/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh
index 43e1afd44c..0387f35a32 100755
--- a/t/t6112-rev-list-filters-objects.sh
+++ b/t/t6112-rev-list-filters-objects.sh
@@ -701,4 +701,16 @@ test_expect_success 'expand blob limit in protocol' '
grep "blob:limit=1024" trace
'
+test_expect_success EXPENSIVE 'large sparse filter file ignored' '
+ blob=$(dd if=/dev/zero bs=101M count=1 |
+ git hash-object -w --stdin) &&
+ test_must_fail \
+ git rev-list --all --objects --filter=sparse:oid=$blob 2>err &&
+ cat >expect <<-EOF &&
+ warning: ignoring excessively large pattern blob: $blob
+ fatal: unable to parse sparse filter data in $blob
+ EOF
+ test_cmp expect err
+'
+
test_done
diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh
index 43d40175f8..1b5909d1b7 100755
--- a/t/t6500-gc.sh
+++ b/t/t6500-gc.sh
@@ -158,7 +158,7 @@ test_expect_success TTY 'with TTY: gc --no-quiet' '
git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr &&
test_must_be_empty stdout &&
test_grep "Enumerating objects" stderr &&
- test_grep "Computing commit graph generation numbers" stderr
+ test_grep "Computing commit graph generation numbers: 100% (4/4), done." stderr
'
test_expect_success 'gc --quiet' '
diff --git a/t/t7002-mv-sparse-checkout.sh b/t/t7002-mv-sparse-checkout.sh
index 26582ae4e5..57969ce805 100755
--- a/t/t7002-mv-sparse-checkout.sh
+++ b/t/t7002-mv-sparse-checkout.sh
@@ -2,6 +2,7 @@
test_description='git mv in sparse working trees'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
setup_sparse_checkout () {
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 60e4c90de1..a0296d6ca4 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -726,18 +726,11 @@ test_expect_success TTY 'git discards pager non-zero exit without SIGPIPE' '
test_path_is_file pager-used
'
-test_expect_success TTY 'git skips paging nonexisting command' '
- test_when_finished "rm trace.normal" &&
+test_expect_success TTY 'git errors when asked to execute nonexisting pager' '
+ test_when_finished "rm -f err" &&
test_config core.pager "does-not-exist" &&
- GIT_TRACE2="$(pwd)/trace.normal" &&
- export GIT_TRACE2 &&
- test_when_finished "unset GIT_TRACE2" &&
-
- test_terminal git log &&
-
- grep child_exit trace.normal >child-exits &&
- test_line_count = 1 child-exits &&
- grep " code:-1 " child-exits
+ test_must_fail test_terminal git log 2>err &&
+ test_grep "unable to execute pager" err
'
test_expect_success TTY 'git returns SIGPIPE on propagated signals from pager' '
@@ -763,7 +756,7 @@ test_expect_success TTY 'git returns SIGPIPE on propagated signals from pager' '
test_expect_success TTY 'non-existent pager doesnt cause crash' '
test_config pager.show invalid-pager &&
- test_terminal git show
+ test_must_fail test_terminal git show
'
test_done
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 041f1077b0..65fd3d8552 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -237,6 +237,16 @@ test_expect_success 'merge c1 with c2' '
verify_parents $c1 $c2
'
+test_expect_success 'merge c1 with c2 when index.lock exists' '
+ test_when_finished rm .git/index.lock &&
+ git reset --hard c1 &&
+ >.git/index.lock &&
+ test_must_fail git merge c2 &&
+ test_path_is_missing .git/MERGE_HEAD &&
+ test_path_is_missing .git/MERGE_MODE &&
+ test_path_is_missing .git/MERGE_MSG
+'
+
test_expect_success 'merge --squash c3 with c7' '
git reset --hard c3 &&
test_must_fail git merge --squash c7 &&
diff --git a/t/t9004-example.sh b/t/t9004-example.sh
deleted file mode 100755
index 590aab0304..0000000000
--- a/t/t9004-example.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-test_description='check that example code compiles and runs'
-
-TEST_PASSES_SANITIZE_LEAK=true
-. ./test-lib.sh
-
-test_expect_success 'decorate' '
- test-tool example-decorate
-'
-
-test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 862d80c974..1ea9f31225 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -458,6 +458,7 @@ test_commit_bulk () {
indir=.
ref=HEAD
n=1
+ notick=
message='commit %s'
filename='%s.t'
contents='content %s'
@@ -488,6 +489,9 @@ test_commit_bulk () {
filename="${1#--*=}-%s.t"
contents="${1#--*=} %s"
;;
+ --notick)
+ notick=yes
+ ;;
-*)
BUG "invalid test_commit_bulk option: $1"
;;
@@ -507,7 +511,10 @@ test_commit_bulk () {
while test "$total" -gt 0
do
- test_tick &&
+ if test -z "$notick"
+ then
+ test_tick
+ fi &&
echo "commit $ref"
printf 'author %s <%s> %s\n' \
"$GIT_AUTHOR_NAME" \
@@ -1096,6 +1103,11 @@ test_must_fail_acceptable () {
done
fi
+ if test "$1" = "nongit"
+ then
+ shift
+ fi
+
case "$1" in
git|__git*|scalar|test-tool|test_terminal)
return 0
diff --git a/t/test-terminal.perl b/t/test-terminal.perl
index 3810e9bb43..b8fd6a4f13 100755
--- a/t/test-terminal.perl
+++ b/t/test-terminal.perl
@@ -5,17 +5,15 @@ use warnings;
use IO::Pty;
use File::Copy;
-# Run @$argv in the background with stdio redirected to $in, $out and $err.
+# Run @$argv in the background with stdio redirected to $out and $err.
sub start_child {
- my ($argv, $in, $out, $err) = @_;
+ my ($argv, $out, $err) = @_;
my $pid = fork;
if (not defined $pid) {
die "fork failed: $!"
} elsif ($pid == 0) {
- open STDIN, "<&", $in;
open STDOUT, ">&", $out;
open STDERR, ">&", $err;
- close $in;
close $out;
exec(@$argv) or die "cannot exec '$argv->[0]': $!"
}
@@ -51,17 +49,6 @@ sub xsendfile {
copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
}
-sub copy_stdin {
- my ($in) = @_;
- my $pid = fork;
- if (!$pid) {
- xsendfile($in, \*STDIN);
- exit 0;
- }
- close($in);
- return $pid;
-}
-
sub copy_stdio {
my ($out, $err) = @_;
my $pid = fork;
@@ -81,25 +68,15 @@ if ($#ARGV < 1) {
die "usage: test-terminal program args";
}
$ENV{TERM} = 'vt100';
-my $parent_in = new IO::Pty;
my $parent_out = new IO::Pty;
my $parent_err = new IO::Pty;
-$parent_in->set_raw();
$parent_out->set_raw();
$parent_err->set_raw();
-$parent_in->slave->set_raw();
$parent_out->slave->set_raw();
$parent_err->slave->set_raw();
-my $pid = start_child(\@ARGV, $parent_in->slave, $parent_out->slave, $parent_err->slave);
-close $parent_in->slave;
+my $pid = start_child(\@ARGV, $parent_out->slave, $parent_err->slave);
close $parent_out->slave;
close $parent_err->slave;
-my $in_pid = copy_stdin($parent_in);
copy_stdio($parent_out, $parent_err);
my $ret = finish_child($pid);
-# If the child process terminates before our copy_stdin() process is able to
-# write all of its data to $parent_in, the copy_stdin() process could stall.
-# Send SIGTERM to it to ensure it terminates.
-kill 'TERM', $in_pid;
-finish_child($in_pid);
exit($ret);
diff --git a/t/unit-tests/lib-oid.c b/t/unit-tests/lib-oid.c
new file mode 100644
index 0000000000..37105f0a8f
--- /dev/null
+++ b/t/unit-tests/lib-oid.c
@@ -0,0 +1,52 @@
+#include "test-lib.h"
+#include "lib-oid.h"
+#include "strbuf.h"
+#include "hex.h"
+
+static int init_hash_algo(void)
+{
+ static int algo = -1;
+
+ if (algo < 0) {
+ const char *algo_name = getenv("GIT_TEST_DEFAULT_HASH");
+ algo = algo_name ? hash_algo_by_name(algo_name) : GIT_HASH_SHA1;
+
+ if (!check(algo != GIT_HASH_UNKNOWN))
+ test_msg("BUG: invalid GIT_TEST_DEFAULT_HASH value ('%s')",
+ algo_name);
+ }
+ return algo;
+}
+
+static int get_oid_arbitrary_hex_algop(const char *hex, struct object_id *oid,
+ const struct git_hash_algo *algop)
+{
+ int ret;
+ size_t sz = strlen(hex);
+ struct strbuf buf = STRBUF_INIT;
+
+ if (!check(sz <= algop->hexsz)) {
+ test_msg("BUG: hex string (%s) bigger than maximum allowed (%lu)",
+ hex, (unsigned long)algop->hexsz);
+ return -1;
+ }
+
+ strbuf_add(&buf, hex, sz);
+ strbuf_addchars(&buf, '0', algop->hexsz - sz);
+
+ ret = get_oid_hex_algop(buf.buf, oid, algop);
+ if (!check_int(ret, ==, 0))
+ test_msg("BUG: invalid hex input (%s) provided", hex);
+
+ strbuf_release(&buf);
+ return ret;
+}
+
+int get_oid_arbitrary_hex(const char *hex, struct object_id *oid)
+{
+ int hash_algo = init_hash_algo();
+
+ if (!check_int(hash_algo, !=, GIT_HASH_UNKNOWN))
+ return -1;
+ return get_oid_arbitrary_hex_algop(hex, oid, &hash_algos[hash_algo]);
+}
diff --git a/t/unit-tests/lib-oid.h b/t/unit-tests/lib-oid.h
new file mode 100644
index 0000000000..8d2acca768
--- /dev/null
+++ b/t/unit-tests/lib-oid.h
@@ -0,0 +1,17 @@
+#ifndef LIB_OID_H
+#define LIB_OID_H
+
+#include "hash.h"
+
+/*
+ * Convert arbitrary hex string to object_id.
+ * For example, passing "abc12" will generate
+ * "abc1200000000000000000000000000000000000" hex of length 40 for SHA-1 and
+ * create object_id with that.
+ * WARNING: passing a string of length more than the hexsz of respective hash
+ * algo is not allowed. The hash algo is decided based on GIT_TEST_DEFAULT_HASH
+ * environment variable.
+ */
+int get_oid_arbitrary_hex(const char *s, struct object_id *oid);
+
+#endif /* LIB_OID_H */
diff --git a/t/unit-tests/t-example-decorate.c b/t/unit-tests/t-example-decorate.c
new file mode 100644
index 0000000000..a4a75db735
--- /dev/null
+++ b/t/unit-tests/t-example-decorate.c
@@ -0,0 +1,82 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
+#include "test-lib.h"
+#include "object.h"
+#include "decorate.h"
+#include "repository.h"
+
+struct test_vars {
+ struct object *one, *two, *three;
+ struct decoration n;
+ int decoration_a, decoration_b;
+};
+
+static void t_add(struct test_vars *vars)
+{
+ void *ret = add_decoration(&vars->n, vars->one, &vars->decoration_a);
+
+ if (!check(ret == NULL))
+ test_msg("when adding a brand-new object, NULL should be returned");
+ ret = add_decoration(&vars->n, vars->two, NULL);
+ if (!check(ret == NULL))
+ test_msg("when adding a brand-new object, NULL should be returned");
+}
+
+static void t_readd(struct test_vars *vars)
+{
+ void *ret = add_decoration(&vars->n, vars->one, NULL);
+
+ if (!check(ret == &vars->decoration_a))
+ test_msg("when readding an already existing object, existing decoration should be returned");
+ ret = add_decoration(&vars->n, vars->two, &vars->decoration_b);
+ if (!check(ret == NULL))
+ test_msg("when readding an already existing object, existing decoration should be returned");
+}
+
+static void t_lookup(struct test_vars *vars)
+{
+ void *ret = lookup_decoration(&vars->n, vars->one);
+
+ if (!check(ret == NULL))
+ test_msg("lookup should return added declaration");
+ ret = lookup_decoration(&vars->n, vars->two);
+ if (!check(ret == &vars->decoration_b))
+ test_msg("lookup should return added declaration");
+ ret = lookup_decoration(&vars->n, vars->three);
+ if (!check(ret == NULL))
+ test_msg("lookup for unknown object should return NULL");
+}
+
+static void t_loop(struct test_vars *vars)
+{
+ int i, objects_noticed = 0;
+
+ for (i = 0; i < vars->n.size; i++) {
+ if (vars->n.entries[i].base)
+ objects_noticed++;
+ }
+ if (!check_int(objects_noticed, ==, 2))
+ test_msg("should have 2 objects");
+}
+
+int cmd_main(int argc UNUSED, const char **argv UNUSED)
+{
+ struct object_id one_oid = { { 1 } }, two_oid = { { 2 } }, three_oid = { { 3 } };
+ struct test_vars vars = { 0 };
+
+ vars.one = lookup_unknown_object(the_repository, &one_oid);
+ vars.two = lookup_unknown_object(the_repository, &two_oid);
+ vars.three = lookup_unknown_object(the_repository, &three_oid);
+
+ TEST(t_add(&vars),
+ "Add 2 objects, one with a non-NULL decoration and one with a NULL decoration.");
+ TEST(t_readd(&vars),
+ "When re-adding an already existing object, the old decoration is returned.");
+ TEST(t_lookup(&vars),
+ "Lookup returns the added declarations, or NULL if the object was never added.");
+ TEST(t_loop(&vars), "The user can also loop through all entries.");
+
+ clear_decoration(&vars.n, NULL);
+
+ return test_done();
+}
diff --git a/t/unit-tests/t-hash.c b/t/unit-tests/t-hash.c
new file mode 100644
index 0000000000..e9a78bf2c0
--- /dev/null
+++ b/t/unit-tests/t-hash.c
@@ -0,0 +1,84 @@
+#include "test-lib.h"
+#include "hex.h"
+#include "strbuf.h"
+
+static void check_hash_data(const void *data, size_t data_length,
+ const char *expected_hashes[])
+{
+ if (!check(data != NULL)) {
+ test_msg("BUG: NULL data pointer provided");
+ return;
+ }
+
+ for (size_t i = 1; i < ARRAY_SIZE(hash_algos); i++) {
+ git_hash_ctx ctx;
+ unsigned char hash[GIT_MAX_HEXSZ];
+ const struct git_hash_algo *algop = &hash_algos[i];
+
+ algop->init_fn(&ctx);
+ algop->update_fn(&ctx, data, data_length);
+ algop->final_fn(hash, &ctx);
+
+ if (!check_str(hash_to_hex_algop(hash, algop), expected_hashes[i - 1]))
+ test_msg("result does not match with the expected for %s\n", hash_algos[i].name);
+ }
+}
+
+/* Works with a NUL terminated string. Doesn't work if it should contain a NUL character. */
+#define TEST_HASH_STR(data, expected_sha1, expected_sha256) do { \
+ const char *expected_hashes[] = { expected_sha1, expected_sha256 }; \
+ TEST(check_hash_data(data, strlen(data), expected_hashes), \
+ "SHA1 and SHA256 (%s) works", #data); \
+ } while (0)
+
+/* Only works with a literal string, useful when it contains a NUL character. */
+#define TEST_HASH_LITERAL(literal, expected_sha1, expected_sha256) do { \
+ const char *expected_hashes[] = { expected_sha1, expected_sha256 }; \
+ TEST(check_hash_data(literal, (sizeof(literal) - 1), expected_hashes), \
+ "SHA1 and SHA256 (%s) works", #literal); \
+ } while (0)
+
+int cmd_main(int argc, const char **argv)
+{
+ struct strbuf aaaaaaaaaa_100000 = STRBUF_INIT;
+ struct strbuf alphabet_100000 = STRBUF_INIT;
+
+ strbuf_addstrings(&aaaaaaaaaa_100000, "aaaaaaaaaa", 100000);
+ strbuf_addstrings(&alphabet_100000, "abcdefghijklmnopqrstuvwxyz", 100000);
+
+ TEST_HASH_STR("",
+ "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+ TEST_HASH_STR("a",
+ "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8",
+ "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb");
+ TEST_HASH_STR("abc",
+ "a9993e364706816aba3e25717850c26c9cd0d89d",
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
+ TEST_HASH_STR("message digest",
+ "c12252ceda8be8994d5fa0290a47231c1d16aae3",
+ "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650");
+ TEST_HASH_STR("abcdefghijklmnopqrstuvwxyz",
+ "32d10c7b8cf96570ca04ce37f2a19d84240d3a89",
+ "71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73");
+ TEST_HASH_STR(aaaaaaaaaa_100000.buf,
+ "34aa973cd4c4daa4f61eeb2bdbad27316534016f",
+ "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
+ TEST_HASH_STR(alphabet_100000.buf,
+ "e7da7c55b3484fdf52aebec9cbe7b85a98f02fd4",
+ "e406ba321ca712ad35a698bf0af8d61fc4dc40eca6bdcea4697962724ccbde35");
+ TEST_HASH_LITERAL("blob 0\0",
+ "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
+ "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813");
+ TEST_HASH_LITERAL("blob 3\0abc",
+ "f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f",
+ "c1cf6e465077930e88dc5136641d402f72a229ddd996f627d60e9639eaba35a6");
+ TEST_HASH_LITERAL("tree 0\0",
+ "4b825dc642cb6eb9a060e54bf8d69288fbee4904",
+ "6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321");
+
+ strbuf_release(&aaaaaaaaaa_100000);
+ strbuf_release(&alphabet_100000);
+
+ return test_done();
+}
diff --git a/t/unit-tests/t-oidtree.c b/t/unit-tests/t-oidtree.c
new file mode 100644
index 0000000000..a38754b066
--- /dev/null
+++ b/t/unit-tests/t-oidtree.c
@@ -0,0 +1,122 @@
+#include "test-lib.h"
+#include "lib-oid.h"
+#include "oidtree.h"
+#include "hash.h"
+#include "hex.h"
+#include "strvec.h"
+
+#define FILL_TREE(tree, ...) \
+ do { \
+ const char *hexes[] = { __VA_ARGS__ }; \
+ if (fill_tree_loc(tree, hexes, ARRAY_SIZE(hexes))) \
+ return; \
+ } while (0)
+
+static int fill_tree_loc(struct oidtree *ot, const char *hexes[], size_t n)
+{
+ for (size_t i = 0; i < n; i++) {
+ struct object_id oid;
+ if (!check_int(get_oid_arbitrary_hex(hexes[i], &oid), ==, 0))
+ return -1;
+ oidtree_insert(ot, &oid);
+ }
+ return 0;
+}
+
+static void check_contains(struct oidtree *ot, const char *hex, int expected)
+{
+ struct object_id oid;
+
+ if (!check_int(get_oid_arbitrary_hex(hex, &oid), ==, 0))
+ return;
+ if (!check_int(oidtree_contains(ot, &oid), ==, expected))
+ test_msg("oid: %s", oid_to_hex(&oid));
+}
+
+struct expected_hex_iter {
+ size_t i;
+ struct strvec expected_hexes;
+ const char *query;
+};
+
+static enum cb_next check_each_cb(const struct object_id *oid, void *data)
+{
+ struct expected_hex_iter *hex_iter = data;
+ struct object_id expected;
+
+ if (!check_int(hex_iter->i, <, hex_iter->expected_hexes.nr)) {
+ test_msg("error: extraneous callback for query: ('%s'), object_id: ('%s')",
+ hex_iter->query, oid_to_hex(oid));
+ return CB_BREAK;
+ }
+
+ if (!check_int(get_oid_arbitrary_hex(hex_iter->expected_hexes.v[hex_iter->i],
+ &expected), ==, 0))
+ ; /* the data is bogus and cannot be used */
+ else if (!check(oideq(oid, &expected)))
+ test_msg("expected: %s\n got: %s\n query: %s",
+ oid_to_hex(&expected), oid_to_hex(oid), hex_iter->query);
+
+ hex_iter->i += 1;
+ return CB_CONTINUE;
+}
+
+LAST_ARG_MUST_BE_NULL
+static void check_each(struct oidtree *ot, const char *query, ...)
+{
+ struct object_id oid;
+ struct expected_hex_iter hex_iter = { .expected_hexes = STRVEC_INIT,
+ .query = query };
+ const char *arg;
+ va_list hex_args;
+
+ va_start(hex_args, query);
+ while ((arg = va_arg(hex_args, const char *)))
+ strvec_push(&hex_iter.expected_hexes, arg);
+ va_end(hex_args);
+
+ if (!check_int(get_oid_arbitrary_hex(query, &oid), ==, 0))
+ return;
+ oidtree_each(ot, &oid, strlen(query), check_each_cb, &hex_iter);
+
+ if (!check_int(hex_iter.i, ==, hex_iter.expected_hexes.nr))
+ test_msg("error: could not find some 'object_id's for query ('%s')", query);
+ strvec_clear(&hex_iter.expected_hexes);
+}
+
+static void setup(void (*f)(struct oidtree *ot))
+{
+ struct oidtree ot;
+
+ oidtree_init(&ot);
+ f(&ot);
+ oidtree_clear(&ot);
+}
+
+static void t_contains(struct oidtree *ot)
+{
+ FILL_TREE(ot, "444", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e");
+ check_contains(ot, "44", 0);
+ check_contains(ot, "441", 0);
+ check_contains(ot, "440", 0);
+ check_contains(ot, "444", 1);
+ check_contains(ot, "4440", 1);
+ check_contains(ot, "4444", 0);
+}
+
+static void t_each(struct oidtree *ot)
+{
+ FILL_TREE(ot, "f", "9", "8", "123", "321", "320", "a", "b", "c", "d", "e");
+ check_each(ot, "12300", "123", NULL);
+ check_each(ot, "3211", NULL); /* should not reach callback */
+ check_each(ot, "3210", "321", NULL);
+ check_each(ot, "32100", "321", NULL);
+ check_each(ot, "32", "320", "321", NULL);
+}
+
+int cmd_main(int argc UNUSED, const char **argv UNUSED)
+{
+ TEST(setup(t_contains), "oidtree insert and contains works");
+ TEST(setup(t_each), "oidtree each works");
+ return test_done();
+}
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c
new file mode 100644
index 0000000000..4e80bdf16d
--- /dev/null
+++ b/t/unit-tests/t-reftable-basics.c
@@ -0,0 +1,160 @@
+/*
+Copyright 2020 Google LLC
+
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file or at
+https://developers.google.com/open-source/licenses/bsd
+*/
+
+#include "test-lib.h"
+#include "reftable/basics.h"
+
+struct integer_needle_lesseq_args {
+ int needle;
+ int *haystack;
+};
+
+static int integer_needle_lesseq(size_t i, void *_args)
+{
+ struct integer_needle_lesseq_args *args = _args;
+ return args->needle <= args->haystack[i];
+}
+
+static void test_binsearch(void)
+{
+ int haystack[] = { 2, 4, 6, 8, 10 };
+ struct {
+ int needle;
+ size_t expected_idx;
+ } testcases[] = {
+ {-9000, 0},
+ {-1, 0},
+ {0, 0},
+ {2, 0},
+ {3, 1},
+ {4, 1},
+ {7, 3},
+ {9, 4},
+ {10, 4},
+ {11, 5},
+ {9000, 5},
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) {
+ struct integer_needle_lesseq_args args = {
+ .haystack = haystack,
+ .needle = testcases[i].needle,
+ };
+ size_t idx;
+
+ idx = binsearch(ARRAY_SIZE(haystack), &integer_needle_lesseq, &args);
+ check_int(idx, ==, testcases[i].expected_idx);
+ }
+}
+
+static void test_names_length(void)
+{
+ const char *a[] = { "a", "b", NULL };
+ check_int(names_length(a), ==, 2);
+}
+
+static void test_names_equal(void)
+{
+ const char *a[] = { "a", "b", "c", NULL };
+ const char *b[] = { "a", "b", "d", NULL };
+ const char *c[] = { "a", "b", NULL };
+
+ check(names_equal(a, a));
+ check(!names_equal(a, b));
+ check(!names_equal(a, c));
+}
+
+static void test_parse_names_normal(void)
+{
+ char in1[] = "line\n";
+ char in2[] = "a\nb\nc";
+ char **out = NULL;
+ parse_names(in1, strlen(in1), &out);
+ check_str(out[0], "line");
+ check(!out[1]);
+ free_names(out);
+
+ parse_names(in2, strlen(in2), &out);
+ check_str(out[0], "a");
+ check_str(out[1], "b");
+ check_str(out[2], "c");
+ check(!out[3]);
+ free_names(out);
+}
+
+static void test_parse_names_drop_empty(void)
+{
+ char in[] = "a\n\nb\n";
+ char **out = NULL;
+ parse_names(in, strlen(in), &out);
+ check_str(out[0], "a");
+ /* simply '\n' should be dropped as empty string */
+ check_str(out[1], "b");
+ check(!out[2]);
+ free_names(out);
+}
+
+static void test_common_prefix(void)
+{
+ struct strbuf a = STRBUF_INIT;
+ struct strbuf b = STRBUF_INIT;
+ struct {
+ const char *a, *b;
+ int want;
+ } cases[] = {
+ {"abcdef", "abc", 3},
+ { "abc", "ab", 2 },
+ { "", "abc", 0 },
+ { "abc", "abd", 2 },
+ { "abc", "pqr", 0 },
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(cases); i++) {
+ strbuf_addstr(&a, cases[i].a);
+ strbuf_addstr(&b, cases[i].b);
+ check_int(common_prefix_size(&a, &b), ==, cases[i].want);
+ strbuf_reset(&a);
+ strbuf_reset(&b);
+ }
+ strbuf_release(&a);
+ strbuf_release(&b);
+}
+
+static void test_u24_roundtrip(void)
+{
+ uint32_t in = 0x112233;
+ uint8_t dest[3];
+ uint32_t out;
+ put_be24(dest, in);
+ out = get_be24(dest);
+ check_int(in, ==, out);
+}
+
+static void test_u16_roundtrip(void)
+{
+ uint32_t in = 0xfef1;
+ uint8_t dest[3];
+ uint32_t out;
+ put_be16(dest, in);
+ out = get_be16(dest);
+ check_int(in, ==, out);
+}
+
+int cmd_main(int argc, const char *argv[])
+{
+ TEST(test_common_prefix(), "common_prefix_size works");
+ TEST(test_parse_names_normal(), "parse_names works for basic input");
+ TEST(test_parse_names_drop_empty(), "parse_names drops empty string");
+ TEST(test_binsearch(), "binary search with binsearch works");
+ TEST(test_names_length(), "names_length retuns size of a NULL-terminated string array");
+ TEST(test_names_equal(), "names_equal compares NULL-terminated string arrays");
+ TEST(test_u24_roundtrip(), "put_be24 and get_be24 work");
+ TEST(test_u16_roundtrip(), "put_be16 and get_be16 work");
+
+ return test_done();
+}
diff --git a/t/unit-tests/t-strbuf.c b/t/unit-tests/t-strbuf.c
index de434a4441..6027dafef7 100644
--- a/t/unit-tests/t-strbuf.c
+++ b/t/unit-tests/t-strbuf.c
@@ -2,7 +2,8 @@
#include "strbuf.h"
/* wrapper that supplies tests with an empty, initialized strbuf */
-static void setup(void (*f)(struct strbuf*, void*), void *data)
+static void setup(void (*f)(struct strbuf*, const void*),
+ const void *data)
{
struct strbuf buf = STRBUF_INIT;
@@ -13,7 +14,8 @@ static void setup(void (*f)(struct strbuf*, void*), void *data)
}
/* wrapper that supplies tests with a populated, initialized strbuf */
-static void setup_populated(void (*f)(struct strbuf*, void*), char *init_str, void *data)
+static void setup_populated(void (*f)(struct strbuf*, const void*),
+ const char *init_str, const void *data)
{
struct strbuf buf = STRBUF_INIT;
@@ -64,7 +66,7 @@ static void t_dynamic_init(void)
strbuf_release(&buf);
}
-static void t_addch(struct strbuf *buf, void *data)
+static void t_addch(struct strbuf *buf, const void *data)
{
const char *p_ch = data;
const char ch = *p_ch;
@@ -83,7 +85,7 @@ static void t_addch(struct strbuf *buf, void *data)
check_char(buf->buf[buf->len], ==, '\0');
}
-static void t_addstr(struct strbuf *buf, void *data)
+static void t_addstr(struct strbuf *buf, const void *data)
{
const char *text = data;
size_t len = strlen(text);
diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
index f17fb10d9e..d4615ab06d 100644
--- a/t/unit-tests/t-strvec.c
+++ b/t/unit-tests/t-strvec.c
@@ -4,6 +4,7 @@
#define check_strvec(vec, ...) \
check_strvec_loc(TEST_LOCATION(), vec, __VA_ARGS__)
+LAST_ARG_MUST_BE_NULL
static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
{
va_list ap;
@@ -22,11 +23,13 @@ static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr);
test_assert(loc, msg.buf, 0);
strbuf_release(&msg);
+ va_end(ap);
return;
}
nr++;
}
+ va_end(ap);
check_uint(vec->nr, ==, nr);
check_uint(vec->alloc, >=, nr);