mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
treestate: implement gc
Summary: Implement gc for treestate. Dirstate writes are protected by wlock. So it's fine to do a gc inside the write method. Reviewed By: markbt Differential Revision: D8394736 fbshipit-source-id: 672087a2c14b855d1ca0449eb5b7d92d65bba418
This commit is contained in:
parent
afc292c75c
commit
fd0ca23d39
@ -733,6 +733,9 @@ def cleanup(ui, repo, debug=None):
|
||||
% (treeid, ", ".join(treesinuse[treeid]))
|
||||
)
|
||||
|
||||
if "treestate" in repo.requirements:
|
||||
repo.dirstate._map._gc()
|
||||
|
||||
|
||||
def wrapdirstate(orig, self):
|
||||
ds = orig(self)
|
||||
|
@ -73,6 +73,9 @@ class treestatemap(object):
|
||||
and an offset.
|
||||
"""
|
||||
|
||||
# Filenames (uuid) that are currently in use. Useful for gc.
|
||||
fileinuse = set()
|
||||
|
||||
def __init__(self, ui, vfs, root, importdirstate=None):
|
||||
self._filename = None
|
||||
self._ui = ui
|
||||
@ -251,8 +254,8 @@ class treestatemap(object):
|
||||
def setparents(self, p1, p2):
|
||||
self._parents = (p1, p2)
|
||||
|
||||
def _read(self):
|
||||
"""Read every metadata automatically"""
|
||||
def _parsedirstate(self, filename):
|
||||
"""Parse given dirstate metadata file"""
|
||||
dirstate = self._vfs.tryread("dirstate")
|
||||
f = util.stringio(dirstate)
|
||||
p1 = f.read(20) or node.nullid
|
||||
@ -276,6 +279,12 @@ class treestatemap(object):
|
||||
rootid = 0
|
||||
threshold = 0
|
||||
|
||||
return p1, p2, filename, rootid, threshold
|
||||
|
||||
def _read(self):
|
||||
"""Read every metadata automatically"""
|
||||
p1, p2, filename, rootid, threshold = self._parsedirstate("dirstate")
|
||||
|
||||
self._parents = (p1, p2)
|
||||
self._threshold = threshold
|
||||
self._rootid = rootid
|
||||
@ -308,10 +317,27 @@ class treestatemap(object):
|
||||
if filename is None:
|
||||
filename = "%s" % uuid.uuid4()
|
||||
assert self._filename != filename
|
||||
self.fileinuse.add(filename)
|
||||
self._filename = filename
|
||||
path = self._vfs.join("treestate", self._filename)
|
||||
return path
|
||||
|
||||
def _gc(self):
|
||||
"""Remove unreferenced treestate files"""
|
||||
for name in ["dirstate", "undo.dirstate", "undo.backup.dirstate"]:
|
||||
try:
|
||||
_p1, _p2, filename = self._parsedirstate(name)[:3]
|
||||
self.fileinuse.add(filename)
|
||||
except Exception:
|
||||
# dirstate file does not exist, or is in an incompatible
|
||||
# format.
|
||||
pass
|
||||
for name in self._vfs.listdir("treestate"):
|
||||
if name in self.fileinuse:
|
||||
continue
|
||||
self._ui.debug("removing unreferenced treestate/%s\n" % name)
|
||||
self._vfs.tryunlink("treestate/%s" % name)
|
||||
|
||||
def write(self, st, now):
|
||||
# write .hg/treestate/<uuid>
|
||||
metadata = {}
|
||||
@ -340,6 +366,7 @@ class treestatemap(object):
|
||||
# recalculate threshold
|
||||
self._threshold = 0
|
||||
rootid = self._tree.saveas(path)
|
||||
self._gc()
|
||||
else:
|
||||
rootid = self._tree.flush()
|
||||
|
||||
|
@ -56,9 +56,11 @@ Auto repack happens when treestate exceeds size threshold
|
||||
.
|
||||
.
|
||||
creating treestate/00000000-0000-0000-0000-000000000002
|
||||
removing unreferenced treestate/00000000-0000-0000-0000-000000000000
|
||||
$ hg debugtreestate
|
||||
dirstate v2 (using treestate/00000000-0000-0000-0000-000000000002, offset 88, 5 files tracked)
|
||||
|
||||
Cleanup removes the leftover files
|
||||
|
||||
$ hg debugtreestate cleanup --debug
|
||||
removing unreferenced treestate/00000000-0000-0000-0000-000000000001
|
||||
|
Loading…
Reference in New Issue
Block a user