mercurial/util.py
changeset 8256 e68e149f4d44
parent 8227 0a9542703300
parent 8255 ea82a23cf887
child 8257 e745063b94dd
equal deleted inserted replaced
8254:f108e89400d8 8256:e68e149f4d44
   628 def rename(src, dst):
   628 def rename(src, dst):
   629     """forcibly rename a file"""
   629     """forcibly rename a file"""
   630     try:
   630     try:
   631         os.rename(src, dst)
   631         os.rename(src, dst)
   632     except OSError, err: # FIXME: check err (EEXIST ?)
   632     except OSError, err: # FIXME: check err (EEXIST ?)
   633         # on windows, rename to existing file is not allowed, so we
   633 
   634         # must delete destination first. but if file is open, unlink
   634         # On windows, rename to existing file is not allowed, so we
   635         # schedules it for delete but does not delete it. rename
   635         # must delete destination first. But if a file is open, unlink
       
   636         # schedules it for delete but does not delete it. Rename
   636         # happens immediately even for open files, so we rename
   637         # happens immediately even for open files, so we rename
   637         # destination to a temporary name, then delete that. then
   638         # destination to a temporary name, then delete that. Then
   638         # rename is safe to do.
   639         # rename is safe to do.
   639         temp = dst + "-force-rename"
   640         # The temporary name is chosen at random to avoid the situation
       
   641         # where a file is left lying around from a previous aborted run.
       
   642         # The usual race condition this introduces can't be avoided as
       
   643         # we need the name to rename into, and not the file itself. Due
       
   644         # to the nature of the operation however, any races will at worst
       
   645         # lead to the rename failing and the current operation aborting.
       
   646 
       
   647         def tempname(prefix):
       
   648             for tries in xrange(10):
       
   649                 temp = '%s-%08x' % (prefix, random.randint(0, 0xffffffff))
       
   650                 if not os.path.exists(temp):
       
   651                     return temp
       
   652             raise IOError, (errno.EEXIST, "No usable temporary filename found")
       
   653 
       
   654         temp = tempname(dst)
   640         os.rename(dst, temp)
   655         os.rename(dst, temp)
   641         os.unlink(temp)
   656         os.unlink(temp)
   642         os.rename(src, dst)
   657         os.rename(src, dst)
   643 
   658 
   644 def unlink(f):
   659 def unlink(f):