{"thread":{"id":"60895","subject":"[BUG] git 2.44.0-rc0 t0080.1 Breaks on NonStop x86 and ia64","startedAt":"2024-02-10T18:14:37Z","lastAt":"2024-02-12T19:26:54Z","messageCount":9,"participants":["rsbecker@nexbridge.com","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"488362","messageId":"000401da5c4c$fd4ad260$f7e07720$@nexbridge.com","threadId":"60895","inReplyTo":null,"subject":"[BUG] git 2.44.0-rc0 t0080.1 Breaks on NonStop x86 and ia64","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2024-02-10T18:14:24Z","receivedAt":"2024-02-10T18:14:37Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"I encountered a new problem on git 2.44.0-rc0 for test t0080.1. Run very\nverbose (--verbose -x):\n\n++ cat\n++ /home/randall/git/t/unit-tests/bin/t-basic\n++ test_cmp expect actual\n++ test 2 -ne 2\n++ eval 'diff -u' '\"$@\"'\n+++ diff -u expect actual\n--- expect      2024-02-10 18:04:28 +0000\n+++ actual      2024-02-10 18:04:28 +0000\n@@ -1,43 +1,43 @@\n ok 1 - passing test\n ok 2 - passing test and assertion return 1\n-# check \"1 == 2\" failed at t/unit-tests/t-basic.c:76\n+# check \"1 == 2\" failed at /home/randall/git/t/unit-tests/t-basic.c:76\n #    left: 1\n #   right: 2\n not ok 3 - failing test\n ok 4 - failing test and assertion return 0\n not ok 5 - passing TEST_TODO() # TODO\n ok 6 - passing TEST_TODO() returns 1\n-# todo check 'check(x)' succeeded at t/unit-tests/t-basic.c:25\n+# todo check 'check(x)' succeeded at\n/home/randall/git/t/unit-tests/t-basic.c:25\n not ok 7 - failing TEST_TODO()\n ok 8 - failing TEST_TODO() returns 0\n-# check \"0\" failed at t/unit-tests/t-basic.c:30\n+# check \"0\" failed at /home/randall/git/t/unit-tests/t-basic.c:30\n # skipping test - missing prerequisite\n-# skipping check '1' at t/unit-tests/t-basic.c:32\n+# skipping check '1' at /home/randall/git/t/unit-tests/t-basic.c:32\n ok 9 - test_skip() # SKIP\n ok 10 - skipped test returns 1\n # skipping test - missing prerequisite\n ok 11 - test_skip() inside TEST_TODO() # SKIP\n ok 12 - test_skip() inside TEST_TODO() returns 1\n-# check \"0\" failed at t/unit-tests/t-basic.c:48\n+# check \"0\" failed at /home/randall/git/t/unit-tests/t-basic.c:48\n not ok 13 - TEST_TODO() after failing check\n ok 14 - TEST_TODO() after failing check returns 0\n-# check \"0\" failed at t/unit-tests/t-basic.c:56\n+# check \"0\" failed at /home/randall/git/t/unit-tests/t-basic.c:56\n not ok 15 - failing check after TEST_TODO()\n ok 16 - failing check after TEST_TODO() returns 0\n-# check \"!strcmp(\"\\thello\\\\\", \"there\\\"\\n\")\" failed at\nt/unit-tests/t-basic.c:61\n+# check \"!strcmp(\"\\thello\\\\\", \"there\\\"\\n\")\" failed at\n/home/randall/git/t/unit-tests/t-basic.c:61\n #    left: \"\\011hello\\\\\"\n #   right: \"there\\\"\\012\"\n-# check \"!strcmp(\"NULL\", NULL)\" failed at t/unit-tests/t-basic.c:62\n+# check \"!strcmp(\"NULL\", NULL)\" failed at\n/home/randall/git/t/unit-tests/t-basic.c:62\n #    left: \"NULL\"\n #   right: NULL\n-# check \"'a' == '\\n'\" failed at t/unit-tests/t-basic.c:63\n+# check \"'a' == '\\n'\" failed at /home/randall/git/t/unit-tests/t-basic.c:63\n #    left: 'a'\n #   right: '\\012'\n-# check \"'\\\\' == '\\''\" failed at t/unit-tests/t-basic.c:64\n+# check \"'\\\\' == '\\''\" failed at\n/home/randall/git/t/unit-tests/t-basic.c:64\n #    left: '\\\\'\n #   right: '\\''\n not ok 17 - messages from failing string and char comparison\n-# BUG: test has no checks at t/unit-tests/t-basic.c:91\n+# BUG: test has no checks at /home/randall/git/t/unit-tests/t-basic.c:91\n not ok 18 - test with no checks\n ok 19 - test with no checks returns 0\n 1..19\nerror: last command exited with $?=1\n\nThe diff appears to have failed because of an assumption of how paths are\nresolved during compilation. The assumption is that files remain partially\nqualified, which is not the case in all C compilers. This is c99. My\nexperience with gcc is that it qualifies names differently than other\ncompilers. It might be useful to pipe to sed to strip ${HOME}/ when building\nthe actual file, something like:\n\nsed -i \"1,\\$s/${HOME}\\//g\" actual    # Not that that will actually work\nbecause sed will process /. A different delimiter would work.\n\nRandall\n\n--\nRandall S. Becker\nNSGit Chief Architect\nNexbridge Inc.\n+1.416.984.9826\n\n\n"},{"id":"488375","messageId":"002301da5c78$11959ea0$34c0dbe0$@nexbridge.com","threadId":"60895","inReplyTo":"000401da5c4c$fd4ad260$f7e07720$@nexbridge.com","subject":"RE: [BUG] git 2.44.0-rc0 t0080.1 Breaks on NonStop x86 and ia64","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2024-02-10T23:22:46Z","receivedAt":"2024-02-10T23:22:54Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On Saturday, February 10, 2024 1:14 PM, I wrote:\n>I encountered a new problem on git 2.44.0-rc0 for test t0080.1. Run very\nverbose\n>(--verbose -x):\n>\n>++ cat\n>++ /home/randall/git/t/unit-tests/bin/t-basic\n>++ test_cmp expect actual\n>++ test 2 -ne 2\n>++ eval 'diff -u' '\"$@\"'\n>+++ diff -u expect actual\n>--- expect      2024-02-10 18:04:28 +0000\n>+++ actual      2024-02-10 18:04:28 +0000\n>@@ -1,43 +1,43 @@\n> ok 1 - passing test\n> ok 2 - passing test and assertion return 1 -# check \"1 == 2\" failed at\nt/unit-tests/t-\n>basic.c:76\n>+# check \"1 == 2\" failed at /home/randall/git/t/unit-tests/t-basic.c:76\n> #    left: 1\n> #   right: 2\n> not ok 3 - failing test\n> ok 4 - failing test and assertion return 0  not ok 5 - passing TEST_TODO()\n# TODO\n>ok 6 - passing TEST_TODO() returns 1 -# todo check 'check(x)' succeeded at\nt/unit-\n>tests/t-basic.c:25\n>+# todo check 'check(x)' succeeded at\n>/home/randall/git/t/unit-tests/t-basic.c:25\n> not ok 7 - failing TEST_TODO()\n> ok 8 - failing TEST_TODO() returns 0\n>-# check \"0\" failed at t/unit-tests/t-basic.c:30\n>+# check \"0\" failed at /home/randall/git/t/unit-tests/t-basic.c:30\n> # skipping test - missing prerequisite\n>-# skipping check '1' at t/unit-tests/t-basic.c:32\n>+# skipping check '1' at /home/randall/git/t/unit-tests/t-basic.c:32\n> ok 9 - test_skip() # SKIP\n> ok 10 - skipped test returns 1\n> # skipping test - missing prerequisite\n> ok 11 - test_skip() inside TEST_TODO() # SKIP  ok 12 - test_skip() inside\n>TEST_TODO() returns 1 -# check \"0\" failed at t/unit-tests/t-basic.c:48\n>+# check \"0\" failed at /home/randall/git/t/unit-tests/t-basic.c:48\n> not ok 13 - TEST_TODO() after failing check  ok 14 - TEST_TODO() after\nfailing check\n>returns 0 -# check \"0\" failed at t/unit-tests/t-basic.c:56\n>+# check \"0\" failed at /home/randall/git/t/unit-tests/t-basic.c:56\n> not ok 15 - failing check after TEST_TODO()  ok 16 - failing check after\nTEST_TODO()\n>returns 0 -# check \"!strcmp(\"\\thello\\\\\", \"there\\\"\\n\")\" failed at\n>t/unit-tests/t-basic.c:61\n>+# check \"!strcmp(\"\\thello\\\\\", \"there\\\"\\n\")\" failed at\n>/home/randall/git/t/unit-tests/t-basic.c:61\n> #    left: \"\\011hello\\\\\"\n> #   right: \"there\\\"\\012\"\n>-# check \"!strcmp(\"NULL\", NULL)\" failed at t/unit-tests/t-basic.c:62\n>+# check \"!strcmp(\"NULL\", NULL)\" failed at\n>/home/randall/git/t/unit-tests/t-basic.c:62\n> #    left: \"NULL\"\n> #   right: NULL\n>-# check \"'a' == '\\n'\" failed at t/unit-tests/t-basic.c:63\n>+# check \"'a' == '\\n'\" failed at\n>+/home/randall/git/t/unit-tests/t-basic.c:63\n> #    left: 'a'\n> #   right: '\\012'\n>-# check \"'\\\\' == '\\''\" failed at t/unit-tests/t-basic.c:64\n>+# check \"'\\\\' == '\\''\" failed at\n>/home/randall/git/t/unit-tests/t-basic.c:64\n> #    left: '\\\\'\n> #   right: '\\''\n> not ok 17 - messages from failing string and char comparison -# BUG: test\nhas no\n>checks at t/unit-tests/t-basic.c:91\n>+# BUG: test has no checks at\n>+/home/randall/git/t/unit-tests/t-basic.c:91\n> not ok 18 - test with no checks\n> ok 19 - test with no checks returns 0\n> 1..19\n>error: last command exited with $?=1\n>\n>The diff appears to have failed because of an assumption of how paths are\nresolved\n>during compilation. The assumption is that files remain partially\nqualified, which is\n>not the case in all C compilers. This is c99. My experience with gcc is\nthat it qualifies\n>names differently than other compilers. It might be useful to pipe to sed\nto strip\n>${HOME}/ when building the actual file, something like:\n>\n>sed -i \"1,\\$s/${HOME}\\//g\" actual    # Not that that will actually work\n>because sed will process /. A different delimiter would work.\n>\n>Randall\n\nPutting the sed command in, as follows:\n\ndiff --git a/t/t0080-unit-test-output.sh b/t/t0080-unit-test-output.sh\nindex 6657c114a3..eaf25f2ddc 100755\n--- a/t/t0080-unit-test-output.sh\n+++ b/t/t0080-unit-test-output.sh\n@@ -52,7 +52,7 @@ test_expect_success 'TAP output from unit tests' '\n        1..19\n        EOF\n\n-       ! \"$GIT_BUILD_DIR\"/t/unit-tests/bin/t-basic >actual &&\n+       ! \"$GIT_BUILD_DIR\"/t/unit-tests/bin/t-basic | sed \"s?/.*/t/?t/?\"\n>actual &&\n        test_cmp expect actual\n '\n\nstill results in a problem. The ! in the above line is being interpreted\nincorrectly:\n\ndiff expect actual\n27c27\n< # check \"!strcmp(\"\\thello\\\\\", \"there\"\\n\")\" failed at\nt/unit-tests/t-basic.c:61\n---\n> # check \"!strcmp(\"\\thello\\\\\", \"there\\\"\\n\")\" failed at\nt/unit-tests/t-basic.c:61\n29c29\n< #   right: \"there\"\\012\"\n---\n> #   right: \"there\\\"\\012\"\n\nI am not convinced the test is working properly. The ! appears to be causing\n/bin/ksh to be invoked instead of bash. If I remove !, the test works\ncorrectly. Did we not have issues with using ! in the past?\n\n--Randall\n\n--\nBrief whoami: NonStop&UNIX developer since approximately\nUNIX(421664400)\nNonStop(211288444200000000)\n-- In real life, I talk too much.\n\n\n\n"},{"id":"488379","messageId":"xmqqbk8nbvqy.fsf@gitster.g","threadId":"60895","inReplyTo":"000401da5c4c$fd4ad260$f7e07720$@nexbridge.com","subject":"Re: [BUG] git 2.44.0-rc0 t0080.1 Breaks on NonStop x86 and ia64","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-02-11T02:05:57Z","receivedAt":"2024-02-11T02:06:08Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"<rsbecker@nexbridge.com> writes:\n\n> The diff appears to have failed because of an assumption of how paths are\n> resolved during compilation. The assumption is that files remain partially\n> qualified, which is not the case in all C compilers. This is c99. My\n> experience with gcc is that it qualifies names differently than other\n> compilers.\n\nI just found this bit of gem in t/unit-tests/test-lib.c.  I guess\nVisual C falls into the same category as yours, while GCC and Clang\nare from different camps?\n\nThe easiest way forward may be to build on top of it, perhaps like\nso, to generalize the make_relative() to cover your case, too?\n\n t/unit-tests/test-lib.c | 63 +++++++++++++++++++++++++++++++++++++------------\n 1 file changed, 48 insertions(+), 15 deletions(-)\n\ndiff --git c/t/unit-tests/test-lib.c w/t/unit-tests/test-lib.c\nindex 7bf9dfdb95..69dbe1bbc7 100644\n--- c/t/unit-tests/test-lib.c\n+++ w/t/unit-tests/test-lib.c\n@@ -21,45 +21,78 @@ static struct {\n \t.result = RESULT_NONE,\n };\n \n-#ifndef _MSC_VER\n-#define make_relative(location) location\n-#else\n+#include \"dir.h\"\n /*\n  * Visual C interpolates the absolute Windows path for `__FILE__`,\n  * but we want to see relative paths, as verified by t0080.\n+ * There are other compilers that do the same, and are not for\n+ * Windows.\n  */\n-#include \"dir.h\"\n-\n static const char *make_relative(const char *location)\n {\n \tstatic char prefix[] = __FILE__, buf[PATH_MAX], *p;\n \tstatic size_t prefix_len;\n+\tstatic int need_bs_to_fs = -1;\n \n-\tif (!prefix_len) {\n+\t/* one-time preparation */\n+\tif (need_bs_to_fs < 0) {\n \t\tsize_t len = strlen(prefix);\n-\t\tconst char *needle = \"\\\\t\\\\unit-tests\\\\test-lib.c\";\n+\t\tchar needle[] = \"t\\\\unit-tests\\\\test-lib.c\";\n \t\tsize_t needle_len = strlen(needle);\n \n-\t\tif (len < needle_len || strcmp(needle, prefix + len - needle_len))\n+\t\tif (len < needle_len)\n+\t\t\tdie(\"unexpected prefix '%s'\", prefix);\n+\n+\t\t/*\n+\t\t * The path could be relative (t/unit-tests/test-lib.c)\n+\t\t * or full (/home/user/git/t/unit-tests/test-lib.c).\n+\t\t * Check the slash between \"t\" and \"unit-tests\".\n+\t\t */\n+\t\tprefix_len = len - needle_len;\n+\t\tif (prefix[prefix_len + 1] == '/') {\n+\t\t\t/* Oh, we're not Windows */\n+\t\t\tfor (size_t i = 0; i < needle_len; i++)\n+\t\t\t\tif (needle[i] == '\\\\')\n+\t\t\t\t\tneedle[i] = '/';\n+\t\t\tneed_bs_to_fs = 0;\n+\t\t} else {\n+\t\t\tneed_bs_to_fs = 1;\n+\t\t}\n+\n+\t\t/* \n+\t\t * prefix_len == 0 if the compiler gives paths relative\n+\t\t * to the root of the working tree.  Otherwise, we want\n+\t\t * to see that we did find the needle[] at a directory\n+\t\t * boundary.\n+\t\t */\n+\t\tif (fspathcmp(needle, prefix + prefix_len) ||\n+\t\t    (prefix_len &&\n+\t\t     prefix[prefix_len - 1] != '/' &&\n+\t\t     prefix[prefix_len - 1] != '\\\\'))\n \t\t\tdie(\"unexpected suffix of '%s'\", prefix);\n \n-\t\t/* let it end in a directory separator */\n-\t\tprefix_len = len - needle_len + 1;\n \t}\n \n+\t/* \n+\t * If our compiler gives relative paths and we do not need\n+\t * to munge directory separator, we can return location as-is.\n+\t */\n+\tif (!prefix_len && !need_bs_to_fs)\n+\t\treturn location;\n+\n \t/* Does it not start with the expected prefix? */\n \tif (fspathncmp(location, prefix, prefix_len))\n \t\treturn location;\n \n \tstrlcpy(buf, location + prefix_len, sizeof(buf));\n \t/* convert backslashes to forward slashes */\n-\tfor (p = buf; *p; p++)\n-\t\tif (*p == '\\\\')\n-\t\t\t*p = '/';\n-\n+\tif (need_bs_to_fs) {\n+\t\tfor (p = buf; *p; p++)\n+\t\t\tif (*p == '\\\\')\n+\t\t\t\t*p = '/';\n+\t}\n \treturn buf;\n }\n-#endif\n \n static void msg_with_prefix(const char *prefix, const char *format, va_list ap)\n {\n"},{"id":"488381","messageId":"002a01da5c94$a1bc5340$e534f9c0$@nexbridge.com","threadId":"60895","inReplyTo":"xmqqbk8nbvqy.fsf@gitster.g","subject":"RE: [BUG] git 2.44.0-rc0 t0080.1 Breaks on NonStop x86 and ia64","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2024-02-11T02:47:14Z","receivedAt":"2024-02-11T02:47:23Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On Saturday, February 10, 2024 9:06 PM, Junio C Hamano wrote:\n><rsbecker@nexbridge.com> writes:\n>\n>> The diff appears to have failed because of an assumption of how paths\n>> are resolved during compilation. The assumption is that files remain\n>> partially qualified, which is not the case in all C compilers. This is\n>> c99. My experience with gcc is that it qualifies names differently\n>> than other compilers.\n>\n>I just found this bit of gem in t/unit-tests/test-lib.c.  I guess Visual C\nfalls into the\n>same category as yours, while GCC and Clang are from different camps?\n>\n>The easiest way forward may be to build on top of it, perhaps like so, to\ngeneralize\n>the make_relative() to cover your case, too?\n>\n> t/unit-tests/test-lib.c | 63\n+++++++++++++++++++++++++++++++++++++---------\n>---\n> 1 file changed, 48 insertions(+), 15 deletions(-)\n>\n>diff --git c/t/unit-tests/test-lib.c w/t/unit-tests/test-lib.c index\n>7bf9dfdb95..69dbe1bbc7 100644\n>--- c/t/unit-tests/test-lib.c\n>+++ w/t/unit-tests/test-lib.c\n>@@ -21,45 +21,78 @@ static struct {\n> \t.result = RESULT_NONE,\n> };\n>\n>-#ifndef _MSC_VER\n>-#define make_relative(location) location -#else\n>+#include \"dir.h\"\n> /*\n>  * Visual C interpolates the absolute Windows path for `__FILE__`,\n>  * but we want to see relative paths, as verified by t0080.\n>+ * There are other compilers that do the same, and are not for\n>+ * Windows.\n>  */\n>-#include \"dir.h\"\n>-\n> static const char *make_relative(const char *location)  {\n> \tstatic char prefix[] = __FILE__, buf[PATH_MAX], *p;\n> \tstatic size_t prefix_len;\n>+\tstatic int need_bs_to_fs = -1;\n>\n>-\tif (!prefix_len) {\n>+\t/* one-time preparation */\n>+\tif (need_bs_to_fs < 0) {\n> \t\tsize_t len = strlen(prefix);\n>-\t\tconst char *needle = \"\\\\t\\\\unit-tests\\\\test-lib.c\";\n>+\t\tchar needle[] = \"t\\\\unit-tests\\\\test-lib.c\";\n> \t\tsize_t needle_len = strlen(needle);\n>\n>-\t\tif (len < needle_len || strcmp(needle, prefix + len -\nneedle_len))\n>+\t\tif (len < needle_len)\n>+\t\t\tdie(\"unexpected prefix '%s'\", prefix);\n>+\n>+\t\t/*\n>+\t\t * The path could be relative (t/unit-tests/test-lib.c)\n>+\t\t * or full (/home/user/git/t/unit-tests/test-lib.c).\n>+\t\t * Check the slash between \"t\" and \"unit-tests\".\n>+\t\t */\n>+\t\tprefix_len = len - needle_len;\n>+\t\tif (prefix[prefix_len + 1] == '/') {\n>+\t\t\t/* Oh, we're not Windows */\n>+\t\t\tfor (size_t i = 0; i < needle_len; i++)\n>+\t\t\t\tif (needle[i] == '\\\\')\n>+\t\t\t\t\tneedle[i] = '/';\n>+\t\t\tneed_bs_to_fs = 0;\n>+\t\t} else {\n>+\t\t\tneed_bs_to_fs = 1;\n>+\t\t}\n>+\n>+\t\t/*\n>+\t\t * prefix_len == 0 if the compiler gives paths relative\n>+\t\t * to the root of the working tree.  Otherwise, we want\n>+\t\t * to see that we did find the needle[] at a directory\n>+\t\t * boundary.\n>+\t\t */\n>+\t\tif (fspathcmp(needle, prefix + prefix_len) ||\n>+\t\t    (prefix_len &&\n>+\t\t     prefix[prefix_len - 1] != '/' &&\n>+\t\t     prefix[prefix_len - 1] != '\\\\'))\n> \t\t\tdie(\"unexpected suffix of '%s'\", prefix);\n>\n>-\t\t/* let it end in a directory separator */\n>-\t\tprefix_len = len - needle_len + 1;\n> \t}\n>\n>+\t/*\n>+\t * If our compiler gives relative paths and we do not need\n>+\t * to munge directory separator, we can return location as-is.\n>+\t */\n>+\tif (!prefix_len && !need_bs_to_fs)\n>+\t\treturn location;\n>+\n> \t/* Does it not start with the expected prefix? */\n> \tif (fspathncmp(location, prefix, prefix_len))\n> \t\treturn location;\n>\n> \tstrlcpy(buf, location + prefix_len, sizeof(buf));\n> \t/* convert backslashes to forward slashes */\n>-\tfor (p = buf; *p; p++)\n>-\t\tif (*p == '\\\\')\n>-\t\t\t*p = '/';\n>-\n>+\tif (need_bs_to_fs) {\n>+\t\tfor (p = buf; *p; p++)\n>+\t\t\tif (*p == '\\\\')\n>+\t\t\t\t*p = '/';\n>+\t}\n> \treturn buf;\n> }\n>-#endif\n>\n> static void msg_with_prefix(const char *prefix, const char *format,\nva_list ap)  {\n\nThis looks like a good plan.\n\n--Randall\n\n"},{"id":"488446","messageId":"00fa01da5dcd$5b060150$111203f0$@nexbridge.com","threadId":"60895","inReplyTo":"002a01da5c94$a1bc5340$e534f9c0$@nexbridge.com","subject":"RE: [BUG] git 2.44.0-rc0 t0080.1 Breaks on NonStop x86 and ia64","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2024-02-12T16:05:47Z","receivedAt":"2024-02-12T16:05:56Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On Saturday, February 10, 2024 9:47 PM, Junio C Hamano wrote:\n>On Saturday, February 10, 2024 9:06 PM, Junio C Hamano wrote:\n>><rsbecker@nexbridge.com> writes:\n>>\n>>> The diff appears to have failed because of an assumption of how paths\n>>> are resolved during compilation. The assumption is that files remain\n>>> partially qualified, which is not the case in all C compilers. This\n>>> is c99. My experience with gcc is that it qualifies names differently\n>>> than other compilers.\n>>\n>>I just found this bit of gem in t/unit-tests/test-lib.c.  I guess\n>>Visual C\n>falls into the\n>>same category as yours, while GCC and Clang are from different camps?\n>>\n>>The easiest way forward may be to build on top of it, perhaps like so,\n>>to\n>generalize\n>>the make_relative() to cover your case, too?\n>>\n>> t/unit-tests/test-lib.c | 63\n>+++++++++++++++++++++++++++++++++++++---------\n>>---\n>> 1 file changed, 48 insertions(+), 15 deletions(-)\n>>\n>>diff --git c/t/unit-tests/test-lib.c w/t/unit-tests/test-lib.c index\n>>7bf9dfdb95..69dbe1bbc7 100644\n>>--- c/t/unit-tests/test-lib.c\n>>+++ w/t/unit-tests/test-lib.c\n>>@@ -21,45 +21,78 @@ static struct {\n>> \t.result = RESULT_NONE,\n>> };\n>>\n>>-#ifndef _MSC_VER\n>>-#define make_relative(location) location -#else\n>>+#include \"dir.h\"\n>> /*\n>>  * Visual C interpolates the absolute Windows path for `__FILE__`,\n>>  * but we want to see relative paths, as verified by t0080.\n>>+ * There are other compilers that do the same, and are not for\n>>+ * Windows.\n>>  */\n>>-#include \"dir.h\"\n>>-\n>> static const char *make_relative(const char *location)  {\n>> \tstatic char prefix[] = __FILE__, buf[PATH_MAX], *p;\n>> \tstatic size_t prefix_len;\n>>+\tstatic int need_bs_to_fs = -1;\n>>\n>>-\tif (!prefix_len) {\n>>+\t/* one-time preparation */\n>>+\tif (need_bs_to_fs < 0) {\n>> \t\tsize_t len = strlen(prefix);\n>>-\t\tconst char *needle = \"\\\\t\\\\unit-tests\\\\test-lib.c\";\n>>+\t\tchar needle[] = \"t\\\\unit-tests\\\\test-lib.c\";\n>> \t\tsize_t needle_len = strlen(needle);\n>>\n>>-\t\tif (len < needle_len || strcmp(needle, prefix + len -\n>needle_len))\n>>+\t\tif (len < needle_len)\n>>+\t\t\tdie(\"unexpected prefix '%s'\", prefix);\n>>+\n>>+\t\t/*\n>>+\t\t * The path could be relative (t/unit-tests/test-lib.c)\n>>+\t\t * or full (/home/user/git/t/unit-tests/test-lib.c).\n>>+\t\t * Check the slash between \"t\" and \"unit-tests\".\n>>+\t\t */\n>>+\t\tprefix_len = len - needle_len;\n>>+\t\tif (prefix[prefix_len + 1] == '/') {\n>>+\t\t\t/* Oh, we're not Windows */\n>>+\t\t\tfor (size_t i = 0; i < needle_len; i++)\n>>+\t\t\t\tif (needle[i] == '\\\\')\n>>+\t\t\t\t\tneedle[i] = '/';\n>>+\t\t\tneed_bs_to_fs = 0;\n>>+\t\t} else {\n>>+\t\t\tneed_bs_to_fs = 1;\n>>+\t\t}\n>>+\n>>+\t\t/*\n>>+\t\t * prefix_len == 0 if the compiler gives paths relative\n>>+\t\t * to the root of the working tree.  Otherwise, we want\n>>+\t\t * to see that we did find the needle[] at a directory\n>>+\t\t * boundary.\n>>+\t\t */\n>>+\t\tif (fspathcmp(needle, prefix + prefix_len) ||\n>>+\t\t    (prefix_len &&\n>>+\t\t     prefix[prefix_len - 1] != '/' &&\n>>+\t\t     prefix[prefix_len - 1] != '\\\\'))\n>> \t\t\tdie(\"unexpected suffix of '%s'\", prefix);\n>>\n>>-\t\t/* let it end in a directory separator */\n>>-\t\tprefix_len = len - needle_len + 1;\n>> \t}\n>>\n>>+\t/*\n>>+\t * If our compiler gives relative paths and we do not need\n>>+\t * to munge directory separator, we can return location as-is.\n>>+\t */\n>>+\tif (!prefix_len && !need_bs_to_fs)\n>>+\t\treturn location;\n>>+\n>> \t/* Does it not start with the expected prefix? */\n>> \tif (fspathncmp(location, prefix, prefix_len))\n>> \t\treturn location;\n>>\n>> \tstrlcpy(buf, lnocation + prefix_len, sizeof(buf));\n>> \t/* convert backslashes to forward slashes */\n>>-\tfor (p = buf; *p; p++)\n>>-\t\tif (*p == '\\\\')\n>>-\t\t\t*p = '/';\n>>-\n>>+\tif (need_bs_to_fs) {\n>>+\t\tfor (p = buf; *p; p++)\n>>+\t\t\tif (*p == '\\\\')\n>>+\t\t\t\t*p = '/';\n>>+\t}\n>> \treturn buf;\n>> }\n>>-#endif\n>>\n>> static void msg_with_prefix(const char *prefix, const char *format,\n>va_list ap)  {\n>\n>This looks like a good plan.\n\nThis might be trivial, but I cannot tell. The #ifndef should be changed as\nfollows:\n\ndiff --git a/t/unit-tests/test-lib.c b/t/unit-tests/test-lib.c\nindex 7bf9dfdb95..2d1f6b7648 100644\n--- a/t/unit-tests/test-lib.c\n+++ b/t/unit-tests/test-lib.c\n@@ -21,7 +21,7 @@ static struct {\n        .result = RESULT_NONE,\n };\n\n-#ifndef _MSC_VER\n+#if !defined(_MSC_VER) && !defined(__TANDEM)\n #define make_relative(location) location\n #else\n /*\n\nHowever, if this goes beyond Windows and NonStop, which I suspect it does,\nwe could add a separate knob in config.mak.uname to pull this in. However,\nthis does not correct the problem. actual ends up with only:\n\nok 1 - passing test\nok 2 - passing test and assertion return 1\n\nwhich fails the test_cmp at the end of the test.\n\n\n"},{"id":"488451","messageId":"xmqqzfw57hw0.fsf@gitster.g","threadId":"60895","inReplyTo":"00fa01da5dcd$5b060150$111203f0$@nexbridge.com","subject":"Re: [BUG] git 2.44.0-rc0 t0080.1 Breaks on NonStop x86 and ia64","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-02-12T16:43:27Z","receivedAt":"2024-02-12T16:43:36Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"<rsbecker@nexbridge.com> writes:\n\n>>This looks like a good plan.\n>\n> This might be trivial, but I cannot tell. The #ifndef should be changed as\n> follows:\n\nhttps://lore.kernel.org/git/xmqqttmf9y46.fsf@gitster.g/\n\n"},{"id":"488459","messageId":"010601da5ddd$3dec41a0$b9c4c4e0$@nexbridge.com","threadId":"60895","inReplyTo":"xmqqzfw57hw0.fsf@gitster.g","subject":"RE: [BUG] git 2.44.0-rc0 t0080.1 Breaks on NonStop x86 and ia64","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2024-02-12T17:59:31Z","receivedAt":"2024-02-12T17:59:40Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On Monday, February 12, 2024 11:43 AM, Junio C Hamano wrote:\n><rsbecker@nexbridge.com> writes:\n>\n>>>This looks like a good plan.\n>>\n>> This might be trivial, but I cannot tell. The #ifndef should be changed\nas\n>> follows:\n>\n>https://lore.kernel.org/git/xmqqttmf9y46.fsf@gitster.g/\n\nI applied this fix but there is no improvement in the result from the last\nreport. actual just has two lines. expect looks reasonable. I still had to\nmodify the #ifndef.\n\nI have tried cherry-picking the change (no effect), building on master,\nnext... am lost.\n\n"},{"id":"488462","messageId":"xmqqil2t5wwk.fsf@gitster.g","threadId":"60895","inReplyTo":"010601da5ddd$3dec41a0$b9c4c4e0$@nexbridge.com","subject":"Re: [BUG] git 2.44.0-rc0 t0080.1 Breaks on NonStop x86 and ia64","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-02-12T19:02:03Z","receivedAt":"2024-02-12T19:02:09Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"<rsbecker@nexbridge.com> writes:\n\n> On Monday, February 12, 2024 11:43 AM, Junio C Hamano wrote:\n>><rsbecker@nexbridge.com> writes:\n>>\n>>>>This looks like a good plan.\n>>>\n>>> This might be trivial, but I cannot tell. The #ifndef should be changed\n> as\n>>> follows:\n>>\n>>https://lore.kernel.org/git/xmqqttmf9y46.fsf@gitster.g/\n>\n> I applied this fix but there is no improvement in the result from the last\n> report. actual just has two lines. expect looks reasonable. I still had to\n> modify the #ifndef.\n>\n> I have tried cherry-picking the change (no effect), building on master,\n> next... am lost.\n\nWe seem to be looking at something totally different.  The later\npatch in question (not the \"looks like a good plan\" outline) does\nnot have any #ifndef and applies the make_relative() logic\neverywhere.\n\nI would suspect that cherry-picking f6628636 (unit-tests: do show\nrelative file paths on non-Windows, too, 2024-02-11) would be the\nsimplest.\n\n--- >8 ---\nSubject: [PATCH] unit-tests: do show relative file paths on non-Windows, too\n\nThere are compilers other than Visual C that want to show absolute\npaths.  Generalize the helper introduced by a2c5e294 (unit-tests: do\nshow relative file paths, 2023-09-25) so that it can also work with\na path that uses slash as the directory separator, and becomes\nalmost no-op once one-time preparation finds out that we are using a\ncompiler that already gives relative paths.  Incidentally, this also\nshould do the right thing on Windows with a compiler that shows\nrelative paths but with backslash as the directory separator (if\nsuch a thing exists and is used to build git).\n\nReported-by: Randall S. Becker <rsbecker@nexbridge.com>\nHelped-by: Phillip Wood <phillip.wood@dunelm.org.uk>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/unit-tests/test-lib.c | 61 +++++++++++++++++++++++++++++++----------\n 1 file changed, 47 insertions(+), 14 deletions(-)\n\ndiff --git a/t/unit-tests/test-lib.c b/t/unit-tests/test-lib.c\nindex 7bf9dfdb95..66d6980ffb 100644\n--- a/t/unit-tests/test-lib.c\n+++ b/t/unit-tests/test-lib.c\n@@ -21,12 +21,11 @@ static struct {\n \t.result = RESULT_NONE,\n };\n \n-#ifndef _MSC_VER\n-#define make_relative(location) location\n-#else\n /*\n  * Visual C interpolates the absolute Windows path for `__FILE__`,\n  * but we want to see relative paths, as verified by t0080.\n+ * There are other compilers that do the same, and are not for\n+ * Windows.\n  */\n #include \"dir.h\"\n \n@@ -34,32 +33,66 @@ static const char *make_relative(const char *location)\n {\n \tstatic char prefix[] = __FILE__, buf[PATH_MAX], *p;\n \tstatic size_t prefix_len;\n+\tstatic int need_bs_to_fs = -1;\n \n-\tif (!prefix_len) {\n+\t/* one-time preparation */\n+\tif (need_bs_to_fs < 0) {\n \t\tsize_t len = strlen(prefix);\n-\t\tconst char *needle = \"\\\\t\\\\unit-tests\\\\test-lib.c\";\n+\t\tchar needle[] = \"t\\\\unit-tests\\\\test-lib.c\";\n \t\tsize_t needle_len = strlen(needle);\n \n-\t\tif (len < needle_len || strcmp(needle, prefix + len - needle_len))\n-\t\t\tdie(\"unexpected suffix of '%s'\", prefix);\n+\t\tif (len < needle_len)\n+\t\t\tdie(\"unexpected prefix '%s'\", prefix);\n+\n+\t\t/*\n+\t\t * The path could be relative (t/unit-tests/test-lib.c)\n+\t\t * or full (/home/user/git/t/unit-tests/test-lib.c).\n+\t\t * Check the slash between \"t\" and \"unit-tests\".\n+\t\t */\n+\t\tprefix_len = len - needle_len;\n+\t\tif (prefix[prefix_len + 1] == '/') {\n+\t\t\t/* Oh, we're not Windows */\n+\t\t\tfor (size_t i = 0; i < needle_len; i++)\n+\t\t\t\tif (needle[i] == '\\\\')\n+\t\t\t\t\tneedle[i] = '/';\n+\t\t\tneed_bs_to_fs = 0;\n+\t\t} else {\n+\t\t\tneed_bs_to_fs = 1;\n+\t\t}\n \n-\t\t/* let it end in a directory separator */\n-\t\tprefix_len = len - needle_len + 1;\n+\t\t/*\n+\t\t * prefix_len == 0 if the compiler gives paths relative\n+\t\t * to the root of the working tree.  Otherwise, we want\n+\t\t * to see that we did find the needle[] at a directory\n+\t\t * boundary.  Again we rely on that needle[] begins with\n+\t\t * \"t\" followed by the directory separator.\n+\t\t */\n+\t\tif (fspathcmp(needle, prefix + prefix_len) ||\n+\t\t    (prefix_len && prefix[prefix_len - 1] != needle[1]))\n+\t\t\tdie(\"unexpected suffix of '%s'\", prefix);\n \t}\n \n-\t/* Does it not start with the expected prefix? */\n-\tif (fspathncmp(location, prefix, prefix_len))\n+\t/*\n+\t * Does it not start with the expected prefix?\n+\t * Return it as-is without making it worse.\n+\t */\n+\tif (prefix_len && fspathncmp(location, prefix, prefix_len))\n \t\treturn location;\n \n-\tstrlcpy(buf, location + prefix_len, sizeof(buf));\n+\t/*\n+\t * If we do not need to munge directory separator, we can return\n+\t * the substring at the tail of the location.\n+\t */\n+\tif (!need_bs_to_fs)\n+\t\treturn location + prefix_len;\n+\n \t/* convert backslashes to forward slashes */\n+\tstrlcpy(buf, location + prefix_len, sizeof(buf));\n \tfor (p = buf; *p; p++)\n \t\tif (*p == '\\\\')\n \t\t\t*p = '/';\n-\n \treturn buf;\n }\n-#endif\n \n static void msg_with_prefix(const char *prefix, const char *format, va_list ap)\n {\n-- \n2.44.0-rc0\n\n\n"},{"id":"488464","messageId":"010d01da5de9$6c40a530$44c1ef90$@nexbridge.com","threadId":"60895","inReplyTo":"xmqqil2t5wwk.fsf@gitster.g","subject":"RE: [BUG] git 2.44.0-rc0 t0080.1 Breaks on NonStop x86 and ia64","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2024-02-12T19:26:42Z","receivedAt":"2024-02-12T19:26:54Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On Monday, February 12, 2024 2:02 PM, Junio C Hamano wrote:\n><rsbecker@nexbridge.com> writes:\n>\n>> On Monday, February 12, 2024 11:43 AM, Junio C Hamano wrote:\n>>><rsbecker@nexbridge.com> writes:\n>>>\n>>>>>This looks like a good plan.\n>>>>\n>>>> This might be trivial, but I cannot tell. The #ifndef should be\n>>>> changed\n>> as\n>>>> follows:\n>>>\n>>>https://lore.kernel.org/git/xmqqttmf9y46.fsf@gitster.g/\n>>\n>> I applied this fix but there is no improvement in the result from the\n>> last report. actual just has two lines. expect looks reasonable. I\n>> still had to modify the #ifndef.\n>>\n>> I have tried cherry-picking the change (no effect), building on\n>> master, next... am lost.\n>\n>We seem to be looking at something totally different.  The later patch in\nquestion\n>(not the \"looks like a good plan\" outline) does not have any #ifndef and\napplies the\n>make_relative() logic everywhere.\n>\n>I would suspect that cherry-picking f6628636 (unit-tests: do show relative\nfile\n>paths on non-Windows, too, 2024-02-11) would be the simplest.\n\nWould you mind pushing that commit to github, please? It is not in the\ncurrent history.\n\n"}]}