+ self._subs[name] = File(self, name, mode, sha, bupmode,
+ self._repo_dir)
+
+ def metadata(self):
+ """Return this Dir's Metadata() object, if any."""
+ self._populate_metadata()
+ return self._metadata
+
+ def metadata_file(self):
+ """Return this Dir's .bupm File, if any."""
+ if not self._subs:
+ self._mksubs()
+ return self._bupm
+
+ def release(self):
+ """Release restorable resources held by this node."""
+ self._bupm = None
+ super(Dir, self).release()
+
+
+class CommitDir(Node):
+ """A directory that contains all commits that are reachable by a ref.
+
+ Contains a set of subdirectories named after the commits' first byte in
+ hexadecimal. Each of those directories contain all commits with hashes that
+ start the same as the directory name. The name used for those
+ subdirectories is the hash of the commit without the first byte. This
+ separation helps us avoid having too much directories on the same level as
+ the number of commits grows big.
+ """
+ def __init__(self, parent, name, repo_dir=None):
+ Node.__init__(self, parent, name, GIT_MODE_TREE, EMPTY_SHA, repo_dir)
+
+ def _mksubs(self):
+ self._subs = {}
+ refs = git.list_refs(repo_dir = self._repo_dir)
+ for ref in refs:
+ #debug2('ref name: %s\n' % ref[0])
+ revs = git.rev_list(ref[1].encode('hex'), repo_dir = self._repo_dir)
+ for (date, commit) in revs:
+ #debug2('commit: %s date: %s\n' % (commit.encode('hex'), date))
+ commithex = commit.encode('hex')
+ containername = commithex[:2]
+ dirname = commithex[2:]
+ n1 = self._subs.get(containername)
+ if not n1:
+ n1 = CommitList(self, containername, self._repo_dir)
+ self._subs[containername] = n1
+
+ if n1.commits.get(dirname):
+ # Stop work for this ref, the rest should already be present
+ break
+
+ n1.commits[dirname] = (commit, date)
+