# HG changeset patch # User Hao Lian # Date 1319145899 14400 # Node ID a5a6a9b7f3b92225512d277505bd49e2a32cd2b8 # Parent fffe49886a51d664f798aca561130e16d73a76f7 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 -r fffe49886a51 -r a5a6a9b7f3b9 hgext/largefiles/lfutil.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 diff -r fffe49886a51 -r a5a6a9b7f3b9 hgext/largefiles/proto.py --- 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)