Source code for swh.graphql.resolvers.snapshot_branch

# Copyright (C) 2022 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information

from typing import List, Optional, Tuple

from swh.model.model import CoreSWHID, SnapshotBranch
from swh.storage.interface import PagedResult

from .base_connection import BaseConnection, ConnectionData
from .base_node import BaseNode
from .snapshot import BaseSnapshotNode


[docs] class BaseSnapshotBranchNode(BaseNode): def _get_node_from_data(self, node_data: Tuple[bytes, Optional[SnapshotBranch]]): # node_data is a tuple as returned by _get_connection_data in SnapshotBranchConnection # overriding to support this special data structure branch_name, branch_obj = node_data updated_node_data = { # Name of the branch, exposed in the schema "name": branch_name, # Type of the branch, exposed in the schema "type": branch_obj.target_type.value if branch_obj else None, # not exposed in the schema, to be used by the target object "snapshot_id": self._get_snapshot_swhid().object_id, # not exposed in the schema, to be used by the target object "target": branch_obj, } return super()._get_node_from_data(updated_node_data)
[docs] class SnapshotBranchConnectionNode(BaseSnapshotBranchNode): """ Node resolver for an item in the snapshot branch connection """ obj: "SnapshotBranchConnection" def _get_snapshot_swhid(self) -> CoreSWHID: # As of now parent of a SnapshotBranchConnection will always be a snapshot object # so, self.obj.obj will always be a BaseSnapshot object assert isinstance(self.obj.obj, BaseSnapshotNode) return self.obj.obj.swhid
[docs] class SnapshotHeadBranchNode(BaseSnapshotBranchNode): """ Node resolver for a snapshot.headBranch object """ obj: BaseSnapshotNode _can_be_null = True def _get_node_data(self) -> Optional[Tuple[bytes, Optional[SnapshotBranch]]]: snapshot_id = self._get_snapshot_swhid().object_id name = b"HEAD" # Get just the branch without following the alias chain # final target will be resolved only on requesting the target head_branch = self.archive.get_branch_by_name( snapshot_id=snapshot_id, branch_name=name, follow_chain=False ) if head_branch is None or head_branch.branch_found is False: return None return (name, head_branch.target) def _get_snapshot_swhid(self) -> CoreSWHID: return self.obj.swhid
[docs] class SnapshotBranchConnection(BaseConnection): """ Connection resolver for the branches in a snapshot """ obj: BaseSnapshotNode _node_class = SnapshotBranchConnectionNode def _get_connection_data(self) -> ConnectionData: branches = self.archive.get_snapshot_branches( snapshot=self.obj.swhid.object_id, after=self._get_after_arg(), first=self._get_first_arg(), target_types=self.kwargs.get("types"), name_include=self._get_name_include_arg(), name_exclude_prefix=self._get_name_exclude_prefix_arg(), ) end_cursor: Optional[bytes] = branches.get("next_branch") if branches else None # FIXME, this pagination is not consistent with other connections # FIX in swh-storage to return PagedResult # STORAGE-TODO # each result item will be converted to a dict in _get_node_from_data # method in the node class results: List[Tuple[bytes, Optional[SnapshotBranch]]] = ( list(branches["branches"].items()) if branches else [] ) return ConnectionData( paged_result=PagedResult( results=results, next_page_token=end_cursor.decode() if end_cursor else None, ) ) def _get_after_arg(self): # after argument must be an empty string by default after = super()._get_after_arg() return after.encode() if after else b"" def _get_name_include_arg(self): name_include = self.kwargs.get("nameInclude", None) return name_include.encode() if name_include else None def _get_name_exclude_prefix_arg(self): name_exclude_prefix = self.kwargs.get("nameExcludePrefix", None) return name_exclude_prefix.encode() if name_exclude_prefix else None def _get_index_cursor(self, index: int, node: BaseSnapshotBranchNode): # Snapshot branch is using a different cursor, hence the override # No item cursor is provided in this case # FIXME: Return the right cursor when enabling index cursors return None