From 73f141903abee3ace93c596392fd3a39688ddc70 Mon Sep 17 00:00:00 2001
From: Jayesh Velayudhan <jayesh@softwareheritage.org>
Date: Mon, 19 Sep 2022 12:32:23 +0200
Subject: [PATCH] Basic integration

---
 swh/web/api/views/directory.py |  2 +
 swh/web/api/views/origin.py    | 27 ++++++------
 swh/web/api/views/release.py   | 25 +++++++----
 swh/web/api/views/revision.py  | 21 ++++++---
 swh/web/api/views/snapshot.py  | 79 ++++++++++++++++++++--------------
 swh/web/utils/graphql.py       | 30 +++++++++++++
 6 files changed, 126 insertions(+), 58 deletions(-)
 create mode 100644 swh/web/utils/graphql.py

diff --git a/swh/web/api/views/directory.py b/swh/web/api/views/directory.py
index 931456641..c18d86c1e 100644
--- a/swh/web/api/views/directory.py
+++ b/swh/web/api/views/directory.py
@@ -75,6 +75,7 @@ def api_directory(request: Request, sha1_git: str, path: Optional[str] = None):
             :swh_web_api:`directory/977fc4b98c0e85816348cebd3b12026407c368b6/`
     """
     if path:
+        # query directory entry
         error_msg_path = (
             "Entry with path %s relative to directory " "with sha1_git %s not found."
         ) % (path, sha1_git)
@@ -87,6 +88,7 @@ def api_directory(request: Request, sha1_git: str, path: Optional[str] = None):
             request=request,
         )
     else:
+        # query directory
         error_msg_nopath = "Directory with sha1_git %s not found." % sha1_git
         return api_lookup(
             archive.lookup_directory,
diff --git a/swh/web/api/views/origin.py b/swh/web/api/views/origin.py
index a5b28d300..2996d0abc 100644
--- a/swh/web/api/views/origin.py
+++ b/swh/web/api/views/origin.py
@@ -18,7 +18,7 @@ from swh.web.api.utils import (
     enrich_origin_visit,
 )
 from swh.web.api.views.utils import api_lookup
-from swh.web.utils import archive, origin_visit_types, reverse
+from swh.web.utils import archive, graphql, origin_visit_types, reverse
 from swh.web.utils.exc import BadInputExc
 from swh.web.utils.origin_visits import get_origin_visits
 from swh.web.utils.typing import OriginInfo
@@ -106,6 +106,7 @@ def api_origins(request: Request):
     next_page_token = page_result.next_page_token
 
     headers: Dict[str, str] = {}
+
     if next_page_token is not None:
         headers["link-next"] = reverse(
             "api-1-origins",
@@ -140,16 +141,19 @@ def api_origin(request: Request, origin_url: str):
             :swh_web_api:`origin/https://github.com/python/cpython/get/`
 
     """
-    ori_dict = {"url": origin_url}
-
-    error_msg = "Origin with url %s not found." % ori_dict["url"]
-
-    return api_lookup(
-        archive.lookup_origin,
-        ori_dict,
-        lookup_similar_urls=False,
-        notfound_msg=error_msg,
-        enrich_fn=enrich_origin,
+    query = """
+    query GetOrigin($url: String!) {
+      origin(url: $url) {
+        url
+      }
+    }
+    """
+    return graphql.get_one(
+        query,
+        {"url": origin_url},
+        query_root="origin",
+        enrich=enrich_origin,
+        error_msg=f"Origin with url {origin_url} not found.",
         request=request,
     )
 
@@ -424,7 +428,6 @@ def api_origin_visit_latest(request: Request, origin_url: str):
 
             :swh_web_api:`origin/https://github.com/hylang/hy/visit/latest/`
     """
-
     require_snapshot = request.query_params.get("require_snapshot", "false")
     return api_lookup(
         archive.lookup_origin_visit_latest,
diff --git a/swh/web/api/views/release.py b/swh/web/api/views/release.py
index edc6a5f58..b7452289d 100644
--- a/swh/web/api/views/release.py
+++ b/swh/web/api/views/release.py
@@ -5,11 +5,12 @@
 
 from rest_framework.request import Request
 
+from swh.model.hashutil import hash_to_bytes
+from swh.model.swhids import CoreSWHID, ObjectType
 from swh.web.api import utils
 from swh.web.api.apidoc import api_doc, format_docstring
 from swh.web.api.apiurls import api_route
-from swh.web.api.views.utils import api_lookup
-from swh.web.utils import archive
+from swh.web.utils import graphql
 
 
 @api_route(
@@ -52,11 +53,19 @@ def api_release(request: Request, sha1_git: str):
 
             :swh_web_api:`release/208f61cc7a5dbc9879ae6e5c2f95891e270f09ef/`
     """
-    error_msg = "Release with sha1_git %s not found." % sha1_git
-    return api_lookup(
-        archive.lookup_release,
-        sha1_git,
-        notfound_msg=error_msg,
-        enrich_fn=utils.enrich_release,
+    query = """
+    query GetRelease($swhid: SWHID!) {
+      release(swhid: $swhid) {
+        date
+        id
+      }
+    }
+    """
+    return graphql.get_one(
+        query,
+        {"swhid": f"swh:1:rel:{sha1_git}"},
+        query_root="release",
+        enrich=utils.enrich_release,
+        error_msg=f"Release with {sha1_git} not found.",
         request=request,
     )
diff --git a/swh/web/api/views/revision.py b/swh/web/api/views/revision.py
index 8d4ec8b08..db59d448b 100644
--- a/swh/web/api/views/revision.py
+++ b/swh/web/api/views/revision.py
@@ -12,7 +12,7 @@ from swh.web.api import utils
 from swh.web.api.apidoc import api_doc, format_docstring
 from swh.web.api.apiurls import api_route
 from swh.web.api.views.utils import api_lookup
-from swh.web.utils import archive
+from swh.web.utils import archive, graphql
 
 DOC_RETURN_REVISION = """
         :>json object author: information about the author of the revision
@@ -71,11 +71,20 @@ def api_revision(request: Request, sha1_git: str):
 
             :swh_web_api:`revision/aafb16d69fd30ff58afdd69036a26047f3aebdc6/`
     """
-    return api_lookup(
-        archive.lookup_revision,
-        sha1_git,
-        notfound_msg="Revision with sha1_git {} not found.".format(sha1_git),
-        enrich_fn=utils.enrich_revision,
+    query = """
+    query GetRevision($swhid: SWHID!) {
+      revision(swhid: $swhid) {
+        date
+        id
+      }
+    }
+    """
+    return graphql.get_one(
+        query,
+        {"swhid": f"swh:1:rev:{sha1_git}"},
+        query_root="revision",
+        enrich=utils.enrich_revision,
+        error_msg=f"Revision with sha1_git {sha1_git} not found.",
         request=request,
     )
 
diff --git a/swh/web/api/views/snapshot.py b/swh/web/api/views/snapshot.py
index e64227fa3..54cfba186 100644
--- a/swh/web/api/views/snapshot.py
+++ b/swh/web/api/views/snapshot.py
@@ -10,7 +10,7 @@ from swh.web.api.apiurls import api_route
 from swh.web.api.utils import enrich_snapshot
 from swh.web.api.views.utils import api_lookup
 from swh.web.config import get_config
-from swh.web.utils import archive, reverse
+from swh.web.utils import archive, graphql, reverse
 
 
 @api_route(
@@ -69,37 +69,52 @@ def api_snapshot(request: Request, snapshot_id: str):
             :swh_web_api:`snapshot/6a3a2cf0b2b90ce7ae1cf0a221ed68035b686f5a/`
     """
 
-    snapshot_content_max_size = get_config()["snapshot_content_max_size"]
-
-    branches_from = request.GET.get("branches_from", "")
-    branches_count = int(request.GET.get("branches_count", snapshot_content_max_size))
-    target_types_str = request.GET.get("target_types", None)
-    target_types = target_types_str.split(",") if target_types_str else None
-
-    results = api_lookup(
-        archive.lookup_snapshot,
-        snapshot_id,
-        branches_from,
-        branches_count,
-        target_types,
-        branch_name_exclude_prefix=None,
-        notfound_msg="Snapshot with id {} not found.".format(snapshot_id),
-        enrich_fn=enrich_snapshot,
+    query = """
+    query GetSnapshot($swhid: SWHID!) {
+      snapshot(swhid: $swhid) {
+        id
+      }
+    }
+    """
+    return graphql.get_one(
+        query,
+        {"swhid": f"swh:1:snp:{snapshot_id}"},
+        query_root="snapshot",
+        error_msg=f"Snapshot with sha1_git {snapshot_id} not found.",
         request=request,
     )
 
-    response = {"results": results, "headers": {}}
-
-    if results["next_branch"] is not None:
-        response["headers"]["link-next"] = reverse(
-            "api-1-snapshot",
-            url_args={"snapshot_id": snapshot_id},
-            query_params={
-                "branches_from": results["next_branch"],
-                "branches_count": str(branches_count),
-                "target_types": ",".join(target_types) if target_types else None,
-            },
-            request=request,
-        )
-
-    return response
+    # snapshot_content_max_size = get_config()["snapshot_content_max_size"]
+
+    # branches_from = request.GET.get("branches_from", "")
+    # branches_count = int(request.GET.get("branches_count", snapshot_content_max_size))
+    # target_types_str = request.GET.get("target_types", None)
+    # target_types = target_types_str.split(",") if target_types_str else None
+
+    # results = api_lookup(
+    #     archive.lookup_snapshot,
+    #     snapshot_id,
+    #     branches_from,
+    #     branches_count,
+    #     target_types,
+    #     branch_name_exclude_prefix=None,
+    #     notfound_msg="Snapshot with id {} not found.".format(snapshot_id),
+    #     enrich_fn=enrich_snapshot,
+    #     request=request,
+    # )
+
+    # response = {"results": results, "headers": {}}
+
+    # if results["next_branch"] is not None:
+    #     response["headers"]["link-next"] = reverse(
+    #         "api-1-snapshot",
+    #         url_args={"snapshot_id": snapshot_id},
+    #         query_params={
+    #             "branches_from": results["next_branch"],
+    #             "branches_count": str(branches_count),
+    #             "target_types": ",".join(target_types) if target_types else None,
+    #         },
+    #         request=request,
+    #     )
+
+    # return response
diff --git a/swh/web/utils/graphql.py b/swh/web/utils/graphql.py
new file mode 100644
index 000000000..8394378e7
--- /dev/null
+++ b/swh/web/utils/graphql.py
@@ -0,0 +1,30 @@
+from typing import Dict
+
+from gql import Client, gql
+from gql.transport.aiohttp import AIOHTTPTransport
+
+from swh.web.utils.exc import NotFoundExc
+
+transport = AIOHTTPTransport(url="http://127.0.0.1:8000/")
+client = Client(transport=transport, fetch_schema_from_transport=True)
+
+
+def get_one(
+    query: str, variables, query_root, enrich=None, error_msg="", request=None
+) -> Dict:
+    # FIXME add a cache with query normalization
+    try:
+        result = client.execute(gql(query), variable_values=variables)[query_root]
+    except Exception as e:
+        # not found error
+        raise NotFoundExc(error_msg, e)
+    except Exception as e:
+        # unknown error
+        raise NotFoundExc(error_msg, e)
+    if enrich is not None:
+        result = enrich(result, request)
+    return result
+
+
+def get_many(query: str):
+    pass
-- 
GitLab