Show More
@@ -6,7 +6,7 b'' | |||||
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | import encoding |
|
8 | import encoding | |
9 | import ctypes, errno, os, struct, subprocess |
|
9 | import ctypes, errno, os, struct, subprocess, random | |
10 |
|
10 | |||
11 | _kernel32 = ctypes.windll.kernel32 |
|
11 | _kernel32 = ctypes.windll.kernel32 | |
12 |
|
12 | |||
@@ -316,3 +316,43 b' def spawndetached(args):' | |||||
316 | raise ctypes.WinError() |
|
316 | raise ctypes.WinError() | |
317 |
|
317 | |||
318 | return pi.dwProcessId |
|
318 | return pi.dwProcessId | |
|
319 | ||||
|
320 | def unlink(f): | |||
|
321 | '''try to implement POSIX' unlink semantics on Windows''' | |||
|
322 | ||||
|
323 | # POSIX allows to unlink and rename open files. Windows has serious | |||
|
324 | # problems with doing that: | |||
|
325 | # - Calling os.unlink (or os.rename) on a file f fails if f or any | |||
|
326 | # hardlinked copy of f has been opened with Python's open(). There is no | |||
|
327 | # way such a file can be deleted or renamed on Windows (other than | |||
|
328 | # scheduling the delete or rename for the next reboot). | |||
|
329 | # - Calling os.unlink on a file that has been opened with Mercurial's | |||
|
330 | # posixfile (or comparable methods) will delay the actual deletion of | |||
|
331 | # the file for as long as the file is held open. The filename is blocked | |||
|
332 | # during that time and cannot be used for recreating a new file under | |||
|
333 | # that same name ("zombie file"). Directories containing such zombie files | |||
|
334 | # cannot be removed or moved. | |||
|
335 | # A file that has been opened with posixfile can be renamed, so we rename | |||
|
336 | # f to a random temporary name before calling os.unlink on it. This allows | |||
|
337 | # callers to recreate f immediately while having other readers do their | |||
|
338 | # implicit zombie filename blocking on a temporary name. | |||
|
339 | ||||
|
340 | for tries in xrange(10): | |||
|
341 | temp = '%s-%08x' % (f, random.randint(0, 0xffffffff)) | |||
|
342 | try: | |||
|
343 | os.rename(f, temp) # raises OSError EEXIST if temp exists | |||
|
344 | break | |||
|
345 | except OSError, e: | |||
|
346 | if e.errno != errno.EEXIST: | |||
|
347 | raise | |||
|
348 | else: | |||
|
349 | raise IOError, (errno.EEXIST, "No usable temporary filename found") | |||
|
350 | ||||
|
351 | try: | |||
|
352 | os.unlink(temp) | |||
|
353 | except: | |||
|
354 | # Some very rude AV-scanners on Windows may cause this unlink to fail. | |||
|
355 | # Not aborting here just leaks the temp file, whereas aborting at this | |||
|
356 | # point may leave serious inconsistencies. Ideally, we would notify | |||
|
357 | # the user in this case here. | |||
|
358 | pass |
@@ -7,7 +7,7 b'' | |||||
7 |
|
7 | |||
8 | from i18n import _ |
|
8 | from i18n import _ | |
9 | import osutil, error |
|
9 | import osutil, error | |
10 |
import errno, msvcrt, os, re, sys, |
|
10 | import errno, msvcrt, os, re, sys, subprocess | |
11 |
|
11 | |||
12 | nulldev = 'NUL:' |
|
12 | nulldev = 'NUL:' | |
13 | umask = 002 |
|
13 | umask = 002 | |
@@ -293,46 +293,6 b' def unlinkpath(f):' | |||||
293 | except OSError: |
|
293 | except OSError: | |
294 | pass |
|
294 | pass | |
295 |
|
295 | |||
296 | def unlink(f): |
|
|||
297 | '''try to implement POSIX' unlink semantics on Windows''' |
|
|||
298 |
|
||||
299 | # POSIX allows to unlink and rename open files. Windows has serious |
|
|||
300 | # problems with doing that: |
|
|||
301 | # - Calling os.unlink (or os.rename) on a file f fails if f or any |
|
|||
302 | # hardlinked copy of f has been opened with Python's open(). There is no |
|
|||
303 | # way such a file can be deleted or renamed on Windows (other than |
|
|||
304 | # scheduling the delete or rename for the next reboot). |
|
|||
305 | # - Calling os.unlink on a file that has been opened with Mercurial's |
|
|||
306 | # posixfile (or comparable methods) will delay the actual deletion of |
|
|||
307 | # the file for as long as the file is held open. The filename is blocked |
|
|||
308 | # during that time and cannot be used for recreating a new file under |
|
|||
309 | # that same name ("zombie file"). Directories containing such zombie files |
|
|||
310 | # cannot be removed or moved. |
|
|||
311 | # A file that has been opened with posixfile can be renamed, so we rename |
|
|||
312 | # f to a random temporary name before calling os.unlink on it. This allows |
|
|||
313 | # callers to recreate f immediately while having other readers do their |
|
|||
314 | # implicit zombie filename blocking on a temporary name. |
|
|||
315 |
|
||||
316 | for tries in xrange(10): |
|
|||
317 | temp = '%s-%08x' % (f, random.randint(0, 0xffffffff)) |
|
|||
318 | try: |
|
|||
319 | os.rename(f, temp) # raises OSError EEXIST if temp exists |
|
|||
320 | break |
|
|||
321 | except OSError, e: |
|
|||
322 | if e.errno != errno.EEXIST: |
|
|||
323 | raise |
|
|||
324 | else: |
|
|||
325 | raise IOError, (errno.EEXIST, "No usable temporary filename found") |
|
|||
326 |
|
||||
327 | try: |
|
|||
328 | os.unlink(temp) |
|
|||
329 | except: |
|
|||
330 | # Some very rude AV-scanners on Windows may cause this unlink to fail. |
|
|||
331 | # Not aborting here just leaks the temp file, whereas aborting at this |
|
|||
332 | # point may leave serious inconsistencies. Ideally, we would notify |
|
|||
333 | # the user in this case here. |
|
|||
334 | pass |
|
|||
335 |
|
||||
336 | def rename(src, dst): |
|
296 | def rename(src, dst): | |
337 | '''atomically rename file src to dst, replacing dst if it exists''' |
|
297 | '''atomically rename file src to dst, replacing dst if it exists''' | |
338 | try: |
|
298 | try: |
General Comments 0
You need to be logged in to leave comments.
Login now