diff --git a/compat/mingw.c b/compat/mingw.c index a94fc63073c3ce..35847a0da8c649 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -456,10 +456,6 @@ FILE *mingw_fopen (const char *filename, const char *otype) int hide = 0; FILE *file; wchar_t wfilename[MAX_PATH], wotype[4]; - - if (is_dos_device_name(filename)) - return fopen(filename, otype); - if (hide_dotfiles == HIDE_DOTFILES_TRUE && basename((char*)filename)[0] == '.') hide = access(filename, F_OK); @@ -474,16 +470,11 @@ FILE *mingw_fopen (const char *filename, const char *otype) return file; } -#undef freopen FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream) { int hide = 0; FILE *file; wchar_t wfilename[MAX_PATH], wotype[4]; - - if (is_dos_device_name(filename)) - return freopen(filename, otype, stream); - if (hide_dotfiles == HIDE_DOTFILES_TRUE && basename((char*)filename)[0] == '.') hide = access(filename, F_OK); @@ -2148,6 +2139,30 @@ int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen) return wpos; } +int xutftowcs_canonical_path(wchar_t *wcs, const char *utf) +{ + wchar_t tmp[MAX_PATH]; + int result; + result = xutftowcsn(tmp, utf, MAX_PATH, -1); + if (result < 0 && errno == ERANGE) { + errno = ENAMETOOLONG; + } + else if (is_dos_device_name(utf)) + wcscpy(wcs, tmp); + else { + wchar_t tmp2[MAX_PATH*2]; + result = GetFullPathNameW(tmp, MAX_PATH*2, tmp2, NULL); + if (result && result < MAX_PATH) { + wcsncpy(wcs, tmp2, MAX_PATH-1); + wcs[MAX_PATH-1] = 0; + } else { + result = -1; + errno = ENAMETOOLONG; + } + } + return result; +} + int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen) { if (!wcs || !utf || utflen < 1) { diff --git a/compat/mingw.h b/compat/mingw.h index 4b3df96d619fd5..741fa56bb4988b 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -455,29 +455,7 @@ static inline int xutftowcs_path(wchar_t *wcs, const char *utf) * fails with ENAMETOOLONG if input string is too long. This version * also canonicalizes the path before returning. */ -static inline int xutftowcs_canonical_path(wchar_t *wcs, const char *utf) -{ - wchar_t tmp[SHRT_MAX]; - int result; - result = xutftowcsn(tmp, utf, SHRT_MAX, -1); - if (result < 0 && errno == ERANGE) - errno = ENAMETOOLONG; - else if (wcsncmp(tmp, L"nul", 4) == 0 ) - wcsncpy(wcs, tmp, 4); - else { - wchar_t tmp2[SHRT_MAX]; - GetFullPathNameW(tmp, SHRT_MAX, tmp2, NULL); - if (wcslen(tmp2) < MAX_PATH) - wcsncpy(wcs, tmp2, MAX_PATH - 1); - else { - result = -1; - errno = ENAMETOOLONG; - } - } - if (result != -1) - result = wcslen(wcs); - return result; -} +int xutftowcs_canonical_path(wchar_t *wcs, const char *utf); /** * Converts UTF-16LE encoded string to UTF-8. diff --git a/t/t7410-submodule-long-path.sh b/t/t7410-submodule-long-path.sh new file mode 100644 index 00000000000000..86641d99bfbac6 --- /dev/null +++ b/t/t7410-submodule-long-path.sh @@ -0,0 +1,101 @@ +#!/bin/sh +# +# Copyright (c) 2013 Doug Kelly +# + +test_description='Test submodules with a path near PATH_MAX + +This test verifies that "git submodule" initialization, update and clones work, including with recursive submodules and paths approaching PATH_MAX (260 characters on Windows) +' + +TEST_NO_CREATE_REPO=1 +. ./test-lib.sh + +longpath="" +for (( i=0; i<4; i++ )); do + longpath="0123456789abcdefghijklmnopqrstuvwxyz$longpath" +done +# Pick a substring maximum of 90 characters +# This should be good, since we'll add on a lot for temp directories +export longpath=${longpath:0:90} + +test_expect_success 'submodule with a long path' ' + git init --bare remote && + test_create_repo bundle1 && + ( + cd bundle1 && + test_commit "shoot" && + git rev-parse --verify HEAD >../expect + ) && + mkdir home && + ( + cd home && + git clone ../remote test && + cd test && + git submodule add ../bundle1 $longpath && + test_commit "sogood" && + ( + cd $longpath && + git rev-parse --verify HEAD >actual && + test_cmp ../../../expect actual + ) && + git push origin master + ) && + mkdir home2 && + ( + cd home2 && + git clone ../remote test && + cd test && + git checkout master && + git submodule update --init && + ( + cd $longpath && + git rev-parse --verify HEAD >actual && + test_cmp ../../../expect actual + ) + ) +' + +test_expect_success 'recursive submodule with a long path' ' + git init --bare super && + test_create_repo child && + ( + cd child && + test_commit "shoot" && + git rev-parse --verify HEAD >../expect + ) && + test_create_repo parent && + ( + cd parent && + git submodule add ../child $longpath && + test_commit "aim" + ) && + mkdir home3 && + ( + cd home3 && + git clone ../super test && + cd test && + git submodule add ../parent foo && + git submodule update --init --recursive + test_commit "sogood" && + ( + cd foo/$longpath && + git rev-parse --verify HEAD >actual && + test_cmp ../../../../expect actual + ) && + git push origin master + ) && + mkdir home4 && + ( + cd home4 && + git clone ../super test --recursive && + ( + cd test/foo/$longpath && + git rev-parse --verify HEAD >actual && + test_cmp ../../../../expect actual + ) + ) +' +unset longpath + +test_done