3030
3131#define HCAST (type , handle ) ((type)(intptr_t)handle)
3232
33- static const int delay [] = { 0 , 1 , 10 , 20 , 40 };
34-
3533void open_in_gdb (void )
3634{
3735 static struct child_process cp = CHILD_PROCESS_INIT ;
@@ -207,15 +205,12 @@ static int read_yes_no_answer(void)
207205 return -1 ;
208206}
209207
210- static int ask_yes_no_if_possible (const char * format , ... )
208+ static int ask_yes_no_if_possible (const char * format , va_list args )
211209{
212210 char question [4096 ];
213211 const char * retry_hook ;
214- va_list args ;
215212
216- va_start (args , format );
217213 vsnprintf (question , sizeof (question ), format , args );
218- va_end (args );
219214
220215 retry_hook = mingw_getenv ("GIT_ASK_YESNO" );
221216 if (retry_hook ) {
@@ -240,6 +235,31 @@ static int ask_yes_no_if_possible(const char *format, ...)
240235 }
241236}
242237
238+ static int retry_ask_yes_no (int * tries , const char * format , ...)
239+ {
240+ static const int delay [] = { 0 , 1 , 10 , 20 , 40 };
241+ va_list args ;
242+ int result , saved_errno = errno ;
243+
244+ if ((* tries ) < ARRAY_SIZE (delay )) {
245+ /*
246+ * We assume that some other process had the file open at the wrong
247+ * moment and retry. In order to give the other process a higher
248+ * chance to complete its operation, we give up our time slice now.
249+ * If we have to retry again, we do sleep a bit.
250+ */
251+ Sleep (delay [* tries ]);
252+ (* tries )++ ;
253+ return 1 ;
254+ }
255+
256+ va_start (args , format );
257+ result = ask_yes_no_if_possible (format , args );
258+ va_end (args );
259+ errno = saved_errno ;
260+ return result ;
261+ }
262+
243263/* Windows only */
244264enum hide_dotfiles_type {
245265 HIDE_DOTFILES_FALSE = 0 ,
@@ -332,37 +352,27 @@ static wchar_t *normalize_ntpath(wchar_t *wbuf)
332352
333353int mingw_unlink (const char * pathname , int handle_in_use_error )
334354{
335- int ret , tries = 0 ;
355+ int tries = 0 ;
336356 wchar_t wpathname [MAX_LONG_PATH ];
337357 if (xutftowcs_long_path (wpathname , pathname ) < 0 )
338358 return -1 ;
339359
340360 if (DeleteFileW (wpathname ))
341361 return 0 ;
342362
343- /* read-only files cannot be removed */
344- _wchmod (wpathname , 0666 );
345- while ((ret = _wunlink (wpathname )) == -1 && tries < ARRAY_SIZE (delay )) {
363+ do {
364+ /* read-only files cannot be removed */
365+ _wchmod (wpathname , 0666 );
366+ if (!_wunlink (wpathname ))
367+ return 0 ;
346368 if (!is_file_in_use_error (GetLastError ()))
347369 break ;
348370 if (!handle_in_use_error )
349- return ret ;
371+ return -1 ;
350372
351- /*
352- * We assume that some other process had the source or
353- * destination file open at the wrong moment and retry.
354- * In order to give the other process a higher chance to
355- * complete its operation, we give up our time slice now.
356- * If we have to retry again, we do sleep a bit.
357- */
358- Sleep (delay [tries ]);
359- tries ++ ;
360- }
361- while (ret == -1 && is_file_in_use_error (GetLastError ()) &&
362- ask_yes_no_if_possible ("Unlink of file '%s' failed. "
363- "Should I try again?" , pathname ))
364- ret = _wunlink (wpathname );
365- return ret ;
373+ } while (retry_ask_yes_no (& tries , "Unlink of file '%s' failed. "
374+ "Should I try again?" , pathname ));
375+ return -1 ;
366376}
367377
368378static int is_dir_empty (const wchar_t * wpath )
@@ -389,7 +399,7 @@ static int is_dir_empty(const wchar_t *wpath)
389399
390400int mingw_rmdir (const char * pathname )
391401{
392- int ret , tries = 0 ;
402+ int tries = 0 ;
393403 wchar_t wpathname [MAX_LONG_PATH ];
394404 struct stat st ;
395405
@@ -415,7 +425,11 @@ int mingw_rmdir(const char *pathname)
415425 if (xutftowcs_long_path (wpathname , pathname ) < 0 )
416426 return -1 ;
417427
418- while ((ret = _wrmdir (wpathname )) == -1 && tries < ARRAY_SIZE (delay )) {
428+ do {
429+ if (!_wrmdir (wpathname )) {
430+ invalidate_lstat_cache ();
431+ return 0 ;
432+ }
419433 if (!is_file_in_use_error (GetLastError ()))
420434 errno = err_win_to_posix (GetLastError ());
421435 if (errno != EACCES )
@@ -424,23 +438,9 @@ int mingw_rmdir(const char *pathname)
424438 errno = ENOTEMPTY ;
425439 break ;
426440 }
427- /*
428- * We assume that some other process had the source or
429- * destination file open at the wrong moment and retry.
430- * In order to give the other process a higher chance to
431- * complete its operation, we give up our time slice now.
432- * If we have to retry again, we do sleep a bit.
433- */
434- Sleep (delay [tries ]);
435- tries ++ ;
436- }
437- while (ret == -1 && errno == EACCES && is_file_in_use_error (GetLastError ()) &&
438- ask_yes_no_if_possible ("Deletion of directory '%s' failed. "
439- "Should I try again?" , pathname ))
440- ret = _wrmdir (wpathname );
441- if (!ret )
442- invalidate_lstat_cache ();
443- return ret ;
441+ } while (retry_ask_yes_no (& tries , "Deletion of directory '%s' failed. "
442+ "Should I try again?" , pathname ));
443+ return -1 ;
444444}
445445
446446static inline int needs_hiding (const char * path )
@@ -2652,20 +2652,8 @@ int mingw_rename(const char *pold, const char *pnew)
26522652 SetFileAttributesW (wpnew , attrs );
26532653 }
26542654 }
2655- if (tries < ARRAY_SIZE (delay ) && gle == ERROR_ACCESS_DENIED ) {
2656- /*
2657- * We assume that some other process had the source or
2658- * destination file open at the wrong moment and retry.
2659- * In order to give the other process a higher chance to
2660- * complete its operation, we give up our time slice now.
2661- * If we have to retry again, we do sleep a bit.
2662- */
2663- Sleep (delay [tries ]);
2664- tries ++ ;
2665- goto repeat ;
2666- }
26672655 if (gle == ERROR_ACCESS_DENIED &&
2668- ask_yes_no_if_possible ( "Rename from '%s' to '%s' failed. "
2656+ retry_ask_yes_no ( & tries , "Rename from '%s' to '%s' failed. "
26692657 "Should I try again?" , pold , pnew ))
26702658 goto repeat ;
26712659
0 commit comments