[PATCH] largefiles: replace usage of tempfile.NamedTemporaryFile with tempfile.mkstemp

Greg Ward greg-hg at gerg.ca
Thu Oct 20 19:52:02 CDT 2011


On Thu, Oct 20, 2011 at 5:31 PM, Hao Lian <hao at fogcreek.com> wrote:
> # HG changeset patch
> # User Hao Lian <hao at fogcreek.com>
> # Date 1319145899 14400
> # Branch stable
> # Node ID 569feddf9101067ced5a3375a9a9d844ee5dc64a
> # Parent  3eb1a90ea40941ad7a920daad665e27ffdb6f291
> largefiles: replace usage of 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.

Please wrap commit messages to 80 columns
(http://mercurial.selenic.com/wiki/ContributingChanges).

> diff --git a/hgext/largefiles/proto.py b/hgext/largefiles/proto.py
> --- a/hgext/largefiles/proto.py
> +++ b/hgext/largefiles/proto.py
> @@ -19,23 +19,26 @@
>  def putlfile(repo, proto, sha):
>     '''Put a largefile into a repository's local cache and into the
>     system cache.'''
> -    f = None
> +

Unnecessary blank line.

>     proto.redirect()
> +
> +    fd, tmpname = tempfile.mkstemp(prefix='hg-putlfile-')
> +    tmpfp = os.fdopen(fd, 'wb+')

At least on Unix, this almost certainly puts the temp file in /tmp.
That is very unlikely to be the same filesystem as my repository,
which means we're going to have to copy the file at the end -- cannot
hardlink.

I'm confused about whether the file is copied to
<repo.root>/.hg/largefiles or ~/.largefiles (or whatever the user
cache is called now). If the former, you should pass
dir=<repo.root>/.hg/largefiles to mkstemp(). If the latter, pass
dir=<usercache>. If both, it doesn't really matter. You might still be
able to hardlink one of them, but you might not. But if you put the
temp file in /tmp, it's more likely that you'll have to copy at least
once.

>     try:
> -        try:
> -            f = tempfile.NamedTemporaryFile(mode='wb+', prefix='hg-putlfile-')
> -            proto.getfile(f)
> -            f.seek(0)
> -            if sha != lfutil.hexsha1(f):
> -                return wireproto.pushres(1)
> -            lfutil.copytocacheabsolute(repo, f.name, sha)
> -        except IOError:
> -            repo.ui.warn(
> -                _('error: could not put received data into largefile store'))
> +        proto.getfile(tmpfp)
> +        tmpfp.seek(0)
> +        if sha != lfutil.hexsha1(tmpfp):
>             return wireproto.pushres(1)
> +        tmpfp.close()
> +
> +        lfutil.copytocacheabsolute(repo, tmpname, sha)
> +    except IOError:
> +        repo.ui.warn(
> +            _('error: could not put received data into largefile store'))

We generally don't start error messages with "error:" (unfortunately).
Also, there's no indication of where the error happened (what file,
what dir) or what it was (disk full? permission denied?). Please use
the exception object!

> +        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