comparison mercurial/win32.py @ 21226:4898c37e03c0 stable

win32: backout 1a9ebc83a74c This change conflicted with TortoiseHg's use of QFileSystemWatcher. Files which were being monitored (for file-system events) were unable to be reliably updated using util.atomictempfile. Often the update would error out in the middle of the process leaving neither the old or the new file in place. My guess is that _kernel32.CreateFileA() is triggering an exception that is not handled correctly within unlink()
author Steve Borho <steve@borho.org>
date Sat, 03 May 2014 10:33:54 +0200
parents 07f9825865de
children a2285e2fc949
comparison
equal deleted inserted replaced
21219:cadad384c97c 21226:4898c37e03c0
23 _INVALID_HANDLE_VALUE = _HANDLE(-1).value 23 _INVALID_HANDLE_VALUE = _HANDLE(-1).value
24 24
25 # GetLastError 25 # GetLastError
26 _ERROR_SUCCESS = 0 26 _ERROR_SUCCESS = 0
27 _ERROR_NO_MORE_FILES = 18 27 _ERROR_NO_MORE_FILES = 18
28 _ERROR_SHARING_VIOLATION = 32
29 _ERROR_INVALID_PARAMETER = 87 28 _ERROR_INVALID_PARAMETER = 87
30 _ERROR_INSUFFICIENT_BUFFER = 122 29 _ERROR_INSUFFICIENT_BUFFER = 122
31 30
32 # WPARAM is defined as UINT_PTR (unsigned type) 31 # WPARAM is defined as UINT_PTR (unsigned type)
33 # LPARAM is defined as LONG_PTR (signed type) 32 # LPARAM is defined as LONG_PTR (signed type)
59 _FILE_SHARE_WRITE = 0x00000002 58 _FILE_SHARE_WRITE = 0x00000002
60 _FILE_SHARE_DELETE = 0x00000004 59 _FILE_SHARE_DELETE = 0x00000004
61 60
62 _OPEN_EXISTING = 3 61 _OPEN_EXISTING = 3
63 62
64 _FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
65 _FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 63 _FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
66 _FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
67 64
68 # SetFileAttributes 65 # SetFileAttributes
69 _FILE_ATTRIBUTE_NORMAL = 0x80 66 _FILE_ATTRIBUTE_NORMAL = 0x80
70 _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000 67 _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000
71 68
422 return _tochildpid(pi.dwProcessId) 419 return _tochildpid(pi.dwProcessId)
423 420
424 def unlink(f): 421 def unlink(f):
425 '''try to implement POSIX' unlink semantics on Windows''' 422 '''try to implement POSIX' unlink semantics on Windows'''
426 423
427 # If we can open f exclusively, no other processes must have open handles 424 if os.path.isdir(f):
428 # for it and we can expect its name will be deleted immediately when we 425 # use EPERM because it is POSIX prescribed value, even though
429 # close the handle unless we have another in the same process. We also 426 # unlink(2) on directories returns EISDIR on Linux
430 # expect we shall simply fail to open f if it is a directory. 427 raise IOError(errno.EPERM,
431 fh = _kernel32.CreateFileA(f, 0, 0, None, _OPEN_EXISTING, 428 "Unlinking directory not permitted: '%s'" % f)
432 _FILE_FLAG_OPEN_REPARSE_POINT | _FILE_FLAG_DELETE_ON_CLOSE, None)
433 if fh != _INVALID_HANDLE_VALUE:
434 _kernel32.CloseHandle(fh)
435 return
436 error = _kernel32.GetLastError()
437 if error != _ERROR_SHARING_VIOLATION:
438 raise ctypes.WinError(error)
439 429
440 # POSIX allows to unlink and rename open files. Windows has serious 430 # POSIX allows to unlink and rename open files. Windows has serious
441 # problems with doing that: 431 # problems with doing that:
442 # - Calling os.unlink (or os.rename) on a file f fails if f or any 432 # - Calling os.unlink (or os.rename) on a file f fails if f or any
443 # hardlinked copy of f has been opened with Python's open(). There is no 433 # hardlinked copy of f has been opened with Python's open(). There is no