comparison mercurial/util.py @ 9549:8b8920209317

util: move rename into posix.py and windows.py
author Adrian Buehlmann <adrian@cadifra.com>
date Wed, 07 Oct 2009 20:32:07 +0200
parents 7732606b0767
children f0417b6ff98a
comparison
equal deleted inserted replaced
9548:7732606b0767 9549:8b8920209317
14 """ 14 """
15 15
16 from i18n import _ 16 from i18n import _
17 import error, osutil, encoding 17 import error, osutil, encoding
18 import cStringIO, errno, re, shutil, sys, tempfile, traceback 18 import cStringIO, errno, re, shutil, sys, tempfile, traceback
19 import os, stat, time, calendar, random, textwrap 19 import os, stat, time, calendar, textwrap
20 import imp 20 import imp
21 21
22 # Python compatibility 22 # Python compatibility
23 23
24 def sha1(s): 24 def sha1(s):
397 os.lstat(filename) 397 os.lstat(filename)
398 except: 398 except:
399 return False 399 return False
400 return True 400 return True
401 401
402 def rename(src, dst):
403 '''atomically rename file src to dst, replacing dst if it exists'''
404 try:
405 os.rename(src, dst)
406 except OSError, err: # FIXME: check err (EEXIST ?)
407
408 # On windows, rename to existing file is not allowed, so we
409 # must delete destination first. But if a file is open, unlink
410 # schedules it for delete but does not delete it. Rename
411 # happens immediately even for open files, so we rename
412 # destination to a temporary name, then delete that. Then
413 # rename is safe to do.
414 # The temporary name is chosen at random to avoid the situation
415 # where a file is left lying around from a previous aborted run.
416 # The usual race condition this introduces can't be avoided as
417 # we need the name to rename into, and not the file itself. Due
418 # to the nature of the operation however, any races will at worst
419 # lead to the rename failing and the current operation aborting.
420
421 def tempname(prefix):
422 for tries in xrange(10):
423 temp = '%s-%08x' % (prefix, random.randint(0, 0xffffffff))
424 if not os.path.exists(temp):
425 return temp
426 raise IOError, (errno.EEXIST, "No usable temporary filename found")
427
428 temp = tempname(dst)
429 os.rename(dst, temp)
430 try:
431 os.unlink(temp)
432 except:
433 # Some rude AV-scanners on Windows may cause the unlink to
434 # fail. Not aborting here just leaks the temp file, whereas
435 # aborting at this point may leave serious inconsistencies.
436 # Ideally, we would notify the user here.
437 pass
438 os.rename(src, dst)
439
440 def unlink(f): 402 def unlink(f):
441 """unlink and remove the directory if it is empty""" 403 """unlink and remove the directory if it is empty"""
442 os.unlink(f) 404 os.unlink(f)
443 # try removing directories that might now be empty 405 # try removing directories that might now be empty
444 try: 406 try: