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