From d097c5a55c890b258b8c11d10ea6d2485938d4f2 Mon Sep 17 00:00:00 2001 From: Alexander Miller Date: Sat, 6 Apr 2024 22:30:03 +0200 Subject: [PATCH] Make sorting by basename fully deterministic BasenameCompare() completely ignored leading directories. While this is fine with respect to the zip files trrntzip creates, the order of printed messages can differ when directory entries get removed or re-zipping fails because of name clashes. Compare the full paths of entries in case the basenames compare equal to always ensure the same sort order and thus deterministic output. This should fix the flaky directories-2-d.test, so remove it from XFAIL_TESTS on WIN32. --- regress/CMakeLists.txt | 1 - src/util.c | 10 ++++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/regress/CMakeLists.txt b/regress/CMakeLists.txt index 5b94eb7..07b35c6 100644 --- a/regress/CMakeLists.txt +++ b/regress/CMakeLists.txt @@ -4,7 +4,6 @@ if(WIN32) set(XFAIL_TESTS ${XFAIL_TESTS} cli-q.test cli-s.test - directories-2-d.test recurse.test recursive.test ) diff --git a/src/util.c b/src/util.c index 47fcf67..368bd84 100644 --- a/src/util.c +++ b/src/util.c @@ -48,13 +48,19 @@ int StringCompare(const void *str1, const void *str2) { return CanonicalCmp(p1, p2); } -// No tie-breaker for leading dirs required, names must be unique int BasenameCompare(const void *str1, const void *str2) { const char *p1 = *(const char **)str1; const char *p2 = *(const char **)str2; const char *b1 = strrchr(p1, '/'); const char *b2 = strrchr(p2, '/'); - return CanonicalCmp(b1 ? b1 + 1 : p1, b2 ? b2 + 1 : p2); + int res = CanonicalCmp(b1 ? b1 + 1 : p1, b2 ? b2 + 1 : p2); + + // Tie-breaker ensures deterministic output. (It isn't needed for correct + // operation since names of added members must be unique.) + if (!res && b1 && b2) + res = CanonicalCmp(p1, p2); + + return res; } int EndsWithCaseInsensitive(const char *str, const char *tail) {