def get_rev_cache(self):
        """
        Retrieve revision cache

        may rebuild cache on the fly if required

        returns RevCache tuple
        """

        with self.__rev_cache_lock:
            if self.__rev_cache is None: # can be cleared by Storage.__rev_cache_sync()
                self.logger.debug("triggered rebuild of commit tree db for %d" % id(self))
                ts0 = time.time()

                youngest = None
                oldest = None
                new_db = {} # db
                new_sdb = {} # short_rev db

                # helper for reusing strings
                __rev_seen = {}
                def __rev_reuse(rev):
                    rev = str(rev)
                    return __rev_seen.setdefault(rev, rev)

                new_tags = set(__rev_reuse(rev.strip()) for rev in self.repo.rev_parse("--tags").splitlines())

                new_branches = [(k, __rev_reuse(v)) for k, v in self._get_branches()]
                head_revs = set(v for _, v in new_branches)

                rev = ord_rev = 0
                for ord_rev, revs in enumerate(self.repo.rev_list("--parents",
                                                                  "--topo-order",
                                                                  "--all").splitlines()):
                    revs = map(__rev_reuse, revs.strip().split())

                    rev = revs[0]

                    # first rev seen is assumed to be the youngest one
                    if not ord_rev:
                        youngest = rev

                    # shortrev "hash" map
                    srev_key = self.__rev_key(rev)
                    new_sdb.setdefault(srev_key, []).append(rev)

                    # parents
                    parents = tuple(revs[1:])

                    # new_db[rev] = (children(rev), parents(rev), ordinal_id(rev), rheads(rev))
                    if rev in new_db:
                        # (incomplete) entry was already created by children
                        _children, _parents, _ord_rev, _rheads = new_db[rev]
                        assert _children
                        assert not _parents
                        assert _ord_rev == 0

                        if rev in head_revs and rev not in _rheads:
                            _rheads.append(rev)

                    else: # new entry
                        _children = []
                        _rheads = [rev] if rev in head_revs else []

                    # create/update entry -- transform lists into tuples since entry will be final
                    new_db[rev] = tuple(_children), tuple(parents), ord_rev + 1, tuple(_rheads)

                    # update parents(rev)s
                    for parent in parents:
                        # by default, a dummy ordinal_id is used for the mean-time
                        _children, _parents, _ord_rev, _rheads2 = new_db.setdefault(parent, ([], [], 0, []))

                        # update parent(rev)'s children
                        if rev not in _children:
                            _children.append(rev)

                        # update parent(rev)'s rheads
                        for rev in _rheads:
                            if rev not in _rheads2:
                                _rheads2.append(rev)

                # last rev seen is assumed to be the oldest one (with highest ord_rev)
                oldest = rev

                __rev_seen = None

                # convert sdb either to dict or array depending on size
                tmp = [()]*(max(new_sdb.keys())+1) if len(new_sdb) > 5000 else {}

                try:
                    while True:
                        k, v = new_sdb.popitem()
                        tmp[k] = tuple(v)
                except __HOLE__:
                    pass

                assert len(new_sdb) == 0
                new_sdb = tmp

                # atomically update self.__rev_cache
                self.__rev_cache = Storage.RevCache(youngest, oldest, new_db, new_tags, new_sdb, new_branches)
                ts1 = time.time()
                self.logger.debug("rebuilt commit tree db for %d with %d entries (took %.1f ms)"
                                  % (id(self), len(new_db), 1000*(ts1-ts0)))

            assert all(e is not None for e in self.__rev_cache) or not any(self.__rev_cache)

            return self.__rev_cache
        # with self.__rev_cache_lock

    # see RevCache namedtuple
dataset/ETHPy150Open hvr/trac-git-plugin/tracext/git/PyGIT.py/Storage.get_rev_cache