class HistoryCache(AbstractCache): """ The history cache map SWHIDs of type `rev` to a list of all their parent commits (until root commit). """ async def __aenter__(self): await super().__aenter__() await self.conn.execute( """ create table if not exists history_graph ( src text not null, dst text not null, unique(src, dst) ) """ ) await self.conn.execute("create index index_history_graph on history_graph(src)") await self.conn.commit() return self async def get(self, swhid: SWHID) -> Optional[List[SWHID]]: cursor = await self.conn.execute( """ with recursive dfs(node) AS ( values(?) union all select history_graph.dst from history_graph join dfs on history_graph.src = dfs.node ) -- Do not keep the root node since it is not an ancestor select * from dfs limit -1 offset 1 """, (str(swhid), ), ) cache = await cursor.fetchall() if not cache: return None history = [] for parent in cache: parent = parent[0] try: history.append(parse_swhid(parent)) except ValidationError: logging.warning(f"Cannot parse object from history cache: {parent}") return history async def set(self, history: str) -> None: history = history.strip() edges = [edge.split(" ") for edge in history.split("\n")] await self.conn.executemany( "insert or ignore into history_graph values (?, ?)", edges ) await self.conn.commit()