[PATCH V3] largefiles: replace tempfile.NamedTemporaryFile with tempfile.mkstemp

Hao Lian hao at fogcreek.com
Thu Oct 27 10:03:03 CDT 2011


# HG changeset patch
# User Hao Lian <hao at fogcreek.com>
# Date 1319145899 14400
# Branch stable
# Node ID 724db0c36c67a07581deaf8b7567fc3a8542523f
# Parent  8fee2bc0d35916dd38231e97bfa7ef77f53b215d
largefiles: replace tempfile.NamedTemporaryFile with tempfile.mkstemp

This is consistent with the rest of Mercurial's code, mirroring the
try-finally-unlink structure elsewhere. Furthermore, it fixes the case where
largefiles throws an IOError on Windows when the temporary file is opened a
second time by copytocacheabsolute.

This patch creates the temporary file in the repo's largefiles store rather than
/tmp, which might be a different filesystem.

diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -13,6 +13,7 @@
 import platform
 import shutil
 import stat
+import tempfile
 
 from mercurial import dirstate, httpconnection, match as match_, util, scmutil
 from mercurial.i18n import _
@@ -438,6 +439,13 @@
     return ('largefiles' in repo.requirements and
             util.any(shortname + '/' in f[0] for f in repo.store.datafiles()))
 
+def mkstemp(repo, prefix):
+    '''Returns a file descriptor and a filename corresponding to a temporary
+    file in the repo's largefiles store.'''
+    path = repo.join(longname)
+    util.makedirs(repo.join(path))
+    return tempfile.mkstemp(prefix=prefix, dir=path)
+
 class storeprotonotcapable(Exception):
     def __init__(self, storetypes):
         self.storetypes = storetypes
diff --git a/hgext/largefiles/proto.py b/hgext/largefiles/proto.py
--- a/hgext/largefiles/proto.py
+++ b/hgext/largefiles/proto.py
@@ -4,7 +4,6 @@
 # GNU General Public License version 2 or any later version.
 
 import os
-import tempfile
 import urllib2
 
 from mercurial import error, httprepo, util, wireproto
@@ -19,23 +18,25 @@
 def putlfile(repo, proto, sha):
     '''Put a largefile into a repository's local store and into the
     user cache.'''
-    f = None
     proto.redirect()
+
+    fd, tmpname = lfutil.mkstemp(repo, prefix='hg-putlfile')
+    tmpfp = os.fdopen(fd, 'wb+')
     try:
         try:
-            f = tempfile.NamedTemporaryFile(mode='wb+', prefix='hg-putlfile-')
-            proto.getfile(f)
-            f.seek(0)
-            if sha != lfutil.hexsha1(f):
+            proto.getfile(tmpfp)
+            tmpfp.seek(0)
+            if sha != lfutil.hexsha1(tmpfp):
                 return wireproto.pushres(1)
-            lfutil.copytostoreabsolute(repo, f.name, sha)
-        except IOError:
-            repo.ui.warn(
-                _('error: could not put received data into largefile store'))
+            tmpfp.close()
+            lfutil.copytostoreabsolute(repo, tmpname, sha)
+        except IOError, e:
+            repo.ui.warn(_('largefiles: failed to put %s (%s) into store: %s') %
+                         (sha, tmpname, e.strerror))
             return wireproto.pushres(1)
     finally:
-        if f:
-            f.close()
+        tmpfp.close()
+        os.unlink(tmpname)
 
     return wireproto.pushres(0)
 


More information about the Mercurial-devel mailing list