tests/test-largefiles-small-disk.t
author Drew Gottlieb <drgott@google.com>
Mon, 06 Apr 2015 10:51:53 -0700
changeset 24636 36872036169b
parent 20063 8a021cd38719
child 30181 7356e6b1f5b8
permissions -rw-r--r--
treemanifest: further optimize treemanifest.matches() The matches function was previously traversing all submanifests to look for matching files, even though it was possible to know if a submanifest won't contain any matches. This change adds a visitdir function on the match object to decide quickly if a directory should be visited when traversing. The function also decides if _all_ subdirectories should be traversed. Adding this logic as methods on the match object also makes the logic modifiable by extensions, such as largefiles. An example of a command this speeds up is running hg status --rev .^ python/ on the Mozilla repo with the treemanifest experiment enabled. It goes from 2.03s to 1.85s. More improvements to speed from this change will happen when treemanifests are lazily loaded. Because a flat manifest is still loaded and then converted into treemanifests, speed improvements are limited. This change has no negative effect on speed. For a worst-case example, this command is not negatively impacted: hg status --rev .^ 'relglob:*.js' on the Mozilla repo. It goes from 2.83s to 2.82s.

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
  getting changed largefiles
  abort: No space left on device
  [255]

The largefile is not created in .hg/largefiles:

  $ ls bob/.hg/largefiles
  dirstate