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.
--- 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)