@@ -317,6 +317,12 @@ enum _FileOperations {
317317 try path. withNTPathRepresentation {
318318 var faAttributes : WIN32_FILE_ATTRIBUTE_DATA = . init( )
319319 guard GetFileAttributesExW ( $0, GetFileExInfoStandard, & faAttributes) else {
320+ // NOTE: in the case that the 'stat' failed, we want to ensure
321+ // that we query if the item should be removed. If the item
322+ // should not be removed, we can continue, else we should check
323+ // if we should proceed after the error.
324+ guard filemanager? . _shouldRemoveItemAtPath ( path) ?? true else { return }
325+
320326 let error = CocoaError . removeFileError ( GetLastError ( ) , path)
321327 guard ( filemanager? . _shouldProceedAfter ( error: error, removingItemAtPath: path) ?? false ) else {
322328 throw error
@@ -342,47 +348,55 @@ enum _FileOperations {
342348 return
343349 }
344350 }
345- }
346351
347- var stack = [ path]
348- while let directory = stack. popLast ( ) {
349- guard filemanager? . _shouldRemoveItemAtPath ( directory) ?? true else { continue }
350- try directory. withNTPathRepresentation {
351- if RemoveDirectoryW ( $0) { return }
352- let dwError : DWORD = GetLastError ( )
353- guard dwError == ERROR_DIR_NOT_EMPTY else {
354- let error = CocoaError . removeFileError ( dwError, directory)
355- guard ( filemanager? . _shouldProceedAfter ( error: error, removingItemAtPath: directory) ?? false ) else {
356- throw error
352+ var stack = [ ( path, false ) ]
353+ while let ( directory, checked) = stack. popLast ( ) {
354+ try directory. withNTPathRepresentation {
355+ let ntpath = String ( decodingCString: $0, as: UTF16 . self)
356+
357+ guard checked || filemanager? . _shouldRemoveItemAtPath ( ntpath) ?? true else { return }
358+
359+ if RemoveDirectoryW ( $0) { return }
360+ var dwError : DWORD = GetLastError ( )
361+ guard dwError == ERROR_DIR_NOT_EMPTY else {
362+ let error = CocoaError . removeFileError ( dwError, directory)
363+ guard ( filemanager? . _shouldProceedAfter ( error: error, removingItemAtPath: ntpath) ?? false ) else {
364+ throw error
365+ }
366+ return
357367 }
358- return
359- }
360- stack. append ( directory)
368+ stack. append ( ( directory, true ) )
361369
362- for entry in _Win32DirectoryContentsSequence ( path: directory, appendSlashForDirectory: false , prefix: [ directory] ) {
363- try entry. fileNameWithPrefix. withNTPathRepresentation {
364- if entry. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY,
365- entry. dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT != FILE_ATTRIBUTE_REPARSE_POINT {
366- stack. append ( entry. fileNameWithPrefix)
367- } else {
368- if entry. dwFileAttributes & FILE_ATTRIBUTE_READONLY == FILE_ATTRIBUTE_READONLY {
369- guard SetFileAttributesW ( $0, entry. dwFileAttributes & ~ FILE_ATTRIBUTE_READONLY) else {
370- throw CocoaError . removeFileError ( GetLastError ( ) , path)
370+ for entry in _Win32DirectoryContentsSequence ( path: directory, appendSlashForDirectory: false , prefix: [ directory] ) {
371+ try entry. fileNameWithPrefix. withNTPathRepresentation {
372+ let ntpath = String ( decodingCString: $0, as: UTF16 . self)
373+
374+ if entry. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY,
375+ entry. dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT != FILE_ATTRIBUTE_REPARSE_POINT {
376+ if filemanager? . _shouldRemoveItemAtPath ( ntpath) ?? true {
377+ stack. append ( ( ntpath, true ) )
371378 }
372- }
373- guard filemanager? . _shouldRemoveItemAtPath ( entry. fileNameWithPrefix) ?? true else { return }
374- if entry. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY {
375- if !RemoveDirectoryW( $0) {
376- let error = CocoaError . removeFileError ( GetLastError ( ) , entry. fileName)
377- guard ( filemanager? . _shouldProceedAfter ( error: error, removingItemAtPath: entry. fileNameWithPrefix) ?? false ) else {
378- throw error
379+ } else {
380+ if entry. dwFileAttributes & FILE_ATTRIBUTE_READONLY == FILE_ATTRIBUTE_READONLY {
381+ guard SetFileAttributesW ( $0, entry. dwFileAttributes & ~ FILE_ATTRIBUTE_READONLY) else {
382+ throw CocoaError . removeFileError ( GetLastError ( ) , ntpath)
379383 }
380384 }
381- } else {
382- if !DeleteFileW( $0) {
383- let error = CocoaError . removeFileError ( GetLastError ( ) , entry. fileName)
384- guard ( filemanager? . _shouldProceedAfter ( error: error, removingItemAtPath: entry. fileNameWithPrefix) ?? false ) else {
385- throw error
385+ if entry. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY {
386+ guard filemanager? . _shouldRemoveItemAtPath ( ntpath) ?? true else { return }
387+ if !RemoveDirectoryW( $0) {
388+ let error = CocoaError . removeFileError ( GetLastError ( ) , entry. fileName)
389+ guard ( filemanager? . _shouldProceedAfter ( error: error, removingItemAtPath: entry. fileNameWithPrefix) ?? false ) else {
390+ throw error
391+ }
392+ }
393+ } else {
394+ guard filemanager? . _shouldRemoveItemAtPath ( ntpath) ?? true else { return }
395+ if !DeleteFileW( $0) {
396+ let error = CocoaError . removeFileError ( GetLastError ( ) , entry. fileName)
397+ guard ( filemanager? . _shouldProceedAfter ( error: error, removingItemAtPath: entry. fileNameWithPrefix) ?? false ) else {
398+ throw error
399+ }
386400 }
387401 }
388402 }
0 commit comments