merge with i18n stable
authorMatt Mackall <mpm@selenic.com>
Wed, 30 Nov 2011 17:16:43 -0600
branchstable
changeset 15593 f9c6a575baa4
parent 15582 3da1f60fc80d (current diff)
parent 15592 db286472f79f (diff)
child 15594 39f418979059
child 15595 a585d78e7b2f
merge with i18n
--- a/hgext/largefiles/lfutil.py	Tue Nov 29 19:51:35 2011 +0100
+++ b/hgext/largefiles/lfutil.py	Wed Nov 30 17:16:43 2011 -0600
@@ -77,8 +77,11 @@
     try:
         util.oslink(src, dest)
     except OSError:
-        # if hardlinks fail, fallback on copy
-        shutil.copyfile(src, dest)
+        # if hardlinks fail, fallback on atomic copy
+        dst = util.atomictempfile(dest)
+        for chunk in util.filechunkiter(open(src)):
+            dst.write(chunk)
+        dst.close()
         os.chmod(dest, os.stat(src).st_mode)
 
 def usercachepath(ui, hash):
@@ -212,6 +215,8 @@
     if path is None:
         return False
     util.makedirs(os.path.dirname(repo.wjoin(filename)))
+    # The write may fail before the file is fully written, but we
+    # don't use atomic writes in the working copy.
     shutil.copy(path, repo.wjoin(filename))
     return True
 
@@ -226,8 +231,11 @@
     if inusercache(repo.ui, hash):
         link(usercachepath(repo.ui, hash), storepath(repo, hash))
     else:
-        shutil.copyfile(file, storepath(repo, hash))
-        os.chmod(storepath(repo, hash), os.stat(file).st_mode)
+        dst = util.atomictempfile(storepath(repo, hash))
+        for chunk in util.filechunkiter(open(file)):
+            dst.write(chunk)
+        dst.close()
+        util.copymode(file, storepath(repo, hash))
         linktousercache(repo, hash)
 
 def linktousercache(repo, hash):
--- a/hgext/largefiles/overrides.py	Tue Nov 29 19:51:35 2011 +0100
+++ b/hgext/largefiles/overrides.py	Wed Nov 30 17:16:43 2011 -0600
@@ -619,11 +619,13 @@
             f = lfutil.splitstandin(f)
 
             def getdatafn():
+                fd = None
                 try:
                     fd = open(path, 'rb')
                     return fd.read()
                 finally:
-                    fd.close()
+                    if fd:
+                        fd.close()
 
             getdata = getdatafn
         write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
--- a/i18n/pt_BR.po	Tue Nov 29 19:51:35 2011 +0100
+++ b/i18n/pt_BR.po	Wed Nov 30 17:16:43 2011 -0600
@@ -19781,13 +19781,13 @@
 
 msgid ""
 "  local/filesystem/path[#revision]\n"
-"  file://localhost/filesystem/path[#revision]\n"
+"  file://local/filesystem/path[#revision]\n"
 "  http://[user[:pass]@]host[:port]/[path][#revision]\n"
 "  https://[user[:pass]@]host[:port]/[path][#revision]\n"
 "  ssh://[user@]host[:port]/[path][#revision]"
 msgstr ""
 "  caminho/no/sistema/de/arquivos/local[#revisão]\n"
-"  file://localhost/caminho/no/sistema/de/arquivos[#revisão]\n"
+"  file://caminho/no/sistema/de/arquivos/local[#revisão]\n"
 "  http://[usuário[:senha]@]servidor[:porta]/[caminho][#revisão]\n"
 "  https://[usuário[:senha]@]servidor[:porta]/[caminho][#revisão]\n"
 "  ssh://[usuário@]servidor[:porta]/[caminho][#revisão]"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-largefiles-small-disk.t	Wed Nov 30 17:16:43 2011 -0600
@@ -0,0 +1,68 @@
+Test how largefiles abort in case the disk runs full
+
+  $ cat > criple.py <<EOF
+  > import os, errno, shutil
+  > from mercurial import util
+  > #
+  > # this makes the original largefiles code abort:
+  > def copyfileobj(fsrc, fdst, length=16*1024):
+  >     fdst.write(fsrc.read(4))
+  >     raise IOError(errno.ENOSPC, os.strerror(errno.ENOSPC))
+  > shutil.copyfileobj = copyfileobj
+  > #
+  > # this makes the rewritten code abort:
+  > def filechunkiter(f, size=65536, limit=None):
+  >     yield f.read(4)
+  >     raise IOError(errno.ENOSPC, os.strerror(errno.ENOSPC))
+  > util.filechunkiter = filechunkiter
+  > #
+  > def oslink(src, dest):
+  >     raise OSError("no hardlinks, try copying instead")
+  > util.oslink = oslink
+  > EOF
+
+  $ echo "[extensions]" >> $HGRCPATH
+  $ echo "largefiles =" >> $HGRCPATH
+
+  $ hg init alice
+  $ cd alice
+  $ echo "this is a very big file" > big
+  $ hg add --large big
+  $ hg commit --config extensions.criple=$TESTTMP/criple.py -m big
+  abort: No space left on device
+  [255]
+
+The largefile is not created in .hg/largefiles:
+
+  $ ls .hg/largefiles
+  dirstate
+
+The user cache is not even created:
+
+  >>> import os; os.path.exists("$HOME/.cache/largefiles/")
+  False
+
+Make the commit with space on the device:
+
+  $ hg commit -m big
+
+Now make a clone with a full disk, and make sure lfutil.link function
+makes copies instead of hardlinks:
+
+  $ cd ..
+  $ hg --config extensions.criple=$TESTTMP/criple.py clone --pull alice bob
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  getting changed largefiles
+  abort: No space left on device
+  [255]
+
+The largefile is not created in .hg/largefiles:
+
+  $ ls bob/.hg/largefiles
+  dirstate
--- a/tests/test-largefiles.t	Tue Nov 29 19:51:35 2011 +0100
+++ b/tests/test-largefiles.t	Wed Nov 30 17:16:43 2011 -0600
@@ -257,12 +257,6 @@
   5 files updated, 0 files merged, 0 files removed, 0 files unresolved
   getting changed largefiles
   3 largefiles updated, 0 removed
-  $ hg debugstate --nodates
-  n 644         41 .hglf/sub/large4
-  n   0         -1 .hglf/sub2/large6
-  n   0         -1 .hglf/sub2/large7
-  n 644          9 normal3
-  n 644          9 sub/normal4
   $ cd ../b
   $ hg log --template '{rev}:{node|short}  {desc|firstline}\n'
   7:daea875e9014  add/edit more largefiles