diff options
Diffstat (limited to 't')
94 files changed, 2165 insertions, 679 deletions
@@ -415,6 +415,10 @@ GIT_TEST_PACK_SPARSE=<boolean> if disabled will default the pack-objects builtin to use the non-sparse object walk. This can still be overridden by the --sparse command-line argument. +GIT_TEST_PACK_PATH_WALK=<boolean> if enabled will default the pack-objects +builtin to use the path-walk API for the object walk. This can still be +overridden by the --no-path-walk command-line argument. + GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path by overriding the minimum number of cache entries required per thread. diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c index 3f23f21072..16a01669e4 100644 --- a/t/helper/test-bitmap.c +++ b/t/helper/test-bitmap.c @@ -10,6 +10,11 @@ static int bitmap_list_commits(void) return test_bitmap_commits(the_repository); } +static int bitmap_list_commits_with_offset(void) +{ + return test_bitmap_commits_with_offset(the_repository); +} + static int bitmap_dump_hashes(void) { return test_bitmap_hashes(the_repository); @@ -36,6 +41,8 @@ int cmd__bitmap(int argc, const char **argv) if (argc == 2 && !strcmp(argv[1], "list-commits")) return bitmap_list_commits(); + if (argc == 2 && !strcmp(argv[1], "list-commits-with-offset")) + return bitmap_list_commits_with_offset(); if (argc == 2 && !strcmp(argv[1], "dump-hashes")) return bitmap_dump_hashes(); if (argc == 2 && !strcmp(argv[1], "dump-pseudo-merges")) @@ -46,6 +53,7 @@ int cmd__bitmap(int argc, const char **argv) return bitmap_dump_pseudo_merge_objects(atoi(argv[2])); usage("\ttest-tool bitmap list-commits\n" + "\ttest-tool bitmap list-commits-with-offset\n" "\ttest-tool bitmap dump-hashes\n" "\ttest-tool bitmap dump-pseudo-merges\n" "\ttest-tool bitmap dump-pseudo-merge-commits <n>\n" diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c index 9aa2c5a592..3283544bd3 100644 --- a/t/helper/test-bloom.c +++ b/t/helper/test-bloom.c @@ -12,13 +12,13 @@ static struct bloom_filter_settings settings = DEFAULT_BLOOM_FILTER_SETTINGS; static void add_string_to_filter(const char *data, struct bloom_filter *filter) { struct bloom_key key; - fill_bloom_key(data, strlen(data), &key, &settings); + bloom_key_fill(&key, data, strlen(data), &settings); printf("Hashes:"); for (size_t i = 0; i < settings.num_hashes; i++) printf("0x%08x|", key.hashes[i]); printf("\n"); add_key_to_filter(&key, filter, &settings); - clear_bloom_key(&key); + bloom_key_clear(&key); } static void print_bloom_filter(struct bloom_filter *filter) { @@ -61,13 +61,13 @@ int cmd__bloom(int argc, const char **argv) uint32_t hashed; if (argc < 3) usage(bloom_usage); - hashed = murmur3_seeded_v2(0, argv[2], strlen(argv[2])); + hashed = test_bloom_murmur3_seeded(0, argv[2], strlen(argv[2]), 2); printf("Murmur3 Hash with seed=0:0x%08x\n", hashed); } if (!strcmp(argv[1], "get_murmur3_seven_highbit")) { uint32_t hashed; - hashed = murmur3_seeded_v2(0, "\x99\xaa\xbb\xcc\xdd\xee\xff", 7); + hashed = test_bloom_murmur3_seeded(0, "\x99\xaa\xbb\xcc\xdd\xee\xff", 7, 2); printf("Murmur3 Hash with seed=0:0x%08x\n", hashed); } diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c index 76c2f4eba8..611a13a326 100644 --- a/t/helper/test-find-pack.c +++ b/t/helper/test-find-pack.c @@ -2,7 +2,7 @@ #include "test-tool.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "packfile.h" #include "parse-options.h" #include "setup.h" diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c index fdf1b13437..d51aaa3dc4 100644 --- a/t/helper/test-pack-mtimes.c +++ b/t/helper/test-pack-mtimes.c @@ -3,7 +3,7 @@ #include "test-tool.h" #include "hex.h" #include "strbuf.h" -#include "object-store.h" +#include "odb.h" #include "packfile.h" #include "pack-mtimes.h" #include "setup.h" diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index f2663dd0c0..68579d83f3 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -131,6 +131,7 @@ int cmd__parse_options(int argc, const char **argv) .short_name = 'B', .long_name = "no-fear", .value = &boolean, + .precision = sizeof(boolean), .help = "be brave", .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, .defval = 1, @@ -148,9 +149,16 @@ int cmd__parse_options(int argc, const char **argv) OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23), OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1), OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2), - OPT_CALLBACK_F(0, "mode34", &integer, "(3|4)", - "set integer to 3 or 4 (cmdmode option)", - PARSE_OPT_CMDMODE, mode34_callback), + { + .type = OPTION_CALLBACK, + .long_name = "mode34", + .value = &integer, + .precision = sizeof(integer), + .argh = "(3|4)", + .help = "set integer to 3 or 4 (cmdmode option)", + .flags = PARSE_OPT_CMDMODE, + .callback = mode34_callback, + }, OPT_CALLBACK('L', "length", &integer, "str", "get length of <str>", length_callback), OPT_FILENAME('F', "file", &file, "set file to <file>"), @@ -170,6 +178,7 @@ int cmd__parse_options(int argc, const char **argv) .type = OPTION_COUNTUP, .short_name = '+', .value = &boolean, + .precision = sizeof(boolean), .help = "same as -b", .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH, }, @@ -177,6 +186,7 @@ int cmd__parse_options(int argc, const char **argv) .type = OPTION_COUNTUP, .long_name = "ambiguous", .value = &ambiguous, + .precision = sizeof(ambiguous), .help = "positive ambiguity", .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, }, @@ -184,6 +194,7 @@ int cmd__parse_options(int argc, const char **argv) .type = OPTION_COUNTUP, .long_name = "no-ambiguous", .value = &ambiguous, + .precision = sizeof(ambiguous), .help = "negative ambiguity", .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, }, diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c index 34f1aee558..d848800749 100644 --- a/t/helper/test-partial-clone.c +++ b/t/helper/test-partial-clone.c @@ -1,7 +1,7 @@ #include "test-tool.h" #include "hex.h" #include "repository.h" -#include "object-store.h" +#include "odb.h" #include "setup.h" /* @@ -23,7 +23,7 @@ static void object_info(const char *gitdir, const char *oid_hex) die("could not init repo"); if (parse_oid_hex_algop(oid_hex, &oid, &p, r.hash_algo)) die("could not parse oid"); - if (oid_object_info_extended(&r, &oid, &oi, 0)) + if (odb_read_object_info_extended(r.objects, &oid, &oi, 0)) die("could not obtain object info"); printf("%d\n", (int) size); diff --git a/t/helper/test-path-walk.c b/t/helper/test-path-walk.c index 61e845e5ec..fe63002c2b 100644 --- a/t/helper/test-path-walk.c +++ b/t/helper/test-path-walk.c @@ -82,6 +82,8 @@ int cmd__path_walk(int argc, const char **argv) N_("toggle inclusion of tree objects")), OPT_BOOL(0, "prune", &info.prune_all_uninteresting, N_("toggle pruning of uninteresting paths")), + OPT_BOOL(0, "edge-aggressive", &info.edge_aggressive, + N_("toggle aggressive edge walk")), OPT_BOOL(0, "stdin-pl", &stdin_pl, N_("read a pattern list over stdin")), OPT_END(), diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c index 8b413b644b..ef5339bbee 100644 --- a/t/helper/test-read-graph.c +++ b/t/helper/test-read-graph.c @@ -3,7 +3,7 @@ #include "test-tool.h" #include "commit-graph.h" #include "repository.h" -#include "object-store.h" +#include "odb.h" #include "bloom.h" #include "setup.h" @@ -73,15 +73,15 @@ static void dump_graph_bloom_filters(struct commit_graph *graph) int cmd__read_graph(int argc, const char **argv) { struct commit_graph *graph = NULL; - struct object_directory *odb; + struct odb_source *source; int ret = 0; setup_git_directory(); - odb = the_repository->objects->odb; + source = the_repository->objects->sources; prepare_repo_settings(the_repository); - graph = read_commit_graph_one(the_repository, odb); + graph = read_commit_graph_one(the_repository, source); if (!graph) { ret = 1; goto done; diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c index ac81390899..da2aa036b5 100644 --- a/t/helper/test-read-midx.c +++ b/t/helper/test-read-midx.c @@ -4,7 +4,7 @@ #include "hex.h" #include "midx.h" #include "repository.h" -#include "object-store.h" +#include "odb.h" #include "pack-bitmap.h" #include "packfile.h" #include "setup.h" diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 4cfc7c90b5..8d9a271845 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -5,7 +5,7 @@ #include "refs.h" #include "setup.h" #include "worktree.h" -#include "object-store.h" +#include "odb.h" #include "path.h" #include "repository.h" #include "strbuf.h" @@ -79,7 +79,7 @@ static const char **get_store(const char **argv, struct ref_store **refs) if (!repo_submodule_path_append(the_repository, &sb, gitdir, "objects/")) die("computing submodule path failed"); - add_to_alternates_memory(sb.buf); + odb_add_to_alternates_memory(the_repository->objects, sb.buf); strbuf_release(&sb); *refs = repo_get_submodule_ref_store(the_repository, gitdir); diff --git a/t/helper/test-string-list.c b/t/helper/test-string-list.c index 6f10c5a435..6be0cdb8e2 100644 --- a/t/helper/test-string-list.c +++ b/t/helper/test-string-list.c @@ -1,105 +1,9 @@ -#define DISABLE_SIGN_COMPARE_WARNINGS - #include "test-tool.h" #include "strbuf.h" #include "string-list.h" -/* - * Parse an argument into a string list. arg should either be a - * ':'-separated list of strings, or "-" to indicate an empty string - * list (as opposed to "", which indicates a string list containing a - * single empty string). list->strdup_strings must be set. - */ -static void parse_string_list(struct string_list *list, const char *arg) -{ - if (!strcmp(arg, "-")) - return; - - (void)string_list_split(list, arg, ':', -1); -} - -static void write_list(const struct string_list *list) -{ - int i; - for (i = 0; i < list->nr; i++) - printf("[%d]: \"%s\"\n", i, list->items[i].string); -} - -static void write_list_compact(const struct string_list *list) -{ - int i; - if (!list->nr) - printf("-\n"); - else { - printf("%s", list->items[0].string); - for (i = 1; i < list->nr; i++) - printf(":%s", list->items[i].string); - printf("\n"); - } -} - -static int prefix_cb(struct string_list_item *item, void *cb_data) -{ - const char *prefix = (const char *)cb_data; - return starts_with(item->string, prefix); -} - int cmd__string_list(int argc, const char **argv) { - if (argc == 5 && !strcmp(argv[1], "split")) { - struct string_list list = STRING_LIST_INIT_DUP; - int i; - const char *s = argv[2]; - int delim = *argv[3]; - int maxsplit = atoi(argv[4]); - - i = string_list_split(&list, s, delim, maxsplit); - printf("%d\n", i); - write_list(&list); - string_list_clear(&list, 0); - return 0; - } - - if (argc == 5 && !strcmp(argv[1], "split_in_place")) { - struct string_list list = STRING_LIST_INIT_NODUP; - int i; - char *s = xstrdup(argv[2]); - const char *delim = argv[3]; - int maxsplit = atoi(argv[4]); - - i = string_list_split_in_place(&list, s, delim, maxsplit); - printf("%d\n", i); - write_list(&list); - string_list_clear(&list, 0); - free(s); - return 0; - } - - if (argc == 4 && !strcmp(argv[1], "filter")) { - /* - * Retain only the items that have the specified prefix. - * Arguments: list|- prefix - */ - struct string_list list = STRING_LIST_INIT_DUP; - const char *prefix = argv[3]; - - parse_string_list(&list, argv[2]); - filter_string_list(&list, 0, prefix_cb, (void *)prefix); - write_list_compact(&list); - string_list_clear(&list, 0); - return 0; - } - - if (argc == 3 && !strcmp(argv[1], "remove_duplicates")) { - struct string_list list = STRING_LIST_INIT_DUP; - - parse_string_list(&list, argv[2]); - string_list_remove_duplicates(&list, 0); - write_list_compact(&list); - string_list_clear(&list, 0); - return 0; - } - if (argc == 2 && !strcmp(argv[1], "sort")) { struct string_list list = STRING_LIST_INIT_NODUP; struct strbuf sb = STRBUF_INIT; diff --git a/t/meson.build b/t/meson.build index be96a9639f..09f3068f98 100644 --- a/t/meson.build +++ b/t/meson.build @@ -19,6 +19,7 @@ clar_test_suites = [ 'unit-tests/u-reftable-tree.c', 'unit-tests/u-strbuf.c', 'unit-tests/u-strcmp-offset.c', + 'unit-tests/u-string-list.c', 'unit-tests/u-strvec.c', 'unit-tests/u-trailer.c', 'unit-tests/u-urlmatch-normalization.c', @@ -60,7 +61,7 @@ clar_unit_tests = executable('unit-tests', sources: clar_sources + clar_test_suites, dependencies: [libgit_commonmain], ) -test('unit-tests', clar_unit_tests) +test('unit-tests', clar_unit_tests, kwargs: test_kwargs) subdir('helper') @@ -105,7 +106,6 @@ integration_tests = [ 't0060-path-utils.sh', 't0061-run-command.sh', 't0062-revision-walking.sh', - 't0063-string-list.sh', 't0066-dir-iterator.sh', 't0067-parse_pathspec_file.sh', 't0068-for-each-repo.sh', @@ -160,7 +160,6 @@ integration_tests = [ 't1015-read-index-unmerged.sh', 't1016-compatObjectFormat.sh', 't1020-subdirectory.sh', - 't1021-rerere-in-workdir.sh', 't1022-read-tree-partial-clone.sh', 't1050-large.sh', 't1051-large-conversion.sh', @@ -1099,6 +1098,7 @@ benchmarks = [ 'perf/p1450-fsck.sh', 'perf/p1451-fsck-skip-list.sh', 'perf/p1500-graph-walks.sh', + 'perf/p1501-rev-parse-oneline.sh', 'perf/p2000-sparse-operations.sh', 'perf/p3400-rebase.sh', 'perf/p3404-rebase-interactive.sh', @@ -1192,7 +1192,7 @@ foreach integration_test : integration_tests workdir: meson.current_source_dir(), env: test_environment, depends: test_dependencies + bin_wrappers, - timeout: 0, + kwargs: test_kwargs, ) endforeach diff --git a/t/perf/p1501-rev-parse-oneline.sh b/t/perf/p1501-rev-parse-oneline.sh new file mode 100755 index 0000000000..538fa9c404 --- /dev/null +++ b/t/perf/p1501-rev-parse-oneline.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +test_description='Test :/ object name notation' + +. ./perf-lib.sh + +test_perf_fresh_repo + +# +# Creates lots of merges to make history traversal costly. In +# particular it creates 2^($max_level-1)-1 2-way merges on top of +# 2^($max_level-1) root commits. E.g., the commit history looks like +# this for a $max_level of 3: +# +# _1_ +# / \ +# 2 3 +# / \ / \ +# 4 5 6 7 +# +# The numbers are the fast-import marks, which also are the commit +# messages. 1 is the HEAD commit and a merge, 2 and 3 are also merges, +# 4-7 are the root commits. +# +build_history () { + local max_level="$1" && + local level="${2:-1}" && + local mark="${3:-1}" && + if test $level -eq $max_level + then + echo "reset refs/heads/master" && + echo "from $ZERO_OID" && + echo "commit refs/heads/master" && + echo "mark :$mark" && + echo "committer C <c@example.com> 1234567890 +0000" && + echo "data <<EOF" && + echo "$mark" && + echo "EOF" + else + local level1=$((level+1)) && + local mark1=$((2*mark)) && + local mark2=$((2*mark+1)) && + build_history $max_level $level1 $mark1 && + build_history $max_level $level1 $mark2 && + echo "commit refs/heads/master" && + echo "mark :$mark" && + echo "committer C <c@example.com> 1234567890 +0000" && + echo "data <<EOF" && + echo "$mark" && + echo "EOF" && + echo "from :$mark1" && + echo "merge :$mark2" + fi +} + +test_expect_success 'setup' ' + build_history 16 | git fast-import && + git log --format="%H %s" --reverse >commits && + sed -n -e "s/ .*$//p" -e "q" <commits >expect && + sed -n -e "s/^.* //p" -e "q" <commits >needle +' + +test_perf "rev-parse :/$(cat needle)" ' + git rev-parse :/$(cat needle) >actual +' + +test_expect_success 'verify result' ' + test_cmp expect actual +' + +test_done diff --git a/t/perf/p5313-pack-objects.sh b/t/perf/p5313-pack-objects.sh index 786a2c1c6f..46a6cd32d2 100755 --- a/t/perf/p5313-pack-objects.sh +++ b/t/perf/p5313-pack-objects.sh @@ -22,46 +22,53 @@ test_expect_success 'create rev input' ' EOF ' -for version in 1 2 -do - export version +test_all_with_args () { + parameter=$1 + export parameter - test_perf "thin pack with version $version" ' + test_perf "thin pack with $parameter" ' git pack-objects --thin --stdout --revs --sparse \ - --name-hash-version=$version <in-thin >out + $parameter <in-thin >out ' - test_size "thin pack size with version $version" ' + test_size "thin pack size with $parameter" ' test_file_size out ' - test_perf "big pack with version $version" ' + test_perf "big pack with $parameter" ' git pack-objects --stdout --revs --sparse \ - --name-hash-version=$version <in-big >out + $parameter <in-big >out ' - test_size "big pack size with version $version" ' + test_size "big pack size with $parameter" ' test_file_size out ' - test_perf "shallow fetch pack with version $version" ' + test_perf "shallow fetch pack with $parameter" ' git pack-objects --stdout --revs --sparse --shallow \ - --name-hash-version=$version <in-shallow >out + $parameter <in-shallow >out ' - test_size "shallow pack size with version $version" ' + test_size "shallow pack size with $parameter" ' test_file_size out ' - test_perf "repack with version $version" ' - git repack -adf --name-hash-version=$version + test_perf "repack with $parameter" ' + git repack -adf $parameter ' - test_size "repack size with version $version" ' + test_size "repack size with $parameter" ' gitdir=$(git rev-parse --git-dir) && pack=$(ls $gitdir/objects/pack/pack-*.pack) && test_file_size "$pack" ' +} + +for version in 1 2 +do + test_all_with_args --name-hash-version=$version done +test_all_with_args --path-walk + test_done diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 35c5c2b4f9..2b63e1c86c 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -130,7 +130,7 @@ test_expect_success 'subtest: a failing TODO test' ' ' test_expect_success 'subtest: a passing TODO test' ' - write_and_run_sub_test_lib_test passing-todo <<-\EOF && + write_and_run_sub_test_lib_test_err passing-todo <<-\EOF && test_expect_failure "pretend we have fixed a known breakage" "true" test_done EOF @@ -142,7 +142,7 @@ test_expect_success 'subtest: a passing TODO test' ' ' test_expect_success 'subtest: 2 TODO tests, one passin' ' - write_and_run_sub_test_lib_test partially-passing-todos <<-\EOF && + write_and_run_sub_test_lib_test_err partially-passing-todos <<-\EOF && test_expect_failure "pretend we have a known breakage" "false" test_expect_success "pretend we have a passing test" "true" test_expect_failure "pretend we have fixed another known breakage" "true" @@ -219,41 +219,44 @@ test_expect_success 'subtest: --verbose option' ' test_expect_success "failing test" false test_done EOF - mv t1234-verbose/out t1234-verbose/out+ && - grep -v "^Initialized empty" t1234-verbose/out+ >t1234-verbose/out && - check_sub_test_lib_test t1234-verbose <<-\EOF - > expecting success of 1234.1 '\''passing test'\'': true + mv t1234-verbose/err t1234-verbose/err+ && + grep -v "^Initialized empty" t1234-verbose/err+ >t1234-verbose/err && + check_sub_test_lib_test_err t1234-verbose \ + <<-\EOF_OUT 3<<-\EOF_ERR > ok 1 - passing test + > ok 2 - test with output + > not ok 3 - failing test + > # false + > # failed 1 among 3 test(s) + > 1..3 + EOF_OUT + > expecting success of 1234.1 '\''passing test'\'': true > Z > expecting success of 1234.2 '\''test with output'\'': echo foo > foo - > ok 2 - test with output > Z > expecting success of 1234.3 '\''failing test'\'': false - > not ok 3 - failing test - > # false > Z - > # failed 1 among 3 test(s) - > 1..3 - EOF + EOF_ERR ' test_expect_success 'subtest: --verbose-only option' ' run_sub_test_lib_test_err \ t1234-verbose \ --verbose-only=2 && - check_sub_test_lib_test t1234-verbose <<-\EOF + check_sub_test_lib_test_err t1234-verbose <<-\EOF_OUT 3<<-\EOF_ERR > ok 1 - passing test - > Z - > expecting success of 1234.2 '\''test with output'\'': echo foo - > foo > ok 2 - test with output - > Z > not ok 3 - failing test > # false > # failed 1 among 3 test(s) > 1..3 - EOF + EOF_OUT + > Z + > expecting success of 1234.2 '\''test with output'\'': echo foo + > foo + > Z + EOF_ERR ' test_expect_success 'subtest: skip one with GIT_SKIP_TESTS' ' diff --git a/t/t0001-init.sh b/t/t0001-init.sh index f11a40811f..f593c53687 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -658,6 +658,17 @@ test_expect_success 'init warns about invalid init.defaultRefFormat' ' test_cmp expected actual ' +test_expect_success 'default ref format' ' + test_when_finished "rm -rf refformat" && + ( + sane_unset GIT_DEFAULT_REF_FORMAT && + git init refformat + ) && + git version --build-options | sed -ne "s/^default-ref-format: //p" >expect && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual +' + backends="files reftable" for format in $backends do @@ -738,6 +749,40 @@ test_expect_success "GIT_DEFAULT_REF_FORMAT= overrides init.defaultRefFormat" ' test_cmp expect actual ' +test_expect_success "init with feature.experimental=true" ' + test_when_finished "rm -rf refformat" && + test_config_global feature.experimental true && + ( + sane_unset GIT_DEFAULT_REF_FORMAT && + git init refformat + ) && + echo reftable >expect && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual +' + +test_expect_success "init.defaultRefFormat overrides feature.experimental=true" ' + test_when_finished "rm -rf refformat" && + test_config_global feature.experimental true && + test_config_global init.defaultRefFormat files && + ( + sane_unset GIT_DEFAULT_REF_FORMAT && + git init refformat + ) && + echo files >expect && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual +' + +test_expect_success "GIT_DEFAULT_REF_FORMAT= overrides feature.experimental=true" ' + test_when_finished "rm -rf refformat" && + test_config_global feature.experimental true && + GIT_DEFAULT_REF_FORMAT=files git init refformat && + echo files >expect && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual +' + for from_format in $backends do test_expect_success "re-init with same format ($from_format)" ' diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index bf10d253ec..f0d50d769e 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -281,7 +281,7 @@ test_expect_success 'required filter with absent smudge field' ' test_expect_success 'filtering large input to small output should use little memory' ' test_config filter.devnull.clean "cat >/dev/null" && test_config filter.devnull.required true && - for i in $(test_seq 1 30); do printf "%1048576d" 1 || return 1; done >30MB && + test_seq -f "%1048576d" 1 30 >30MB && echo "30MB filter=devnull" >.gitattributes && GIT_MMAP_LIMIT=1m GIT_ALLOC_LIMIT=1m git add 30MB ' @@ -299,7 +299,7 @@ test_expect_success 'filter that does not read is fine' ' test_expect_success EXPENSIVE 'filter large file' ' test_config filter.largefile.smudge cat && test_config filter.largefile.clean cat && - for i in $(test_seq 1 2048); do printf "%1048576d" 1 || return 1; done >2GB && + test_seq -f "%1048576d" 1 2048 >2GB && echo "2GB filter=largefile" >.gitattributes && git add 2GB 2>err && test_must_be_empty err && diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh index 5c9dc90d0b..ca8568067d 100755 --- a/t/t0050-filesystem.sh +++ b/t/t0050-filesystem.sh @@ -10,53 +10,35 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME auml=$(printf '\303\244') aumlcdiar=$(printf '\141\314\210') -if test_have_prereq CASE_INSENSITIVE_FS -then - say "will test on a case insensitive filesystem" - test_case=test_expect_failure -else - test_case=test_expect_success -fi - if test_have_prereq UTF8_NFD_TO_NFC then - say "will test on a unicode corrupting filesystem" test_unicode=test_expect_failure else test_unicode=test_expect_success fi -test_have_prereq SYMLINKS || - say "will test on a filesystem lacking symbolic links" - -if test_have_prereq CASE_INSENSITIVE_FS -then -test_expect_success "detection of case insensitive filesystem during repo init" ' +test_expect_success CASE_INSENSITIVE_FS "detection of case insensitive filesystem during repo init" ' test $(git config --bool core.ignorecase) = true ' -else -test_expect_success "detection of case insensitive filesystem during repo init" ' + +test_expect_success !CASE_INSENSITIVE_FS "detection of case insensitive filesystem during repo init" ' { test_must_fail git config --bool core.ignorecase >/dev/null || test $(git config --bool core.ignorecase) = false } ' -fi -if test_have_prereq SYMLINKS -then -test_expect_success "detection of filesystem w/o symlink support during repo init" ' +test_expect_success SYMLINKS "detection of filesystem w/o symlink support during repo init" ' { test_must_fail git config --bool core.symlinks || test "$(git config --bool core.symlinks)" = true } ' -else -test_expect_success "detection of filesystem w/o symlink support during repo init" ' + +test_expect_success !SYMLINKS "detection of filesystem w/o symlink support during repo init" ' v=$(git config --bool core.symlinks) && test "$v" = false ' -fi test_expect_success "setup case tests" ' git config core.ignorecase true && diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh deleted file mode 100755 index aac63ba506..0000000000 --- a/t/t0063-string-list.sh +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2012 Michael Haggerty -# - -test_description='Test string list functionality' - -. ./test-lib.sh - -test_split () { - cat >expected && - test_expect_success "split $1 at $2, max $3" " - test-tool string-list split '$1' '$2' '$3' >actual && - test_cmp expected actual && - test-tool string-list split_in_place '$1' '$2' '$3' >actual && - test_cmp expected actual - " -} - -test_split_in_place() { - cat >expected && - test_expect_success "split (in place) $1 at $2, max $3" " - test-tool string-list split_in_place '$1' '$2' '$3' >actual && - test_cmp expected actual - " -} - -test_split "foo:bar:baz" ":" "-1" <<EOF -3 -[0]: "foo" -[1]: "bar" -[2]: "baz" -EOF - -test_split "foo:bar:baz" ":" "0" <<EOF -1 -[0]: "foo:bar:baz" -EOF - -test_split "foo:bar:baz" ":" "1" <<EOF -2 -[0]: "foo" -[1]: "bar:baz" -EOF - -test_split "foo:bar:baz" ":" "2" <<EOF -3 -[0]: "foo" -[1]: "bar" -[2]: "baz" -EOF - -test_split "foo:bar:" ":" "-1" <<EOF -3 -[0]: "foo" -[1]: "bar" -[2]: "" -EOF - -test_split "" ":" "-1" <<EOF -1 -[0]: "" -EOF - -test_split ":" ":" "-1" <<EOF -2 -[0]: "" -[1]: "" -EOF - -test_split_in_place "foo:;:bar:;:baz:;:" ":;" "-1" <<EOF -10 -[0]: "foo" -[1]: "" -[2]: "" -[3]: "bar" -[4]: "" -[5]: "" -[6]: "baz" -[7]: "" -[8]: "" -[9]: "" -EOF - -test_split_in_place "foo:;:bar:;:baz" ":;" "0" <<EOF -1 -[0]: "foo:;:bar:;:baz" -EOF - -test_split_in_place "foo:;:bar:;:baz" ":;" "1" <<EOF -2 -[0]: "foo" -[1]: ";:bar:;:baz" -EOF - -test_split_in_place "foo:;:bar:;:baz" ":;" "2" <<EOF -3 -[0]: "foo" -[1]: "" -[2]: ":bar:;:baz" -EOF - -test_split_in_place "foo:;:bar:;:" ":;" "-1" <<EOF -7 -[0]: "foo" -[1]: "" -[2]: "" -[3]: "bar" -[4]: "" -[5]: "" -[6]: "" -EOF - -test_expect_success "test filter_string_list" ' - test "x-" = "x$(test-tool string-list filter - y)" && - test "x-" = "x$(test-tool string-list filter no y)" && - test yes = "$(test-tool string-list filter yes y)" && - test yes = "$(test-tool string-list filter no:yes y)" && - test yes = "$(test-tool string-list filter yes:no y)" && - test y1:y2 = "$(test-tool string-list filter y1:y2 y)" && - test y2:y1 = "$(test-tool string-list filter y2:y1 y)" && - test "x-" = "x$(test-tool string-list filter x1:x2 y)" -' - -test_expect_success "test remove_duplicates" ' - test "x-" = "x$(test-tool string-list remove_duplicates -)" && - test "x" = "x$(test-tool string-list remove_duplicates "")" && - test a = "$(test-tool string-list remove_duplicates a)" && - test a = "$(test-tool string-list remove_duplicates a:a)" && - test a = "$(test-tool string-list remove_duplicates a:a:a:a:a)" && - test a:b = "$(test-tool string-list remove_duplicates a:b)" && - test a:b = "$(test-tool string-list remove_duplicates a:a:b)" && - test a:b = "$(test-tool string-list remove_duplicates a:b:b)" && - test a:b:c = "$(test-tool string-list remove_duplicates a:b:c)" && - test a:b:c = "$(test-tool string-list remove_duplicates a:a:b:c)" && - test a:b:c = "$(test-tool string-list remove_duplicates a:b:b:c)" && - test a:b:c = "$(test-tool string-list remove_duplicates a:b:c:c)" && - test a:b:c = "$(test-tool string-list remove_duplicates a:a:b:b:c:c)" && - test a:b:c = "$(test-tool string-list remove_duplicates a:a:a:b:b:b:c:c:c)" -' - -test_done diff --git a/t/t0411-clone-from-partial.sh b/t/t0411-clone-from-partial.sh index 196fc61784..9e6bca5625 100755 --- a/t/t0411-clone-from-partial.sh +++ b/t/t0411-clone-from-partial.sh @@ -59,6 +59,12 @@ test_expect_success 'pack-objects should fetch from promisor remote and execute test_expect_success 'clone from promisor remote does not lazy-fetch by default' ' rm -f script-executed && + + # The --path-walk feature of "git pack-objects" is not + # compatible with this kind of fetch from an incomplete repo. + GIT_TEST_PACK_PATH_WALK=0 && + export GIT_TEST_PACK_PATH_WALK && + test_must_fail git clone evil no-lazy 2>err && test_grep "lazy fetching disabled" err && test_path_is_missing script-executed diff --git a/t/t0450/adoc-help-mismatches b/t/t0450/adoc-help-mismatches index c4a15fd0cb..06b469bdee 100644 --- a/t/t0450/adoc-help-mismatches +++ b/t/t0450/adoc-help-mismatches @@ -38,7 +38,6 @@ merge-one-file multi-pack-index name-rev notes -pack-objects push range-diff rebase diff --git a/t/t0602-reffiles-fsck.sh b/t/t0602-reffiles-fsck.sh index f671ac4d3a..0ef483659d 100755 --- a/t/t0602-reffiles-fsck.sh +++ b/t/t0602-reffiles-fsck.sh @@ -110,6 +110,25 @@ test_expect_success 'ref name check should be adapted into fsck messages' ' ) ' +test_expect_success 'no refs directory of worktree should not cause problems' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit initial && + git worktree add --detach ./worktree && + + ( + cd worktree && + worktree_refdir="$(git rev-parse --git-dir)/refs" && + # Simulate old directory layout + rmdir "$worktree_refdir" && + git refs verify 2>err && + test_must_be_empty err + ) + ) +' + test_expect_success 'ref name check should work for multiple worktrees' ' test_when_finished "rm -rf repo" && git init repo && diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh index 1be534a895..3ea5d51532 100755 --- a/t/t0610-reftable-basics.sh +++ b/t/t0610-reftable-basics.sh @@ -477,11 +477,7 @@ test_expect_success !CYGWIN 'ref transaction: many concurrent writers' ' test_commit --no-tag initial && head=$(git rev-parse HEAD) && - for i in $(test_seq 100) - do - printf "%s commit\trefs/heads/branch-%s\n" "$head" "$i" || - return 1 - done >expect && + test_seq -f "$head commit\trefs/heads/branch-%d" 100 >expect && printf "%s commit\trefs/heads/main\n" "$head" >>expect && for i in $(test_seq 100) diff --git a/t/t0612-reftable-jgit-compatibility.sh b/t/t0612-reftable-jgit-compatibility.sh index d0d7e80b49..7df2ad5817 100755 --- a/t/t0612-reftable-jgit-compatibility.sh +++ b/t/t0612-reftable-jgit-compatibility.sh @@ -112,14 +112,11 @@ test_expect_success 'JGit can read multi-level index' ' cd repo && test_commit A && - awk " - BEGIN { - print \"start\"; - for (i = 0; i < 10000; i++) - printf \"create refs/heads/branch-%d HEAD\n\", i; - print \"commit\"; - } - " >input && + { + echo start && + test_seq -f "create refs/heads/branch-%d HEAD" 10000 && + echo commit + } >input && git update-ref --stdin <input && test_same_refs && diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh index 6447920c9b..d77e601111 100755 --- a/t/t0613-reftable-write-options.sh +++ b/t/t0613-reftable-write-options.sh @@ -66,11 +66,7 @@ test_expect_success 'many refs results in multiple blocks' ' ( cd repo && test_commit initial && - for i in $(test_seq 200) - do - printf "update refs/heads/branch-%d HEAD\n" "$i" || - return 1 - done >input && + test_seq -f "update refs/heads/branch-%d HEAD" 200 >input && git update-ref --stdin <input && git pack-refs && @@ -180,11 +176,7 @@ test_expect_success 'restart interval at every single record' ' ( cd repo && test_commit initial && - for i in $(test_seq 10) - do - printf "update refs/heads/branch-%d HEAD\n" "$i" || - return 1 - done >input && + test_seq -f "update refs/heads/branch-%d HEAD" 10 >input && git update-ref --stdin <input && git -c reftable.restartInterval=1 pack-refs && @@ -224,11 +216,7 @@ test_expect_success 'object index gets written by default with ref index' ' ( cd repo && test_commit initial && - for i in $(test_seq 5) - do - printf "update refs/heads/branch-%d HEAD\n" "$i" || - return 1 - done >input && + test_seq -f "update refs/heads/branch-%d HEAD" 5 >input && git update-ref --stdin <input && git -c reftable.blockSize=100 pack-refs && @@ -263,11 +251,7 @@ test_expect_success 'object index can be disabled' ' ( cd repo && test_commit initial && - for i in $(test_seq 5) - do - printf "update refs/heads/branch-%d HEAD\n" "$i" || - return 1 - done >input && + test_seq -f "update refs/heads/branch-%d HEAD" 5 >input && git update-ref --stdin <input && git -c reftable.blockSize=100 -c reftable.indexObjects=false pack-refs && diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index 317da6869c..1f61b666a7 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -113,53 +113,55 @@ strlen () { run_tests () { type=$1 - oid=$2 - size=$3 - content=$4 - pretty_content=$5 + object_name="$2" + mode=$3 + size=$4 + content=$5 + pretty_content=$6 + oid=${7:-"$object_name"} batch_output="$oid $type $size $content" test_expect_success "$type exists" ' - git cat-file -e $oid + git cat-file -e "$object_name" ' test_expect_success "Type of $type is correct" ' echo $type >expect && - git cat-file -t $oid >actual && + git cat-file -t "$object_name" >actual && test_cmp expect actual ' test_expect_success "Size of $type is correct" ' echo $size >expect && - git cat-file -s $oid >actual && + git cat-file -s "$object_name" >actual && test_cmp expect actual ' test -z "$content" || test_expect_success "Content of $type is correct" ' echo_without_newline "$content" >expect && - git cat-file $type $oid >actual && + git cat-file $type "$object_name" >actual && test_cmp expect actual ' test_expect_success "Pretty content of $type is correct" ' echo_without_newline "$pretty_content" >expect && - git cat-file -p $oid >actual && + git cat-file -p "$object_name" >actual && test_cmp expect actual ' test -z "$content" || test_expect_success "--batch output of $type is correct" ' echo "$batch_output" >expect && - echo $oid | git cat-file --batch >actual && + echo "$object_name" | git cat-file --batch >actual && test_cmp expect actual ' test_expect_success "--batch-check output of $type is correct" ' echo "$oid $type $size" >expect && - echo_without_newline $oid | git cat-file --batch-check >actual && + echo_without_newline "$object_name" | git cat-file --batch-check >actual && test_cmp expect actual ' @@ -168,13 +170,13 @@ $content" test -z "$content" || test_expect_success "--batch-command $opt output of $type content is correct" ' echo "$batch_output" >expect && - test_write_lines "contents $oid" | git cat-file --batch-command $opt >actual && + test_write_lines "contents $object_name" | git cat-file --batch-command $opt >actual && test_cmp expect actual ' test_expect_success "--batch-command $opt output of $type info is correct" ' echo "$oid $type $size" >expect && - test_write_lines "info $oid" | + test_write_lines "info $object_name" | git cat-file --batch-command $opt >actual && test_cmp expect actual ' @@ -182,30 +184,45 @@ $content" test_expect_success "custom --batch-check format" ' echo "$type $oid" >expect && - echo $oid | git cat-file --batch-check="%(objecttype) %(objectname)" >actual && + echo "$object_name" | git cat-file --batch-check="%(objecttype) %(objectname)" >actual && test_cmp expect actual ' test_expect_success "custom --batch-command format" ' echo "$type $oid" >expect && - echo "info $oid" | git cat-file --batch-command="%(objecttype) %(objectname)" >actual && + echo "info $object_name" | git cat-file --batch-command="%(objecttype) %(objectname)" >actual && test_cmp expect actual ' - test_expect_success '--batch-check with %(rest)' ' + # FIXME: %(rest) is incompatible with object names that include whitespace, + # e.g. HEAD:path/to/a/file with spaces. Use the resolved OID as input to + # test this instead of the raw object name. + if echo "$object_name" | grep -q " "; then + test_rest=test_expect_failure + else + test_rest=test_expect_success + fi + + $test_rest '--batch-check with %(rest)' ' echo "$type this is some extra content" >expect && - echo "$oid this is some extra content" | + echo "$object_name this is some extra content" | git cat-file --batch-check="%(objecttype) %(rest)" >actual && test_cmp expect actual ' + test_expect_success '--batch-check with %(objectmode)' ' + echo "$mode $oid" >expect && + echo $object_name | git cat-file --batch-check="%(objectmode) %(objectname)" >actual && + test_cmp expect actual + ' + test -z "$content" || test_expect_success "--batch without type ($type)" ' { echo "$size" && echo "$content" } >expect && - echo $oid | git cat-file --batch="%(objectsize)" >actual && + echo "$object_name" | git cat-file --batch="%(objectsize)" >actual && test_cmp expect actual ' @@ -215,7 +232,7 @@ $content" echo "$type" && echo "$content" } >expect && - echo $oid | git cat-file --batch="%(objecttype)" >actual && + echo "$object_name" | git cat-file --batch="%(objecttype)" >actual && test_cmp expect actual ' } @@ -230,13 +247,14 @@ test_expect_success "setup" ' git config extensions.compatobjectformat $test_compat_hash_algo && echo_without_newline "$hello_content" > hello && git update-index --add hello && + echo_without_newline "$hello_content" > "path with spaces" && + git update-index --add --chmod=+x "path with spaces" && git commit -m "add hello file" ' run_blob_tests () { oid=$1 - - run_tests 'blob' $oid $hello_size "$hello_content" "$hello_content" + run_tests 'blob' $oid "" $hello_size "$hello_content" "$hello_content" test_expect_success '--batch-command --buffer with flush for blob info' ' echo "$oid blob $hello_size" >expect && @@ -269,13 +287,17 @@ test_expect_success '--batch-check without %(rest) considers whole line' ' tree_oid=$(git write-tree) tree_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $tree_oid) -tree_size=$(($(test_oid rawsz) + 13)) -tree_compat_size=$(($(test_oid --hash=compat rawsz) + 13)) -tree_pretty_content="100644 blob $hello_oid hello${LF}" -tree_compat_pretty_content="100644 blob $hello_compat_oid hello${LF}" - -run_tests 'tree' $tree_oid $tree_size "" "$tree_pretty_content" -run_tests 'tree' $tree_compat_oid $tree_compat_size "" "$tree_compat_pretty_content" +tree_size=$((2 * $(test_oid rawsz) + 13 + 24)) +tree_compat_size=$((2 * $(test_oid --hash=compat rawsz) + 13 + 24)) +tree_pretty_content="100644 blob $hello_oid hello${LF}100755 blob $hello_oid path with spaces${LF}" +tree_compat_pretty_content="100644 blob $hello_compat_oid hello${LF}100755 blob $hello_compat_oid path with spaces${LF}" + +run_tests 'tree' $tree_oid "" $tree_size "" "$tree_pretty_content" +run_tests 'tree' $tree_compat_oid "" $tree_compat_size "" "$tree_compat_pretty_content" +run_tests 'blob' "$tree_oid:hello" "100644" $hello_size "" "$hello_content" $hello_oid +run_tests 'blob' "$tree_compat_oid:hello" "100644" $hello_size "" "$hello_content" $hello_compat_oid +run_tests 'blob' "$tree_oid:path with spaces" "100755" $hello_size "" "$hello_content" $hello_oid +run_tests 'blob' "$tree_compat_oid:path with spaces" "100755" $hello_size "" "$hello_content" $hello_compat_oid commit_message="Initial commit" commit_oid=$(echo_without_newline "$commit_message" | git commit-tree $tree_oid) @@ -294,8 +316,8 @@ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE $commit_message" -run_tests 'commit' $commit_oid $commit_size "$commit_content" "$commit_content" -run_tests 'commit' $commit_compat_oid $commit_compat_size "$commit_compat_content" "$commit_compat_content" +run_tests 'commit' $commit_oid "" $commit_size "$commit_content" "$commit_content" +run_tests 'commit' $commit_compat_oid "" $commit_compat_size "$commit_compat_content" "$commit_compat_content" tag_header_without_oid="type blob tag hellotag @@ -318,8 +340,8 @@ tag_size=$(strlen "$tag_content") tag_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $tag_oid) tag_compat_size=$(strlen "$tag_compat_content") -run_tests 'tag' $tag_oid $tag_size "$tag_content" "$tag_content" -run_tests 'tag' $tag_compat_oid $tag_compat_size "$tag_compat_content" "$tag_compat_content" +run_tests 'tag' $tag_oid "" $tag_size "$tag_content" "$tag_content" +run_tests 'tag' $tag_compat_oid "" $tag_compat_size "$tag_compat_content" "$tag_compat_content" test_expect_success "Reach a blob from a tag pointing to it" ' echo_without_newline "$hello_content" >expect && @@ -1198,6 +1220,31 @@ test_expect_success 'cat-file --batch-check respects replace objects' ' test_cmp expect actual ' +test_expect_success 'batch-check with a submodule' ' + # FIXME: this call to mktree is incompatible with compatObjectFormat + # because the submodule OID cannot be mapped to the compat hash algo. + test_unconfig extensions.compatobjectformat && + printf "160000 commit $(test_oid deadbeef)\tsub\n" >tree-with-sub && + tree=$(git mktree <tree-with-sub) && + test_config extensions.compatobjectformat $test_compat_hash_algo && + + git cat-file --batch-check >actual <<-EOF && + $tree:sub + EOF + printf "$(test_oid deadbeef) submodule\n" >expect && + test_cmp expect actual +' + +test_expect_success 'batch-check with a submodule, object exists' ' + printf "160000 commit $commit_oid\tsub\n" >tree-with-sub && + tree=$(git mktree <tree-with-sub) && + git cat-file --batch-check >actual <<-EOF && + $tree:sub + EOF + printf "$commit_oid commit $commit_size\n" >expect && + test_cmp expect actual +' + # Pull the entry for object with oid "$1" out of the output of # "cat-file --batch", including its object content (which requires # parsing and reading a set amount of bytes, hence perl). diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index dbbe9fb0d4..de076293b6 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -30,7 +30,7 @@ setup_repo() { test_repo=test push_repo() { - test_create_repo $test_repo + git init --quiet $test_repo cd $test_repo setup_repo @@ -252,9 +252,9 @@ test_expect_success '--literally complains about non-standard types' ' test_must_fail git hash-object -t bogus --literally --stdin ' -test_expect_success '--stdin outside of repository (uses SHA-1)' ' +test_expect_success '--stdin outside of repository (uses default hash)' ' nongit git hash-object --stdin <hello >actual && - echo "$(test_oid --hash=sha1 hello)" >expect && + echo "$(test_oid --hash=builtin hello)" >expect && test_cmp expect actual ' diff --git a/t/t1021-rerere-in-workdir.sh b/t/t1021-rerere-in-workdir.sh deleted file mode 100755 index 0b892894eb..0000000000 --- a/t/t1021-rerere-in-workdir.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/sh - -test_description='rerere run in a workdir' -GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main -export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME - -. ./test-lib.sh - -test_expect_success SYMLINKS setup ' - git config rerere.enabled true && - >world && - git add world && - test_tick && - git commit -m initial && - - echo hello >world && - test_tick && - git commit -a -m hello && - - git checkout -b side HEAD^ && - echo goodbye >world && - test_tick && - git commit -a -m goodbye && - - git checkout main -' - -test_expect_success SYMLINKS 'rerere in workdir' ' - rm -rf .git/rr-cache && - "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" . work && - ( - cd work && - test_must_fail git merge side && - git rerere status >actual && - echo world >expect && - test_cmp expect actual - ) -' - -# This fails because we don't resolve relative symlink in mkdir_in_gitdir() -# For the purpose of helping contrib/workdir/git-new-workdir users, we do not -# have to support relative symlinks, but it might be nicer to make this work -# with a relative symbolic link someday. -test_expect_failure SYMLINKS 'rerere in workdir (relative)' ' - rm -rf .git/rr-cache && - "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" . krow && - ( - cd krow && - rm -f .git/rr-cache && - ln -s ../.git/rr-cache .git/rr-cache && - test_must_fail git merge side && - git rerere status >actual && - echo world >expect && - test_cmp expect actual - ) -' - -test_done diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 51a85e83c2..f856821839 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -2851,4 +2851,15 @@ test_expect_success 'writing to stdin is rejected' ' done +test_expect_success 'writing value with trailing CR not stripped on read' ' + test_when_finished "rm -rf cr-test" && + + printf "bar\r\n" >expect && + git init cr-test && + git -C cr-test config set core.foo $(printf "bar\r") && + git -C cr-test config get core.foo >actual && + + test_cmp expect actual +' + test_done diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index d29d23cb89..96648a6e5d 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -1380,10 +1380,7 @@ test_expect_success 'fails with duplicate ref update via symref' ' test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction creating branches does not burst open file limit' ' ( - for i in $(test_seq 33) - do - echo "create refs/heads/$i HEAD" || exit 1 - done >large_input && + test_seq -f "create refs/heads/%d HEAD" 33 >large_input && run_with_limited_open_files git update-ref --stdin <large_input && git rev-parse --verify -q refs/heads/33 ) @@ -1391,10 +1388,7 @@ test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction creating branches test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction deleting branches does not burst open file limit' ' ( - for i in $(test_seq 33) - do - echo "delete refs/heads/$i HEAD" || exit 1 - done >large_input && + test_seq -f "delete refs/heads/%d HEAD" 33 >large_input && run_with_limited_open_files git update-ref --stdin <large_input && test_must_fail git rev-parse --verify -q refs/heads/33 ) @@ -2299,6 +2293,51 @@ do test_grep -q "refname conflict" stdout ) ' + + test_expect_success "stdin $type batch-updates delete incorrect symbolic ref" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit c1 && + head=$(git rev-parse HEAD) && + git symbolic-ref refs/heads/symbolic refs/heads/non-existent && + + format_command $type "delete refs/heads/symbolic" "$head" >stdin && + git update-ref $type --stdin --batch-updates <stdin >stdout && + test_grep "reference does not exist" stdout + ) + ' + + test_expect_success "stdin $type batch-updates delete with incorrect old_oid" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit c1 && + git branch new-branch && + test_commit c2 && + head=$(git rev-parse HEAD) && + + format_command $type "delete refs/heads/new-branch" "$head" >stdin && + git update-ref $type --stdin --batch-updates <stdin >stdout && + test_grep "incorrect old value provided" stdout + ) + ' + + test_expect_success "stdin $type batch-updates delete non-existent ref" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit commit && + head=$(git rev-parse HEAD) && + + format_command $type "delete refs/heads/non-existent" "$head" >stdin && + git update-ref $type --stdin --batch-updates <stdin >stdout && + test_grep "reference does not exist" stdout + ) + ' done test_expect_success 'update-ref should also create reflog for HEAD' ' @@ -2310,4 +2349,23 @@ test_expect_success 'update-ref should also create reflog for HEAD' ' test_cmp expect actual ' +test_expect_success REFFILES 'empty directories are pruned when aborting a transaction' ' + test_path_is_missing .git/refs/heads/nested && + git update-ref --stdin <<-EOF && + create refs/heads/nested/something HEAD + prepare + abort + EOF + test_path_is_missing .git/refs/heads/nested +' + +test_expect_success REFFILES 'empty directories are pruned when not committing' ' + test_path_is_missing .git/refs/heads/nested && + git update-ref --stdin <<-EOF && + create refs/heads/nested/something HEAD + prepare + EOF + test_path_is_missing .git/refs/heads/nested +' + test_done diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index 42b501f163..e30f87a358 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -673,4 +673,32 @@ test_expect_success 'reflog drop --all with reference' ' ) ' +test_expect_success 'expire with pattern config' ' + # Split refs/heads/ into two roots so we can apply config to each. Make + # two branches per root to verify that config is applied correctly + # multiple times. + git branch root1/branch1 && + git branch root1/branch2 && + git branch root2/branch1 && + git branch root2/branch2 && + + test_config "gc.reflogexpire" "never" && + test_config "gc.refs/heads/root2/*.reflogExpire" "now" && + git reflog expire \ + root1/branch1 root1/branch2 \ + root2/branch1 root2/branch2 && + + cat >expect <<-\EOF && + root1/branch1@{0} + root1/branch2@{0} + EOF + git log -g --branches="root*" --format=%gD >actual.raw && + # The sole reflog entry of each branch points to the same commit, so + # the order in which they are shown is nondeterministic. We just care + # about the what was expired (and what was not), so sort to get a known + # order. + sort <actual.raw >actual.sorted && + test_cmp expect actual.sorted +' + test_done diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh index 8c777f7cf8..d91dd3a3b5 100755 --- a/t/t1416-ref-transaction-hooks.sh +++ b/t/t1416-ref-transaction-hooks.sh @@ -120,8 +120,6 @@ test_expect_success 'interleaving hook calls succeed' ' cat >expect <<-EOF && hooks/update refs/tags/PRE $ZERO_OID $PRE_OID - hooks/reference-transaction prepared - hooks/reference-transaction committed hooks/update refs/tags/POST $ZERO_OID $POST_OID hooks/reference-transaction prepared hooks/reference-transaction committed diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh index 6824581317..8f59b867f2 100755 --- a/t/t1517-outside-repo.sh +++ b/t/t1517-outside-repo.sh @@ -114,4 +114,11 @@ test_expect_success 'update-server-info does not crash with -h' ' test_grep "[Uu]sage: git update-server-info " usage ' +test_expect_success 'prune does not crash with -h' ' + test_expect_code 129 git prune -h >usage && + test_grep "[Uu]sage: git prune " usage && + test_expect_code 129 nongit git prune -h >usage && + test_grep "[Uu]sage: git prune " usage +' + test_done diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh index 90638fa886..023e1301c8 100755 --- a/t/t2400-worktree-add.sh +++ b/t/t2400-worktree-add.sh @@ -42,8 +42,8 @@ test_expect_success '"add" using - shorthand' ' test_expect_success '"add" refuses to checkout locked branch' ' test_must_fail git worktree add zere main && - ! test -d zere && - ! test -d .git/worktrees/zere + test_path_is_missing zere && + test_path_is_missing .git/worktrees/zere ' test_expect_success 'checking out paths not complaining about linked checkouts' ' @@ -70,14 +70,14 @@ test_expect_success '"add" worktree' ' test_expect_success '"add" worktree with lock' ' git worktree add --detach --lock here-with-lock main && test_when_finished "git worktree unlock here-with-lock || :" && - test -f .git/worktrees/here-with-lock/locked + test_path_is_file .git/worktrees/here-with-lock/locked ' test_expect_success '"add" worktree with lock and reason' ' lock_reason="why not" && git worktree add --detach --lock --reason "$lock_reason" here-with-lock-reason main && test_when_finished "git worktree unlock here-with-lock-reason || :" && - test -f .git/worktrees/here-with-lock-reason/locked && + test_path_is_file .git/worktrees/here-with-lock-reason/locked && echo "$lock_reason" >expect && test_cmp expect .git/worktrees/here-with-lock-reason/locked ' @@ -412,14 +412,14 @@ test_expect_success '"add --orphan" with empty repository' ' test_expect_success '"add" worktree with orphan branch and lock' ' git worktree add --lock --orphan -b orphanbr orphan-with-lock && test_when_finished "git worktree unlock orphan-with-lock || :" && - test -f .git/worktrees/orphan-with-lock/locked + test_path_is_file .git/worktrees/orphan-with-lock/locked ' test_expect_success '"add" worktree with orphan branch, lock, and reason' ' lock_reason="why not" && git worktree add --detach --lock --reason "$lock_reason" orphan-with-lock-reason main && test_when_finished "git worktree unlock orphan-with-lock-reason || :" && - test -f .git/worktrees/orphan-with-lock-reason/locked && + test_path_is_file .git/worktrees/orphan-with-lock-reason/locked && echo "$lock_reason" >expect && test_cmp expect .git/worktrees/orphan-with-lock-reason/locked ' @@ -474,7 +474,7 @@ test_expect_success 'local clone --shared from linked checkout' ' test_expect_success '"add" worktree with --no-checkout' ' git worktree add --no-checkout -b swamp swamp && - ! test -e swamp/init.t && + test_path_is_missing swamp/init.t && git -C swamp reset --hard && test_cmp init.t swamp/init.t ' @@ -497,7 +497,7 @@ test_expect_success 'put a worktree under rebase' ' test_expect_success 'add a worktree, checking out a rebased branch' ' test_must_fail git worktree add new-rebase under-rebase && - ! test -d new-rebase + test_path_is_missing new-rebase ' test_expect_success 'checking out a rebased branch from another worktree' ' @@ -535,7 +535,7 @@ test_expect_success 'checkout a branch under bisect' ' git worktree list >actual && grep "under-bisect.*detached HEAD" actual && test_must_fail git worktree add new-bisect under-bisect && - ! test -d new-bisect + test_path_is_missing new-bisect ) ' @@ -1165,7 +1165,7 @@ test_expect_success '"add" not tripped up by magic worktree matching"' ' test_expect_success FUNNYNAMES 'sanitize generated worktree name' ' git worktree add --detach ". weird*..?.lock.lock" && - test -d .git/worktrees/---weird-.- + test_path_is_dir .git/worktrees/---weird-.- ' test_expect_success '"add" should not fail because of another bad worktree' ' diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh index 13f66fd649..b41e7f0daa 100755 --- a/t/t3000-ls-files-others.sh +++ b/t/t3000-ls-files-others.sh @@ -73,25 +73,6 @@ test_expect_success 'ls-files --others handles non-submodule .git' ' test_cmp expected1 output ' -test_expect_success SYMLINKS 'ls-files --others with symlinked submodule' ' - git init super && - git init sub && - ( - cd sub && - >a && - git add a && - git commit -m sub && - git pack-refs --all - ) && - ( - cd super && - "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" ../sub sub && - git ls-files --others --exclude-standard >../actual - ) && - echo sub/ >expect && - test_cmp expect actual -' - test_expect_success 'setup nested pathspec search' ' test_create_repo nested && ( diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index 127216f722..b8a8dd77e7 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -328,6 +328,19 @@ test_expect_success 'there is no --no-reschedule-failed-exec in an ongoing rebas test_expect_code 129 git rebase --edit-todo --no-reschedule-failed-exec ' +test_expect_success 'no change in comment character due to conflicts markers with core.commentChar=auto' ' + git checkout -b branch-a && + test_commit A F1 && + git checkout -b branch-b HEAD^ && + test_commit B F1 && + test_must_fail git rebase branch-a && + printf "B\nA\n" >F1 && + git add F1 && + GIT_EDITOR="cat >actual" git -c core.commentChar=auto rebase --continue && + # Check that "#" is still the comment character. + test_grep "^# Changes to be committed" actual +' + test_orig_head_helper () { test_when_finished 'git rebase --abort && git checkout topic && diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index 98259e2ada..1f16e6b522 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -17,11 +17,6 @@ test_expect_success 'Initialize test directory' ' git commit -m "add normal files" ' -if test_have_prereq !FUNNYNAMES -then - say 'Your filesystem does not allow tabs in filenames.' -fi - test_expect_success FUNNYNAMES 'add files with funny names' ' touch -- "tab embedded" "newline${LF}embedded" && git add -- "tab embedded" "newline${LF}embedded" && diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 74666ff3e4..0bb4648e36 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -11,6 +11,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY"/lib-unique-files.sh +test_expect_success 'setup' ' + test_oid_cache <<-EOF + export_base sha1:73c9bab443d1f88ac61aa533d2eeaaa15451239c + export_base sha256:f210fa6346e3e2ce047bdb570426b17075980c1ac01fec8fc4b75bd3ab4bcfe4 + EOF +' + test_expect_success 'usage on cmd and subcommand invalid option' ' test_expect_code 129 git stash --invalid-option 2>usage && grep "or: git stash" usage && @@ -1177,6 +1184,28 @@ test_expect_success 'stash -- <pathspec> stashes and restores the file' ' test_path_is_file bar ' +test_expect_success 'stash --patch <pathspec> stash and restores the file' ' + test_write_lines b c >file && + git commit -m "add a few lines" file && + test_write_lines a b c d >file && + test_write_lines b c d >expect-file && + echo changed-other-file >other-file && + test_write_lines s y n | git stash -m "stash bar" --patch file && + test_cmp expect-file file && + echo changed-other-file >expect && + test_cmp expect other-file && + git checkout HEAD -- file && + git stash pop && + test_cmp expect other-file && + test_write_lines a b c >expect && + test_cmp expect file +' + +test_expect_success 'stash <pathspec> -p is rejected' ' + test_must_fail git stash file -p 2>err && + test_grep "subcommand wasn${SQ}t specified; ${SQ}push${SQ} can${SQ}t be assumed due to unexpected token ${SQ}file${SQ}" err +' + test_expect_success 'stash -- <pathspec> stashes in subdirectory' ' mkdir sub && >foo && @@ -1412,6 +1441,100 @@ test_expect_success 'stash --keep-index --include-untracked with empty tree' ' ) ' +test_expect_success 'stash export and import round-trip stashes' ' + git reset && + >untracked && + >tracked1 && + >tracked2 && + git add tracked* && + git stash -- && + >subdir/untracked && + >subdir/tracked1 && + >subdir/tracked2 && + git add subdir/tracked* && + git stash --include-untracked -- subdir/ && + git tag t-stash0 stash@{0} && + git tag t-stash1 stash@{1} && + simple=$(git stash export --print) && + git stash clear && + git stash import "$simple" && + test_cmp_rev stash@{0} t-stash0 && + test_cmp_rev stash@{1} t-stash1 && + git stash export --to-ref refs/heads/foo && + test_cmp_rev "$(test_oid empty_tree)" foo: && + test_cmp_rev "$(test_oid empty_tree)" foo^: && + test_cmp_rev t-stash0 foo^2 && + test_cmp_rev t-stash1 foo^^2 && + git log --first-parent --format="%s" refs/heads/foo >log && + grep "^git stash: " log >log2 && + test_line_count = 13 log2 && + git stash clear && + git stash import foo && + test_cmp_rev stash@{0} t-stash0 && + test_cmp_rev stash@{1} t-stash1 +' + +test_expect_success 'stash import appends commits' ' + git log --format=oneline -g refs/stash >out && + cat out out >out2 && + git stash import refs/heads/foo && + git log --format=oneline -g refs/stash >actual && + test_line_count = $(wc -l <out2) actual +' + +test_expect_success 'stash export can accept specified stashes' ' + git stash clear && + git stash import foo && + git stash export --to-ref refs/heads/bar stash@{1} stash@{0} && + git stash clear && + git stash import refs/heads/bar && + test_cmp_rev stash@{1} t-stash0 && + test_cmp_rev stash@{0} t-stash1 && + git log --format=oneline -g refs/stash >actual && + test_line_count = 2 actual +' + +test_expect_success 'stash export rejects invalid arguments' ' + test_must_fail git stash export --print --to-ref refs/heads/invalid 2>err && + grep "exactly one of --print and --to-ref is required" err && + test_must_fail git stash export 2>err2 && + grep "exactly one of --print and --to-ref is required" err2 +' + +test_expect_success 'stash can import and export zero stashes' ' + git stash clear && + git stash export --to-ref refs/heads/baz && + test_cmp_rev "$(test_oid empty_tree)" baz: && + test_cmp_rev "$(test_oid export_base)" baz && + test_must_fail git rev-parse baz^1 && + git stash import baz && + test_must_fail git rev-parse refs/stash +' + +test_expect_success 'stash rejects invalid attempts to import commits' ' + git stash import foo && + test_must_fail git stash import HEAD 2>output && + oid=$(git rev-parse HEAD) && + grep "$oid is not a valid exported stash commit" output && + test_cmp_rev stash@{0} t-stash0 && + + git checkout --orphan orphan && + git commit-tree $(test_oid empty_tree) -p "$oid" -p "$oid^" -m "" >fake-commit && + git update-ref refs/heads/orphan "$(cat fake-commit)" && + oid=$(git rev-parse HEAD) && + test_must_fail git stash import orphan 2>output && + grep "found stash commit $oid without expected prefix" output && + test_cmp_rev stash@{0} t-stash0 && + + git checkout --orphan orphan2 && + git commit-tree $(test_oid empty_tree) -m "" >fake-commit && + git update-ref refs/heads/orphan2 "$(cat fake-commit)" && + oid=$(git rev-parse HEAD) && + test_must_fail git stash import orphan2 2>output && + grep "found root commit $oid with invalid data" output && + test_cmp_rev stash@{0} t-stash0 +' + test_expect_success 'stash apply should succeed with unmodified file' ' echo base >file && git add file && @@ -1549,11 +1672,9 @@ test_expect_success 'stash create reports a locked index' ' echo change >A.file && touch .git/index.lock && - cat >expect <<-EOF && - error: could not write index - EOF test_must_fail git stash create 2>err && - test_cmp expect err + test_grep "error: could not write index" err && + test_grep "error: Unable to create '.*index.lock'" err ) ' @@ -1566,11 +1687,9 @@ test_expect_success 'stash push reports a locked index' ' echo change >A.file && touch .git/index.lock && - cat >expect <<-EOF && - error: could not write index - EOF test_must_fail git stash push 2>err && - test_cmp expect err + test_grep "error: could not write index" err && + test_grep "error: Unable to create '.*index.lock'" err ) ' @@ -1584,11 +1703,41 @@ test_expect_success 'stash apply reports a locked index' ' git stash push && touch .git/index.lock && - cat >expect <<-EOF && - error: could not write index - EOF test_must_fail git stash apply 2>err && - test_cmp expect err + test_grep "error: could not write index" err && + test_grep "error: Unable to create '.*index.lock'" err + ) +' + +test_expect_success 'submodules does not affect the branch recorded in stash message' ' + git init sub_project && + ( + cd sub_project && + echo "Initial content in sub_project" >sub_file.txt && + git add sub_file.txt && + git commit -m "Initial commit in sub_project" + ) && + + git init main_project && + ( + cd main_project && + echo "Initial content in main_project" >main_file.txt && + git add main_file.txt && + git commit -m "Initial commit in main_project" && + + git -c protocol.file.allow=always submodule add ../sub_project sub && + git commit -m "Added submodule sub_project" && + + git checkout -b feature_main && + git -C sub checkout -b feature_sub && + + git checkout -b work_branch && + echo "Important work to be stashed" >work_item.txt && + git add work_item.txt && + git stash push -m "custom stash for work_branch" && + + git stash list >../actual_stash_list.txt && + grep "On work_branch: custom stash for work_branch" ../actual_stash_list.txt ) ' diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh index a51f881b1c..32b14e3a71 100755 --- a/t/t4000-diff-format.sh +++ b/t/t4000-diff-format.sh @@ -36,7 +36,7 @@ test_expect_success 'git diff-files -p after editing work tree.' ' # that's as far as it comes if [ "$(git config --get core.filemode)" = false ] then - say 'filemode disabled on the filesystem' + skip_all='filemode disabled on the filesystem' test_done fi diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 782d97fb7d..8ebd170451 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -206,14 +206,30 @@ do expect="$TEST_DIRECTORY/t4013/diff.$test" actual="$pfx-diff.$test" - test_expect_success "git $cmd # magic is ${magic:-(not used)}" ' + case "$cmd" in + whatchanged | whatchanged" "*) + prereq=!WITH_BREAKING_CHANGES + ;; + *) + prereq=;; + esac + + test_expect_success $prereq "git $cmd # magic is ${magic:-(not used)}" ' { echo "$ git $cmd" + + case "$cmd" in + whatchanged | whatchanged" "*) + run="whatchanged --i-still-use-this" + run="$run ${cmd#whatchanged}" ;; + *) + run=$cmd ;; + esac && case "$magic" in "") - GIT_PRINT_SHA1_ELLIPSIS=yes git $cmd ;; + GIT_PRINT_SHA1_ELLIPSIS=yes git $run ;; noellipses) - git $cmd ;; + git $run ;; esac | sed -e "s/^\\(-*\\)$V\\(-*\\)\$/\\1g-i-t--v-e-r-s-i-o-n\2/" \ -e "s/^\\(.*mixed; boundary=\"-*\\)$V\\(-*\\)\"\$/\\1g-i-t--v-e-r-s-i-o-n\2\"/" @@ -460,6 +476,11 @@ diff-tree --stat --compact-summary initial mode diff-tree -R --stat --compact-summary initial mode EOF +test_expect_success !WITH_BREAKING_CHANGES 'whatchanged needs --i-still-use-this' ' + test_must_fail git whatchanged >message 2>&1 && + test_grep "nominated for removal" message +' + test_expect_success 'log -m matches pure log' ' git log master >result && process_diffs result >expected && diff --git a/t/t4018/r-indent b/t/t4018/r-indent new file mode 100644 index 0000000000..9df440f2a4 --- /dev/null +++ b/t/t4018/r-indent @@ -0,0 +1,6 @@ +RIGHT <- function(a, b) { + c = mean(a, b) + d = c + 2 + ChangeMe() + return (d) +} diff --git a/t/t4018/r-indent-nested b/t/t4018/r-indent-nested new file mode 100644 index 0000000000..30412e6c79 --- /dev/null +++ b/t/t4018/r-indent-nested @@ -0,0 +1,10 @@ +LEFT = function(a, b) { + c = mean(a, b) + RIGHT = function(d, e) { + f = var(d, e) + g = f + 1 + ChangeMe() + return (g) + } + return (RIGHT(2, 3)) +} diff --git a/t/t4018/r-noindent b/t/t4018/r-noindent new file mode 100644 index 0000000000..6d9b01ffe3 --- /dev/null +++ b/t/t4018/r-noindent @@ -0,0 +1,6 @@ +RIGHT <- function(a, b) { +c = mean(a, b) +d = c + 2 +ChangeMe() +return (c) +} diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh index 28f9d83d4c..4d4aa1650f 100755 --- a/t/t4041-diff-submodule-option.sh +++ b/t/t4041-diff-submodule-option.sh @@ -48,11 +48,12 @@ commit_file () { git commit "$@" -m "Commit $*" >/dev/null } -test_create_repo sm1 && -add_file . foo >/dev/null - -head1=$(add_file sm1 foo1 foo2) -fullhead1=$(cd sm1; git rev-parse --verify HEAD) +test_expect_success 'setup submodule' ' + git init sm1 && + add_file . foo && + head1=$(add_file sm1 foo1 foo2) && + fullhead1=$(cd sm1 && git rev-parse --verify HEAD) +' test_expect_success 'added submodule' ' git add sm1 && @@ -235,10 +236,13 @@ test_expect_success 'typechanged submodule(submodule->blob)' ' test_cmp expected actual ' -rm -f sm1 && -test_create_repo sm1 && -head6=$(add_file sm1 foo6 foo7) -fullhead6=$(cd sm1; git rev-parse --verify HEAD) +test_expect_success 'setup submodule anew' ' + rm -f sm1 && + git init sm1 && + head6=$(add_file sm1 foo6 foo7) && + fullhead6=$(cd sm1 && git rev-parse --verify HEAD) +' + test_expect_success 'nonexistent commit' ' git diff-index -p --submodule=log HEAD >actual && cat >expected <<-EOF && diff --git a/t/t4042-diff-textconv-caching.sh b/t/t4042-diff-textconv-caching.sh index ff0e73531b..31018ceba2 100755 --- a/t/t4042-diff-textconv-caching.sh +++ b/t/t4042-diff-textconv-caching.sh @@ -120,6 +120,14 @@ test_expect_success 'log notes cache and still use cache for -p' ' ' test_expect_success 'caching is silently ignored outside repo' ' + test_oid_cache <<-\EOM && + oid1 sha1:5626abf + oid1 sha256:a4ed1f3 + oid2 sha1:f719efd + oid2 sha256:aa9e7dc + EOM + oid1=$(test_oid --hash=builtin oid1) && + oid2=$(test_oid --hash=builtin oid2) && mkdir -p non-repo && echo one >non-repo/one && echo two >non-repo/two && @@ -129,9 +137,9 @@ test_expect_success 'caching is silently ignored outside repo' ' -c diff.test.textconv="tr a-z A-Z <" \ -c diff.test.cachetextconv=true \ diff --no-index one two >actual && - cat >expect <<-\EOF && + cat >expect <<-EOF && diff --git a/one b/two - index 5626abf..f719efd 100644 + index $oid1..$oid2 100644 --- a/one +++ b/two @@ -1 +1 @@ diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh index 5e5bad61ca..01db9243ab 100755 --- a/t/t4053-diff-no-index.sh +++ b/t/t4053-diff-no-index.sh @@ -295,4 +295,79 @@ test_expect_success PIPE,SYMLINKS 'diff --no-index reads from pipes' ' test_cmp expect actual ' +test_expect_success 'diff --no-index F F rejects pathspecs' ' + test_must_fail git diff --no-index -- a/1 a/2 a 2>actual.err && + test_grep "usage: git diff --no-index" actual.err +' + +test_expect_success 'diff --no-index D F rejects pathspecs' ' + test_must_fail git diff --no-index -- a a/2 a 2>actual.err && + test_grep "usage: git diff --no-index" actual.err +' + +test_expect_success 'diff --no-index F D rejects pathspecs' ' + test_must_fail git diff --no-index -- a/1 b b 2>actual.err && + test_grep "usage: git diff --no-index" actual.err +' + +test_expect_success 'diff --no-index rejects absolute pathspec' ' + test_must_fail git diff --no-index -- a b $(pwd)/a/1 +' + +test_expect_success 'diff --no-index with pathspec' ' + test_expect_code 1 git diff --name-status --no-index a b 1 >actual && + cat >expect <<-EOF && + D a/1 + EOF + test_cmp expect actual +' + +test_expect_success 'diff --no-index with pathspec no matches' ' + test_expect_code 0 git diff --name-status --no-index a b missing +' + +test_expect_success 'diff --no-index with negative pathspec' ' + test_expect_code 1 git diff --name-status --no-index a b ":!2" >actual && + cat >expect <<-EOF && + D a/1 + EOF + test_cmp expect actual +' + +test_expect_success 'setup nested' ' + mkdir -p c/1/2 && + mkdir -p d/1/2 && + echo 1 >c/1/2/a && + echo 2 >c/1/2/b +' + +test_expect_success 'diff --no-index with pathspec nested negative pathspec' ' + test_expect_code 0 git diff --no-index c d ":!1" +' + +test_expect_success 'diff --no-index with pathspec nested pathspec' ' + test_expect_code 1 git diff --name-status --no-index c d 1/2 >actual && + cat >expect <<-EOF && + D c/1/2/a + D c/1/2/b + EOF + test_cmp expect actual +' + +test_expect_success 'diff --no-index with pathspec glob' ' + test_expect_code 1 git diff --name-status --no-index c d ":(glob)**/a" >actual && + cat >expect <<-EOF && + D c/1/2/a + EOF + test_cmp expect actual +' + +test_expect_success 'diff --no-index with pathspec glob and exclude' ' + test_expect_code 1 git diff --name-status --no-index c d ":(glob,exclude)**/a" >actual && + cat >expect <<-EOF && + D c/1/2/b + EOF + test_cmp expect actual +' + test_done diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh index 76b83101d3..dbfeb7470b 100755 --- a/t/t4060-diff-submodule-option-diff-format.sh +++ b/t/t4060-diff-submodule-option-diff-format.sh @@ -363,9 +363,12 @@ test_expect_success 'typechanged submodule(submodule->blob)' ' diff_cmp expected actual ' -rm -f sm1 && -test_create_repo sm1 && -head6=$(add_file sm1 foo6 foo7) +test_expect_success 'setup' ' + rm -f sm1 && + git init sm1 && + head6=$(add_file sm1 foo6 foo7) +' + test_expect_success 'nonexistent commit' ' git diff-index -p --submodule=diff HEAD >actual && cat >expected <<-EOF && diff --git a/t/t4140-apply-ita.sh b/t/t4140-apply-ita.sh index c614eaf04c..0b11a8aef4 100755 --- a/t/t4140-apply-ita.sh +++ b/t/t4140-apply-ita.sh @@ -7,6 +7,10 @@ test_description='git apply of i-t-a file' test_expect_success setup ' test_write_lines 1 2 3 4 5 >blueprint && + cat blueprint >committed-file && + git add committed-file && + git commit -m "commit" && + cat blueprint >test-file && git add -N test-file && git diff >creation-patch && @@ -14,7 +18,14 @@ test_expect_success setup ' rm -f test-file && git diff >deletion-patch && - grep "deleted file mode 100644" deletion-patch + grep "deleted file mode 100644" deletion-patch && + + git rm -f test-file && + test_write_lines 6 >>committed-file && + cat blueprint >test-file && + git add -N test-file && + git diff >complex-patch && + git restore committed-file ' test_expect_success 'apply creation patch to ita path (--cached)' ' @@ -53,4 +64,22 @@ test_expect_success 'apply deletion patch to ita path (--index)' ' git ls-files --stage --error-unmatch test-file ' +test_expect_success 'apply creation patch to existing index with -N' ' + git rm -f test-file && + cat blueprint >index-file && + git add index-file && + git apply -N creation-patch && + + git ls-files --stage --error-unmatch index-file && + git ls-files --stage --error-unmatch test-file +' + +test_expect_success 'apply complex patch with -N' ' + git rm -f test-file index-file && + git apply -N complex-patch && + + git ls-files --stage --error-unmatch test-file && + git diff | grep "a/committed-file" +' + test_done diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 2ae93d3c96..699a81ab5c 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -1086,7 +1086,7 @@ test_expect_success 'am works with multi-line in-body headers' ' # bump from, date, and subject down to in-body header awk " /^From:/{ - print \"From: x <x\@example.com>\"; + print \"From: x <x@example.com>\"; print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\"; print \"Subject: x\n\"; }; 1 diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 51f7beb59f..05cee9e41b 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -134,6 +134,12 @@ test_expect_success 'diff-filter=D' ' ' +test_expect_success 'all-negative filter' ' + git log --no-renames --format=%s --diff-filter=d HEAD >actual && + printf "%s\n" fifth fourth third second initial >expect && + test_cmp expect actual +' + test_expect_success 'diff-filter=R' ' git log -M --pretty="format:%s" --diff-filter=R HEAD >actual && @@ -486,10 +492,16 @@ test_expect_success !FAIL_PREREQS 'log with various grep.patternType configurati ) ' -for cmd in show whatchanged reflog format-patch +cmds="show reflog format-patch" +if test_have_prereq !WITH_BREAKING_CHANGES +then + cmds="$cmds whatchanged" +fi +for cmd in $cmds do case "$cmd" in format-patch) myarg="HEAD~.." ;; + whatchanged) myarg=--i-still-use-this ;; *) myarg= ;; esac @@ -1201,20 +1213,27 @@ test_expect_success 'reflog is expected format' ' test_cmp expect actual ' -test_expect_success 'whatchanged is expected format' ' +test_expect_success !WITH_BREAKING_CHANGES 'whatchanged is expected format' ' + whatchanged="whatchanged --i-still-use-this" && git log --no-merges --raw >expect && - git whatchanged >actual && + git $whatchanged >actual && test_cmp expect actual ' test_expect_success 'log.abbrevCommit configuration' ' + whatchanged="whatchanged --i-still-use-this" && + git log --abbrev-commit >expect.log.abbrev && git log --no-abbrev-commit >expect.log.full && git log --pretty=raw >expect.log.raw && git reflog --abbrev-commit >expect.reflog.abbrev && git reflog --no-abbrev-commit >expect.reflog.full && - git whatchanged --abbrev-commit >expect.whatchanged.abbrev && - git whatchanged --no-abbrev-commit >expect.whatchanged.full && + + if test_have_prereq !WITH_BREAKING_CHANGES + then + git $whatchanged --abbrev-commit >expect.whatchanged.abbrev && + git $whatchanged --no-abbrev-commit >expect.whatchanged.full + fi && test_config log.abbrevCommit true && @@ -1231,10 +1250,13 @@ test_expect_success 'log.abbrevCommit configuration' ' git reflog --no-abbrev-commit >actual && test_cmp expect.reflog.full actual && - git whatchanged >actual && - test_cmp expect.whatchanged.abbrev actual && - git whatchanged --no-abbrev-commit >actual && - test_cmp expect.whatchanged.full actual + if test_have_prereq !WITH_BREAKING_CHANGES + then + git $whatchanged >actual && + test_cmp expect.whatchanged.abbrev actual && + git $whatchanged --no-abbrev-commit >actual && + test_cmp expect.whatchanged.full actual + fi ' test_expect_success '--abbrev-commit with core.abbrev=false' ' diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 4a6242ff99..74b7ddccb2 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -1133,4 +1133,37 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us test_cmp expect actual ' +test_expect_success 'git cat-file --mailmap works with different author and committer' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + Mailmapped User <mailmapped-user@gitlab.com> C O Mitter <committer@example.com> + EOF + git commit --allow-empty -m "different author/committer" \ + --author="Different Author <different@example.com>" && + cat >expect <<-\EOF && + author Different Author <different@example.com> + committer Mailmapped User <mailmapped-user@gitlab.com> + EOF + git cat-file --mailmap commit HEAD >log && + sed -n -e "/^author /s/>.*/>/p" -e "/^committer /s/>.*/>/p" log >actual && + test_cmp expect actual +' + +test_expect_success 'git cat-file --mailmap maps both author and committer when both need mapping' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + Mapped Author <mapped-author@example.com> <different@example.com> + Mapped Committer <mapped-committer@example.com> C O Mitter <committer@example.com> + EOF + git commit --allow-empty -m "both author and committer mapped" \ + --author="Different Author <different@example.com>" && + cat >expect <<-\EOF && + author Mapped Author <mapped-author@example.com> + committer Mapped Committer <mapped-committer@example.com> + EOF + git cat-file --mailmap commit HEAD >log && + sed -n -e "/^author /s/>.*/>/p" -e "/^committer /s/>.*/>/p" log >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh index 8910d53cac..639868ac56 100755 --- a/t/t4216-log-bloom.sh +++ b/t/t4216-log-bloom.sh @@ -66,8 +66,9 @@ sane_unset GIT_TRACE2_CONFIG_PARAMS setup () { rm -f "$TRASH_DIRECTORY/trace.perf" && - git -c core.commitGraph=false log --pretty="format:%s" $1 >log_wo_bloom && - GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.perf" git -c core.commitGraph=true log --pretty="format:%s" $1 >log_w_bloom + eval git -c core.commitGraph=false log --pretty="format:%s" "$1" >log_wo_bloom && + eval "GIT_TRACE2_PERF=\"$TRASH_DIRECTORY/trace.perf\"" \ + git -c core.commitGraph=true log --pretty="format:%s" "$1" >log_w_bloom } test_bloom_filters_used () { @@ -138,10 +139,6 @@ test_expect_success 'git log with --walk-reflogs does not use Bloom filters' ' test_bloom_filters_not_used "--walk-reflogs -- A" ' -test_expect_success 'git log -- multiple path specs does not use Bloom filters' ' - test_bloom_filters_not_used "-- file4 A/file1" -' - test_expect_success 'git log -- "." pathspec at root does not use Bloom filters' ' test_bloom_filters_not_used "-- ." ' @@ -151,9 +148,17 @@ test_expect_success 'git log with wildcard that resolves to a single path uses B test_bloom_filters_used "-- *renamed" ' -test_expect_success 'git log with wildcard that resolves to a multiple paths does not uses Bloom filters' ' - test_bloom_filters_not_used "-- *" && - test_bloom_filters_not_used "-- file*" +test_expect_success 'git log with multiple literal paths uses Bloom filter' ' + test_bloom_filters_used "-- file4 A/file1" && + test_bloom_filters_used "-- *" && + test_bloom_filters_used "-- file*" +' + +test_expect_success 'git log with path contains a wildcard does not use Bloom filter' ' + test_bloom_filters_not_used "-- file\*" && + test_bloom_filters_not_used "-- A/\* file4" && + test_bloom_filters_not_used "-- file4 A/\*" && + test_bloom_filters_not_used "-- * A/\*" ' test_expect_success 'setup - add commit-graph to the chain without Bloom filters' ' diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh index 5174995191..027dedd976 100755 --- a/t/t5004-archive-corner-cases.sh +++ b/t/t5004-archive-corner-cases.sh @@ -176,10 +176,7 @@ test_expect_success EXPENSIVE,UNZIP,UNZIP_ZIP64_SUPPORT \ blob=$(echo $s | git hash-object -w --stdin) && # create tree containing 65500 entries of that blob - for i in $(test_seq 1 65500) - do - echo "100644 blob $blob $i" || return 1 - done >tree && + test_seq -f "100644 blob $blob\t%d" 1 65500 >tree && tree=$(git mktree <tree) && # zip it, creating an archive a bit bigger than 4GB diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index a5932b6a8b..73445782e7 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -525,7 +525,7 @@ test_expect_success 'index-pack --strict <pack> works in non-repo' ' test_path_is_file foo.idx ' -test_expect_success SHA1 'show-index works OK outside a repository' ' +test_expect_success DEFAULT_HASH_ALGORITHM 'show-index works OK outside a repository' ' nongit git show-index <foo.idx ' @@ -658,7 +658,7 @@ do test_commit -C repo initial && git -C repo repack -ad && git -C repo verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx && - if test $hash = sha1 + if test $hash = $GIT_TEST_BUILTIN_HASH then nongit git verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx else @@ -676,7 +676,7 @@ do test_commit -C repo initial && git -C repo repack -ad && git -C repo index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack && - if test $hash = sha1 + if test $hash = $GIT_TEST_BUILTIN_HASH then nongit git index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack else @@ -723,4 +723,23 @@ test_expect_success '--name-hash-version=2 and --write-bitmap-index are incompat ! test_grep "currently, --write-bitmap-index requires --name-hash-version=1" err ' +test_expect_success '--path-walk pack everything' ' + git -C server rev-parse HEAD >in && + GIT_PROGRESS_DELAY=0 git -C server pack-objects \ + --stdout --revs --path-walk --progress <in >out.pack 2>err && + grep "Compressing objects by path" err && + git -C server index-pack --stdin <out.pack +' + +test_expect_success '--path-walk thin pack' ' + cat >in <<-EOF && + $(git -C server rev-parse HEAD) + ^$(git -C server rev-parse HEAD~2) + EOF + GIT_PROGRESS_DELAY=0 git -C server pack-objects \ + --thin --stdout --revs --path-walk --progress <in >out.pack 2>err && + grep "Compressing objects by path" err && + git -C server index-pack --fix-thin --stdin <out.pack +' + test_done diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh index 805d60ff31..609399d54f 100755 --- a/t/t5306-pack-nobase.sh +++ b/t/t5306-pack-nobase.sh @@ -59,6 +59,11 @@ test_expect_success 'indirectly clone patch_clone' ' git pull ../.git && test $(git rev-parse HEAD) = $B && + # The --path-walk feature of "git pack-objects" is not + # compatible with this kind of fetch from an incomplete repo. + GIT_TEST_PACK_PATH_WALK=0 && + export GIT_TEST_PACK_PATH_WALK && + git pull ../patch_clone/.git && test $(git rev-parse HEAD) = $C ) diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index a62b463eaf..6718fb98c0 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -158,8 +158,9 @@ test_bitmap_cases () { ls .git/objects/pack/ | grep bitmap >output && test_line_count = 1 output && # verify equivalent packs are generated with/without using bitmap index - packasha1=$(git pack-objects --no-use-bitmap-index --all packa </dev/null) && - packbsha1=$(git pack-objects --use-bitmap-index --all packb </dev/null) && + # Be careful to not use the path-walk option in either case. + packasha1=$(git pack-objects --no-use-bitmap-index --no-path-walk --all packa </dev/null) && + packbsha1=$(git pack-objects --use-bitmap-index --no-path-walk --all packb </dev/null) && list_packed_objects packa-$packasha1.idx >packa.objects && list_packed_objects packb-$packbsha1.idx >packb.objects && test_cmp packa.objects packb.objects @@ -388,6 +389,14 @@ test_bitmap_cases () { git init --bare client.git && ( cd client.git && + + # This test relies on reusing a delta, but if the + # path-walk machinery is engaged, the base object + # is considered too small to use during the + # dynamic computation, so is not used. + GIT_TEST_PACK_PATH_WALK=0 && + export GIT_TEST_PACK_PATH_WALK && + git config transfer.unpackLimit 1 && git fetch .. delta-reuse-old:delta-reuse-old && git fetch .. delta-reuse-new:delta-reuse-new && @@ -486,6 +495,36 @@ test_bitmap_cases () { grep "ignoring extra bitmap" trace2.txt ) ' + + test_expect_success 'load corrupt bitmap' ' + rm -fr repo && + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + git config pack.writeBitmapLookupTable '"$writeLookupTable"' && + + test_commit base && + + git repack -adb && + bitmap="$(ls .git/objects/pack/pack-*.bitmap)" && + chmod +w $bitmap && + + test-tool bitmap list-commits-with-offset >offsets && + xor_off=$(head -n1 offsets | awk "{print \$3}") && + printf '\161' | + dd of=$bitmap count=1 bs=1 conv=notrunc seek=$xor_off && + + git rev-list --objects --no-object-names HEAD >expect.raw && + git rev-list --objects --use-bitmap-index --no-object-names HEAD \ + >actual.raw && + + sort expect.raw >expect && + sort actual.raw >actual && + + test_cmp expect actual + ) + ' } test_bitmap_cases diff --git a/t/t5316-pack-delta-depth.sh b/t/t5316-pack-delta-depth.sh index defaa06d65..03dfb7a61e 100755 --- a/t/t5316-pack-delta-depth.sh +++ b/t/t5316-pack-delta-depth.sh @@ -89,15 +89,18 @@ max_chain() { # adjusted (or scrapped if the heuristics have become too unreliable) test_expect_success 'packing produces a long delta' ' # Use --window=0 to make sure we are seeing reused deltas, - # not computing a new long chain. - pack=$(git pack-objects --all --window=0 </dev/null pack) && + # not computing a new long chain. (Also avoid the --path-walk + # option as it may break delta chains.) + pack=$(git pack-objects --all --window=0 --no-path-walk </dev/null pack) && echo 9 >expect && max_chain pack-$pack.pack >actual && test_cmp expect actual ' test_expect_success '--depth limits depth' ' - pack=$(git pack-objects --all --depth=5 </dev/null pack) && + # Avoid --path-walk to avoid breaking delta chains across path + # boundaries. + pack=$(git pack-objects --all --depth=5 --no-path-walk </dev/null pack) && echo 5 >expect && max_chain pack-$pack.pack >actual && test_cmp expect actual diff --git a/t/t5323-pack-redundant.sh b/t/t5323-pack-redundant.sh index bc30bc9652..2d96afd6f7 100755 --- a/t/t5323-pack-redundant.sh +++ b/t/t5323-pack-redundant.sh @@ -45,6 +45,11 @@ fi main_repo=main.git shared_repo=shared.git +test_expect_success 'pack-redundant needs --i-still-use-this' ' + test_must_fail git pack-redundant >message 2>&1 && + test_grep "nominated for removal" message +' + git_pack_redundant='git pack-redundant --i-still-use-this' # Create commits in <repo> and assign each commit's oid to shell variables diff --git a/t/t5331-pack-objects-stdin.sh b/t/t5331-pack-objects-stdin.sh index b48c0cbe8f..4a8df5a389 100755 --- a/t/t5331-pack-objects-stdin.sh +++ b/t/t5331-pack-objects-stdin.sh @@ -64,7 +64,7 @@ test_expect_success '--stdin-packs is incompatible with --filter' ' cd stdin-packs && test_must_fail git pack-objects --stdin-packs --stdout \ --filter=blob:none </dev/null 2>err && - test_grep "cannot use --filter with --stdin-packs" err + test_grep "options .--stdin-packs. and .--filter. cannot be used together" err ) ' @@ -236,4 +236,124 @@ test_expect_success 'pack-objects --stdin with packfiles from main and alternate test_cmp expected-objects actual-objects ' +objdir=.git/objects +packdir=$objdir/pack + +objects_in_packs () { + for p in "$@" + do + git show-index <"$packdir/pack-$p.idx" || return 1 + done >objects.raw && + + cut -d' ' -f2 objects.raw | sort && + rm -f objects.raw +} + +test_expect_success '--stdin-packs=follow walks into unknown packs' ' + test_when_finished "rm -fr repo" && + + git init repo && + ( + cd repo && + + for c in A B C D + do + test_commit "$c" || return 1 + done && + + A="$(echo A | git pack-objects --revs $packdir/pack)" && + B="$(echo A..B | git pack-objects --revs $packdir/pack)" && + C="$(echo B..C | git pack-objects --revs $packdir/pack)" && + D="$(echo C..D | git pack-objects --revs $packdir/pack)" && + test_commit E && + + git prune-packed && + + cat >in <<-EOF && + pack-$B.pack + ^pack-$C.pack + pack-$D.pack + EOF + + # With just --stdin-packs, pack "A" is unknown to us, so + # only objects from packs "B" and "D" are included in + # the output pack. + P=$(git pack-objects --stdin-packs $packdir/pack <in) && + objects_in_packs $B $D >expect && + objects_in_packs $P >actual && + test_cmp expect actual && + + # But with --stdin-packs=follow, objects from both + # included packs reach objects from the unknown pack, so + # objects from pack "A" is included in the output pack + # in addition to the above. + P=$(git pack-objects --stdin-packs=follow $packdir/pack <in) && + objects_in_packs $A $B $D >expect && + objects_in_packs $P >actual && + test_cmp expect actual && + + # And with --unpacked, we will pick up objects from unknown + # packs that are reachable from loose objects. Loose object E + # reaches objects in pack A, but there are three excluded packs + # in between. + # + # The resulting pack should include objects reachable from E + # that are not present in packs B, C, or D, along with those + # present in pack A. + cat >in <<-EOF && + ^pack-$B.pack + ^pack-$C.pack + ^pack-$D.pack + EOF + + P=$(git pack-objects --stdin-packs=follow --unpacked \ + $packdir/pack <in) && + + { + objects_in_packs $A && + git rev-list --objects --no-object-names D..E + }>expect.raw && + sort expect.raw >expect && + objects_in_packs $P >actual && + test_cmp expect actual + ) +' + +stdin_packs__follow_with_only () { + rm -fr stdin_packs__follow_with_only && + git init stdin_packs__follow_with_only && + ( + cd stdin_packs__follow_with_only && + + test_commit A && + test_commit B && + + git rev-parse "$@" >B.objects && + + echo A | git pack-objects --revs $packdir/pack && + B="$(git pack-objects $packdir/pack <B.objects)" && + + git cat-file --batch-check="%(objectname)" --batch-all-objects >objs && + for obj in $(cat objs) + do + rm -f $objdir/$(test_oid_to_path $obj) || return 1 + done && + + ( cd $packdir && ls pack-*.pack ) >in && + git pack-objects --stdin-packs=follow --stdout >/dev/null <in + ) +} + +test_expect_success '--stdin-packs=follow tolerates missing blobs' ' + stdin_packs__follow_with_only HEAD HEAD^{tree} +' + +test_expect_success '--stdin-packs=follow tolerates missing trees' ' + stdin_packs__follow_with_only HEAD HEAD:B.t +' + +test_expect_success '--stdin-packs=follow tolerates missing commits' ' + stdin_packs__follow_with_only HEAD HEAD^{tree} +' + test_done diff --git a/t/t5332-multi-pack-reuse.sh b/t/t5332-multi-pack-reuse.sh index 57cad7708f..395d09444c 100755 --- a/t/t5332-multi-pack-reuse.sh +++ b/t/t5332-multi-pack-reuse.sh @@ -7,6 +7,13 @@ test_description='pack-objects multi-pack reuse' GIT_TEST_MULTI_PACK_INDEX=0 GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 + +# The --path-walk option does not consider the preferred pack +# at all for reusing deltas, so this variable changes the +# behavior of this test, if enabled. +GIT_TEST_PACK_PATH_WALK=0 +export GIT_TEST_PACK_PATH_WALK + objdir=.git/objects packdir=$objdir/pack diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh index 56674db562..1f7a5d82ee 100755 --- a/t/t5333-pseudo-merge-bitmaps.sh +++ b/t/t5333-pseudo-merge-bitmaps.sh @@ -234,8 +234,8 @@ test_expect_success 'pseudo-merge pattern with capture groups' ' test_commit_bulk 16 && git rev-list HEAD~16.. >in && - sed "s|\(.*\)|create refs/remotes/$r/tags/\1 \1" in | - git update-ref --stdin || return 1 + sed "s|\(.*\)|create refs/remotes/$r/tags/\1 \1|" in >refs && + git update-ref --stdin <refs || return 1 done && git \ @@ -445,4 +445,21 @@ test_expect_success 'pseudo-merge closure' ' ) ' +test_expect_success 'use pseudo-merge in boundary traversal' ' + git init pseudo-merge-boundary-traversal && + ( + cd pseudo-merge-boundary-traversal && + + git config bitmapPseudoMerge.test.pattern refs/ && + git config pack.useBitmapBoundaryTraversal true && + + test_commit A && + git repack -adb && + test_commit B && + + nr=$(git rev-list --count --use-bitmap-index HEAD~1..HEAD) && + test 1 -eq "$nr" + ) +' + test_done diff --git a/t/t5408-send-pack-stdin.sh b/t/t5408-send-pack-stdin.sh index 526a675045..ec339761c2 100755 --- a/t/t5408-send-pack-stdin.sh +++ b/t/t5408-send-pack-stdin.sh @@ -69,15 +69,24 @@ test_expect_success 'stdin mixed with cmdline' ' test_expect_success 'cmdline refs written in order' ' clear_remote && - test_must_fail git send-pack remote.git A:foo B:foo && - verify_push A foo + test_must_fail git send-pack remote.git A:foo B:foo 2>err && + test_grep "multiple updates for ref ${SQ}refs/heads/foo${SQ} not allowed" err && + test_must_fail git --git-dir=remote.git rev-parse foo +' + +test_expect_success 'cmdline refs with multiple duplicates' ' + clear_remote && + test_must_fail git send-pack remote.git A:foo B:foo C:foo 2>err && + test_grep "multiple updates for ref ${SQ}refs/heads/foo${SQ} not allowed" err && + test_must_fail git --git-dir=remote.git rev-parse foo ' test_expect_success '--stdin refs come after cmdline' ' clear_remote && echo A:foo >input && test_must_fail git send-pack remote.git --stdin B:foo <input && - verify_push B foo + test_grep "multiple updates for ref ${SQ}refs/heads/foo${SQ} not allowed" err && + test_must_fail git --git-dir=remote.git rev-parse foo ' test_expect_success 'refspecs and --mirror do not mix (cmdline)' ' diff --git a/t/t5410-receive-pack.sh b/t/t5410-receive-pack.sh index f76a22943e..09d6bfd2a1 100755 --- a/t/t5410-receive-pack.sh +++ b/t/t5410-receive-pack.sh @@ -41,7 +41,19 @@ test_expect_success 'with core.alternateRefsPrefixes' ' test_cmp expect actual.haves ' -test_expect_success 'receive-pack missing objects fails connectivity check' ' +# The `tee.exe` shipped in Git for Windows v2.49.0 is known to hang frequently +# when spawned from `git.exe` and piping its output to `git.exe`. This seems +# related to MSYS2 runtime bug fixes regarding the signal handling; Let's just +# skip the tests that need to exercise this when the faulty MSYS2 runtime is +# detected; The test cases are exercised enough in other matrix jobs of the CI +# runs. +test_lazy_prereq TEE_DOES_NOT_HANG ' + test_have_prereq !MINGW && + case "$(uname -a)" in *3.5.7-463ebcdc.x86_64*) false;; esac +' + +test_expect_success TEE_DOES_NOT_HANG \ + 'receive-pack missing objects fails connectivity check' ' test_when_finished rm -rf repo remote.git setup.git && git init repo && @@ -62,7 +74,8 @@ test_expect_success 'receive-pack missing objects fails connectivity check' ' test_must_fail git -C remote.git cat-file -e $(git -C repo rev-parse HEAD) ' -test_expect_success 'receive-pack missing objects bypasses connectivity check' ' +test_expect_success TEE_DOES_NOT_HANG \ + 'receive-pack missing objects bypasses connectivity check' ' test_when_finished rm -rf repo remote.git setup.git && git init repo && diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index bef0250e89..2701eef85e 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -1644,4 +1644,18 @@ test_expect_success 'empty config clears remote.*.pushurl list' ' test_cmp expect actual ' +test_expect_success 'forbid adding subset of existing remote' ' + test_when_finished "git remote rm outer" && + git remote add outer url && + test_must_fail git remote add outer/inner url 2>err && + test_grep ".outer/inner. is a subset of existing remote .outer." err +' + +test_expect_success 'forbid adding superset of existing remote' ' + test_when_finished "git remote rm outer/inner" && + git remote add outer/inner url && + test_must_fail git remote add outer url 2>err && + test_grep ".outer. is a superset of existing remote .outer/inner." err +' + test_done diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index dabcc5f811..4e9c27b0f2 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -744,8 +744,8 @@ test_expect_success 'pushing valid refs triggers post-receive and post-update ho EOF cat >update.expect <<-EOF && - refs/heads/main $orgmain $newmain refs/heads/next $orgnext $newnext + refs/heads/main $orgmain $newmain EOF cat >post-receive.expect <<-EOF && @@ -808,8 +808,8 @@ test_expect_success 'deletion of a non-existent ref is not fed to post-receive a EOF cat >update.expect <<-EOF && - refs/heads/main $orgmain $newmain refs/heads/nonexistent $ZERO_OID $ZERO_OID + refs/heads/main $orgmain $newmain EOF cat >post-receive.expect <<-EOF && @@ -868,10 +868,10 @@ test_expect_success 'mixed ref updates, deletes, invalid deletes trigger hooks w EOF cat >update.expect <<-EOF && - refs/heads/main $orgmain $newmain refs/heads/next $orgnext $newnext - refs/heads/seen $orgseen $newseen refs/heads/nonexistent $ZERO_OID $ZERO_OID + refs/heads/main $orgmain $newmain + refs/heads/seen $orgseen $newseen EOF cat >post-receive.expect <<-EOF && @@ -1909,4 +1909,23 @@ test_expect_success 'push with config push.useBitmaps' ' --thin --delta-base-offset -q --no-use-bitmap-index <false ' +test_expect_success 'push with config pack.usePathWalk=true' ' + mk_test testrepo heads/main && + git checkout main && + test_config pack.usePathWalk true && + GIT_TRACE2_EVENT="$(pwd)/path-walk.txt" \ + git push --quiet testrepo main:test && + + test_region pack-objects path-walk path-walk.txt +' + +test_expect_success 'push with F/D conflict with deletion and creation' ' + test_when_finished "git branch -D branch" && + git branch branch/conflict && + mk_test testrepo heads/branch/conflict && + git branch -D branch/conflict && + git branch branch && + git push testrepo :refs/heads/branch/conflict refs/heads/branch +' + test_done diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 63c9a8f04b..0e0019347e 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -472,6 +472,66 @@ test_expect_success 'pull --no-autostash & merge.autostash unset' ' test_pull_autostash_fail --no-autostash --no-rebase ' +test_expect_success 'pull succeeds with dirty working directory and pull.autostash=true' ' + test_config pull.autostash true && + test_pull_autostash 1 --rebase && + test_pull_autostash 2 --no-rebase && + test_pull_autostash 1 --autostash --rebase && + test_pull_autostash 2 --autostash --no-rebase +' + +test_expect_success 'pull fails with dirty working directory and pull.autostash=false' ' + test_config pull.autostash false && + test_pull_autostash_fail --rebase && + test_pull_autostash_fail --no-rebase && + test_pull_autostash_fail --no-autostash --rebase && + test_pull_autostash_fail --no-autostash --no-rebase +' + +test_expect_success 'pull --autostash overrides pull.autostash=false' ' + test_config pull.autostash false && + test_pull_autostash 1 --autostash --rebase && + test_pull_autostash 2 --autostash --no-rebase +' + +test_expect_success 'pull --no-autostash overrides pull.autostash=true' ' + test_config pull.autostash true && + test_pull_autostash_fail --no-autostash --rebase && + test_pull_autostash_fail --no-autostash --no-rebase +' + +test_expect_success 'pull.autostash=true overrides rebase.autostash' ' + test_config pull.autostash true && + test_config rebase.autostash true && + test_pull_autostash 1 --rebase && + test_config rebase.autostash false && + test_pull_autostash 1 --rebase +' + +test_expect_success 'pull.autostash=false overrides rebase.autostash' ' + test_config pull.autostash false && + test_config rebase.autostash true && + test_pull_autostash_fail --rebase && + test_config rebase.autostash false && + test_pull_autostash_fail --rebase +' + +test_expect_success 'pull.autostash=true overrides merge.autostash' ' + test_config pull.autostash true && + test_config merge.autostash true && + test_pull_autostash 2 --no-rebase && + test_config merge.autostash false && + test_pull_autostash 2 --no-rebase +' + +test_expect_success 'pull.autostash=false overrides merge.autostash' ' + test_config pull.autostash false && + test_config merge.autostash true && + test_pull_autostash_fail --no-rebase && + test_config merge.autostash false && + test_pull_autostash_fail --no-rebase +' + test_expect_success 'pull.rebase' ' git reset --hard before-rebase && test_config pull.rebase true && diff --git a/t/t5538-push-shallow.sh b/t/t5538-push-shallow.sh index e91fcc173e..dc0e972943 100755 --- a/t/t5538-push-shallow.sh +++ b/t/t5538-push-shallow.sh @@ -123,4 +123,45 @@ EOF git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null ) ' + +test_expect_success 'push new commit from shallow clone has correct object count' ' + git init origin && + test_commit -C origin a && + test_commit -C origin b && + + git clone --depth=1 "file://$(pwd)/origin" client && + git -C client checkout -b topic && + git -C client commit --allow-empty -m "empty" && + GIT_PROGRESS_DELAY=0 git -C client push --progress origin topic 2>err && + test_grep "Enumerating objects: 1, done." err +' + +test_expect_success 'push new commit from shallow clone has good deltas' ' + git init base && + test_seq 1 999 >base/a && + test_commit -C base initial && + git -C base add a && + git -C base commit -m "big a" && + + git clone --depth=1 "file://$(pwd)/base" deltas && + git -C deltas checkout -b deltas && + test_seq 1 1000 >deltas/a && + git -C deltas commit -a -m "bigger a" && + GIT_PROGRESS_DELAY=0 git -C deltas push --progress origin deltas 2>err && + + test_grep "Enumerating objects: 5, done" err && + + # If the delta base is found, then this message uses "bytes". + # If the delta base is not found, then this message uses "KiB". + test_grep "Writing objects: .* bytes" err && + + git -C deltas commit --amend -m "changed message" && + GIT_TRACE2_EVENT="$(pwd)/config-push.txt" \ + GIT_PROGRESS_DELAY=0 git -C deltas -c pack.usePathWalk=true \ + push --progress -f origin deltas 2>err && + + test_grep "Enumerating objects: 1, done" err && + test_region pack-objects path-walk config-push.txt +' + test_done diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh index 9b211a626b..7a0943bd36 100755 --- a/t/t5558-clone-bundle-uri.sh +++ b/t/t5558-clone-bundle-uri.sh @@ -1279,6 +1279,29 @@ test_expect_success 'bundles are downloaded once during fetch --all' ' trace-mult.txt >bundle-fetches && test_line_count = 1 bundle-fetches ' + +test_expect_success 'bundles with space in URI are rejected' ' + test_when_finished "rm -rf busted repo" && + mkdir -p "$HOME/busted/ /$HOME/repo/.git/objects/bundles" && + git clone --bundle-uri="$HTTPD_URL/bogus $HOME/busted/" "$HTTPD_URL/smart/fetch.git" repo 2>err && + test_grep "error: bundle-uri: URI is malformed: " err && + find busted -type f >files && + test_must_be_empty files +' + +test_expect_success 'bundles with newline in URI are rejected' ' + test_when_finished "rm -rf busted repo" && + git clone --bundle-uri="$HTTPD_URL/bogus\nget $HTTPD_URL/bogus $HOME/busted" "$HTTPD_URL/smart/fetch.git" repo 2>err && + test_grep "error: bundle-uri: URI is malformed: " err && + test_path_is_missing "$HOME/busted" +' + +test_expect_success 'bundles with newline in target path are rejected' ' + git clone --bundle-uri="$HTTPD_URL/bogus" "$HTTPD_URL/smart/fetch.git" "$(printf "escape\nget $HTTPD_URL/bogus .")" 2>err && + test_grep "error: bundle-uri: filename is malformed: " err && + test_path_is_missing escape +' + # Do not add tests here unless they use the HTTP server, as they will # not run unless the HTTP dependencies exist. diff --git a/t/t6422-merge-rename-corner-cases.sh b/t/t6422-merge-rename-corner-cases.sh index 9cbe7ca782..f14c0fb30e 100755 --- a/t/t6422-merge-rename-corner-cases.sh +++ b/t/t6422-merge-rename-corner-cases.sh @@ -1146,10 +1146,7 @@ test_conflicts_with_adds_and_renames() { cd simple_${sideL}_${sideR} && # Create some related files now - for i in $(test_seq 1 10) - do - echo Random base content line $i - done >file_v1 && + test_seq -f "Random base content line %d" 1 10 >file_v1 && cp file_v1 file_v2 && echo modification >>file_v2 && @@ -1293,10 +1290,7 @@ test_setup_nested_conflicts_from_rename_rename () { cd nested_conflicts_from_rename_rename && # Create some related files now - for i in $(test_seq 1 10) - do - echo Random base content line $i - done >file_v1 && + test_seq -f "Random base content line %d" 1 10 >file_v1 && cp file_v1 file_v2 && cp file_v1 file_v3 && diff --git a/t/t6601-path-walk.sh b/t/t6601-path-walk.sh index 8d187f7279..56bd1e3c5b 100755 --- a/t/t6601-path-walk.sh +++ b/t/t6601-path-walk.sh @@ -376,6 +376,26 @@ test_expect_success 'topic, not base, boundary with pruning' ' test_cmp_sorted expect out ' +test_expect_success 'topic, not base, --edge-aggressive with pruning' ' + test-tool path-walk --prune --edge-aggressive -- topic --not base >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 1:tree::$(git rev-parse topic^{tree}) + 1:tree::$(git rev-parse base^{tree}):UNINTERESTING + 2:tree:right/:$(git rev-parse topic:right) + 2:tree:right/:$(git rev-parse base:right):UNINTERESTING + 3:blob:right/c:$(git rev-parse base:right/c):UNINTERESTING + 3:blob:right/c:$(git rev-parse topic:right/c) + blobs:2 + commits:1 + tags:0 + trees:4 + EOF + + test_cmp_sorted expect out +' + test_expect_success 'trees are reported exactly once' ' test_when_finished "rm -rf unique-trees" && test_create_repo unique-trees && diff --git a/t/t7007-show.sh b/t/t7007-show.sh index d6cc69e0f2..2d322b53d1 100755 --- a/t/t7007-show.sh +++ b/t/t7007-show.sh @@ -167,4 +167,28 @@ test_expect_success 'show --graph is forbidden' ' test_must_fail git show --graph HEAD ' +test_expect_success 'show unmerged index' ' + git reset --hard && + + git switch -C base && + echo "base" >conflicting && + git add conflicting && + git commit -m "base" && + + git branch hello && + git branch goodbye && + + git switch hello && + echo "hello" >conflicting && + git commit -am "hello" && + + git switch goodbye && + echo "goodbye" >conflicting && + git commit -am "goodbye" && + + git switch hello && + test_must_fail git merge goodbye && + git show --merge HEAD +' + test_done diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh index 9c3cc4cf40..66c3ec2da2 100755 --- a/t/t7401-submodule-summary.sh +++ b/t/t7401-submodule-summary.sh @@ -38,10 +38,11 @@ commit_file () { git commit "$@" -m "Commit $*" >/dev/null } -test_create_repo sm1 && -add_file . foo >/dev/null - -head1=$(add_file sm1 foo1 foo2) +test_expect_success 'setup submodule' ' + git init sm1 && + add_file . foo && + head1=$(add_file sm1 foo1 foo2) +' test_expect_success 'added submodule' " git add sm1 && @@ -214,9 +215,12 @@ test_expect_success 'typechanged submodule(submodule->blob)' " test_cmp expected actual " -rm -f sm1 && -test_create_repo sm1 && -head6=$(add_file sm1 foo6 foo7) +test_expect_success 'setup submodule' ' + rm -f sm1 && + git init sm1 && + head6=$(add_file sm1 foo6 foo7) +' + test_expect_success 'nonexistent commit' " git submodule summary >actual && cat >expected <<-EOF && diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index c562bad042..3adab12091 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -1095,12 +1095,15 @@ test_expect_success 'submodule update --quiet passes quietness to fetch with a s (cd super5 && # This test var can mess with the stderr output checked in this test. GIT_TEST_NAME_HASH_VERSION=1 \ + GIT_TEST_PACK_PATH_WALK=0 \ git submodule update --quiet --init --depth=1 submodule3 >out 2>err && test_must_be_empty out && test_must_be_empty err ) && git clone super4 super6 && (cd super6 && + # This test variable will create a "warning" message to stderr + GIT_TEST_PACK_PATH_WALK=0 \ git submodule update --init --depth=1 submodule3 >out 2>err && test_file_not_empty out && test_file_not_empty err @@ -1134,6 +1137,67 @@ test_expect_success 'setup clean recursive superproject' ' git clone --recurse-submodules top top-clean ' +test_expect_success 'submodule update with multiple remotes' ' + test_when_finished "rm -fr top-cloned" && + cp -r top-clean top-cloned && + + # Create a commit in each repo, starting with bottom + test_commit -C bottom multiple_remote_commit && + # Create middle commit + git -C middle/bottom fetch && + git -C middle/bottom checkout -f FETCH_HEAD && + git -C middle add bottom && + git -C middle commit -m "multiple_remote_commit" && + # Create top commit + git -C top/middle fetch && + git -C top/middle checkout -f FETCH_HEAD && + git -C top add middle && + git -C top commit -m "multiple_remote_commit" && + + # rename the submodule remote + git -C top-cloned/middle remote rename origin upstream && + + # Add another remote + git -C top-cloned/middle remote add other bogus && + + # Make the update of "middle" a no-op, otherwise we error out + # because of its unmerged state + test_config -C top-cloned submodule.middle.update !true && + git -C top-cloned submodule update --recursive 2>actual.err && + cat >expect.err <<-\EOF && + EOF + test_cmp expect.err actual.err +' + +test_expect_success 'submodule update with renamed remote' ' + test_when_finished "rm -fr top-cloned" && + cp -r top-clean top-cloned && + + # Create a commit in each repo, starting with bottom + test_commit -C bottom rename_commit && + # Create middle commit + git -C middle/bottom fetch && + git -C middle/bottom checkout -f FETCH_HEAD && + git -C middle add bottom && + git -C middle commit -m "rename_commit" && + # Create top commit + git -C top/middle fetch && + git -C top/middle checkout -f FETCH_HEAD && + git -C top add middle && + git -C top commit -m "rename_commit" && + + # rename the submodule remote + git -C top-cloned/middle remote rename origin upstream && + + # Make the update of "middle" a no-op, otherwise we error out + # because of its unmerged state + test_config -C top-cloned submodule.middle.update !true && + git -C top-cloned submodule update --recursive 2>actual.err && + cat >expect.err <<-\EOF && + EOF + test_cmp expect.err actual.err +' + test_expect_success 'submodule update should skip unmerged submodules' ' test_when_finished "rm -fr top-cloned" && cp -r top-clean top-cloned && diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh index 023a5cbdc4..aea1ddf117 100755 --- a/t/t7422-submodule-output.sh +++ b/t/t7422-submodule-output.sh @@ -180,17 +180,14 @@ test_expect_success !MINGW 'git submodule status --recursive propagates SIGPIPE' COMMIT=$(git rev-parse HEAD) && for i in $(test_seq 2000) do - printf "[submodule \"sm-$i\"]\npath = recursive-submodule-path-$i\n" "$i" || + echo "[submodule \"sm-$i\"]" && + echo "path = recursive-submodule-path-$i" || return 1 done >gitmodules && BLOB=$(git hash-object -w --stdin <gitmodules) && printf "100644 blob $BLOB\t.gitmodules\n" >tree && - for i in $(test_seq 2000) - do - printf "160000 commit $COMMIT\trecursive-submodule-path-%d\n" "$i" || - return 1 - done >>tree && + test_seq -f "160000 commit $COMMIT\trecursive-submodule-path-%d" 2000 >>tree && TREE=$(git mktree <tree) && COMMIT=$(git commit-tree "$TREE") && diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh index 9367794641..14b5743b96 100755 --- a/t/t7450-bad-git-dotfiles.sh +++ b/t/t7450-bad-git-dotfiles.sh @@ -372,4 +372,37 @@ test_expect_success 'checkout -f --recurse-submodules must not use a nested gitd test_path_is_missing nested_checkout/thing2/.git ' +test_expect_success SYMLINKS,!WINDOWS,!MINGW 'submodule must not checkout into different directory' ' + test_when_finished "rm -rf sub repo bad-clone" && + + git init sub && + write_script sub/post-checkout <<-\EOF && + touch "$PWD/foo" + EOF + git -C sub add post-checkout && + git -C sub commit -m hook && + + git init repo && + git -C repo -c protocol.file.allow=always submodule add "$PWD/sub" sub && + git -C repo mv sub $(printf "sub\r") && + + # Ensure config values containing CR are wrapped in quotes. + git config unset -f repo/.gitmodules submodule.sub.path && + printf "\tpath = \"sub\r\"\n" >>repo/.gitmodules && + + git config unset -f repo/.git/modules/sub/config core.worktree && + { + printf "[core]\n" && + printf "\tworktree = \"../../../sub\r\"\n" + } >>repo/.git/modules/sub/config && + + ln -s .git/modules/sub/hooks repo/sub && + git -C repo add -A && + git -C repo commit -m submodule && + + git -c protocol.file.allow=always clone --recurse-submodules repo bad-clone && + ! test -f "$PWD/foo" && + test -f $(printf "bad-clone/sub\r/post-checkout") +' + test_done diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh index 065f780636..0f887a3ebe 100755 --- a/t/t7528-signed-commit-ssh.sh +++ b/t/t7528-signed-commit-ssh.sh @@ -84,18 +84,26 @@ test_expect_success GPGSSH 'sign commits using literal public keys with ssh-agen test_config gpg.format ssh && eval $(ssh-agent) && test_when_finished "kill ${SSH_AGENT_PID}" && - ssh-add "${GPGSSH_KEY_PRIMARY}" && - echo 1 >file && git add file && - git commit -a -m rsa-inline -S"$(cat "${GPGSSH_KEY_PRIMARY}.pub")" && - echo 2 >file && - test_config user.signingkey "$(cat "${GPGSSH_KEY_PRIMARY}.pub")" && - git commit -a -m rsa-config -S && - ssh-add "${GPGSSH_KEY_ECDSA}" && - echo 3 >file && - git commit -a -m ecdsa-inline -S"key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" && - echo 4 >file && - test_config user.signingkey "key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" && - git commit -a -m ecdsa-config -S + test_when_finished "test_unconfig user.signingkey" && + mkdir tmpdir && + TMPDIR="$(pwd)/tmpdir" && + ( + export TMPDIR && + ssh-add "${GPGSSH_KEY_PRIMARY}" && + echo 1 >file && git add file && + git commit -a -m rsa-inline -S"$(cat "${GPGSSH_KEY_PRIMARY}.pub")" && + echo 2 >file && + git config user.signingkey "$(cat "${GPGSSH_KEY_PRIMARY}.pub")" && + git commit -a -m rsa-config -S && + ssh-add "${GPGSSH_KEY_ECDSA}" && + echo 3 >file && + git commit -a -m ecdsa-inline -S"key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" && + echo 4 >file && + git config user.signingkey "key::$(cat "${GPGSSH_KEY_ECDSA}.pub")" && + git commit -a -m ecdsa-config -S + ) && + find tmpdir -type f >tmpfiles && + test_must_be_empty tmpfiles ' test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'create signed commits with keys having defined lifetimes' ' diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 2a8df29219..9838094b66 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -185,8 +185,19 @@ test_expect_success 'reject non-strategy with a git-merge-foo name' ' test_expect_success 'merge c0 with c1' ' echo "OBJID HEAD@{0}: merge c1: Fast-forward" >reflog.expected && + cat >expect <<-\EOF && + Updating FROM..TO + Fast-forward + file | 2 +- + other | 9 +++++++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + create mode 100644 other + EOF + git reset --hard c0 && - git merge c1 && + git merge c1 >out && + sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual && + test_cmp expect actual && verify_merge file result.1 && verify_head "$c1" && @@ -205,6 +216,67 @@ test_expect_success 'merge c0 with c1 with --ff-only' ' verify_head "$c1" ' +test_expect_success 'the same merge with merge.stat=diffstat' ' + cat >expect <<-\EOF && + Updating FROM..TO + Fast-forward + file | 2 +- + other | 9 +++++++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + create mode 100644 other + EOF + + git reset --hard c0 && + git -c merge.stat=diffstat merge c1 >out && + sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual && + test_cmp expect actual +' + +test_expect_success 'the same merge with compact summary' ' + cat >expect <<-\EOF && + Updating FROM..TO + Fast-forward + file | 2 +- + other (new) | 9 +++++++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + EOF + + git reset --hard c0 && + git merge --compact-summary c1 >out && + sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual && + test_cmp expect actual +' + +test_expect_success 'the same merge with compact summary' ' + cat >expect <<-\EOF && + Updating FROM..TO + Fast-forward + file | 2 +- + other (new) | 9 +++++++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + EOF + + git reset --hard c0 && + git merge --compact-summary c1 >out && + sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual && + test_cmp expect actual +' + +test_expect_success 'the same merge with merge.stat=compact' ' + cat >expect <<-\EOF && + Updating FROM..TO + Fast-forward + file | 2 +- + other (new) | 9 +++++++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + EOF + + git reset --hard c0 && + git -c merge.stat=compact merge c1 >out && + sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual && + test_cmp expect actual +' + test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge from unborn branch' ' diff --git a/t/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh index 8aebfb45f5..aa2e2e6ad8 100755 --- a/t/t7704-repack-cruft.sh +++ b/t/t7704-repack-cruft.sh @@ -724,4 +724,149 @@ test_expect_success 'cruft repack respects --quiet' ' ) ' +setup_cruft_exclude_tests() { + git init "$1" && + ( + cd "$1" && + + git config repack.midxMustContainCruft false && + + test_commit one && + + test_commit --no-tag two && + two="$(git rev-parse HEAD)" && + test_commit --no-tag three && + three="$(git rev-parse HEAD)" && + git reset --hard one && + git reflog expire --all --expire=all && + + GIT_TEST_MULTI_PACK_INDEX=0 git repack --cruft -d && + + git merge $two && + test_commit four + ) +} + +test_expect_success 'repack --write-midx excludes cruft where possible' ' + setup_cruft_exclude_tests exclude-cruft-when-possible && + ( + cd exclude-cruft-when-possible && + + GIT_TEST_MULTI_PACK_INDEX=0 \ + git repack -d --geometric=2 --write-midx --write-bitmap-index && + + test-tool read-midx --show-objects $objdir >midx && + cruft="$(ls $packdir/*.mtimes)" && + test_grep ! "$(basename "$cruft" .mtimes).idx" midx && + + git rev-list --all --objects --no-object-names >reachable.raw && + sort reachable.raw >reachable.objects && + awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects && + + test_cmp reachable.objects midx.objects + ) +' + +test_expect_success 'repack --write-midx includes cruft when instructed' ' + setup_cruft_exclude_tests exclude-cruft-when-instructed && + ( + cd exclude-cruft-when-instructed && + + GIT_TEST_MULTI_PACK_INDEX=0 \ + git -c repack.midxMustContainCruft=true repack \ + -d --geometric=2 --write-midx --write-bitmap-index && + + test-tool read-midx --show-objects $objdir >midx && + cruft="$(ls $packdir/*.mtimes)" && + test_grep "$(basename "$cruft" .mtimes).idx" midx && + + git cat-file --batch-check="%(objectname)" --batch-all-objects \ + >all.objects && + awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects && + + test_cmp all.objects midx.objects + ) +' + +test_expect_success 'repack --write-midx includes cruft when necessary' ' + setup_cruft_exclude_tests exclude-cruft-when-necessary && + ( + cd exclude-cruft-when-necessary && + + test_path_is_file $(ls $packdir/pack-*.mtimes) && + ( cd $packdir && ls pack-*.idx ) | sort >packs.all && + git multi-pack-index write --stdin-packs --bitmap <packs.all && + + test_commit five && + GIT_TEST_MULTI_PACK_INDEX=0 \ + git repack -d --geometric=2 --write-midx --write-bitmap-index && + + test-tool read-midx --show-objects $objdir >midx && + awk "/\.pack$/ { print \$1 }" <midx | sort >midx.objects && + git cat-file --batch-all-objects --batch-check="%(objectname)" \ + >expect.objects && + test_cmp expect.objects midx.objects && + + grep "^pack-" midx >midx.packs && + test_line_count = "$(($(wc -l <packs.all) + 1))" midx.packs + ) +' + +test_expect_success 'repack --write-midx includes cruft when already geometric' ' + git init repack--write-midx-geometric-noop && + ( + cd repack--write-midx-geometric-noop && + + git branch -M main && + test_commit A && + test_commit B && + + git checkout -B side && + test_commit --no-tag C && + C="$(git rev-parse HEAD)" && + + git checkout main && + git branch -D side && + git reflog expire --all --expire=all && + + # At this point we have two packs: one containing the + # objects belonging to commits A and B, and another + # (cruft) pack containing the objects belonging to + # commit C. + git repack --cruft -d && + + # Create a third pack which contains a merge commit + # making commit C reachable again. + # + # --no-ff is important here, as it ensures that we + # actually write a new object and subsequently a new + # pack to contain it. + git merge --no-ff $C && + git repack -d && + + ls $packdir/pack-*.idx | sort >packs.all && + cruft="$(ls $packdir/pack-*.mtimes)" && + cruft="${cruft%.mtimes}.idx" && + + for idx in $(grep -v $cruft <packs.all) + do + git show-index <$idx >out && + wc -l <out || return 1 + done >sizes.raw && + + # Make sure that there are two non-cruft packs, and + # that one of them contains at least twice as many + # objects as the other, ensuring that they are already + # in a geometric progression. + sort -n sizes.raw >sizes && + test_line_count = 2 sizes && + s1=$(head -n 1 sizes) && + s2=$(tail -n 1 sizes) && + test "$s2" -gt "$((2 * $s1))" && + + git -c repack.midxMustContainCruft=false repack --geometric=2 \ + --write-midx --write-bitmap-index + ) +' + test_done diff --git a/t/t7815-grep-binary.sh b/t/t7815-grep-binary.sh index b7d83f9a5d..55d5e6de17 100755 --- a/t/t7815-grep-binary.sh +++ b/t/t7815-grep-binary.sh @@ -63,7 +63,7 @@ test_expect_success 'git grep ile a' ' git grep ile a ' -test_expect_failure !CYGWIN 'git grep .fi a' ' +test_expect_failure !CYGWIN,!MACOS 'git grep .fi a' ' git grep .fi a ' diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh index 8cf89e285f..ddd273d8dc 100755 --- a/t/t7900-maintenance.sh +++ b/t/t7900-maintenance.sh @@ -49,9 +49,9 @@ test_expect_success 'run [--auto|--quiet]' ' git maintenance run --auto 2>/dev/null && GIT_TRACE2_EVENT="$(pwd)/run-no-quiet.txt" \ git maintenance run --no-quiet 2>/dev/null && - test_subcommand git gc --quiet --no-detach <run-no-auto.txt && - test_subcommand ! git gc --auto --quiet --no-detach <run-auto.txt && - test_subcommand git gc --no-quiet --no-detach <run-no-quiet.txt + test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-no-auto.txt && + test_subcommand ! git gc --auto --quiet --no-detach --skip-foreground-tasks <run-auto.txt && + test_subcommand git gc --no-quiet --no-detach --skip-foreground-tasks <run-no-quiet.txt ' test_expect_success 'maintenance.auto config option' ' @@ -154,9 +154,9 @@ test_expect_success 'run --task=<task>' ' git maintenance run --task=commit-graph 2>/dev/null && GIT_TRACE2_EVENT="$(pwd)/run-both.txt" \ git maintenance run --task=commit-graph --task=gc 2>/dev/null && - test_subcommand ! git gc --quiet --no-detach <run-commit-graph.txt && - test_subcommand git gc --quiet --no-detach <run-gc.txt && - test_subcommand git gc --quiet --no-detach <run-both.txt && + test_subcommand ! git gc --quiet --no-detach --skip-foreground-tasks <run-commit-graph.txt && + test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-gc.txt && + test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-both.txt && test_subcommand git commit-graph write --split --reachable --no-progress <run-commit-graph.txt && test_subcommand ! git commit-graph write --split --reachable --no-progress <run-gc.txt && test_subcommand git commit-graph write --split --reachable --no-progress <run-both.txt @@ -610,7 +610,12 @@ test_expect_success 'rerere-gc task with --auto honors maintenance.rerere-gc.aut test_expect_success '--auto and --schedule incompatible' ' test_must_fail git maintenance run --auto --schedule=daily 2>err && - test_grep "at most one" err + test_grep "cannot be used together" err +' + +test_expect_success '--task and --schedule incompatible' ' + test_must_fail git maintenance run --task=pack-refs --schedule=daily 2>err && + test_grep "cannot be used together" err ' test_expect_success 'invalid --schedule value' ' diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 0c1af43f6f..e56e0c8d77 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -201,6 +201,13 @@ test_expect_success $PREREQ 'cc trailer with get_maintainer.pl output' ' test_cmp expected-cc commandline1 ' +test_expect_failure $PREREQ 'invalid smtp server port value' ' + clean_fake_sendmail && + git send-email -1 --to=recipient@example.com \ + --smtp-server-port=bogus-symbolic-name \ + --smtp-server="$(pwd)/fake.sendmail" +' + test_expect_success $PREREQ 'setup expect' " cat >expected-show-all-headers <<\EOF 0001-Second.patch diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index b258dbf1df..4dc3d645bf 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -120,7 +120,7 @@ test_expect_success 'A: create pack from stdin' ' INPUT_END git fast-import --export-marks=marks.out <input && - git whatchanged main + git log --raw main ' test_expect_success 'A: verify pack' ' @@ -279,7 +279,7 @@ test_expect_success 'A: verify marks import does not crash' ' INPUT_END git fast-import --import-marks=marks.out <input && - git whatchanged verify--import-marks + git log --raw verify--import-marks ' test_expect_success 'A: verify pack' ' @@ -652,7 +652,7 @@ test_expect_success 'C: incremental import create pack from stdin' ' INPUT_END git fast-import <input && - git whatchanged branch + git log --raw branch ' test_expect_success 'C: verify pack' ' @@ -715,7 +715,7 @@ test_expect_success 'D: inline data in commit' ' INPUT_END git fast-import <input && - git whatchanged branch + git log --raw branch ' test_expect_success 'D: verify pack' ' @@ -882,7 +882,7 @@ test_expect_success 'H: deletall, add 1' ' INPUT_END git fast-import <input && - git whatchanged H + git log --raw H ' test_expect_success 'H: verify pack' ' @@ -2066,7 +2066,7 @@ test_expect_success 'Q: commit notes' ' INPUT_END git fast-import <input && - git whatchanged notes-test + git log --raw notes-test ' test_expect_success 'Q: verify pack' ' diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh index 1ae4d7c0d3..e62173cf1f 100755 --- a/t/t9301-fast-import-notes.sh +++ b/t/t9301-fast-import-notes.sh @@ -76,7 +76,7 @@ INPUT_END test_expect_success 'set up main branch' ' git fast-import <input && - git whatchanged main + git log --raw main ' commit4=$(git rev-parse refs/heads/main) diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index dda9e7c3e7..46700dbc40 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -299,22 +299,10 @@ test_expect_success GPG 'set up signed commit' ' ' -test_expect_success GPG 'signed-commits default' ' - - sane_unset FAST_EXPORT_SIGNED_COMMITS_NOABORT && - test_must_fail git fast-export --reencode=no commit-signing && - - FAST_EXPORT_SIGNED_COMMITS_NOABORT=1 git fast-export --reencode=no commit-signing >output 2>err && - ! grep ^gpgsig output && - grep "^encoding ISO-8859-1" output && - test -s err && - sed "s/commit-signing/commit-strip-signing/" output | ( - cd new && - git fast-import && - STRIPPED=$(git rev-parse --verify refs/heads/commit-strip-signing) && - test $COMMIT_SIGNING != $STRIPPED - ) - +test_expect_success GPG 'signed-commits default is same as strip' ' + git fast-export --reencode=no commit-signing >out1 2>err && + git fast-export --reencode=no --signed-commits=strip commit-signing >out2 && + test_cmp out1 out2 ' test_expect_success GPG 'signed-commits=abort' ' @@ -326,7 +314,7 @@ test_expect_success GPG 'signed-commits=abort' ' test_expect_success GPG 'signed-commits=verbatim' ' git fast-export --signed-commits=verbatim --reencode=no commit-signing >output && - grep "^gpgsig sha" output && + test_grep -E "^gpgsig $GIT_DEFAULT_HASH openpgp" output && grep "encoding ISO-8859-1" output && ( cd new && @@ -340,7 +328,7 @@ test_expect_success GPG 'signed-commits=verbatim' ' test_expect_success GPG 'signed-commits=warn-verbatim' ' git fast-export --signed-commits=warn-verbatim --reencode=no commit-signing >output 2>err && - grep "^gpgsig sha" output && + test_grep -E "^gpgsig $GIT_DEFAULT_HASH openpgp" output && grep "encoding ISO-8859-1" output && test -s err && ( @@ -381,6 +369,62 @@ test_expect_success GPG 'signed-commits=warn-strip' ' ' +test_expect_success GPGSM 'setup X.509 signed commit' ' + + git checkout -b x509-signing main && + test_config gpg.format x509 && + test_config user.signingkey $GIT_COMMITTER_EMAIL && + echo "X.509 content" >file && + git add file && + git commit -S -m "X.509 signed commit" && + X509_COMMIT=$(git rev-parse HEAD) && + git checkout main + +' + +test_expect_success GPGSM 'round-trip X.509 signed commit' ' + + git fast-export --signed-commits=verbatim x509-signing >output && + test_grep -E "^gpgsig $GIT_DEFAULT_HASH x509" output && + ( + cd new && + git fast-import && + git cat-file commit refs/heads/x509-signing >actual && + grep "^gpgsig" actual && + IMPORTED=$(git rev-parse refs/heads/x509-signing) && + test $X509_COMMIT = $IMPORTED + ) <output + +' + +test_expect_success GPGSSH 'setup SSH signed commit' ' + + git checkout -b ssh-signing main && + test_config gpg.format ssh && + test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" && + echo "SSH content" >file && + git add file && + git commit -S -m "SSH signed commit" && + SSH_COMMIT=$(git rev-parse HEAD) && + git checkout main + +' + +test_expect_success GPGSSH 'round-trip SSH signed commit' ' + + git fast-export --signed-commits=verbatim ssh-signing >output && + test_grep -E "^gpgsig $GIT_DEFAULT_HASH ssh" output && + ( + cd new && + git fast-import && + git cat-file commit refs/heads/ssh-signing >actual && + grep "^gpgsig" actual && + IMPORTED=$(git rev-parse refs/heads/ssh-signing) && + test $SSH_COMMIT = $IMPORTED + ) <output + +' + test_expect_success 'setup submodule' ' test_config_global protocol.file.allow always && @@ -917,4 +961,46 @@ test_expect_success 'fast-export handles --end-of-options' ' test_cmp expect actual ' +test_expect_success GPG 'setup a commit with dual signatures on its SHA-1 and SHA-256 formats' ' + # Create a signed SHA-256 commit + git init --object-format=sha256 explicit-sha256 && + git -C explicit-sha256 config extensions.compatObjectFormat sha1 && + git -C explicit-sha256 checkout -b dual-signed && + test_commit -C explicit-sha256 A && + echo B >explicit-sha256/B && + git -C explicit-sha256 add B && + test_tick && + git -C explicit-sha256 commit -S -m "signed" B && + SHA256_B=$(git -C explicit-sha256 rev-parse dual-signed) && + + # Create the corresponding SHA-1 commit + SHA1_B=$(git -C explicit-sha256 rev-parse --output-object-format=sha1 dual-signed) && + + # Check that the resulting SHA-1 commit has both signatures + echo $SHA1_B | git -C explicit-sha256 cat-file --batch >out && + test_grep -E "^gpgsig " out && + test_grep -E "^gpgsig-sha256 " out +' + +test_expect_success GPG 'export and import of doubly signed commit' ' + git -C explicit-sha256 fast-export --signed-commits=verbatim dual-signed >output && + test_grep -E "^gpgsig sha1 openpgp" output && + test_grep -E "^gpgsig sha256 openpgp" output && + + ( + cd new && + git fast-import && + git cat-file commit refs/heads/dual-signed >actual && + test_grep -E "^gpgsig " actual && + test_grep -E "^gpgsig-sha256 " actual && + IMPORTED=$(git rev-parse refs/heads/dual-signed) && + if test "$GIT_DEFAULT_HASH" = "sha1" + then + test $SHA1_B = $IMPORTED + else + test $SHA256_B = $IMPORTED + fi + ) <output +' + test_done diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 7679780fb8..578d6c8b32 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -700,19 +700,17 @@ test_expect_success \ # ---------------------------------------------------------------------- # syntax highlighting +test_lazy_prereq HIGHLIGHT ' + highlight_version=$(highlight --version </dev/null 2>/dev/null) && + test -n "$highlight_version" +' -highlight_version=$(highlight --version </dev/null 2>/dev/null) -if [ $? -eq 127 ]; then - say "Skipping syntax highlighting tests: 'highlight' not found" -elif test -z "$highlight_version"; then - say "Skipping syntax highlighting tests: incorrect 'highlight' found" -else - test_set_prereq HIGHLIGHT +test_expect_success HIGHLIGHT ' cat >>gitweb_config.perl <<-\EOF our $highlight_bin = "highlight"; - $feature{'highlight'}{'override'} = 1; + $feature{"highlight"}{"override"} = 1; EOF -fi +' test_expect_success HIGHLIGHT \ 'syntax highlighting (no highlight, unknown syntax)' \ diff --git a/t/t9822-git-p4-path-encoding.sh b/t/t9822-git-p4-path-encoding.sh index 572d395498..e6e07facd4 100755 --- a/t/t9822-git-p4-path-encoding.sh +++ b/t/t9822-git-p4-path-encoding.sh @@ -7,12 +7,17 @@ test_description='Clone repositories with non ASCII paths' UTF8_ESCAPED="a-\303\244_o-\303\266_u-\303\274.txt" ISO8859_ESCAPED="a-\344_o-\366_u-\374.txt" -ISO8859="$(printf "$ISO8859_ESCAPED")" && -echo content123 >"$ISO8859" && -rm "$ISO8859" || { +test_lazy_prereq FS_ACCEPTS_ISO_8859_1 ' + ISO8859="$(printf "$ISO8859_ESCAPED")" && + echo content123 >"$ISO8859" && + rm "$ISO8859" +' + +if ! test_have_prereq FS_ACCEPTS_ISO_8859_1 +then skip_all="fs does not accept ISO-8859-1 filenames" test_done -} +fi test_expect_success 'start p4d' ' start_p4d diff --git a/t/t9835-git-p4-metadata-encoding-python2.sh b/t/t9835-git-p4-metadata-encoding-python2.sh index 6116f806f6..b969c7e0d5 100755 --- a/t/t9835-git-p4-metadata-encoding-python2.sh +++ b/t/t9835-git-p4-metadata-encoding-python2.sh @@ -12,23 +12,25 @@ failing, and produces maximally sane output in git.' ## SECTION REPEATED IN t9836 ## ############################### +EXTRA_PATH="$(pwd)/temp_python" +mkdir "$EXTRA_PATH" +PATH="$EXTRA_PATH:$PATH" +export PATH + # These tests are specific to Python 2. Write a custom script that executes # git-p4 directly with the Python 2 interpreter to ensure that we use that # version even if Git was compiled with Python 3. -python_target_binary=$(which python2) -if test -n "$python_target_binary" -then - mkdir temp_python - PATH="$(pwd)/temp_python:$PATH" - export PATH - - write_script temp_python/git-p4-python2 <<-EOF +test_lazy_prereq P4_PYTHON2 ' + python_target_binary=$(which python2) && + test -n "$python_target_binary" && + write_script "$EXTRA_PATH"/git-p4-python2 <<-EOF && exec "$python_target_binary" "$(git --exec-path)/git-p4" "\$@" EOF -fi + ( git p4-python2 || true ) >err && + test_grep "valid commands" err +' -git p4-python2 >err -if ! grep 'valid commands' err +if ! test_have_prereq P4_PYTHON2 then skip_all="skipping python2 git p4 tests; python2 not available" test_done diff --git a/t/t9836-git-p4-metadata-encoding-python3.sh b/t/t9836-git-p4-metadata-encoding-python3.sh index 5e5217a66b..da6669bf71 100755 --- a/t/t9836-git-p4-metadata-encoding-python3.sh +++ b/t/t9836-git-p4-metadata-encoding-python3.sh @@ -12,23 +12,25 @@ failing, and produces maximally sane output in git.' ## SECTION REPEATED IN t9835 ## ############################### +EXTRA_PATH="$(pwd)/temp_python" +mkdir "$EXTRA_PATH" +PATH="$EXTRA_PATH:$PATH" +export PATH + # These tests are specific to Python 3. Write a custom script that executes # git-p4 directly with the Python 3 interpreter to ensure that we use that # version even if Git was compiled with Python 2. -python_target_binary=$(which python3) -if test -n "$python_target_binary" -then - mkdir temp_python - PATH="$(pwd)/temp_python:$PATH" - export PATH - - write_script temp_python/git-p4-python3 <<-EOF +test_lazy_prereq P4_PYTHON3 ' + python_target_binary=$(which python3) && + test -n "$python_target_binary" && + write_script "$EXTRA_PATH"/git-p4-python3 <<-EOF && exec "$python_target_binary" "$(git --exec-path)/git-p4" "\$@" EOF -fi + ( git p4-python3 || true ) >err && + test_grep "valid commands" err +' -git p4-python3 >err -if ! grep 'valid commands' err +if ! test_have_prereq P4_PYTHON3 then skip_all="skipping python3 git p4 tests; python3 not available" test_done diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh index d667dda654..637a6f13a6 100755 --- a/t/t9903-bash-prompt.sh +++ b/t/t9903-bash-prompt.sh @@ -66,10 +66,6 @@ test_expect_success 'prompt - unborn branch' ' test_cmp expected "$actual" ' -if test_have_prereq !FUNNYNAMES; then - say 'Your filesystem does not allow newlines in filenames.' -fi - test_expect_success FUNNYNAMES 'prompt - with newline in path' ' repo_with_newline="repo with diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index bee4a2ca34..a28de7b19b 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -1451,9 +1451,21 @@ test_cmp_fspath () { # test_seq 1 5 -- outputs 1 2 3 4 5 one line at a time # # or with one argument (end), in which case it starts counting -# from 1. +# from 1. In addition to the start/end arguments, you can pass an optional +# printf format. For example: +# +# test_seq -f "line %d" 1 5 +# +# would print 5 lines, "line 1" through "line 5". test_seq () { + local fmt="%d" + case "$1" in + -f) + fmt="$2" + shift 2 + ;; + esac case $# in 1) set 1 "$@" ;; 2) ;; @@ -1462,7 +1474,7 @@ test_seq () { test_seq_counter__=$1 while test "$test_seq_counter__" -le "$2" do - echo "$test_seq_counter__" + printf "$fmt\n" "$test_seq_counter__" test_seq_counter__=$(( $test_seq_counter__ + 1 )) done } @@ -1695,7 +1707,7 @@ test_set_hash () { # Detect the hash algorithm in use. test_detect_hash () { - case "$GIT_TEST_DEFAULT_HASH" in + case "${GIT_TEST_DEFAULT_HASH:-$GIT_TEST_BUILTIN_HASH}" in "sha256") test_hash_algo=sha256 test_compat_hash_algo=sha1 @@ -1767,6 +1779,9 @@ test_oid () { --hash=compat) algo="$test_compat_hash_algo" && shift;; + --hash=builtin) + algo="$GIT_TEST_BUILTIN_HASH" && + shift;; --hash=*) algo="${1#--hash=}" && shift;; diff --git a/t/test-lib.sh b/t/test-lib.sh index af722d383d..621cd31ae1 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -134,7 +134,8 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME ################################################################ # It appears that people try to run tests without building... -"${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X" >/dev/null +GIT_BINARY="${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X" +"$GIT_BINARY" >/dev/null if test $? != 1 then if test -n "$GIT_TEST_INSTALLED" @@ -470,7 +471,7 @@ then then : Executed by a Bash version supporting BASH_XTRACEFD. Good. else - echo >&2 "warning: ignoring -x; '$0' is untraceable without BASH_XTRACEFD" + echo >&2 "# warning: ignoring -x; '$0' is untraceable without BASH_XTRACEFD" trace= fi fi @@ -536,7 +537,8 @@ export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME export GIT_COMMITTER_DATE GIT_AUTHOR_DATE export EDITOR -GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-sha1}" +GIT_TEST_BUILTIN_HASH=$("$GIT_BINARY" version --build-options | sed -ne 's/^default-hash: //p') +GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-$GIT_TEST_BUILTIN_HASH}" export GIT_DEFAULT_HASH GIT_DEFAULT_REF_FORMAT="${GIT_TEST_DEFAULT_REF_FORMAT:-files}" export GIT_DEFAULT_REF_FORMAT @@ -707,7 +709,7 @@ then exec 3>>"$GIT_TEST_TEE_OUTPUT_FILE" 4>&3 elif test "$verbose" = "t" then - exec 4>&2 3>&1 + exec 4>&2 3>&2 else exec 4>/dev/null 3>/dev/null fi @@ -949,7 +951,7 @@ maybe_setup_verbose () { test -z "$verbose_only" && return if match_pattern_list $test_count "$verbose_only" then - exec 4>&2 3>&1 + exec 4>&2 3>&2 # Emit a delimiting blank line when going from # non-verbose to verbose. Within verbose mode the # delimiter is printed by test_expect_*. The choice @@ -1272,7 +1274,14 @@ test_done () { check_test_results_san_file_ "$test_failure" - if test -z "$skip_all" && test -n "$invert_exit_code" + if test "$test_fixed" != 0 + then + if test -z "$invert_exit_code" + then + GIT_EXIT_OK=t + exit 1 + fi + elif test -z "$skip_all" && test -n "$invert_exit_code" then say_color warn "# faking up non-zero exit with --invert-exit-code" GIT_EXIT_OK=t @@ -1577,6 +1586,8 @@ fi # Use -P to resolve symlinks in our working directory so that the cwd # in subprocesses like git equals our $PWD (for pathname comparisons). cd -P "$TRASH_DIRECTORY" || BAIL_OUT "cannot cd -P to \"$TRASH_DIRECTORY\"" +TRASH_DIRECTORY=$(pwd) +HOME="$TRASH_DIRECTORY" start_test_output "$0" @@ -1636,6 +1647,12 @@ fi # Fix some commands on Windows, and other OS-specific things uname_s=$(uname -s) case $uname_s in +Darwin) + test_set_prereq MACOS + test_set_prereq POSIXPERM + test_set_prereq BSLASHPSPEC + test_set_prereq EXECKEEPSPID + ;; *MINGW*) # Windows has its own (incompatible) sort and find sort () { @@ -1893,6 +1910,10 @@ test_lazy_prereq SHA1 ' esac ' +test_lazy_prereq DEFAULT_HASH_ALGORITHM ' + test "$GIT_TEST_BUILTIN_HASH" = "$GIT_DEFAULT_HASH" +' + test_lazy_prereq DEFAULT_REPO_FORMAT ' test_have_prereq SHA1,REFFILES ' diff --git a/t/unit-tests/u-prio-queue.c b/t/unit-tests/u-prio-queue.c index 145e689c9c..63e58114ae 100644 --- a/t/unit-tests/u-prio-queue.c +++ b/t/unit-tests/u-prio-queue.c @@ -13,6 +13,7 @@ static int intcmp(const void *va, const void *vb, void *data UNUSED) #define STACK -3 #define GET -4 #define REVERSE -5 +#define REPLACE -6 static int show(int *v) { @@ -51,6 +52,15 @@ static void test_prio_queue(int *input, size_t input_size, case REVERSE: prio_queue_reverse(&pq); break; + case REPLACE: + peek = prio_queue_peek(&pq); + cl_assert(i + 1 < input_size); + cl_assert(input[i + 1] >= 0); + cl_assert(j < result_size); + cl_assert_equal_i(result[j], show(peek)); + j++; + prio_queue_replace(&pq, &input[++i]); + break; default: prio_queue_put(&pq, &input[i]); break; @@ -81,6 +91,13 @@ void test_prio_queue__empty(void) ((int []){ 1, 2, MISSING, 1, 2, MISSING })); } +void test_prio_queue__replace(void) +{ + TEST_INPUT(((int []){ REPLACE, 6, 2, 4, REPLACE, 5, 7, GET, + REPLACE, 1, DUMP }), + ((int []){ MISSING, 2, 4, 5, 1, 6, 7 })); +} + void test_prio_queue__stack(void) { TEST_INPUT(((int []){ STACK, 8, 1, 5, 4, 6, 2, 3, DUMP }), @@ -92,3 +109,9 @@ void test_prio_queue__reverse_stack(void) TEST_INPUT(((int []){ STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP }), ((int []){ 1, 2, 3, 4, 5, 6 })); } + +void test_prio_queue__replace_stack(void) +{ + TEST_INPUT(((int []){ STACK, 8, 1, 5, REPLACE, 4, 6, 2, 3, DUMP }), + ((int []){ 5, 3, 2, 6, 4, 1, 8 })); +} diff --git a/t/unit-tests/u-string-list.c b/t/unit-tests/u-string-list.c new file mode 100644 index 0000000000..d4ba5f9fa5 --- /dev/null +++ b/t/unit-tests/u-string-list.c @@ -0,0 +1,227 @@ +#include "unit-test.h" +#include "string-list.h" + +static void t_vcreate_string_list_dup(struct string_list *list, + int free_util, va_list ap) +{ + const char *arg; + + cl_assert(list->strdup_strings); + + string_list_clear(list, free_util); + while ((arg = va_arg(ap, const char *))) + string_list_append(list, arg); +} + +static void t_create_string_list_dup(struct string_list *list, int free_util, ...) +{ + va_list ap; + + cl_assert(list->strdup_strings); + + string_list_clear(list, free_util); + va_start(ap, free_util); + t_vcreate_string_list_dup(list, free_util, ap); + va_end(ap); +} + +static void t_string_list_clear(struct string_list *list, int free_util) +{ + string_list_clear(list, free_util); + cl_assert_equal_p(list->items, NULL); + cl_assert_equal_i(list->nr, 0); + cl_assert_equal_i(list->alloc, 0); +} + +static void t_string_list_equal(struct string_list *list, + struct string_list *expected_strings) +{ + cl_assert_equal_i(list->nr, expected_strings->nr); + cl_assert(list->nr <= list->alloc); + for (size_t i = 0; i < expected_strings->nr; i++) + cl_assert_equal_s(list->items[i].string, + expected_strings->items[i].string); +} + +static void t_string_list_split(const char *data, int delim, int maxsplit, ...) +{ + struct string_list expected_strings = STRING_LIST_INIT_DUP; + struct string_list list = STRING_LIST_INIT_DUP; + va_list ap; + int len; + + va_start(ap, maxsplit); + t_vcreate_string_list_dup(&expected_strings, 0, ap); + va_end(ap); + + string_list_clear(&list, 0); + len = string_list_split(&list, data, delim, maxsplit); + cl_assert_equal_i(len, expected_strings.nr); + t_string_list_equal(&list, &expected_strings); + + string_list_clear(&expected_strings, 0); + string_list_clear(&list, 0); +} + +void test_string_list__split(void) +{ + t_string_list_split("foo:bar:baz", ':', -1, "foo", "bar", "baz", NULL); + t_string_list_split("foo:bar:baz", ':', 0, "foo:bar:baz", NULL); + t_string_list_split("foo:bar:baz", ':', 1, "foo", "bar:baz", NULL); + t_string_list_split("foo:bar:baz", ':', 2, "foo", "bar", "baz", NULL); + t_string_list_split("foo:bar:", ':', -1, "foo", "bar", "", NULL); + t_string_list_split("", ':', -1, "", NULL); + t_string_list_split(":", ':', -1, "", "", NULL); +} + +static void t_string_list_split_in_place(const char *data, const char *delim, + int maxsplit, ...) +{ + struct string_list expected_strings = STRING_LIST_INIT_DUP; + struct string_list list = STRING_LIST_INIT_NODUP; + char *string = xstrdup(data); + va_list ap; + int len; + + va_start(ap, maxsplit); + t_vcreate_string_list_dup(&expected_strings, 0, ap); + va_end(ap); + + string_list_clear(&list, 0); + len = string_list_split_in_place(&list, string, delim, maxsplit); + cl_assert_equal_i(len, expected_strings.nr); + t_string_list_equal(&list, &expected_strings); + + free(string); + string_list_clear(&expected_strings, 0); + string_list_clear(&list, 0); +} + +void test_string_list__split_in_place(void) +{ + t_string_list_split_in_place("foo:;:bar:;:baz:;:", ":;", -1, + "foo", "", "", "bar", "", "", "baz", "", "", "", NULL); + t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 0, + "foo:;:bar:;:baz", NULL); + t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 1, + "foo", ";:bar:;:baz", NULL); + t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 2, + "foo", "", ":bar:;:baz", NULL); + t_string_list_split_in_place("foo:;:bar:;:", ":;", -1, + "foo", "", "", "bar", "", "", "", NULL); +} + +static int prefix_cb(struct string_list_item *item, void *cb_data) +{ + const char *prefix = (const char *)cb_data; + return starts_with(item->string, prefix); +} + +static void t_string_list_filter(struct string_list *list, ...) +{ + struct string_list expected_strings = STRING_LIST_INIT_DUP; + const char *prefix = "y"; + va_list ap; + + va_start(ap, list); + t_vcreate_string_list_dup(&expected_strings, 0, ap); + va_end(ap); + + filter_string_list(list, 0, prefix_cb, (void *)prefix); + t_string_list_equal(list, &expected_strings); + + string_list_clear(&expected_strings, 0); +} + +void test_string_list__filter(void) +{ + struct string_list list = STRING_LIST_INIT_DUP; + + t_create_string_list_dup(&list, 0, NULL); + t_string_list_filter(&list, NULL); + + t_create_string_list_dup(&list, 0, "no", NULL); + t_string_list_filter(&list, NULL); + + t_create_string_list_dup(&list, 0, "yes", NULL); + t_string_list_filter(&list, "yes", NULL); + + t_create_string_list_dup(&list, 0, "no", "yes", NULL); + t_string_list_filter(&list, "yes", NULL); + + t_create_string_list_dup(&list, 0, "yes", "no", NULL); + t_string_list_filter(&list, "yes", NULL); + + t_create_string_list_dup(&list, 0, "y1", "y2", NULL); + t_string_list_filter(&list, "y1", "y2", NULL); + + t_create_string_list_dup(&list, 0, "y2", "y1", NULL); + t_string_list_filter(&list, "y2", "y1", NULL); + + t_create_string_list_dup(&list, 0, "x1", "x2", NULL); + t_string_list_filter(&list, NULL); + + t_string_list_clear(&list, 0); +} + +static void t_string_list_remove_duplicates(struct string_list *list, ...) +{ + struct string_list expected_strings = STRING_LIST_INIT_DUP; + va_list ap; + + va_start(ap, list); + t_vcreate_string_list_dup(&expected_strings, 0, ap); + va_end(ap); + + string_list_remove_duplicates(list, 0); + t_string_list_equal(list, &expected_strings); + + string_list_clear(&expected_strings, 0); +} + +void test_string_list__remove_duplicates(void) +{ + struct string_list list = STRING_LIST_INIT_DUP; + + t_create_string_list_dup(&list, 0, NULL); + t_string_list_remove_duplicates(&list, NULL); + + t_create_string_list_dup(&list, 0, "", NULL); + t_string_list_remove_duplicates(&list, "", NULL); + + t_create_string_list_dup(&list, 0, "a", NULL); + t_string_list_remove_duplicates(&list, "a", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", NULL); + t_string_list_remove_duplicates(&list, "a", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", "a", NULL); + t_string_list_remove_duplicates(&list, "a", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", "b", NULL); + t_string_list_remove_duplicates(&list, "a", "b", NULL); + + t_create_string_list_dup(&list, 0, "a", "b", "b", NULL); + t_string_list_remove_duplicates(&list, "a", "b", NULL); + + t_create_string_list_dup(&list, 0, "a", "b", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", "b", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_create_string_list_dup(&list, 0, "a", "b", "b", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_create_string_list_dup(&list, 0, "a", "b", "c", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", "b", "b", "c", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", "a", "b", "b", "b", + "c", "c", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_string_list_clear(&list, 0); +} |
