2424
2525#define HCAST (type , handle ) ((type)(intptr_t)handle)
2626
27- static const int delay [] = { 0 , 1 , 10 , 20 , 40 };
28-
2927void open_in_gdb (void )
3028{
3129 static struct child_process cp = CHILD_PROCESS_INIT ;
@@ -202,15 +200,12 @@ static int read_yes_no_answer(void)
202200 return -1 ;
203201}
204202
205- static int ask_yes_no_if_possible (const char * format , ... )
203+ static int ask_yes_no_if_possible (const char * format , va_list args )
206204{
207205 char question [4096 ];
208206 const char * retry_hook ;
209- va_list args ;
210207
211- va_start (args , format );
212208 vsnprintf (question , sizeof (question ), format , args );
213- va_end (args );
214209
215210 retry_hook = mingw_getenv ("GIT_ASK_YESNO" );
216211 if (retry_hook ) {
@@ -235,6 +230,31 @@ static int ask_yes_no_if_possible(const char *format, ...)
235230 }
236231}
237232
233+ static int retry_ask_yes_no (int * tries , const char * format , ...)
234+ {
235+ static const int delay [] = { 0 , 1 , 10 , 20 , 40 };
236+ va_list args ;
237+ int result , saved_errno = errno ;
238+
239+ if ((* tries ) < ARRAY_SIZE (delay )) {
240+ /*
241+ * We assume that some other process had the file open at the wrong
242+ * moment and retry. In order to give the other process a higher
243+ * chance to complete its operation, we give up our time slice now.
244+ * If we have to retry again, we do sleep a bit.
245+ */
246+ Sleep (delay [* tries ]);
247+ (* tries )++ ;
248+ return 1 ;
249+ }
250+
251+ va_start (args , format );
252+ result = ask_yes_no_if_possible (format , args );
253+ va_end (args );
254+ errno = saved_errno ;
255+ return result ;
256+ }
257+
238258/* Windows only */
239259enum hide_dotfiles_type {
240260 HIDE_DOTFILES_FALSE = 0 ,
@@ -331,34 +351,24 @@ static wchar_t *normalize_ntpath(wchar_t *wbuf)
331351
332352int mingw_unlink (const char * pathname )
333353{
334- int ret , tries = 0 ;
354+ int tries = 0 ;
335355 wchar_t wpathname [MAX_LONG_PATH ];
336356 if (xutftowcs_long_path (wpathname , pathname ) < 0 )
337357 return -1 ;
338358
339359 if (DeleteFileW (wpathname ))
340360 return 0 ;
341361
342- /* read-only files cannot be removed */
343- _wchmod (wpathname , 0666 );
344- while ((ret = _wunlink (wpathname )) == -1 && tries < ARRAY_SIZE (delay )) {
362+ do {
363+ /* read-only files cannot be removed */
364+ _wchmod (wpathname , 0666 );
365+ if (!_wunlink (wpathname ))
366+ return 0 ;
345367 if (!is_file_in_use_error (GetLastError ()))
346368 break ;
347- /*
348- * We assume that some other process had the source or
349- * destination file open at the wrong moment and retry.
350- * In order to give the other process a higher chance to
351- * complete its operation, we give up our time slice now.
352- * If we have to retry again, we do sleep a bit.
353- */
354- Sleep (delay [tries ]);
355- tries ++ ;
356- }
357- while (ret == -1 && is_file_in_use_error (GetLastError ()) &&
358- ask_yes_no_if_possible ("Unlink of file '%s' failed. "
359- "Should I try again?" , pathname ))
360- ret = _wunlink (wpathname );
361- return ret ;
369+ } while (retry_ask_yes_no (& tries , "Unlink of file '%s' failed. "
370+ "Should I try again?" , pathname ));
371+ return -1 ;
362372}
363373
364374static int is_dir_empty (const wchar_t * wpath )
@@ -385,7 +395,7 @@ static int is_dir_empty(const wchar_t *wpath)
385395
386396int mingw_rmdir (const char * pathname )
387397{
388- int ret , tries = 0 ;
398+ int tries = 0 ;
389399 wchar_t wpathname [MAX_LONG_PATH ];
390400 struct stat st ;
391401
@@ -411,7 +421,11 @@ int mingw_rmdir(const char *pathname)
411421 if (xutftowcs_long_path (wpathname , pathname ) < 0 )
412422 return -1 ;
413423
414- while ((ret = _wrmdir (wpathname )) == -1 && tries < ARRAY_SIZE (delay )) {
424+ do {
425+ if (!_wrmdir (wpathname )) {
426+ invalidate_lstat_cache ();
427+ return 0 ;
428+ }
415429 if (!is_file_in_use_error (GetLastError ()))
416430 errno = err_win_to_posix (GetLastError ());
417431 if (errno != EACCES )
@@ -420,23 +434,9 @@ int mingw_rmdir(const char *pathname)
420434 errno = ENOTEMPTY ;
421435 break ;
422436 }
423- /*
424- * We assume that some other process had the source or
425- * destination file open at the wrong moment and retry.
426- * In order to give the other process a higher chance to
427- * complete its operation, we give up our time slice now.
428- * If we have to retry again, we do sleep a bit.
429- */
430- Sleep (delay [tries ]);
431- tries ++ ;
432- }
433- while (ret == -1 && errno == EACCES && is_file_in_use_error (GetLastError ()) &&
434- ask_yes_no_if_possible ("Deletion of directory '%s' failed. "
435- "Should I try again?" , pathname ))
436- ret = _wrmdir (wpathname );
437- if (!ret )
438- invalidate_lstat_cache ();
439- return ret ;
437+ } while (retry_ask_yes_no (& tries , "Deletion of directory '%s' failed. "
438+ "Should I try again?" , pathname ));
439+ return -1 ;
440440}
441441
442442static inline int needs_hiding (const char * path )
@@ -2440,20 +2440,8 @@ int mingw_rename(const char *pold, const char *pnew)
24402440 SetFileAttributesW (wpnew , attrs );
24412441 }
24422442 }
2443- if (tries < ARRAY_SIZE (delay ) && gle == ERROR_ACCESS_DENIED ) {
2444- /*
2445- * We assume that some other process had the source or
2446- * destination file open at the wrong moment and retry.
2447- * In order to give the other process a higher chance to
2448- * complete its operation, we give up our time slice now.
2449- * If we have to retry again, we do sleep a bit.
2450- */
2451- Sleep (delay [tries ]);
2452- tries ++ ;
2453- goto repeat ;
2454- }
24552443 if (gle == ERROR_ACCESS_DENIED &&
2456- ask_yes_no_if_possible ( "Rename from '%s' to '%s' failed. "
2444+ retry_ask_yes_no ( & tries , "Rename from '%s' to '%s' failed. "
24572445 "Should I try again?" , pold , pnew ))
24582446 goto repeat ;
24592447
0 commit comments