largefiles: replace tempfile.NamedTemporaryFile with tempfile.mkstemp stable
authorHao Lian <hao@fogcreek.com>
Thu, 20 Oct 2011 17:24:59 -0400
branchstable
changeset 15391 a5a6a9b7f3b9
parent 15390 fffe49886a51
child 15392 d7bfbc92a1c0
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.
hgext/largefiles/lfutil.py
hgext/largefiles/proto.py
--- a/hgext/largefiles/lfutil.py	Mon Oct 31 14:22:11 2011 -0500
+++ b/hgext/largefiles/lfutil.py	Thu Oct 20 17:24:59 2011 -0400
@@ -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
--- a/hgext/largefiles/proto.py	Mon Oct 31 14:22:11 2011 -0500
+++ b/hgext/largefiles/proto.py	Thu Oct 20 17:24:59 2011 -0400
@@ -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)