[PATCH 2 of 2] util: move rename into posix.py and windows.py

Adrian Buehlmann adrian at cadifra.com
Wed Oct 7 15:11:22 CDT 2009


# HG changeset patch
# User Adrian Buehlmann <adrian at cadifra.com>
# Date 1254940327 -7200
# Node ID 37b337e597d0387d0c5b98876ac7fd5279e90e08
# Parent  0a8a3f3fadbb925f0e28f716a5544b68d803709f
util: move rename into posix.py and windows.py

diff --git a/mercurial/posix.py b/mercurial/posix.py
--- a/mercurial/posix.py
+++ b/mercurial/posix.py
@@ -13,6 +13,7 @@ posixfile = open
 nulldev = '/dev/null'
 normpath = os.path.normpath
 samestat = os.path.samestat
+rename = os.rename
 expandglobs = False
 
 umask = os.umask(0)
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -16,7 +16,7 @@ hide platform-specific details from the 
 from i18n import _
 import error, osutil, encoding
 import cStringIO, errno, re, shutil, sys, tempfile, traceback
-import os, stat, time, calendar, random, textwrap
+import os, stat, time, calendar, textwrap
 import imp
 
 # Python compatibility
@@ -399,44 +399,6 @@ def lexists(filename):
         return False
     return True
 
-def rename(src, dst):
-    '''atomically rename file src to dst, replacing dst if it exists'''
-    try:
-        os.rename(src, dst)
-    except OSError, err: # FIXME: check err (EEXIST ?)
-
-        # On windows, rename to existing file is not allowed, so we
-        # must delete destination first. But if a file is open, unlink
-        # schedules it for delete but does not delete it. Rename
-        # happens immediately even for open files, so we rename
-        # destination to a temporary name, then delete that. Then
-        # rename is safe to do.
-        # The temporary name is chosen at random to avoid the situation
-        # where a file is left lying around from a previous aborted run.
-        # The usual race condition this introduces can't be avoided as
-        # we need the name to rename into, and not the file itself. Due
-        # to the nature of the operation however, any races will at worst
-        # lead to the rename failing and the current operation aborting.
-
-        def tempname(prefix):
-            for tries in xrange(10):
-                temp = '%s-%08x' % (prefix, random.randint(0, 0xffffffff))
-                if not os.path.exists(temp):
-                    return temp
-            raise IOError, (errno.EEXIST, "No usable temporary filename found")
-
-        temp = tempname(dst)
-        os.rename(dst, temp)
-        try:
-            os.unlink(temp)
-        except:
-            # Some rude AV-scanners on Windows may cause the unlink to
-            # fail. Not aborting here just leaks the temp file, whereas
-            # aborting at this point may leave serious inconsistencies.
-            # Ideally, we would notify the user here.
-            pass
-        os.rename(src, dst)
-
 def unlink(f):
     """unlink and remove the directory if it is empty"""
     os.unlink(f)
diff --git a/mercurial/windows.py b/mercurial/windows.py
--- a/mercurial/windows.py
+++ b/mercurial/windows.py
@@ -7,7 +7,7 @@
 
 from i18n import _
 import osutil, error
-import errno, msvcrt, os, re, sys
+import errno, msvcrt, os, re, sys, random
 
 nulldev = 'NUL:'
 umask = 002
@@ -283,6 +283,44 @@ def unlink(f):
     except OSError:
         pass
 
+def rename(src, dst):
+    '''atomically rename file src to dst, replacing dst if it exists'''
+    try:
+        os.rename(src, dst)
+    except OSError, err: # FIXME: check err (EEXIST ?)
+
+        # On windows, rename to existing file is not allowed, so we
+        # must delete destination first. But if a file is open, unlink
+        # schedules it for delete but does not delete it. Rename
+        # happens immediately even for open files, so we rename
+        # destination to a temporary name, then delete that. Then
+        # rename is safe to do.
+        # The temporary name is chosen at random to avoid the situation
+        # where a file is left lying around from a previous aborted run.
+        # The usual race condition this introduces can't be avoided as
+        # we need the name to rename into, and not the file itself. Due
+        # to the nature of the operation however, any races will at worst
+        # lead to the rename failing and the current operation aborting.
+
+        def tempname(prefix):
+            for tries in xrange(10):
+                temp = '%s-%08x' % (prefix, random.randint(0, 0xffffffff))
+                if not os.path.exists(temp):
+                    return temp
+            raise IOError, (errno.EEXIST, "No usable temporary filename found")
+
+        temp = tempname(dst)
+        os.rename(dst, temp)
+        try:
+            os.unlink(temp)
+        except:
+            # Some rude AV-scanners on Windows may cause the unlink to
+            # fail. Not aborting here just leaks the temp file, whereas
+            # aborting at this point may leave serious inconsistencies.
+            # Ideally, we would notify the user here.
+            pass
+        os.rename(src, dst)
+
 try:
     # override functions with win32 versions if possible
     from win32 import *


More information about the Mercurial-devel mailing list