diff --git a/swh/graphql/backends/archive.py b/swh/graphql/backends/archive.py --- a/swh/graphql/backends/archive.py +++ b/swh/graphql/backends/archive.py @@ -74,6 +74,8 @@ directory_id, limit=first, page_token=after ) - def get_content(self, content_id): - # FIXME, only for tests - return self.storage.content_find({"sha1_git": content_id}) + def get_content(self, hash_value: bytes, hash_type: str): + return self.storage.content_find({hash_type: hash_value}) + + def get_content_data(self, content_sha1): + return self.storage.content_get_data(content_sha1) diff --git a/swh/graphql/resolvers/content.py b/swh/graphql/resolvers/content.py --- a/swh/graphql/resolvers/content.py +++ b/swh/graphql/resolvers/content.py @@ -6,6 +6,7 @@ from typing import Union from swh.graphql.backends import archive +from swh.model import hashutil from .base_node import BaseSWHNode from .directory_entry import DirectoryEntryNode @@ -18,8 +19,10 @@ Base resolver for all the content nodes """ - def _get_content_by_id(self, content_id): - content = archive.Archive().get_content(content_id) + def _get_content_by_hash(self, hash_value: bytes, hash_type="sha1_git"): + content = archive.Archive().get_content( + hash_value=hash_value, hash_type=hash_type + ) return content[0] if content else None @property @@ -31,6 +34,12 @@ def id(self): return self._node.sha1_git + @property + def data(self): + # FIXME, return a Node object + content_sha1 = self._node.hashes()["sha1"] + return {"raw": archive.Archive().get_content_data(content_sha1)} + def is_type_of(self): # is_type_of is required only when resolving a UNION type # This is for ariadne to return the right type @@ -40,10 +49,20 @@ class ContentNode(BaseContentNode): """ Node resolver for a content requested directly with its SWHID + or with a contentHash (hash_type:hash_value) string """ def _get_node_data(self): - return self._get_content_by_id(self.kwargs.get("swhid").object_id) + if self.kwargs.get("swhid"): + # SWHID gets precedence in case both the arguments are available + hash_type, hash_value = "sha1_git", self.kwargs.get("swhid").object_id + elif self.kwargs.get("contentHash"): + hash_type, hash_string = self.kwargs.get("contentHash").split(":") + hash_value = hashutil.hash_to_bytes(hash_string) + else: + # raise ObjectNotFoundError in case both the arguments are missing + return None + return self._get_content_by_hash(hash_value=hash_value, hash_type=hash_type) class TargetContentNode(BaseContentNode): @@ -55,5 +74,4 @@ obj: Union[DirectoryEntryNode, BaseReleaseNode, SnapshotBranchNode] def _get_node_data(self): - content_id = self.obj.target_hash - return self._get_content_by_id(content_id) + return self._get_content_by_hash(hash_value=self.obj.target_hash) diff --git a/swh/graphql/schema/schema.graphql b/swh/graphql/schema/schema.graphql --- a/swh/graphql/schema/schema.graphql +++ b/swh/graphql/schema/schema.graphql @@ -775,6 +775,42 @@ sha256: String } +""" +Object with different content data representations +""" +type ContentData { + """ + Content as a base64 string + """ + raw: BinaryString +} + +type ContentFileType { + """ + Detected content encoding + """ + encoding: String + + """ + Detected MIME type of the content + """ + mimetype: String +} + +type ContentLanguage { + """ + Detected programming language if any + """ + lang: String +} + +type ContentLicense { + """ + Array of strings containing the detected license names + """ + licenses: [String] +} + """ A content object """ @@ -803,6 +839,26 @@ Content status, visible or hidden """ status: String + + """ + File content + """ + data: ContentData + + """ + Information about the content MIME type + """ + fileType: ContentFileType + + """ + Information about the programming language used in the content + """ + language: ContentLanguage + + """ + Information about the license of the content + """ + license: ContentLicense } """ @@ -896,11 +952,17 @@ """ Get the content with a SWHID + Either the swhid or the contentHash is mandatory """ content( """ SWHID of the content object """ - swhid: SWHID! + swhid: SWHID + + """ + hashType:hashValue string + """ + contentHash: String ): Content }