Commits

Patrick Mézard committed bfbfc9b

editor: add a pop() method to RevisionMeta to reduce resource usage

The commit pass only has to read files once, removing the related data
after the read helps not keeping large temporary files around after they
have been stored

  • Participants
  • Parent commits d6db289

Comments (2)

  1. Anton Malakhov

    I'm getting "trying to get a popped file trunk/tbb/1.0/include/tbb/internal/_concurrent_unordered_impl.h" error. Probably, it is related to EOL extension. How to fix it?

Files changed (3)

File hgsubversion/editor.py

         # object which prevent us from calling getvalue() afterwards.
         pass
 
+class EditingError(Exception):
+    pass
+
 class FileStore(object):
     def __init__(self, maxsize=None):
         self._tempdir = None
             self._maxsize = 100*(2**20)
         self._size = 0
         self._data = {}
+        self._popped = set()
 
     def setfile(self, fname, data):
+        if fname in self._popped:
+            raise EditingError('trying to set a popped file %s' % fname)
+
         if self._maxsize < 0 or (len(data) + self._size) <= self._maxsize:
             self._data[fname] = data
             self._size += len(data)
             self._files[fname] = fn
 
     def delfile(self, fname):
+        if fname in self._popped:
+            raise EditingError('trying to delete a popped file %s' % fname)
+
         if fname in self._data:
             del self._data[fname]
         elif fname in self._files:
             os.unlink(path)
 
     def getfile(self, fname):
+        if fname in self._popped:
+            raise EditingError('trying to get a popped file %s' % fname)
+
         if fname in self._data:
             return self._data[fname]
         if self._tempdir is None or fname not in self._files:
         finally:
             fp.close()
 
+    def popfile(self, fname):
+        self.delfile(fname)
+        self._popped.add(fname)
+
     def files(self):
         return list(self._files) + list(self._data)
 
         copied = self.copies.get(path)
         return data, isexec, islink, copied
 
+    def pop(self, path):
+        ret = self.get(path)
+        self.store.popfile(path)
+        return ret
+
     def delete(self, path):
         self.deleted[path] = True
         self.store.delfile(path)
     def close(self):
         self.store.close()
 
-class EditingError(Exception):
-    pass
-
 class CopiedFile(object):
     def __init__(self, node, path, copypath):
         self.node = node

File hgsubversion/replay.py

 
         def filectxfn(repo, memctx, path):
             current_file = files[path]
-            data, isexec, islink, copied = current.get(current_file)
+            data, isexec, islink, copied = current.pop(current_file)
             if isexec is None or islink is None:
                 flags = parentctx.flags(path)
                 if isexec is None:

File tests/test_helpers.py

+import os, sys, unittest
+
+_rootdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+sys.path.insert(0, _rootdir)
+
+from hgsubversion import editor
+
+class TestHelpers(unittest.TestCase):
+    def test_filestore(self):
+        fs = editor.FileStore(2)
+        fs.setfile('a', 'a')
+        fs.setfile('b', 'b')
+        self.assertEqual('a', fs._data.get('a'))
+        self.assertEqual('b', fs._data.get('b'))
+
+        fs.delfile('b')
+        self.assertRaises(IOError, lambda: fs.getfile('b'))
+        fs.setfile('bb', 'bb')
+        self.assertTrue('bb' in fs._files)
+        self.assertTrue('bb' not in fs._data)
+        self.assertEqual('bb', fs.getfile('bb'))
+
+        fs.delfile('bb')
+        self.assertTrue('bb' not in fs._files)
+        self.assertEqual([], os.listdir(fs._tempdir))
+        self.assertRaises(IOError, lambda: fs.getfile('bb'))
+
+        fs.setfile('bb', 'bb')
+        self.assertEqual(1, len(os.listdir(fs._tempdir)))
+        fs.popfile('bb')
+        self.assertEqual([], os.listdir(fs._tempdir))
+        self.assertRaises(editor.EditingError, lambda: fs.getfile('bb'))
+
+def suite():
+    return unittest.TestSuite([
+        unittest.TestLoader().loadTestsFromTestCase(TestHelpers),
+        ])