t/helper/test-chmtime: update mingw to support chmtime on directories

The mingw_utime implementation in mingw.c does not support directories. This means that "test-tool chmtime" fails on Windows when targeting directories. This has previously been noted and sidestepped temporarily by Jeff Hostetler, in "t/helper/test-chmtime: skip directories on Windows" in the "Builtin FSMonitor Part 2" work, but not yet fixed. It would make sense to backdate file and folder changes in untracked cache tests, to avoid needing to insert explicit delays/pauses in the tests. Add support for directory date manipulation in mingw_utime by replacing the file-oriented _wopen() call with the directory-supporting CreateFileW() windows API explicitly. Signed-off-by: Tao Klerks <tao@klerks.biz> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Tao Klerks committed Mar 2, 2022 at 06:05 UTC 090a3085bc9f2101b69b3c8940278fb7c22f02c9
1 file changed +19 -4
compat/mingw.c
+19 -4
@@ -961,9 +961,11 @@ static inline void time_t_to_filetime(time_t t, FILETIME *ft)
961 int mingw_utime (const char *file_name, const struct utimbuf *times)
962 {
963 FILETIME mft, aft;
964 - int fh, rc;
964 + int rc;
965 DWORD attrs;
966 wchar_t wfilename[MAX_PATH];
967 + HANDLE osfilehandle;
968 +
969 if (xutftowcs_path(wfilename, file_name) < 0)
970 return -1;
971
@@ -975,7 +977,17 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
977 SetFileAttributesW(wfilename, attrs & ~FILE_ATTRIBUTE_READONLY);
978 }
979
978 - if ((fh = _wopen(wfilename, O_RDWR | O_BINARY)) < 0) {
980 + osfilehandle = CreateFileW(wfilename,
981 + FILE_WRITE_ATTRIBUTES,
982 + 0 /*FileShare.None*/,
983 + NULL,
984 + OPEN_EXISTING,
985 + (attrs != INVALID_FILE_ATTRIBUTES &&
986 + (attrs & FILE_ATTRIBUTE_DIRECTORY)) ?
987 + FILE_FLAG_BACKUP_SEMANTICS : 0,
988 + NULL);
989 + if (osfilehandle == INVALID_HANDLE_VALUE) {
990 + errno = err_win_to_posix(GetLastError());
991 rc = -1;
992 goto revert_attrs;
993 }
@@ -987,12 +999,15 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
999 GetSystemTimeAsFileTime(&mft);
1000 aft = mft;
1001 }
990 - if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
1002 +
1003 + if (!SetFileTime(osfilehandle, NULL, &aft, &mft)) {
1004 errno = EINVAL;
1005 rc = -1;
1006 } else
1007 rc = 0;
995 - close(fh);
1008 +
1009 + if (osfilehandle != INVALID_HANDLE_VALUE)
1010 + CloseHandle(osfilehandle);
1011
1012 revert_attrs:
1013 if (attrs != INVALID_FILE_ATTRIBUTES &&