diff --git a/mercurial/win32.py b/mercurial/win32.py --- a/mercurial/win32.py +++ b/mercurial/win32.py @@ -12,6 +12,7 @@ import msvcrt import os import random +import stat import subprocess from . import ( @@ -522,11 +523,26 @@ def unlink(f): '''try to implement POSIX' unlink semantics on Windows''' - if os.path.isdir(f): - # use EPERM because it is POSIX prescribed value, even though - # unlink(2) on directories returns EISDIR on Linux - raise IOError(errno.EPERM, - "Unlinking directory not permitted: '%s'" % f) + # If the path doesn't exist, raise that exception. + # If it is a directory, emulate POSIX behavior. + try: + st = os.stat(f) + if stat.S_ISDIR(st.st_mode): + # use EPERM because it is POSIX prescribed value, even though + # unlink(2) on directories returns EISDIR on Linux + raise IOError(errno.EPERM, + "Unlinking directory not permitted: '%s'" % f) + except OSError as e: + if e.errno == errno.ENOENT: + raise + + # In the common case, a normal unlink will work. Try that first and fall + # back to more complexity if and only if we need to. + try: + os.unlink(f) + return + except (IOError, OSError) as e: + pass # POSIX allows to unlink and rename open files. Windows has serious # problems with doing that: