From 8a08d14d0537aa46f89c205c0f33130d9fbff648 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Wed, 17 Dec 2025 14:08:49 +0000 Subject: [PATCH] mingw: allow `mingw_chdir()` to change to symlink-resolved directories If symlinks are enabled, resolve all symlinks when changing directories, as required by POSIX. Note: Git's `real_path()` function bases its link resolution algorithm on this property of `chdir()`. Unfortunately, the current directory on Windows is limited to only MAX_PATH (260) characters. Therefore using symlinks and long paths in combination may be problematic. Signed-off-by: Karsten Blees Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- compat/mingw.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/compat/mingw.c b/compat/mingw.c index 55f0bb478e..5d2a8c247c 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -866,9 +866,27 @@ int mingw_access(const char *filename, int mode) int mingw_chdir(const char *dirname) { wchar_t wdirname[MAX_PATH]; + if (xutftowcs_path(wdirname, dirname) < 0) return -1; - return _wchdir(wdirname); + + if (has_symlinks) { + HANDLE hnd = CreateFileW(wdirname, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hnd == INVALID_HANDLE_VALUE) { + errno = err_win_to_posix(GetLastError()); + return -1; + } + if (!GetFinalPathNameByHandleW(hnd, wdirname, ARRAY_SIZE(wdirname), 0)) { + errno = err_win_to_posix(GetLastError()); + CloseHandle(hnd); + return -1; + } + CloseHandle(hnd); + } + + return _wchdir(normalize_ntpath(wdirname)); } int mingw_chmod(const char *filename, int mode)