[PATCH 3 of 3 STABLE] largefiles: respect store.createmode and avoid extra file copy

Martin Geisler mg at aragost.com
Thu Feb 23 13:41:30 UTC 2012


# HG changeset patch
# User Martin Geisler <mg at aragost.com>
# Date 1330000630 -3600
# Branch stable
# Node ID 1b2b42e866bec02325324749a87c5eb056b5986d
# Parent  9b072a5f8f9284930a0441e0399e7cf2cf60e502
largefiles: respect store.createmode and avoid extra file copy

Before, a tempfile was used to create a temp file was created with 600
permissions and the uploaded data was written into it. This file was
then *copied* to .hg/largefiles/<hash>.

We now simply use atomictempfile to write the data to a temp file with
the right permissions and then rename that into place.

diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -13,7 +13,6 @@
 import platform
 import shutil
 import stat
-import tempfile
 
 from mercurial import dirstate, httpconnection, match as match_, util, scmutil
 from mercurial.i18n import _
@@ -439,13 +438,6 @@
     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(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
@@ -20,23 +20,22 @@
     user cache.'''
     proto.redirect()
 
-    fd, tmpname = lfutil.mkstemp(repo, prefix='hg-putlfile')
-    tmpfp = os.fdopen(fd, 'wb+')
+    tmpfp = util.atomictempfile(lfutil.storepath(repo, sha),
+                                createmode=repo.store.createmode)
     try:
         try:
             proto.getfile(tmpfp)
-            tmpfp.seek(0)
-            if sha != lfutil.hexsha1(tmpfp):
+            tmpfp._fp.seek(0)
+            if sha != lfutil.hexsha1(tmpfp._fp):
                 raise IOError(0, _('largefile contents do not match hash'))
             tmpfp.close()
-            lfutil.copytostoreabsolute(repo, tmpname, sha)
+            lfutil.linktousercache(repo, sha)
         except IOError, e:
             repo.ui.warn(_('largefiles: failed to put %s into store: %s') %
                          (sha, e.strerror))
             return wireproto.pushres(1)
     finally:
-        tmpfp.close()
-        os.unlink(tmpname)
+        tmpfp.discard()
 
     return wireproto.pushres(0)
 
diff --git a/tests/test-largefiles-cache.t b/tests/test-largefiles-cache.t
--- a/tests/test-largefiles-cache.t
+++ b/tests/test-largefiles-cache.t
@@ -103,3 +103,19 @@
   $ hg pull ../src --update -q
   $ ../ls-l.py .hg/largefiles/e151b474069de4ca6898f67ce2f2a7263adf8fea
   640
+
+Test permission of files created by push:
+
+  $ hg serve -R ../src -d -p $HGPORT --pid-file hg.pid \
+  >          --config "web.allow_push=*" --config web.push_ssl=no
+  $ cat hg.pid >> $DAEMON_PIDS
+
+  $ echo change >> large
+  $ hg commit -m change
+
+  $ rm -r "$USERCACHE"
+
+  $ hg push -q http://localhost:$HGPORT/
+
+  $ ../ls-l.py ../src/.hg/largefiles/b734e14a0971e370408ab9bce8d56d8485e368a9
+  640



More information about the Mercurial-devel mailing list