diff options
Diffstat (limited to 't')
43 files changed, 1541 insertions, 61 deletions
diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c new file mode 100644 index 0000000000..37c452535f --- /dev/null +++ b/t/helper/test-json-writer.c @@ -0,0 +1,565 @@ +#include "test-tool.h" +#include "cache.h" +#include "json-writer.h" + +static const char *expect_obj1 = "{\"a\":\"abc\",\"b\":42,\"c\":true}"; +static const char *expect_obj2 = "{\"a\":-1,\"b\":2147483647,\"c\":0}"; +static const char *expect_obj3 = "{\"a\":0,\"b\":4294967295,\"c\":9223372036854775807}"; +static const char *expect_obj4 = "{\"t\":true,\"f\":false,\"n\":null}"; +static const char *expect_obj5 = "{\"abc\\tdef\":\"abc\\\\def\"}"; +static const char *expect_obj6 = "{\"a\":3.14}"; + +static const char *pretty_obj1 = ("{\n" + " \"a\": \"abc\",\n" + " \"b\": 42,\n" + " \"c\": true\n" + "}"); +static const char *pretty_obj2 = ("{\n" + " \"a\": -1,\n" + " \"b\": 2147483647,\n" + " \"c\": 0\n" + "}"); +static const char *pretty_obj3 = ("{\n" + " \"a\": 0,\n" + " \"b\": 4294967295,\n" + " \"c\": 9223372036854775807\n" + "}"); +static const char *pretty_obj4 = ("{\n" + " \"t\": true,\n" + " \"f\": false,\n" + " \"n\": null\n" + "}"); + +static struct json_writer obj1 = JSON_WRITER_INIT; +static struct json_writer obj2 = JSON_WRITER_INIT; +static struct json_writer obj3 = JSON_WRITER_INIT; +static struct json_writer obj4 = JSON_WRITER_INIT; +static struct json_writer obj5 = JSON_WRITER_INIT; +static struct json_writer obj6 = JSON_WRITER_INIT; + +static void make_obj1(int pretty) +{ + jw_object_begin(&obj1, pretty); + { + jw_object_string(&obj1, "a", "abc"); + jw_object_intmax(&obj1, "b", 42); + jw_object_true(&obj1, "c"); + } + jw_end(&obj1); +} + +static void make_obj2(int pretty) +{ + jw_object_begin(&obj2, pretty); + { + jw_object_intmax(&obj2, "a", -1); + jw_object_intmax(&obj2, "b", 0x7fffffff); + jw_object_intmax(&obj2, "c", 0); + } + jw_end(&obj2); +} + +static void make_obj3(int pretty) +{ + jw_object_begin(&obj3, pretty); + { + jw_object_intmax(&obj3, "a", 0); + jw_object_intmax(&obj3, "b", 0xffffffff); + jw_object_intmax(&obj3, "c", 0x7fffffffffffffffULL); + } + jw_end(&obj3); +} + +static void make_obj4(int pretty) +{ + jw_object_begin(&obj4, pretty); + { + jw_object_true(&obj4, "t"); + jw_object_false(&obj4, "f"); + jw_object_null(&obj4, "n"); + } + jw_end(&obj4); +} + +static void make_obj5(int pretty) +{ + jw_object_begin(&obj5, pretty); + { + jw_object_string(&obj5, "abc" "\x09" "def", "abc" "\\" "def"); + } + jw_end(&obj5); +} + +static void make_obj6(int pretty) +{ + jw_object_begin(&obj6, pretty); + { + jw_object_double(&obj6, "a", 2, 3.14159); + } + jw_end(&obj6); +} + +static const char *expect_arr1 = "[\"abc\",42,true]"; +static const char *expect_arr2 = "[-1,2147483647,0]"; +static const char *expect_arr3 = "[0,4294967295,9223372036854775807]"; +static const char *expect_arr4 = "[true,false,null]"; + +static const char *pretty_arr1 = ("[\n" + " \"abc\",\n" + " 42,\n" + " true\n" + "]"); +static const char *pretty_arr2 = ("[\n" + " -1,\n" + " 2147483647,\n" + " 0\n" + "]"); +static const char *pretty_arr3 = ("[\n" + " 0,\n" + " 4294967295,\n" + " 9223372036854775807\n" + "]"); +static const char *pretty_arr4 = ("[\n" + " true,\n" + " false,\n" + " null\n" + "]"); + +static struct json_writer arr1 = JSON_WRITER_INIT; +static struct json_writer arr2 = JSON_WRITER_INIT; +static struct json_writer arr3 = JSON_WRITER_INIT; +static struct json_writer arr4 = JSON_WRITER_INIT; + +static void make_arr1(int pretty) +{ + jw_array_begin(&arr1, pretty); + { + jw_array_string(&arr1, "abc"); + jw_array_intmax(&arr1, 42); + jw_array_true(&arr1); + } + jw_end(&arr1); +} + +static void make_arr2(int pretty) +{ + jw_array_begin(&arr2, pretty); + { + jw_array_intmax(&arr2, -1); + jw_array_intmax(&arr2, 0x7fffffff); + jw_array_intmax(&arr2, 0); + } + jw_end(&arr2); +} + +static void make_arr3(int pretty) +{ + jw_array_begin(&arr3, pretty); + { + jw_array_intmax(&arr3, 0); + jw_array_intmax(&arr3, 0xffffffff); + jw_array_intmax(&arr3, 0x7fffffffffffffffULL); + } + jw_end(&arr3); +} + +static void make_arr4(int pretty) +{ + jw_array_begin(&arr4, pretty); + { + jw_array_true(&arr4); + jw_array_false(&arr4); + jw_array_null(&arr4); + } + jw_end(&arr4); +} + +static char *expect_nest1 = + "{\"obj1\":{\"a\":\"abc\",\"b\":42,\"c\":true},\"arr1\":[\"abc\",42,true]}"; + +static struct json_writer nest1 = JSON_WRITER_INIT; + +static void make_nest1(int pretty) +{ + jw_object_begin(&nest1, pretty); + { + jw_object_sub_jw(&nest1, "obj1", &obj1); + jw_object_sub_jw(&nest1, "arr1", &arr1); + } + jw_end(&nest1); +} + +static char *expect_inline1 = + "{\"obj1\":{\"a\":\"abc\",\"b\":42,\"c\":true},\"arr1\":[\"abc\",42,true]}"; + +static char *pretty_inline1 = + ("{\n" + " \"obj1\": {\n" + " \"a\": \"abc\",\n" + " \"b\": 42,\n" + " \"c\": true\n" + " },\n" + " \"arr1\": [\n" + " \"abc\",\n" + " 42,\n" + " true\n" + " ]\n" + "}"); + +static struct json_writer inline1 = JSON_WRITER_INIT; + +static void make_inline1(int pretty) +{ + jw_object_begin(&inline1, pretty); + { + jw_object_inline_begin_object(&inline1, "obj1"); + { + jw_object_string(&inline1, "a", "abc"); + jw_object_intmax(&inline1, "b", 42); + jw_object_true(&inline1, "c"); + } + jw_end(&inline1); + jw_object_inline_begin_array(&inline1, "arr1"); + { + jw_array_string(&inline1, "abc"); + jw_array_intmax(&inline1, 42); + jw_array_true(&inline1); + } + jw_end(&inline1); + } + jw_end(&inline1); +} + +static char *expect_inline2 = + "[[1,2],[3,4],{\"a\":\"abc\"}]"; + +static char *pretty_inline2 = + ("[\n" + " [\n" + " 1,\n" + " 2\n" + " ],\n" + " [\n" + " 3,\n" + " 4\n" + " ],\n" + " {\n" + " \"a\": \"abc\"\n" + " }\n" + "]"); + +static struct json_writer inline2 = JSON_WRITER_INIT; + +static void make_inline2(int pretty) +{ + jw_array_begin(&inline2, pretty); + { + jw_array_inline_begin_array(&inline2); + { + jw_array_intmax(&inline2, 1); + jw_array_intmax(&inline2, 2); + } + jw_end(&inline2); + jw_array_inline_begin_array(&inline2); + { + jw_array_intmax(&inline2, 3); + jw_array_intmax(&inline2, 4); + } + jw_end(&inline2); + jw_array_inline_begin_object(&inline2); + { + jw_object_string(&inline2, "a", "abc"); + } + jw_end(&inline2); + } + jw_end(&inline2); +} + +/* + * When super is compact, we expect subs to be compacted (even if originally + * pretty). + */ +static const char *expect_mixed1 = + ("{\"obj1\":{\"a\":\"abc\",\"b\":42,\"c\":true}," + "\"arr1\":[\"abc\",42,true]}"); + +/* + * When super is pretty, a compact sub (obj1) is kept compact and a pretty + * sub (arr1) is re-indented. + */ +static const char *pretty_mixed1 = + ("{\n" + " \"obj1\": {\"a\":\"abc\",\"b\":42,\"c\":true},\n" + " \"arr1\": [\n" + " \"abc\",\n" + " 42,\n" + " true\n" + " ]\n" + "}"); + +static struct json_writer mixed1 = JSON_WRITER_INIT; + +static void make_mixed1(int pretty) +{ + jw_init(&obj1); + jw_init(&arr1); + + make_obj1(0); /* obj1 is compact */ + make_arr1(1); /* arr1 is pretty */ + + jw_object_begin(&mixed1, pretty); + { + jw_object_sub_jw(&mixed1, "obj1", &obj1); + jw_object_sub_jw(&mixed1, "arr1", &arr1); + } + jw_end(&mixed1); +} + +static void cmp(const char *test, const struct json_writer *jw, const char *exp) +{ + if (!strcmp(jw->json.buf, exp)) + return; + + printf("error[%s]: observed '%s' expected '%s'\n", + test, jw->json.buf, exp); + exit(1); +} + +#define t(v) do { make_##v(0); cmp(#v, &v, expect_##v); } while (0) +#define p(v) do { make_##v(1); cmp(#v, &v, pretty_##v); } while (0) + +/* + * Run some basic regression tests with some known patterns. + * These tests also demonstrate how to use the jw_ API. + */ +static int unit_tests(void) +{ + /* comptact (canonical) forms */ + t(obj1); + t(obj2); + t(obj3); + t(obj4); + t(obj5); + t(obj6); + + t(arr1); + t(arr2); + t(arr3); + t(arr4); + + t(nest1); + + t(inline1); + t(inline2); + + jw_init(&obj1); + jw_init(&obj2); + jw_init(&obj3); + jw_init(&obj4); + + jw_init(&arr1); + jw_init(&arr2); + jw_init(&arr3); + jw_init(&arr4); + + jw_init(&inline1); + jw_init(&inline2); + + /* pretty forms */ + p(obj1); + p(obj2); + p(obj3); + p(obj4); + + p(arr1); + p(arr2); + p(arr3); + p(arr4); + + p(inline1); + p(inline2); + + /* mixed forms */ + t(mixed1); + jw_init(&mixed1); + p(mixed1); + + return 0; +} + +static void get_s(int line_nr, char **s_in) +{ + *s_in = strtok(NULL, " "); + if (!*s_in) + die("line[%d]: expected: <s>", line_nr); +} + +static void get_i(int line_nr, intmax_t *s_in) +{ + char *s; + char *endptr; + + get_s(line_nr, &s); + + *s_in = strtol(s, &endptr, 10); + if (*endptr || errno == ERANGE) + die("line[%d]: invalid integer value", line_nr); +} + +static void get_d(int line_nr, double *s_in) +{ + char *s; + char *endptr; + + get_s(line_nr, &s); + + *s_in = strtod(s, &endptr); + if (*endptr || errno == ERANGE) + die("line[%d]: invalid float value", line_nr); +} + +static int pretty; + +#define MAX_LINE_LENGTH (64 * 1024) + +static char *get_trimmed_line(char *buf, int buf_size) +{ + int len; + + if (!fgets(buf, buf_size, stdin)) + return NULL; + + len = strlen(buf); + while (len > 0) { + char c = buf[len - 1]; + if (c == '\n' || c == '\r' || c == ' ' || c == '\t') + buf[--len] = 0; + else + break; + } + + while (*buf == ' ' || *buf == '\t') + buf++; + + return buf; +} + +static int scripted(void) +{ + struct json_writer jw = JSON_WRITER_INIT; + char buf[MAX_LINE_LENGTH]; + char *line; + int line_nr = 0; + + line = get_trimmed_line(buf, MAX_LINE_LENGTH); + if (!line) + return 0; + + if (!strcmp(line, "object")) + jw_object_begin(&jw, pretty); + else if (!strcmp(line, "array")) + jw_array_begin(&jw, pretty); + else + die("expected first line to be 'object' or 'array'"); + + while ((line = get_trimmed_line(buf, MAX_LINE_LENGTH)) != NULL) { + char *verb; + char *key; + char *s_value; + intmax_t i_value; + double d_value; + + line_nr++; + + verb = strtok(line, " "); + + if (!strcmp(verb, "end")) { + jw_end(&jw); + } + else if (!strcmp(verb, "object-string")) { + get_s(line_nr, &key); + get_s(line_nr, &s_value); + jw_object_string(&jw, key, s_value); + } + else if (!strcmp(verb, "object-int")) { + get_s(line_nr, &key); + get_i(line_nr, &i_value); + jw_object_intmax(&jw, key, i_value); + } + else if (!strcmp(verb, "object-double")) { + get_s(line_nr, &key); + get_i(line_nr, &i_value); + get_d(line_nr, &d_value); + jw_object_double(&jw, key, i_value, d_value); + } + else if (!strcmp(verb, "object-true")) { + get_s(line_nr, &key); + jw_object_true(&jw, key); + } + else if (!strcmp(verb, "object-false")) { + get_s(line_nr, &key); + jw_object_false(&jw, key); + } + else if (!strcmp(verb, "object-null")) { + get_s(line_nr, &key); + jw_object_null(&jw, key); + } + else if (!strcmp(verb, "object-object")) { + get_s(line_nr, &key); + jw_object_inline_begin_object(&jw, key); + } + else if (!strcmp(verb, "object-array")) { + get_s(line_nr, &key); + jw_object_inline_begin_array(&jw, key); + } + else if (!strcmp(verb, "array-string")) { + get_s(line_nr, &s_value); + jw_array_string(&jw, s_value); + } + else if (!strcmp(verb, "array-int")) { + get_i(line_nr, &i_value); + jw_array_intmax(&jw, i_value); + } + else if (!strcmp(verb, "array-double")) { + get_i(line_nr, &i_value); + get_d(line_nr, &d_value); + jw_array_double(&jw, i_value, d_value); + } + else if (!strcmp(verb, "array-true")) + jw_array_true(&jw); + else if (!strcmp(verb, "array-false")) + jw_array_false(&jw); + else if (!strcmp(verb, "array-null")) + jw_array_null(&jw); + else if (!strcmp(verb, "array-object")) + jw_array_inline_begin_object(&jw); + else if (!strcmp(verb, "array-array")) + jw_array_inline_begin_array(&jw); + else + die("unrecognized token: '%s'", verb); + } + + if (!jw_is_terminated(&jw)) + die("json not terminated: '%s'", jw.json.buf); + + printf("%s\n", jw.json.buf); + + strbuf_release(&jw.json); + return 0; +} + +int cmd__json_writer(int argc, const char **argv) +{ + argc--; /* skip over "json-writer" arg */ + argv++; + + if (argc > 0 && argv[0][0] == '-') { + if (!strcmp(argv[0], "-u") || !strcmp(argv[0], "--unit")) + return unit_tests(); + + if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--pretty")) + pretty = 1; + } + + return scripted(); +} diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index dafc91c240..0edafcfd65 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -19,6 +19,7 @@ static struct test_cmd cmds[] = { { "genrandom", cmd__genrandom }, { "hashmap", cmd__hashmap }, { "index-version", cmd__index_version }, + { "json-writer", cmd__json_writer }, { "lazy-init-name-hash", cmd__lazy_init_name_hash }, { "match-trees", cmd__match_trees }, { "mergesort", cmd__mergesort }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 80cbcf0857..e926c416ea 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -13,6 +13,7 @@ int cmd__example_decorate(int argc, const char **argv); int cmd__genrandom(int argc, const char **argv); int cmd__hashmap(int argc, const char **argv); int cmd__index_version(int argc, const char **argv); +int cmd__json_writer(int argc, const char **argv); int cmd__lazy_init_name_hash(int argc, const char **argv); int cmd__match_trees(int argc, const char **argv); int cmd__mergesort(int argc, const char **argv); diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh index a5d3b2cbaa..3fe02876c1 100755 --- a/t/lib-gpg.sh +++ b/t/lib-gpg.sh @@ -38,7 +38,33 @@ then "$TEST_DIRECTORY"/lib-gpg/ownertrust && gpg --homedir "${GNUPGHOME}" </dev/null >/dev/null 2>&1 \ --sign -u committer@example.com && - test_set_prereq GPG + test_set_prereq GPG && + # Available key info: + # * see t/lib-gpg/gpgsm-gen-key.in + # To generate new certificate: + # * no passphrase + # gpgsm --homedir /tmp/gpghome/ \ + # -o /tmp/gpgsm.crt.user \ + # --generate-key \ + # --batch t/lib-gpg/gpgsm-gen-key.in + # To import certificate: + # gpgsm --homedir /tmp/gpghome/ \ + # --import /tmp/gpgsm.crt.user + # To export into a .p12 we can later import: + # gpgsm --homedir /tmp/gpghome/ \ + # -o t/lib-gpg/gpgsm_cert.p12 \ + # --export-secret-key-p12 "committer@example.com" + echo | gpgsm --homedir "${GNUPGHOME}" 2>/dev/null \ + --passphrase-fd 0 --pinentry-mode loopback \ + --import "$TEST_DIRECTORY"/lib-gpg/gpgsm_cert.p12 && + gpgsm --homedir "${GNUPGHOME}" 2>/dev/null -K \ + | grep fingerprint: | cut -d" " -f4 | tr -d '\n' > \ + ${GNUPGHOME}/trustlist.txt && + echo " S relax" >> ${GNUPGHOME}/trustlist.txt && + (gpgconf --kill gpg-agent >/dev/null 2>&1 || : ) && + echo hello | gpgsm --homedir "${GNUPGHOME}" >/dev/null \ + -u committer@example.com -o /dev/null --sign - 2>&1 && + test_set_prereq GPGSM ;; esac fi diff --git a/t/lib-gpg/gpgsm-gen-key.in b/t/lib-gpg/gpgsm-gen-key.in new file mode 100644 index 0000000000..a7fd87c069 --- /dev/null +++ b/t/lib-gpg/gpgsm-gen-key.in @@ -0,0 +1,8 @@ +Key-Type: RSA +Key-Length: 2048 +Key-Usage: sign +Serial: random +Name-DN: CN=C O Mitter, O=Example, SN=C O, GN=Mitter +Name-Email: committer@example.com +Not-Before: 1970-01-01 00:00:00 +Not-After: 3000-01-01 00:00:00 diff --git a/t/lib-gpg/gpgsm_cert.p12 b/t/lib-gpg/gpgsm_cert.p12 Binary files differnew file mode 100644 index 0000000000..94ffad0d31 --- /dev/null +++ b/t/lib-gpg/gpgsm_cert.p12 diff --git a/t/t0019-json-writer.sh b/t/t0019-json-writer.sh new file mode 100755 index 0000000000..3b0c336b38 --- /dev/null +++ b/t/t0019-json-writer.sh @@ -0,0 +1,331 @@ +#!/bin/sh + +test_description='test json-writer JSON generation' +. ./test-lib.sh + +test_expect_success 'unit test of json-writer routines' ' + test-tool json-writer -u +' + +test_expect_success 'trivial object' ' + cat >expect <<-\EOF && + {} + EOF + cat >input <<-\EOF && + object + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'trivial array' ' + cat >expect <<-\EOF && + [] + EOF + cat >input <<-\EOF && + array + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'simple object' ' + cat >expect <<-\EOF && + {"a":"abc","b":42,"c":3.14,"d":true,"e":false,"f":null} + EOF + cat >input <<-\EOF && + object + object-string a abc + object-int b 42 + object-double c 2 3.140 + object-true d + object-false e + object-null f + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'simple array' ' + cat >expect <<-\EOF && + ["abc",42,3.14,true,false,null] + EOF + cat >input <<-\EOF && + array + array-string abc + array-int 42 + array-double 2 3.140 + array-true + array-false + array-null + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'escape quoting string' ' + cat >expect <<-\EOF && + {"a":"abc\\def"} + EOF + cat >input <<-\EOF && + object + object-string a abc\def + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'escape quoting string 2' ' + cat >expect <<-\EOF && + {"a":"abc\"def"} + EOF + cat >input <<-\EOF && + object + object-string a abc"def + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'nested inline object' ' + cat >expect <<-\EOF && + {"a":"abc","b":42,"sub1":{"c":3.14,"d":true,"sub2":{"e":false,"f":null}}} + EOF + cat >input <<-\EOF && + object + object-string a abc + object-int b 42 + object-object sub1 + object-double c 2 3.140 + object-true d + object-object sub2 + object-false e + object-null f + end + end + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'nested inline array' ' + cat >expect <<-\EOF && + ["abc",42,[3.14,true,[false,null]]] + EOF + cat >input <<-\EOF && + array + array-string abc + array-int 42 + array-array + array-double 2 3.140 + array-true + array-array + array-false + array-null + end + end + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'nested inline object and array' ' + cat >expect <<-\EOF && + {"a":"abc","b":42,"sub1":{"c":3.14,"d":true,"sub2":[false,null]}} + EOF + cat >input <<-\EOF && + object + object-string a abc + object-int b 42 + object-object sub1 + object-double c 2 3.140 + object-true d + object-array sub2 + array-false + array-null + end + end + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'nested inline object and array 2' ' + cat >expect <<-\EOF && + {"a":"abc","b":42,"sub1":{"c":3.14,"d":true,"sub2":[false,{"g":0,"h":1},null]}} + EOF + cat >input <<-\EOF && + object + object-string a abc + object-int b 42 + object-object sub1 + object-double c 2 3.140 + object-true d + object-array sub2 + array-false + array-object + object-int g 0 + object-int h 1 + end + array-null + end + end + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'pretty nested inline object and array 2' ' + sed -e "s/^|//" >expect <<-\EOF && + |{ + | "a": "abc", + | "b": 42, + | "sub1": { + | "c": 3.14, + | "d": true, + | "sub2": [ + | false, + | { + | "g": 0, + | "h": 1 + | }, + | null + | ] + | } + |} + EOF + cat >input <<-\EOF && + object + object-string a abc + object-int b 42 + object-object sub1 + object-double c 2 3.140 + object-true d + object-array sub2 + array-false + array-object + object-int g 0 + object-int h 1 + end + array-null + end + end + end + EOF + test-tool json-writer -p <input >actual && + test_cmp expect actual +' + +test_expect_success 'inline object with no members' ' + cat >expect <<-\EOF && + {"a":"abc","empty":{},"b":42} + EOF + cat >input <<-\EOF && + object + object-string a abc + object-object empty + end + object-int b 42 + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'inline array with no members' ' + cat >expect <<-\EOF && + {"a":"abc","empty":[],"b":42} + EOF + cat >input <<-\EOF && + object + object-string a abc + object-array empty + end + object-int b 42 + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_expect_success 'larger empty example' ' + cat >expect <<-\EOF && + {"a":"abc","empty":[{},{},{},[],{}],"b":42} + EOF + cat >input <<-\EOF && + object + object-string a abc + object-array empty + array-object + end + array-object + end + array-object + end + array-array + end + array-object + end + end + object-int b 42 + end + EOF + test-tool json-writer <input >actual && + test_cmp expect actual +' + +test_lazy_prereq PERLJSON ' + perl -MJSON -e "exit 0" +' + +# As a sanity check, ask Perl to parse our generated JSON and recursively +# dump the resulting data in sorted order. Confirm that that matches our +# expectations. +test_expect_success PERLJSON 'parse JSON using Perl' ' + cat >expect <<-\EOF && + row[0].a abc + row[0].b 42 + row[0].sub1 hash + row[0].sub1.c 3.14 + row[0].sub1.d 1 + row[0].sub1.sub2 array + row[0].sub1.sub2[0] 0 + row[0].sub1.sub2[1] hash + row[0].sub1.sub2[1].g 0 + row[0].sub1.sub2[1].h 1 + row[0].sub1.sub2[2] null + EOF + cat >input <<-\EOF && + object + object-string a abc + object-int b 42 + object-object sub1 + object-double c 2 3.140 + object-true d + object-array sub2 + array-false + array-object + object-int g 0 + object-int h 1 + end + array-null + end + end + end + EOF + test-tool json-writer <input >output.json && + perl "$TEST_DIRECTORY"/t0019/parse_json.perl <output.json >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t0019/parse_json.perl b/t/t0019/parse_json.perl new file mode 100644 index 0000000000..ca4e5bfa78 --- /dev/null +++ b/t/t0019/parse_json.perl @@ -0,0 +1,52 @@ +#!/usr/bin/perl +use strict; +use warnings; +use JSON; + +sub dump_array { + my ($label_in, $ary_ref) = @_; + my @ary = @$ary_ref; + + for ( my $i = 0; $i <= $#{ $ary_ref }; $i++ ) + { + my $label = "$label_in\[$i\]"; + dump_item($label, $ary[$i]); + } +} + +sub dump_hash { + my ($label_in, $obj_ref) = @_; + my %obj = %$obj_ref; + + foreach my $k (sort keys %obj) { + my $label = (length($label_in) > 0) ? "$label_in.$k" : "$k"; + my $value = $obj{$k}; + + dump_item($label, $value); + } +} + +sub dump_item { + my ($label_in, $value) = @_; + if (ref($value) eq 'ARRAY') { + print "$label_in array\n"; + dump_array($label_in, $value); + } elsif (ref($value) eq 'HASH') { + print "$label_in hash\n"; + dump_hash($label_in, $value); + } elsif (defined $value) { + print "$label_in $value\n"; + } else { + print "$label_in null\n"; + } +} + +my $row = 0; +while (<>) { + my $data = decode_json( $_ ); + my $label = "row[$row]"; + + dump_hash($label, $data); + $row++; +} + diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index 6a213608cc..308cd28f3b 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -583,7 +583,7 @@ test_expect_success PERL 'process filter should restart after unexpected write f git checkout --quiet --no-progress . 2>git-stderr.log && grep "smudge write error at" git-stderr.log && - grep "error: external filter" git-stderr.log && + test_i18ngrep "error: external filter" git-stderr.log && cat >expected.log <<-EOF && START diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh index f035ee40a3..635918505d 100755 --- a/t/t1305-config-include.sh +++ b/t/t1305-config-include.sh @@ -310,7 +310,7 @@ test_expect_success 'include cycles are detected' ' cycle EOF test_must_fail git config --get-all test.value 2>stderr && - grep "exceeded maximum include depth" stderr + test_i18ngrep "exceeded maximum include depth" stderr ' test_done diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh index 3e00d1af01..d0a2727b85 100755 --- a/t/t1308-config-set.sh +++ b/t/t1308-config-set.sh @@ -233,7 +233,7 @@ test_expect_success 'check line errors for malformed values' ' test_expect_success 'error on modifying repo config without repo' ' nongit test_must_fail git config a.b c 2>err && - grep "not in a git directory" err + test_i18ngrep "not in a git directory" err ' cmdline_config="'foo.bar=from-cmdline'" diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index e1fd0f0ca8..7c8df20955 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -390,7 +390,7 @@ test_expect_success 'Query "master@{2005-05-26 23:33:01}" (middle of history wit test_when_finished "rm -f o e" && git rev-parse --verify "master@{2005-05-26 23:33:01}" >o 2>e && test $B = $(cat o) && - test "warning: Log for ref $m has gap after $gd." = "$(cat e)" + test_i18ngrep -F "warning: log for ref $m has gap after $gd" e ' test_expect_success 'Query "master@{2005-05-26 23:38:00}" (middle of history)' ' test_when_finished "rm -f o e" && @@ -408,7 +408,7 @@ test_expect_success 'Query "master@{2005-05-28}" (past end of history)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{2005-05-28}" >o 2>e && test $D = $(cat o) && - test "warning: Log for ref $m unexpectedly ended on $ld." = "$(cat e)" + test_i18ngrep -F "warning: log for ref $m unexpectedly ended on $ld" e ' rm -f .git/$m .git/logs/$m expect @@ -462,7 +462,7 @@ test_expect_success 'git cat-file blob master@{2005-05-26 23:42}:F (expect OTHER test_expect_success 'given old value for missing pseudoref, do not create' ' test_must_fail git update-ref PSEUDOREF $A $B 2>err && test_path_is_missing .git/PSEUDOREF && - grep "could not read ref" err + test_i18ngrep "could not read ref" err ' test_expect_success 'create pseudoref' ' @@ -483,7 +483,7 @@ test_expect_success 'overwrite pseudoref with correct old value' ' test_expect_success 'do not overwrite pseudoref with wrong old value' ' test_must_fail git update-ref PSEUDOREF $D $E 2>err && test $C = $(cat .git/PSEUDOREF) && - grep "unexpected object ID" err + test_i18ngrep "unexpected object ID" err ' test_expect_success 'delete pseudoref' ' @@ -495,7 +495,7 @@ test_expect_success 'do not delete pseudoref with wrong old value' ' git update-ref PSEUDOREF $A && test_must_fail git update-ref -d PSEUDOREF $B 2>err && test $A = $(cat .git/PSEUDOREF) && - grep "unexpected object ID" err + test_i18ngrep "unexpected object ID" err ' test_expect_success 'delete pseudoref with correct old value' ' @@ -512,7 +512,7 @@ test_expect_success 'do not overwrite pseudoref with old OID zero' ' test_when_finished git update-ref -d PSEUDOREF && test_must_fail git update-ref PSEUDOREF $B $Z 2>err && test $A = $(cat .git/PSEUDOREF) && - grep "already exists" err + test_i18ngrep "already exists" err ' # Test --stdin @@ -650,7 +650,7 @@ test_expect_success 'stdin fails with duplicate refs' ' create $a $m EOF test_must_fail git update-ref --stdin <stdin 2>err && - grep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed." err + test_i18ngrep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed" err ' test_expect_success 'stdin create ref works' ' @@ -1052,7 +1052,7 @@ test_expect_success 'stdin -z fails option with unknown name' ' test_expect_success 'stdin -z fails with duplicate refs' ' printf $F "create $a" "$m" "create $b" "$m" "create $a" "$m" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed." err + test_i18ngrep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed" err ' test_expect_success 'stdin -z create ref works' ' @@ -1283,7 +1283,7 @@ test_expect_success 'fails with duplicate HEAD update' ' update HEAD $B EOF test_must_fail git update-ref --stdin <stdin 2>err && - grep "fatal: multiple updates for '\''HEAD'\'' (including one via its referent .refs/heads/target1.) are not allowed" err && + test_i18ngrep "fatal: multiple updates for '\''HEAD'\'' (including one via its referent .refs/heads/target1.) are not allowed" err && echo "refs/heads/target1" >expect && git symbolic-ref HEAD >actual && test_cmp expect actual && @@ -1300,7 +1300,7 @@ test_expect_success 'fails with duplicate ref update via symref' ' update refs/heads/symref2 $B EOF test_must_fail git update-ref --stdin <stdin 2>err && - grep "fatal: multiple updates for '\''refs/heads/target2'\'' (including one via symref .refs/heads/symref2.) are not allowed" err && + test_i18ngrep "fatal: multiple updates for '\''refs/heads/target2'\'' (including one via symref .refs/heads/symref2.) are not allowed" err && echo "refs/heads/target2" >expect && git symbolic-ref refs/heads/symref2 >actual && test_cmp expect actual && diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh index 3a887b5113..2a42a589a4 100755 --- a/t/t1404-update-ref-errors.sh +++ b/t/t1404-update-ref-errors.sh @@ -27,7 +27,7 @@ test_update_rejected () { fi && printf "create $prefix/%s $C\n" $create >input && test_must_fail git update-ref --stdin <input 2>output.err && - grep -F "$error" output.err && + test_i18ngrep -F "$error" output.err && git for-each-ref $prefix >actual && test_cmp unchanged actual } @@ -103,7 +103,7 @@ df_test() { printf "%s\n" "delete $delname" "create $addname $D" fi >commands && test_must_fail git update-ref --stdin <commands 2>output.err && - test_cmp expected-err output.err && + test_i18ncmp expected-err output.err && printf "%s\n" "$C $delref" >expected-refs && git for-each-ref --format="%(objectname) %(refname)" $prefix/r >actual-refs && test_cmp expected-refs actual-refs diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 91fd71444d..7b7602ddb4 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -372,7 +372,7 @@ test_expect_success 'rev-list --verify-objects with bad sha1' ' test_might_fail git rev-list --verify-objects refs/heads/bogus >/dev/null 2>out && cat out && - grep -q "error: sha1 mismatch 63ffffffffffffffffffffffffffffffffffffff" out + test_i18ngrep -q "error: sha1 mismatch 63ffffffffffffffffffffffffffffffffffffff" out ' test_expect_success 'force fsck to ignore double author' ' diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh index 26dc3f1fc0..f79dfbbdd6 100755 --- a/t/t2024-checkout-dwim.sh +++ b/t/t2024-checkout-dwim.sh @@ -24,9 +24,8 @@ test_branch_upstream () { } status_uno_is_clean () { - >status.expect && git status -uno --porcelain >status.actual && - test_cmp status.expect status.actual + test_must_be_empty status.actual } test_expect_success 'setup' ' diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh index be6e093142..166942c1bd 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -412,9 +412,8 @@ test_expect_success '"add" <path> <branch> dwims with checkout.defaultRemote' ' git fetch repo_upstream2 && test_must_fail git worktree add ../foo foo && git -c checkout.defaultRemote=repo_upstream worktree add ../foo foo && - >status.expect && git status -uno --porcelain >status.actual && - test_cmp status.expect status.actual + test_must_be_empty status.actual ) && ( cd foo && diff --git a/t/t3005-ls-files-relative.sh b/t/t3005-ls-files-relative.sh index 377869432e..209b4c7cd8 100755 --- a/t/t3005-ls-files-relative.sh +++ b/t/t3005-ls-files-relative.sh @@ -44,13 +44,13 @@ test_expect_success 'ls-files -c' ' cd top/sub && for f in ../y* do - echo "error: pathspec $sq$f$sq did not match any file(s) known to git." + echo "error: pathspec $sq$f$sq did not match any file(s) known to git" done >expect.err && echo "Did you forget to ${sq}git add${sq}?" >>expect.err && ls ../x* >expect.out && test_must_fail git ls-files -c --error-unmatch ../[xy]* >actual.out 2>actual.err && test_cmp expect.out actual.out && - test_cmp expect.err actual.err + test_i18ncmp expect.err actual.err ) ' @@ -59,13 +59,13 @@ test_expect_success 'ls-files -o' ' cd top/sub && for f in ../x* do - echo "error: pathspec $sq$f$sq did not match any file(s) known to git." + echo "error: pathspec $sq$f$sq did not match any file(s) known to git" done >expect.err && echo "Did you forget to ${sq}git add${sq}?" >>expect.err && ls ../y* >expect.out && test_must_fail git ls-files -o --error-unmatch ../[xy]* >actual.out 2>actual.err && test_cmp expect.out actual.out && - test_cmp expect.err actual.err + test_i18ncmp expect.err actual.err ) ' diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh index 724b4b9bc0..7333d7d545 100755 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@ -186,7 +186,7 @@ test_expect_success 'notice d/f conflict with existing directory' ' test_expect_success 'existing directory reports concrete ref' ' test_must_fail git branch foo 2>stderr && - grep refs/heads/foo/bar/baz stderr + test_i18ngrep refs/heads/foo/bar/baz stderr ' test_expect_success 'notice d/f conflict with existing ref' ' diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh index 9c1bf6eb3d..68436eed82 100755 --- a/t/t3310-notes-merge-manual-resolve.sh +++ b/t/t3310-notes-merge-manual-resolve.sh @@ -541,9 +541,9 @@ EOF test "$(git rev-parse refs/notes/y)" = "$(git rev-parse NOTES_MERGE_PARTIAL^1)" && test "$(git rev-parse refs/notes/m)" != "$(git rev-parse NOTES_MERGE_PARTIAL^1)" && # Mention refs/notes/m, and its current and expected value in output - grep -q "refs/notes/m" output && - grep -q "$(git rev-parse refs/notes/m)" output && - grep -q "$(git rev-parse NOTES_MERGE_PARTIAL^1)" output && + test_i18ngrep -q "refs/notes/m" output && + test_i18ngrep -q "$(git rev-parse refs/notes/m)" output && + test_i18ngrep -q "$(git rev-parse NOTES_MERGE_PARTIAL^1)" output && # Verify that other notes refs has not changed (w, x, y and z) verify_notes w && verify_notes x && diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 640fddc9c3..4c7b1ea356 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1247,7 +1247,7 @@ rebase_setup_and_clean () { test_might_fail git branch -D $1 && test_might_fail git rebase --abort " && - git checkout -b $1 master + git checkout -b $1 ${2:-master} } test_expect_success 'drop' ' @@ -1424,4 +1424,12 @@ test_expect_success 'rebase -i --gpg-sign=<key-id> overrides commit.gpgSign' ' test_i18ngrep "$SQ-S\"S I Gner\"$SQ" err ' +test_expect_success 'valid author header after --root swap' ' + rebase_setup_and_clean author-header no-conflict-branch && + set_fake_editor && + FAKE_LINES="2 1" git rebase -i --root && + git cat-file commit HEAD^ >out && + grep "^author ..*> [0-9][0-9]* [-+][0-9][0-9][0-9][0-9]$" out +' + test_done diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index 7c5ad08626..0db166152a 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -392,4 +392,17 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' ' test_cmp expect actual ' +test_expect_success 'cherry-pick preserves sparse-checkout' ' + pristine_detach initial && + test_config core.sparseCheckout true && + test_when_finished " + echo \"/*\" >.git/info/sparse-checkout + git read-tree --reset -u HEAD + rm .git/info/sparse-checkout" && + echo /unrelated >.git/info/sparse-checkout && + git read-tree --reset -u HEAD && + test_must_fail git cherry-pick -Xours picked>actual && + test_i18ngrep ! "Changes not staged for commit:" actual +' + test_done diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 41facf7abf..e2dc1895ba 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -1305,7 +1305,7 @@ test_expect_success 'detect blocks of moved code' ' ' -test_expect_success 'detect permutations inside moved code -- dimmed_zebra' ' +test_expect_success 'detect permutations inside moved code -- dimmed-zebra' ' # reuse setup from test before! test_config color.diff.oldMoved "magenta" && test_config color.diff.newMoved "cyan" && @@ -1315,7 +1315,7 @@ test_expect_success 'detect permutations inside moved code -- dimmed_zebra' ' test_config color.diff.newMovedDimmed "normal cyan" && test_config color.diff.oldMovedAlternativeDimmed "normal blue" && test_config color.diff.newMovedAlternativeDimmed "normal yellow" && - git diff HEAD --no-renames --color-moved=dimmed_zebra --color >actual.raw && + git diff HEAD --no-renames --color-moved=dimmed-zebra --color >actual.raw && grep -v "index" actual.raw | test_decode_color >actual && cat <<-\EOF >expected && <BOLD>diff --git a/lines.txt b/lines.txt<RESET> diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 25b1f8cc73..05d3707e38 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -1556,12 +1556,28 @@ test_expect_success GPG 'setup signed branch' ' git commit -S -m signed_commit ' +test_expect_success GPGSM 'setup signed branch x509' ' + test_when_finished "git reset --hard && git checkout master" && + git checkout -b signed-x509 master && + echo foo >foo && + git add foo && + test_config gpg.format x509 && + test_config user.signingkey $GIT_COMMITTER_EMAIL && + git commit -S -m signed_commit +' + test_expect_success GPG 'log --graph --show-signature' ' git log --graph --show-signature -n1 signed >actual && grep "^| gpg: Signature made" actual && grep "^| gpg: Good signature" actual ' +test_expect_success GPGSM 'log --graph --show-signature x509' ' + git log --graph --show-signature -n1 signed-x509 >actual && + grep "^| gpgsm: Signature made" actual && + grep "^| gpgsm: Good signature" actual +' + test_expect_success GPG 'log --graph --show-signature for merged tag' ' test_when_finished "git reset --hard && git checkout master" && git checkout -b plain master && @@ -1581,6 +1597,27 @@ test_expect_success GPG 'log --graph --show-signature for merged tag' ' grep "^| | gpg: Good signature" actual ' +test_expect_success GPGSM 'log --graph --show-signature for merged tag x509' ' + test_when_finished "git reset --hard && git checkout master" && + test_config gpg.format x509 && + test_config user.signingkey $GIT_COMMITTER_EMAIL && + git checkout -b plain-x509 master && + echo aaa >bar && + git add bar && + git commit -m bar_commit && + git checkout -b tagged-x509 master && + echo bbb >baz && + git add baz && + git commit -m baz_commit && + git tag -s -m signed_tag_msg signed_tag_x509 && + git checkout plain-x509 && + git merge --no-ff -m msg signed_tag_x509 && + git log --graph --show-signature -n1 plain-x509 >actual && + grep "^|\\\ merged tag" actual && + grep "^| | gpgsm: Signature made" actual && + grep "^| | gpgsm: Good signature" actual +' + test_expect_success GPG '--no-show-signature overrides --show-signature' ' git log -1 --show-signature --no-show-signature signed >actual && ! grep "^gpg:" actual diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index fa03f56a20..8f945235e3 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -403,7 +403,7 @@ test_expect_success 'fetch creating new shallow root' ' git fetch --depth=1 --progress 2>actual && # This should fetch only the empty commit, no tree or # blob objects - grep "remote: Total 1" actual + test_i18ngrep "remote: Total 1" actual ) ' diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 49d3621a92..62f3569891 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -3,13 +3,16 @@ test_description='fetch/receive strict mode' . ./test-lib.sh -test_expect_success setup ' +test_expect_success 'setup and inject "corrupt or missing" object' ' echo hello >greetings && git add greetings && git commit -m greetings && S=$(git rev-parse :greetings | sed -e "s|^..|&/|") && X=$(echo bye | git hash-object -w --stdin | sed -e "s|^..|&/|") && + echo $S >S && + echo $X >X && + cp .git/objects/$S .git/objects/$S.back && mv -f .git/objects/$X .git/objects/$S && test_must_fail git fsck @@ -115,6 +118,13 @@ test_expect_success 'push with transfer.fsckobjects' ' test_cmp exp act ' +test_expect_success 'repair the "corrupt or missing" object' ' + mv -f .git/objects/$(cat S) .git/objects/$(cat X) && + mv .git/objects/$(cat S).back .git/objects/$(cat S) && + rm -rf .git/objects/$(cat X) && + git fsck +' + cat >bogus-commit <<EOF tree $EMPTY_TREE author Bugs Bunny 1234567890 +0000 @@ -123,6 +133,14 @@ committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000 This commit object intentionally broken EOF +test_expect_success 'fsck with invalid or bogus skipList input' ' + git -c fsck.skipList=/dev/null -c fsck.missingEmail=ignore fsck && + test_must_fail git -c fsck.skipList=does-not-exist -c fsck.missingEmail=ignore fsck 2>err && + test_i18ngrep "Could not open skip list: does-not-exist" err && + test_must_fail git -c fsck.skipList=.git/config -c fsck.missingEmail=ignore fsck 2>err && + test_i18ngrep "Invalid SHA-1: \[core\]" err +' + test_expect_success 'push with receive.fsck.skipList' ' commit="$(git hash-object -t commit -w --stdin <bogus-commit)" && git push . $commit:refs/heads/bogus && @@ -130,11 +148,61 @@ test_expect_success 'push with receive.fsck.skipList' ' git init dst && git --git-dir=dst/.git config receive.fsckObjects true && test_must_fail git push --porcelain dst bogus && - git --git-dir=dst/.git config receive.fsck.skipList SKIP && echo $commit >dst/.git/SKIP && + + # receive.fsck.* does not fall back on fsck.* + git --git-dir=dst/.git config fsck.skipList SKIP && + test_must_fail git push --porcelain dst bogus && + + # Invalid and/or bogus skipList input + git --git-dir=dst/.git config receive.fsck.skipList /dev/null && + test_must_fail git push --porcelain dst bogus && + git --git-dir=dst/.git config receive.fsck.skipList does-not-exist && + test_must_fail git push --porcelain dst bogus 2>err && + test_i18ngrep "Could not open skip list: does-not-exist" err && + git --git-dir=dst/.git config receive.fsck.skipList config && + test_must_fail git push --porcelain dst bogus 2>err && + test_i18ngrep "Invalid SHA-1: \[core\]" err && + + git --git-dir=dst/.git config receive.fsck.skipList SKIP && git push --porcelain dst bogus ' +test_expect_success 'fetch with fetch.fsck.skipList' ' + commit="$(git hash-object -t commit -w --stdin <bogus-commit)" && + refspec=refs/heads/bogus:refs/heads/bogus && + git push . $commit:refs/heads/bogus && + rm -rf dst && + git init dst && + git --git-dir=dst/.git config fetch.fsckObjects true && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && + git --git-dir=dst/.git config fetch.fsck.skipList /dev/null && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && + echo $commit >dst/.git/SKIP && + + # fetch.fsck.* does not fall back on fsck.* + git --git-dir=dst/.git config fsck.skipList dst/.git/SKIP && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && + + # Invalid and/or bogus skipList input + git --git-dir=dst/.git config fetch.fsck.skipList /dev/null && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && + git --git-dir=dst/.git config fetch.fsck.skipList does-not-exist && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err && + test_i18ngrep "Could not open skip list: does-not-exist" err && + git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/config && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err && + test_i18ngrep "Invalid SHA-1: \[core\]" err && + + git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/SKIP && + git --git-dir=dst/.git fetch "file://$(pwd)" $refspec +' + +test_expect_success 'fsck.<unknownmsg-id> dies' ' + test_must_fail git -c fsck.whatEver=ignore fsck 2>err && + test_i18ngrep "Unhandled message id: whatever" err +' + test_expect_success 'push with receive.fsck.missingEmail=warn' ' commit="$(git hash-object -t commit -w --stdin <bogus-commit)" && git push . $commit:refs/heads/bogus && @@ -142,19 +210,58 @@ test_expect_success 'push with receive.fsck.missingEmail=warn' ' git init dst && git --git-dir=dst/.git config receive.fsckobjects true && test_must_fail git push --porcelain dst bogus && + + # receive.fsck.<msg-id> does not fall back on fsck.<msg-id> + git --git-dir=dst/.git config fsck.missingEmail warn && + test_must_fail git push --porcelain dst bogus && + + # receive.fsck.<unknownmsg-id> warns + git --git-dir=dst/.git config \ + receive.fsck.whatEver error && + git --git-dir=dst/.git config \ receive.fsck.missingEmail warn && git push --porcelain dst bogus >act 2>&1 && grep "missingEmail" act && + test_i18ngrep "Skipping unknown msg id.*whatever" act && git --git-dir=dst/.git branch -D bogus && git --git-dir=dst/.git config --add \ receive.fsck.missingEmail ignore && - git --git-dir=dst/.git config --add \ - receive.fsck.badDate warn && git push --porcelain dst bogus >act 2>&1 && ! grep "missingEmail" act ' +test_expect_success 'fetch with fetch.fsck.missingEmail=warn' ' + commit="$(git hash-object -t commit -w --stdin <bogus-commit)" && + refspec=refs/heads/bogus:refs/heads/bogus && + git push . $commit:refs/heads/bogus && + rm -rf dst && + git init dst && + git --git-dir=dst/.git config fetch.fsckobjects true && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && + + # fetch.fsck.<msg-id> does not fall back on fsck.<msg-id> + git --git-dir=dst/.git config fsck.missingEmail warn && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && + + # receive.fsck.<unknownmsg-id> warns + git --git-dir=dst/.git config \ + fetch.fsck.whatEver error && + + git --git-dir=dst/.git config \ + fetch.fsck.missingEmail warn && + git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 && + grep "missingEmail" act && + test_i18ngrep "Skipping unknown msg id.*whatever" act && + rm -rf dst && + git init dst && + git --git-dir=dst/.git config fetch.fsckobjects true && + git --git-dir=dst/.git config \ + fetch.fsck.missingEmail ignore && + git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 && + ! grep "missingEmail" act +' + test_expect_success \ 'receive.fsck.unterminatedHeader=warn triggers error' ' rm -rf dst && @@ -166,4 +273,15 @@ test_expect_success \ grep "Cannot demote unterminatedheader" act ' +test_expect_success \ + 'fetch.fsck.unterminatedHeader=warn triggers error' ' + rm -rf dst && + git init dst && + git --git-dir=dst/.git config fetch.fsckobjects true && + git --git-dir=dst/.git config \ + fetch.fsck.unterminatedheader warn && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" HEAD && + grep "Cannot demote unterminatedheader" act +' + test_done diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index 11e14a1e0f..a6856e052b 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -872,7 +872,7 @@ test_expect_success 'remote prune to cause a dangling symref' ' cd eight && test_must_fail git branch nomore origin ) 2>err && - grep "dangling symref" err + test_i18ngrep "dangling symref" err ' test_expect_success 'show empty remote' ' diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 62308be499..5e810f494e 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -535,6 +535,41 @@ test_expect_success "should be able to fetch with duplicate refspecs" ' ) ' +test_expect_success 'LHS of refspec follows ref disambiguation rules' ' + mkdir lhs-ambiguous && + ( + cd lhs-ambiguous && + git init server && + test_commit -C server unwanted && + test_commit -C server wanted && + + git init client && + + # Check a name coming after "refs" alphabetically ... + git -C server update-ref refs/heads/s wanted && + git -C server update-ref refs/heads/refs/heads/s unwanted && + git -C client fetch ../server +refs/heads/s:refs/heads/checkthis && + git -C server rev-parse wanted >expect && + git -C client rev-parse checkthis >actual && + test_cmp expect actual && + + # ... and one before. + git -C server update-ref refs/heads/q wanted && + git -C server update-ref refs/heads/refs/heads/q unwanted && + git -C client fetch ../server +refs/heads/q:refs/heads/checkthis && + git -C server rev-parse wanted >expect && + git -C client rev-parse checkthis >actual && + test_cmp expect actual && + + # Tags are preferred over branches like refs/{heads,tags}/* + git -C server update-ref refs/tags/t wanted && + git -C server update-ref refs/heads/t unwanted && + git -C client fetch ../server +t:refs/heads/checkthis && + git -C server rev-parse wanted >expect && + git -C client rev-parse checkthis >actual + ) +' + # configured prune tests set_config_tristate () { diff --git a/t/t5534-push-signed.sh b/t/t5534-push-signed.sh index 1cea758f78..030331f1c5 100755 --- a/t/t5534-push-signed.sh +++ b/t/t5534-push-signed.sh @@ -194,10 +194,12 @@ test_expect_success GPG 'fail without key and heed user.signingkey' ' EOF - unset GIT_COMMITTER_EMAIL && - git config user.email hasnokey@nowhere.com && - test_must_fail git push --signed dst noop ff +noff && - git config user.signingkey committer@example.com && + test_config user.email hasnokey@nowhere.com && + ( + sane_unset GIT_COMMITTER_EMAIL && + test_must_fail git push --signed dst noop ff +noff + ) && + test_config user.signingkey $GIT_COMMITTER_EMAIL && git push --signed dst noop ff +noff && ( @@ -218,4 +220,57 @@ test_expect_success GPG 'fail without key and heed user.signingkey' ' test_cmp expect dst/push-cert-status ' +test_expect_success GPGSM 'fail without key and heed user.signingkey x509' ' + test_config gpg.format x509 && + prepare_dst && + mkdir -p dst/.git/hooks && + git -C dst config receive.certnonceseed sekrit && + write_script dst/.git/hooks/post-receive <<-\EOF && + # discard the update list + cat >/dev/null + # record the push certificate + if test -n "${GIT_PUSH_CERT-}" + then + git cat-file blob $GIT_PUSH_CERT >../push-cert + fi && + + cat >../push-cert-status <<E_O_F + SIGNER=${GIT_PUSH_CERT_SIGNER-nobody} + KEY=${GIT_PUSH_CERT_KEY-nokey} + STATUS=${GIT_PUSH_CERT_STATUS-nostatus} + NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus} + NONCE=${GIT_PUSH_CERT_NONCE-nononce} + E_O_F + + EOF + + test_config user.email hasnokey@nowhere.com && + test_config user.signingkey "" && + ( + sane_unset GIT_COMMITTER_EMAIL && + test_must_fail git push --signed dst noop ff +noff + ) && + test_config user.signingkey $GIT_COMMITTER_EMAIL && + git push --signed dst noop ff +noff && + + ( + cat <<-\EOF && + SIGNER=/CN=C O Mitter/O=Example/SN=C O/GN=Mitter + KEY= + STATUS=G + NONCE_STATUS=OK + EOF + sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert + ) >expect.in && + key=$(cat "${GNUPGHOME}/trustlist.txt" | cut -d" " -f1 | tr -d ":") && + sed -e "s/^KEY=/KEY=${key}/" expect.in >expect && + + noop=$(git rev-parse noop) && + ff=$(git rev-parse ff) && + noff=$(git rev-parse noff) && + grep "$noop $ff refs/heads/ff" dst/push-cert && + grep "$noop $noff refs/heads/noff" dst/push-cert && + test_cmp expect dst/push-cert-status +' + test_done diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index 3aab44bdcb..771f36f9ff 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -363,6 +363,24 @@ test_expect_success 'custom http headers' ' submodule update sub ' +test_expect_success 'using fetch command in remote-curl updates refs' ' + SERVER="$HTTPD_DOCUMENT_ROOT_PATH/twobranch" && + rm -rf "$SERVER" client && + + git init "$SERVER" && + test_commit -C "$SERVER" foo && + git -C "$SERVER" update-ref refs/heads/anotherbranch foo && + + git clone $HTTPD_URL/smart/twobranch client && + + test_commit -C "$SERVER" bar && + git -C client -c protocol.version=0 fetch && + + git -C "$SERVER" rev-parse master >expect && + git -C client rev-parse origin/master >actual && + test_cmp expect actual +' + test_expect_success 'GIT_REDACT_COOKIES redacts cookies' ' rm -rf clone && echo "Set-Cookie: Foo=1" >cookies && diff --git a/t/t5552-skipping-fetch-negotiator.sh b/t/t5552-skipping-fetch-negotiator.sh index 0a8e0e42ed..3b60bd44e0 100755 --- a/t/t5552-skipping-fetch-negotiator.sh +++ b/t/t5552-skipping-fetch-negotiator.sh @@ -47,6 +47,29 @@ test_expect_success 'commits with no parents are sent regardless of skip distanc have_not_sent c6 c4 c3 ' +test_expect_success 'unknown fetch.negotiationAlgorithm values error out' ' + rm -rf server client trace && + git init server && + test_commit -C server to_fetch && + + git init client && + test_commit -C client on_client && + git -C client checkout on_client && + + test_config -C client fetch.negotiationAlgorithm invalid && + test_must_fail git -C client fetch "$(pwd)/server" 2>err && + test_i18ngrep "unknown fetch negotiation algorithm" err && + + # Explicit "default" value + test_config -C client fetch.negotiationAlgorithm default && + git -C client -c fetch.negotiationAlgorithm=default fetch "$(pwd)/server" && + + # Implementation detail: If there is nothing to fetch, we will not error out + test_config -C client fetch.negotiationAlgorithm invalid && + git -C client fetch "$(pwd)/server" 2>err && + test_i18ngrep ! "unknown fetch negotiation algorithm" err +' + test_expect_success 'when two skips collide, favor the larger one' ' rm -rf server client trace && git init server && diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh index 0d4c52016b..a571f22bfd 100755 --- a/t/t5570-git-daemon.sh +++ b/t/t5570-git-daemon.sh @@ -7,9 +7,9 @@ test_description='test fetching over git protocol' start_git_daemon check_verbose_connect () { - grep -F "Looking up 127.0.0.1 ..." stderr && - grep -F "Connecting to 127.0.0.1 (port " stderr && - grep -F "done." stderr + test_i18ngrep -F "Looking up 127.0.0.1 ..." stderr && + test_i18ngrep -F "Connecting to 127.0.0.1 (port " stderr && + test_i18ngrep -F "done." stderr } test_expect_success 'setup repository' ' diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index a4fe6508bd..3beeed4546 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -181,7 +181,12 @@ test_expect_success 'clone with file:// using protocol v2' ' test_cmp expect actual && # Server responded using protocol v2 - grep "clone< version 2" log + grep "clone< version 2" log && + + # Client sent ref-prefixes to filter the ref-advertisement + grep "ref-prefix HEAD" log && + grep "ref-prefix refs/heads/" log && + grep "ref-prefix refs/tags/" log ' test_expect_success 'fetch with file:// using protocol v2' ' @@ -204,6 +209,7 @@ test_expect_success 'ref advertisment is filtered during fetch using protocol v2 test_when_finished "rm -f log" && test_commit -C file_parent three && + git -C file_parent branch unwanted-branch three && GIT_TRACE_PACKET="$(pwd)/log" git -C file_child -c protocol.version=2 \ fetch origin master && @@ -212,9 +218,8 @@ test_expect_success 'ref advertisment is filtered during fetch using protocol v2 git -C file_parent log -1 --format=%s >expect && test_cmp expect actual && - ! grep "refs/tags/one" log && - ! grep "refs/tags/two" log && - ! grep "refs/tags/three" log + grep "refs/heads/master" log && + ! grep "refs/heads/unwanted-branch" log ' test_expect_success 'server-options are sent when fetching' ' @@ -359,6 +364,71 @@ test_expect_success 'default refspec is used to filter ref when fetchcing' ' grep "ref-prefix refs/tags/" log ' +test_expect_success 'fetch supports various ways of have lines' ' + rm -rf server client trace && + git init server && + test_commit -C server dwim && + TREE=$(git -C server rev-parse HEAD^{tree}) && + git -C server tag exact \ + $(git -C server commit-tree -m a "$TREE") && + git -C server tag dwim-unwanted \ + $(git -C server commit-tree -m b "$TREE") && + git -C server tag exact-unwanted \ + $(git -C server commit-tree -m c "$TREE") && + git -C server tag prefix1 \ + $(git -C server commit-tree -m d "$TREE") && + git -C server tag prefix2 \ + $(git -C server commit-tree -m e "$TREE") && + git -C server tag fetch-by-sha1 \ + $(git -C server commit-tree -m f "$TREE") && + git -C server tag completely-unrelated \ + $(git -C server commit-tree -m g "$TREE") && + + git init client && + GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \ + fetch "file://$(pwd)/server" \ + dwim \ + refs/tags/exact \ + refs/tags/prefix*:refs/tags/prefix* \ + "$(git -C server rev-parse fetch-by-sha1)" && + + # Ensure that the appropriate prefixes are sent (using a sample) + grep "fetch> ref-prefix dwim" trace && + grep "fetch> ref-prefix refs/heads/dwim" trace && + grep "fetch> ref-prefix refs/tags/prefix" trace && + + # Ensure that the correct objects are returned + git -C client cat-file -e $(git -C server rev-parse dwim) && + git -C client cat-file -e $(git -C server rev-parse exact) && + git -C client cat-file -e $(git -C server rev-parse prefix1) && + git -C client cat-file -e $(git -C server rev-parse prefix2) && + git -C client cat-file -e $(git -C server rev-parse fetch-by-sha1) && + test_must_fail git -C client cat-file -e \ + $(git -C server rev-parse dwim-unwanted) && + test_must_fail git -C client cat-file -e \ + $(git -C server rev-parse exact-unwanted) && + test_must_fail git -C client cat-file -e \ + $(git -C server rev-parse completely-unrelated) +' + +test_expect_success 'fetch supports include-tag and tag following' ' + rm -rf server client trace && + git init server && + + test_commit -C server to_fetch && + git -C server tag -a annotated_tag -m message && + + git init client && + GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \ + fetch "$(pwd)/server" to_fetch:to_fetch && + + grep "fetch> ref-prefix to_fetch" trace && + grep "fetch> ref-prefix refs/tags/" trace && + grep "fetch> include-tag" trace && + + git -C client cat-file -e $(git -C client rev-parse annotated_tag) +' + # Test protocol v2 with 'http://' transport # . "$TEST_DIRECTORY"/lib-httpd.sh diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index ee5757966f..aaaa722cca 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -126,7 +126,7 @@ test_expect_success 'forced push' ' test_expect_success 'cloning without refspec' ' GIT_REMOTE_TESTGIT_REFSPEC="" \ git clone "testgit::${PWD}/server" local2 2>error && - grep "This remote helper should implement refspec capability" error && + test_i18ngrep "this remote helper should implement refspec capability" error && compare_refs local2 HEAD server HEAD ' @@ -134,7 +134,7 @@ test_expect_success 'pulling without refspecs' ' (cd local2 && git reset --hard && GIT_REMOTE_TESTGIT_REFSPEC="" git pull 2>../error) && - grep "This remote helper should implement refspec capability" error && + test_i18ngrep "this remote helper should implement refspec capability" error && compare_refs local2 HEAD server HEAD ' @@ -146,7 +146,7 @@ test_expect_success 'pushing without refspecs' ' GIT_REMOTE_TESTGIT_REFSPEC="" && export GIT_REMOTE_TESTGIT_REFSPEC && test_must_fail git push 2>../error) && - grep "remote-helper doesn.t support push; refspec needed" error + test_i18ngrep "remote-helper doesn.t support push; refspec needed" error ' test_expect_success 'pulling without marks' ' @@ -246,7 +246,7 @@ test_expect_success 'proper failure checks for fetching' ' (cd local && test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git fetch 2>error && cat error && - grep -q "Error while running fast-import" error + test_i18ngrep -q "error while running fast-import" error ) ' diff --git a/t/t6029-merge-subtree.sh b/t/t6029-merge-subtree.sh index 7d5bc78472..793f0c8bf3 100755 --- a/t/t6029-merge-subtree.sh +++ b/t/t6029-merge-subtree.sh @@ -29,6 +29,34 @@ test_expect_success 'subtree available and works like recursive' ' ' +test_expect_success 'setup branch sub' ' + git checkout --orphan sub && + git rm -rf . && + test_commit foo +' + +test_expect_success 'setup branch main' ' + git checkout -b main master && + git merge -s ours --no-commit --allow-unrelated-histories sub && + git read-tree --prefix=dir/ -u sub && + git commit -m "initial merge of sub into main" && + test_path_is_file dir/foo.t && + test_path_is_file hello +' + +test_expect_success 'update branch sub' ' + git checkout sub && + test_commit bar +' + +test_expect_success 'update branch main' ' + git checkout main && + git merge -s subtree sub -m "second merge of sub into main" && + test_path_is_file dir/bar.t && + test_path_is_file dir/foo.t && + test_path_is_file hello +' + test_expect_success 'setup' ' mkdir git-gui && cd git-gui && diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index aa3e249639..86374a9c52 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -113,6 +113,12 @@ test_expect_success 'test GIT_NO_REPLACE_OBJECTS env variable' ' GIT_NO_REPLACE_OBJECTS=1 git show $HASH2 | grep "A U Thor" ' +test_expect_success 'test core.usereplacerefs config option' ' + test_config core.usereplacerefs false && + git cat-file commit $HASH2 | grep "author A U Thor" && + git show $HASH2 | grep "A U Thor" +' + cat >tag.sig <<EOF object $HASH2 type commit diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index d7b319e919..2147938aa1 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -1354,6 +1354,19 @@ test_expect_success GPG \ 'test_config gpg.program echo && test_must_fail git tag -s -m tail tag-gpg-failure' +# try to sign with bad user.signingkey +test_expect_success GPGSM \ + 'git tag -s fails if gpgsm is misconfigured (bad key)' \ + 'test_config user.signingkey BobTheMouse && + test_config gpg.format x509 && + test_must_fail git tag -s -m tail tag-gpg-failure' + +# try to produce invalid signature +test_expect_success GPGSM \ + 'git tag -s fails if gpgsm is misconfigured (bad signature format)' \ + 'test_config gpg.x509.program echo && + test_config gpg.format x509 && + test_must_fail git tag -s -m tail tag-gpg-failure' # try to verify without gpg: diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh index 291a1e2b07..99f35a5bbe 100755 --- a/t/t7030-verify-tag.sh +++ b/t/t7030-verify-tag.sh @@ -41,6 +41,13 @@ test_expect_success GPG 'create signed tags' ' git tag -uB7227189 -m eighth eighth-signed-alt ' +test_expect_success GPGSM 'create signed tags x509 ' ' + test_config gpg.format x509 && + test_config user.signingkey $GIT_COMMITTER_EMAIL && + echo 9 >file && test_tick && git commit -a -m "nineth gpgsm-signed" && + git tag -s -m nineth nineth-signed-x509 +' + test_expect_success GPG 'verify and show signatures' ' ( for tag in initial second merge fourth-signed sixth-signed seventh-signed @@ -72,6 +79,13 @@ test_expect_success GPG 'verify and show signatures' ' ) ' +test_expect_success GPGSM 'verify and show signatures x509' ' + git verify-tag nineth-signed-x509 2>actual && + grep "Good signature from" actual && + ! grep "BAD signature from" actual && + echo nineth-signed-x509 OK +' + test_expect_success GPG 'detect fudged signature' ' git cat-file tag seventh-signed >raw && sed -e "/^tag / s/seventh/7th forged/" raw >forged1 && @@ -112,6 +126,13 @@ test_expect_success GPG 'verify signatures with --raw' ' ) ' +test_expect_success GPGSM 'verify signatures with --raw x509' ' + git verify-tag --raw nineth-signed-x509 2>actual && + grep "GOODSIG" actual && + ! grep "BADSIG" actual && + echo nineth-signed-x509 OK +' + test_expect_success GPG 'verify multiple tags' ' tags="fourth-signed sixth-signed seventh-signed" && for i in $tags @@ -125,6 +146,19 @@ test_expect_success GPG 'verify multiple tags' ' test_cmp expect.stderr actual.stderr ' +test_expect_success GPGSM 'verify multiple tags x509' ' + tags="seventh-signed nineth-signed-x509" && + for i in $tags + do + git verify-tag -v --raw $i || return 1 + done >expect.stdout 2>expect.stderr.1 && + grep "^.GNUPG:." <expect.stderr.1 >expect.stderr && + git verify-tag -v --raw $tags >actual.stdout 2>actual.stderr.1 && + grep "^.GNUPG:." <actual.stderr.1 >actual.stderr && + test_cmp expect.stdout actual.stdout && + test_cmp expect.stderr actual.stderr +' + test_expect_success GPG 'verifying tag with --format' ' cat >expect <<-\EOF && tagname : fourth-signed diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index c61e304e97..c9162c54f4 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -666,7 +666,7 @@ test_expect_success 'test ident field is working' ' mkdir ../other_worktree && cp -R done dthree dtwo four three ../other_worktree && GIT_WORK_TREE=../other_worktree git status 2>../err && - echo "warning: Untracked cache is disabled on this system or location." >../expect && + echo "warning: untracked cache is disabled on this system or location" >../expect && test_i18ncmp ../expect ../err ' diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 2c2c97e144..2b71e62ec2 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -378,7 +378,7 @@ test_expect_success 'init should register submodule url in .git/config' ' test_failure_with_unknown_submodule () { test_must_fail git submodule $1 no-such-submodule 2>output.err && - grep "^error: .*no-such-submodule" output.err + test_i18ngrep "^error: .*no-such-submodule" output.err } test_expect_success 'init should fail with unknown submodule' ' diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index f604ef7a72..686e6a439e 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -115,17 +115,17 @@ Submodule path '../super/submodule': checked out '$submodulesha1' EOF cat <<EOF >expect2 +Cloning into '$pwd/recursivesuper/super/merging'... +Cloning into '$pwd/recursivesuper/super/none'... +Cloning into '$pwd/recursivesuper/super/rebasing'... +Cloning into '$pwd/recursivesuper/super/submodule'... Submodule 'merging' ($pwd/merging) registered for path '../super/merging' Submodule 'none' ($pwd/none) registered for path '../super/none' Submodule 'rebasing' ($pwd/rebasing) registered for path '../super/rebasing' Submodule 'submodule' ($pwd/submodule) registered for path '../super/submodule' -Cloning into '$pwd/recursivesuper/super/merging'... done. -Cloning into '$pwd/recursivesuper/super/none'... done. -Cloning into '$pwd/recursivesuper/super/rebasing'... done. -Cloning into '$pwd/recursivesuper/super/submodule'... done. EOF @@ -137,7 +137,8 @@ test_expect_success 'submodule update --init --recursive from subdirectory' ' git submodule update --init --recursive ../super >../../actual 2>../../actual2 ) && test_i18ncmp expect actual && - test_i18ncmp expect2 actual2 + sort actual2 >actual2.sorted && + test_i18ncmp expect2 actual2.sorted ' cat <<EOF >expect2 diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh index 6e2015ed9a..4e37ff8f16 100755 --- a/t/t7510-signed-commit.sh +++ b/t/t7510-signed-commit.sh @@ -227,4 +227,11 @@ test_expect_success GPG 'log.showsignature behaves like --show-signature' ' grep "gpg: Good signature" actual ' +test_expect_success GPG 'check config gpg.format values' ' + test_config gpg.format openpgp && + git commit -S --amend -m "success" && + test_config gpg.format OpEnPgP && + test_must_fail git commit -S --amend -m "fail" +' + test_done diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 9e7f96223d..fac33e524c 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -3147,7 +3147,10 @@ background_import_then_checkpoint () { echo $! >V.pid # We don't mind if fast-import has already died by the time the test # ends. - test_when_finished "exec 8>&-; exec 9>&-; kill $(cat V.pid) || true" + test_when_finished " + exec 8>&-; exec 9>&-; + kill $(cat V.pid) && wait $(cat V.pid) + true" # Start in the background to ensure we adhere strictly to (blocking) # pipes writing sequence. We want to assume that the write below could diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh index 4849edc4ef..729cd25770 100755 --- a/t/t9800-git-p4-basic.sh +++ b/t/t9800-git-p4-basic.sh @@ -261,6 +261,35 @@ test_expect_success 'unresolvable host in P4PORT should display error' ' ) ' +# Test following scenarios: +# - Without ".git/hooks/p4-pre-submit" , submit should continue +# - With the hook returning 0, submit should continue +# - With the hook returning 1, submit should abort +test_expect_success 'run hook p4-pre-submit before submit' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + echo "hello world" >hello.txt && + git add hello.txt && + git commit -m "add hello.txt" && + git config git-p4.skipSubmitEdit true && + git p4 submit --dry-run >out && + grep "Would apply" out && + mkdir -p .git/hooks && + write_script .git/hooks/p4-pre-submit <<-\EOF && + exit 0 + EOF + git p4 submit --dry-run >out && + grep "Would apply" out && + write_script .git/hooks/p4-pre-submit <<-\EOF && + exit 1 + EOF + test_must_fail git p4 submit --dry-run >errs 2>&1 && + ! grep "Would apply" errs + ) +' + test_expect_success 'submit from detached head' ' test_when_finished cleanup_git && git p4 clone --dest="$git" //depot && |