From bb1f6238e7e3470bce038269274067ef96f0e98c Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Tue, 6 Oct 2026 05:58:39 +0200 Subject: [PATCH] fix(test-impact): report a Windows case collision as a collision A tree with a file `A` and a directory `a` cannot be materialized on a case-insensitive volume. On Windows, creating the file over the existing directory answers ERROR_ACCESS_DENIED, not ERROR_FILE_EXISTS, so the pinned tree reported an I/O failure where tree_d_native_collision_and_exact_spelling expects CBM_PINNED_TREE_COLLISION (observed: error 5 on the create). An access-denied create whose attempted name is present is now the same collision; one whose name is absent stays an I/O failure. Signed-off-by: Martin Vogel --- src/mcp/test_impact_tree_windows.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/mcp/test_impact_tree_windows.c b/src/mcp/test_impact_tree_windows.c index 617aa42bb..ba0c089a2 100644 --- a/src/mcp/test_impact_tree_windows.c +++ b/src/mcp/test_impact_tree_windows.c @@ -2,7 +2,13 @@ #ifdef _WIN32 bool tpt_win_error(tpt_context *c, DWORD e, bool creating) { - if (creating && (e == ERROR_ALREADY_EXISTS || e == ERROR_FILE_EXISTS)) + /* Creating a file over a directory of the same (case-folded) name answers + * ERROR_ACCESS_DENIED rather than "exists"; with the attempted name + * present it is the same collision. Both create sites leave that name in + * wide_path. */ + bool present = creating && e == ERROR_ACCESS_DENIED && + GetFileAttributesW(c->tree->wide_path) != INVALID_FILE_ATTRIBUTES; + if (creating && (e == ERROR_ALREADY_EXISTS || e == ERROR_FILE_EXISTS || present)) return tpt_fail(c, CBM_PINNED_TREE_COLLISION, "exclusive native name already exists"); if (e == ERROR_NOT_ENOUGH_MEMORY || e == ERROR_OUTOFMEMORY) return tpt_fail(c, CBM_PINNED_TREE_OOM, "native allocation failed");