<div dir="ltr"><div>I wrote a patch that could improve performance of win32.unlink() over CIFS/SMB but I want to confirm that it break nothing.  Could you test this patch if you are using Mercurial on Windows, etiher over CIFS/SMB or on local disks?  Because I am new to make a patch for Mercurial, please let me know if I must change the patch further.<br>
<br></div>FYI, on my environment, I got the following timing results (both are from the second runs):<br><br>Without the patch:<br><br><font face="courier new,monospace">Z:\tmp\xllmnrd>e:hg update --time -r null<br>0 files updated, 0 files merged, 36 files removed, 0 files unresolved<br>
time: real 9.378 secs (user 0.281+0.000 sys 1.123+0.000)<br><br>Z:\tmp\xllmnrd>e:hg update --time -r default<br>36 files updated, 0 files merged, 0 files removed, 0 files unresolved<br>time: real 5.432 secs (user 0.265+0.000 sys 0.749+0.000)</font><br>
<br>With the patch:<br><br><font face="courier new,monospace">Z:\tmp\xllmnrd>e:hg update --time -r null<br>0 files updated, 0 files merged, 36 files removed, 0 files unresolved<br>time: real 4.427 secs (user 0.281+0.000 sys 0.749+0.000)<br>
<br>Z:\tmp\xllmnrd>e:hg update --time -r default<br>36 files updated, 0 files merged, 0 files removed, 0 files unresolved<br>time: real 4.418 secs (user 0.140+0.000 sys 0.593+0.000)</font><br><div><br><br><br><font face="courier new,monospace"># HG changeset patch<br>
# User Kaz Nishimura <<a href="mailto:kazssym@vx68k.org">kazssym@vx68k.org</a>><br># Date 1381984037 -32400<br>#      Thu Oct 17 13:27:17 2013 +0900<br># Branch stable<br># Node ID d854b82381330cee14c01742243ad87af8677795<br>
# Parent  dbf305f499613e6b833847b72f1eb5424f9331cc<br>win32: try to unlink files without renaming if possible<br><br>Unlinking a file with os.rename() and os.unlink() could be slow over CIFS from<br>Windows clients due to its protocol overhead.  This patch changes win32.unlink()<br>
to try an exclusive open with the delete-on-close flag first and if a sharing<br>violation is detected, to fall back to the original method.<br><br>diff -r dbf305f49961 -r d854b8238133 mercurial/win32.py<br>--- a/mercurial/win32.py<br>
+++ b/mercurial/win32.py<br>@@ -25,4 +25,5 @@<br> # GetLastError<br> _ERROR_SUCCESS = 0<br>+_ERROR_SHARING_VIOLATION = 32<br> _ERROR_INVALID_PARAMETER = 87<br> _ERROR_INSUFFICIENT_BUFFER = 122<br>@@ -60,5 +61,7 @@<br> _OPEN_EXISTING = 3<br>
 <br>+_FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000<br> _FILE_FLAG_BACKUP_SEMANTICS = 0x02000000<br>+_FILE_FLAG_DELETE_ON_CLOSE = 0x04000000<br> <br> # SetFileAttributes<br>@@ -345,9 +348,16 @@<br>     '''try to implement POSIX' unlink semantics on Windows'''<br>
 <br>-    if os.path.isdir(f):<br>-        # use EPERM because it is POSIX prescribed value, even though<br>-        # unlink(2) on directories returns EISDIR on Linux<br>-        raise IOError(errno.EPERM,<br>-                      "Unlinking directory not permitted: '%s'" % f)<br>
+    # If we could open f in this way, there must be no other open handles and<br>+    # we could expect its name would be deleted immediately when we close it.<br>+    # We also expect we will fail to open a directory.<br>
+    fh = _kernel32.CreateFileA(f, 0, 0, None, _OPEN_EXISTING,<br>+        _FILE_FLAG_OPEN_REPARSE_POINT | _FILE_FLAG_DELETE_ON_CLOSE, None)<br>+    if fh != _INVALID_HANDLE_VALUE:<br>+        _kernel32.CloseHandle(fh)<br>
+        return<br>+    else:<br>+        e = ctypes.WinError()<br>+        if e.winerror != _ERROR_SHARING_VIOLATION:<br>+            raise e<br> <br>     # POSIX allows to unlink and rename open files. Windows has serious<br>
</font><br></div></div>